Mercurial > repos > public > sbplib_julia
changeset 702:3cd582257072 feature/laplace_opset
Merge in default
author | Vidar Stiernström <vidar.stiernstrom@it.uu.se> |
---|---|
date | Mon, 15 Feb 2021 11:30:34 +0100 |
parents | 54ce3f9771e5 (current diff) 38f9894279cd (diff) |
children | 988e9cfcd58d |
files | Notes.md src/SbpOperators/volumeops/laplace/laplace.jl src/SbpOperators/volumeops/quadratures/inverse_quadrature.jl src/SbpOperators/volumeops/quadratures/quadrature.jl test/testSbpOperators.jl |
diffstat | 15 files changed, 353 insertions(+), 314 deletions(-) [+] |
line wrap: on
line diff
--- a/Notes.md Sat Feb 06 15:26:14 2021 +0100 +++ b/Notes.md Mon Feb 15 11:30:34 2021 +0100 @@ -299,3 +299,16 @@ component(gf,:,2) # Andra kolumnen av en matris @ourview gf[:,:][2] ``` + +## Grids embedded in higher dimensions + +For grids generated by asking for boundary grids for a regular grid, it would +make sense if these grids knew they were embedded in a higher dimension. They +would return coordinates in the full room. This would make sense when +drawing points for example, or when evaluating functions on the boundary. + +Implementation of this is an issue that requires some thought. Adding an extra +"Embedded" type for each grid would make it easy to understand each type but +contribute to "type bloat". On the other hand adapting existing types to +handle embeddedness would complicate the now very simple grid types. Are there +other ways of doing the implentation?
--- a/src/Grids/EquidistantGrid.jl Sat Feb 06 15:26:14 2021 +0100 +++ b/src/Grids/EquidistantGrid.jl Mon Feb 15 11:30:34 2021 +0100 @@ -1,11 +1,19 @@ """ - EquidistantGrid(size::NTuple{Dim, Int}, limit_lower::NTuple{Dim, T}, limit_upper::NTuple{Dim, T} + EquidistantGrid(size::NTuple{Dim, Int}, limit_lower::NTuple{Dim, T}, limit_upper::NTuple{Dim, T}) + EquidistantGrid{T}() + +`EquidistantGrid` is a grid with equidistant grid spacing per coordinat direction. -EquidistantGrid is a grid with equidistant grid spacing per coordinat direction. -The domain is defined through the two points P1 = x̄₁, P2 = x̄₂ by the exterior -product of the vectors obtained by projecting (x̄₂-x̄₁) onto the coordinate -directions. E.g for a 2D grid with x̄₁=(-1,0) and x̄₂=(1,2) the domain is defined -as (-1,1)x(0,2). The side lengths of the grid are not allowed to be negative +`EquidistantGrid(size, limit_lower, limit_upper)` construct the grid with the +domain defined by the two points P1, and P2 given by `limit_lower` and +`limit_upper`. The length of the domain sides are given by the components of +(P2-P1). E.g for a 2D grid with P1=(-1,0) and P2=(1,2) the domain is defined +as (-1,1)x(0,2). The side lengths of the grid are not allowed to be negative. +The number of equidistantly spaced points in each coordinate direction are given +by `size`. + +`EquidistantGrid{T}()` constructs a 0-dimensional grid. + """ struct EquidistantGrid{Dim,T<:Real} <: AbstractGrid size::NTuple{Dim, Int} @@ -22,6 +30,9 @@ end return new{Dim,T}(size, limit_lower, limit_upper) end + + # Specialized constructor for 0-dimensional grid + EquidistantGrid{T}() where T = new{0,T}((),(),()) end export EquidistantGrid @@ -35,9 +46,9 @@ return EquidistantGrid((size,),(limit_lower,),(limit_upper,)) end -function Base.eachindex(grid::EquidistantGrid) - CartesianIndices(grid.size) -end +Base.eltype(grid::EquidistantGrid{Dim,T}) where {Dim,T} = T + +Base.eachindex(grid::EquidistantGrid) = CartesianIndices(grid.size) Base.size(g::EquidistantGrid) = g.size @@ -104,3 +115,23 @@ """ boundary_identifiers(g::EquidistantGrid) = (((ntuple(i->(CartesianBoundary{i,Lower}(),CartesianBoundary{i,Upper}()),dimension(g)))...)...,) export boundary_identifiers + + +""" + boundary_grid(grid::EquidistantGrid,id::CartesianBoundary) + boundary_grid(::EquidistantGrid{1},::CartesianBoundary{1}) + +Creates the lower-dimensional restriciton of `grid` spanned by the dimensions +orthogonal to the boundary specified by `id`. The boundary grid of a 1-dimensional +grid is a zero-dimensional grid. +""" +function boundary_grid(grid::EquidistantGrid,id::CartesianBoundary) + dims = collect(1:dimension(grid)) + orth_dims = dims[dims .!= dim(id)] + if orth_dims == dims + throw(DomainError("boundary identifier not matching grid")) + end + return restrict(grid,orth_dims) +end +export boundary_grid +boundary_grid(::EquidistantGrid{1,T},::CartesianBoundary{1}) where T = EquidistantGrid{T}()
--- a/src/SbpOperators/SbpOperators.jl Sat Feb 06 15:26:14 2021 +0100 +++ b/src/SbpOperators/SbpOperators.jl Mon Feb 15 11:30:34 2021 +0100 @@ -10,8 +10,8 @@ include("volumeops/volume_operator.jl") include("volumeops/derivatives/secondderivative.jl") include("volumeops/laplace/laplace.jl") -include("volumeops/quadratures/quadrature.jl") -include("volumeops/quadratures/inverse_quadrature.jl") +include("volumeops/inner_products/inner_product.jl") +include("volumeops/inner_products/inverse_inner_product.jl") include("boundaryops/boundary_operator.jl") include("boundaryops/boundary_restriction.jl") include("boundaryops/normal_derivative.jl")
--- a/src/SbpOperators/boundaryops/boundary_restriction.jl Sat Feb 06 15:26:14 2021 +0100 +++ b/src/SbpOperators/boundaryops/boundary_restriction.jl Mon Feb 15 11:30:34 2021 +0100 @@ -1,6 +1,6 @@ """ - BoundaryRestriction(grid::EquidistantGrid, closure_stencil::Stencil, boundary::CartesianBoundary) - BoundaryRestriction(grid::EquidistantGrid{1}, closure_stencil::Stencil, region::Region) + boundary_restriction(grid::EquidistantGrid, closure_stencil::Stencil, boundary::CartesianBoundary) + boundary_restriction(grid::EquidistantGrid{1}, closure_stencil::Stencil, region::Region) Creates the boundary restriction operator `e` as a `TensorMapping` @@ -9,7 +9,7 @@ On a one-dimensional `grid`, `e` is a `BoundaryOperator`. On a multi-dimensional `grid`, `e` is the inflation of a `BoundaryOperator`. Also see the documentation of `SbpOperators.boundary_operator(...)` for more details. """ -BoundaryRestriction(grid::EquidistantGrid, closure_stencil::Stencil, boundary::CartesianBoundary) = SbpOperators.boundary_operator(grid, closure_stencil, boundary) -BoundaryRestriction(grid::EquidistantGrid{1}, closure_stencil::Stencil, region::Region) = BoundaryRestriction(grid, closure_stencil, CartesianBoundary{1,typeof(region)}()) +boundary_restriction(grid::EquidistantGrid, closure_stencil::Stencil, boundary::CartesianBoundary) = SbpOperators.boundary_operator(grid, closure_stencil, boundary) +boundary_restriction(grid::EquidistantGrid{1}, closure_stencil::Stencil, region::Region) = boundary_restriction(grid, closure_stencil, CartesianBoundary{1,typeof(region)}()) -export BoundaryRestriction +export boundary_restriction
--- a/src/SbpOperators/boundaryops/normal_derivative.jl Sat Feb 06 15:26:14 2021 +0100 +++ b/src/SbpOperators/boundaryops/normal_derivative.jl Mon Feb 15 11:30:34 2021 +0100 @@ -1,6 +1,6 @@ """ - NormalDerivative(grid::EquidistantGrid, closure_stencil::Stencil, boundary::CartesianBoundary) - NormalDerivative(grid::EquidistantGrid{1}, closure_stencil::Stencil, region::Region) + normal_derivative(grid::EquidistantGrid, closure_stencil::Stencil, boundary::CartesianBoundary) + normal_derivative(grid::EquidistantGrid{1}, closure_stencil::Stencil, region::Region) Creates the normal derivative boundary operator `d` as a `TensorMapping` @@ -9,10 +9,10 @@ On a one-dimensional `grid`, `d` is a `BoundaryOperator`. On a multi-dimensional `grid`, `d` is the inflation of a `BoundaryOperator`. Also see the documentation of `SbpOperators.boundary_operator(...)` for more details. """ -function NormalDerivative(grid::EquidistantGrid, closure_stencil::Stencil, boundary::CartesianBoundary) +function normal_derivative(grid::EquidistantGrid, closure_stencil::Stencil, boundary::CartesianBoundary) direction = dim(boundary) h_inv = inverse_spacing(grid)[direction] return SbpOperators.boundary_operator(grid, scale(closure_stencil,h_inv), boundary) end -NormalDerivative(grid::EquidistantGrid{1}, closure_stencil::Stencil, region::Region) = NormalDerivative(grid, closure_stencil, CartesianBoundary{1,typeof(region)}()) -export NormalDerivative +normal_derivative(grid::EquidistantGrid{1}, closure_stencil::Stencil, region::Region) = normal_derivative(grid, closure_stencil, CartesianBoundary{1,typeof(region)}()) +export normal_derivative
--- a/src/SbpOperators/readoperator.jl Sat Feb 06 15:26:14 2021 +0100 +++ b/src/SbpOperators/readoperator.jl Mon Feb 15 11:30:34 2021 +0100 @@ -26,13 +26,13 @@ closureStencils = (closureStencils..., get_stencil(operators, "D2", "closure_stencils", i; center=i)) end # TODO: Get rid of the padding here. Any padding should be handled by the consturctor accepting the stencils. - eClosure = Stencil(pad_tuple(toml_string_array_to_tuple(Float64, e["closure"]), boundarySize), center=1) - dClosure = Stencil(pad_tuple(toml_string_array_to_tuple(Float64, d1["closure"]), boundarySize), center=1) + eClosure = Stencil(pad_tuple(toml_string_array_to_tuple(Float64, e["closure"]), boundarySize)..., center=1) + dClosure = Stencil(pad_tuple(toml_string_array_to_tuple(Float64, d1["closure"]), boundarySize)..., center=1) q_tuple = pad_tuple(toml_string_array_to_tuple(Float64, H["closure"]), boundarySize) quadratureClosure = Vector{typeof(innerStencil)}() for i ∈ 1:boundarySize - quadratureClosure = (quadratureClosure..., Stencil((q_tuple[i],), center=1)) + quadratureClosure = (quadratureClosure..., Stencil(q_tuple[i], center=1)) end d2 = SbpOperators.D2( @@ -99,7 +99,7 @@ center = div(width,2)+1 end - return Stencil(Tuple(stencil_weights), center=center) + return Stencil(stencil_weights..., center=center) end """
--- a/src/SbpOperators/stencil.jl Sat Feb 06 15:26:14 2021 +0100 +++ b/src/SbpOperators/stencil.jl Mon Feb 15 11:30:34 2021 +0100 @@ -1,3 +1,5 @@ +export CenteredStencil + struct Stencil{T<:Real,N} range::Tuple{Int,Int} weights::NTuple{N,T} @@ -13,13 +15,24 @@ Create a stencil with the given weights with element `center` as the center of the stencil. """ -function Stencil(weights::NTuple; center::Int) +function Stencil(weights::Vararg{Number}; center::Int) N = length(weights) range = (1, N) .- center return Stencil(range, weights) end +function CenteredStencil(weights::Vararg) + if iseven(length(weights)) + throw(ArgumentError("a centered stencil must have an odd number of weights.")) + end + + r = length(weights) ÷ 2 + + return Stencil((-r, r), weights) +end + + """ scale(s::Stencil, a)
--- a/src/SbpOperators/volumeops/derivatives/secondderivative.jl Sat Feb 06 15:26:14 2021 +0100 +++ b/src/SbpOperators/volumeops/derivatives/secondderivative.jl Mon Feb 15 11:30:34 2021 +0100 @@ -1,6 +1,6 @@ """ - SecondDerivative(grid::EquidistantGrid{Dim}, inner_stencil, closure_stencils, direction) - SecondDerivative(grid::EquidistantGrid{1}, inner_stencil, closure_stencils) + second_derivative(grid::EquidistantGrid{Dim}, inner_stencil, closure_stencils, direction) + second_derivative(grid::EquidistantGrid{1}, inner_stencil, closure_stencils) Creates the second-derivative operator `D2` as a `TensorMapping` @@ -12,9 +12,9 @@ one-dimensional operator with the `IdentityMapping`s in orthogonal coordinate dirrections. Also see the documentation of `SbpOperators.volume_operator(...)` for more details. """ -function SecondDerivative(grid::EquidistantGrid{Dim}, inner_stencil, closure_stencils, direction) where Dim +function second_derivative(grid::EquidistantGrid{Dim}, inner_stencil, closure_stencils, direction) where Dim h_inv = inverse_spacing(grid)[direction] return SbpOperators.volume_operator(grid, scale(inner_stencil,h_inv^2), scale.(closure_stencils,h_inv^2), even, direction) end -SecondDerivative(grid::EquidistantGrid{1}, inner_stencil, closure_stencils) = SecondDerivative(grid,inner_stencil,closure_stencils,1) -export SecondDerivative +second_derivative(grid::EquidistantGrid{1}, inner_stencil, closure_stencils) = second_derivative(grid,inner_stencil,closure_stencils,1) +export second_derivative
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/SbpOperators/volumeops/inner_products/inner_product.jl Mon Feb 15 11:30:34 2021 +0100 @@ -0,0 +1,29 @@ +""" + inner_product(grid::EquidistantGrid, closure_stencils, inner_stencil) + +Creates the discrete inner product operator `H` as a `TensorMapping` on an equidistant +grid, defined as `(u,v) = u'Hv` for grid functions `u,v`. + +`inner_product(grid::EquidistantGrid, closure_stencils, inner_stencil)` creates +`H` on `grid` the using a set of stencils `closure_stencils` for the points in +the closure regions and the stencil and `inner_stencil` in the interior. If +`inner_stencil` is omitted a central interior stencil with weight 1 is used. + +On a 1-dimensional `grid`, `H` is a `VolumeOperator`. On a N-dimensional +`grid`, `H` is the outer product of the 1-dimensional inner product operators in +each coordinate direction. Also see the documentation of +`SbpOperators.volume_operator(...)` for more details. On a 0-dimensional `grid`, +`H` is a 0-dimensional `IdentityMapping`. +""" +function inner_product(grid::EquidistantGrid, closure_stencils, inner_stencil = CenteredStencil(one(eltype(grid)))) + h = spacing(grid) + H = SbpOperators.volume_operator(grid, scale(inner_stencil,h[1]), scale.(closure_stencils,h[1]), even, 1) + for i ∈ 2:dimension(grid) + Hᵢ = SbpOperators.volume_operator(grid, scale(inner_stencil,h[i]), scale.(closure_stencils,h[i]), even, i) + H = H∘Hᵢ + end + return H +end +export inner_product + +inner_product(grid::EquidistantGrid{0}, closure_stencils, inner_stencil) = IdentityMapping{eltype(grid)}()
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/SbpOperators/volumeops/inner_products/inverse_inner_product.jl Mon Feb 15 11:30:34 2021 +0100 @@ -0,0 +1,43 @@ +""" + inverse_inner_product(grid::EquidistantGrid, inv_inner_stencil, inv_closure_stencils) + inverse_inner_product(grid::EquidistantGrid, closure_stencils::NTuple{M,Stencil{T,1}}) + +Creates the inverse inner product operator `H⁻¹` as a `TensorMapping` on an +equidistant grid. `H⁻¹` is defined implicitly by `H⁻¹∘H = I`, where +`H` is the corresponding inner product operator and `I` is the `IdentityMapping`. + +`inverse_inner_product(grid::EquidistantGrid, inv_inner_stencil, inv_closure_stencils)` +constructs `H⁻¹` using a set of stencils `inv_closure_stencils` for the points +in the closure regions and the stencil `inv_inner_stencil` in the interior. If +`inv_closure_stencils` is omitted, a central interior stencil with weight 1 is used. + +`inverse_inner_product(grid::EquidistantGrid, closure_stencils::NTuple{M,Stencil{T,1}})` +constructs a diagonal inverse inner product operator where `closure_stencils` are the +closure stencils of `H` (not `H⁻¹`!). + +On a 1-dimensional `grid`, `H⁻¹` is a `VolumeOperator`. On a N-dimensional +`grid`, `H⁻¹` is the outer product of the 1-dimensional inverse inner product +operators in each coordinate direction. Also see the documentation of +`SbpOperators.volume_operator(...)` for more details. On a 0-dimensional `grid`, +`H⁻¹` is a 0-dimensional `IdentityMapping`. +""" +function inverse_inner_product(grid::EquidistantGrid, inv_closure_stencils, inv_inner_stencil = CenteredStencil(one(eltype(grid)))) + h⁻¹ = inverse_spacing(grid) + H⁻¹ = SbpOperators.volume_operator(grid,scale(inv_inner_stencil,h⁻¹[1]),scale.(inv_closure_stencils,h⁻¹[1]),even,1) + for i ∈ 2:dimension(grid) + Hᵢ⁻¹ = SbpOperators.volume_operator(grid,scale(inv_inner_stencil,h⁻¹[i]),scale.(inv_closure_stencils,h⁻¹[i]),even,i) + H⁻¹ = H⁻¹∘Hᵢ⁻¹ + end + return H⁻¹ +end +export inverse_inner_product + +inverse_inner_product(grid::EquidistantGrid{0}, inv_closure_stencils, inv_inner_stencil) = IdentityMapping{eltype(grid)}() + +function inverse_inner_product(grid::EquidistantGrid, closure_stencils::NTuple{M,Stencil{T,1}}) where {M,T} + inv_closure_stencils = reciprocal_stencil.(closure_stencils) + inv_inner_stencil = CenteredStencil(one(T)) + return inverse_inner_product(grid, inv_closure_stencils, inv_inner_stencil) +end + +reciprocal_stencil(s::Stencil{T}) where T = Stencil(s.range,one(T)./s.weights)
--- a/src/SbpOperators/volumeops/laplace/laplace.jl Sat Feb 06 15:26:14 2021 +0100 +++ b/src/SbpOperators/volumeops/laplace/laplace.jl Mon Feb 15 11:30:34 2021 +0100 @@ -37,14 +37,14 @@ # Volume operators Δ = laplace(grid, D_inner_stecil, D_closure_stencils) - H = quadrature(grid, H_closure_stencils) - H⁻¹ = InverseDiagonalQuadrature(grid, H_closure_stencils) + H = inner_product(grid, H_closure_stencils) + H⁻¹ = inverse_inner_product(grid, H_closure_stencils) # Boundary operator - id pairs bids = boundary_identifiers(grid) - e_pairs = ntuple(i -> Pair(bids[i],BoundaryRestriction(grid,e_closure_stencil,bids[i])),length(bids)) - d_pairs = ntuple(i -> Pair(bids[i],NormalDerivative(grid,d_closure_stencil,bids[i])),length(bids)) - Hᵧ_pairs = ntuple(i -> Pair(bids[i],boundary_quadrature(grid,H_closure_stencils,bids[i])),length(bids)) + e_pairs = ntuple(i -> Pair(bids[i],boundary_restriction(grid,e_closure_stencil,bids[i])),length(bids)) + d_pairs = ntuple(i -> Pair(bids[i],normal_derivative(grid,d_closure_stencil,bids[i])),length(bids)) + Hᵧ_pairs = ntuple(i -> Pair(bids[i],inner_product(boundary_grid(grid,bids[i]),H_closure_stencils)),length(bids)) return Laplace(Δ, H, H⁻¹, Dict(e_pairs), Dict(d_pairs), Dict(Hᵧ_pairs)) end @@ -73,13 +73,14 @@ the stencil `inner_stencil` in the interior and a set of stencils `closure_stencils` for the points in the closure regions. -On a one-dimensional `grid`, `Δ` is a `SecondDerivative`. On a multi-dimensional `grid`, `Δ` is the sum of -multi-dimensional `SecondDerivative`s where the sum is carried out lazily. +On a one-dimensional `grid`, `Δ` is equivalent to `second_derivative`. On a +multi-dimensional `grid`, `Δ` is the sum of multi-dimensional `second_derivative`s +where the sum is carried out lazily. """ function laplace(grid::EquidistantGrid{Dim}, inner_stencil, closure_stencils) where Dim - Δ = SecondDerivative(grid, inner_stencil, closure_stencils, 1) + Δ = second_derivative(grid, inner_stencil, closure_stencils, 1) for d = 2:Dim - Δ += SecondDerivative(grid, inner_stencil, closure_stencils, d) + Δ += second_derivative(grid, inner_stencil, closure_stencils, d) end return Δ end
--- a/src/SbpOperators/volumeops/quadratures/inverse_quadrature.jl Sat Feb 06 15:26:14 2021 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,41 +0,0 @@ - -""" - InverseQuadrature(grid::EquidistantGrid, inv_inner_stencil, inv_closure_stencils) - -Creates the inverse `H⁻¹` of the quadrature operator as a `TensorMapping` - -The inverse quadrature approximates the integral operator on the grid using -`inv_inner_stencil` in the interior and a set of stencils `inv_closure_stencils` -for the points in the closure regions. - -On a one-dimensional `grid`, `H⁻¹` is a `VolumeOperator`. On a multi-dimensional -`grid`, `H` is the outer product of the 1-dimensional inverse quadrature operators in -each coordinate direction. Also see the documentation of -`SbpOperators.volume_operator(...)` for more details. -""" -function InverseQuadrature(grid::EquidistantGrid{Dim}, inv_inner_stencil, inv_closure_stencils) where Dim - h⁻¹ = inverse_spacing(grid) - H⁻¹ = SbpOperators.volume_operator(grid,scale(inv_inner_stencil,h⁻¹[1]),scale.(inv_closure_stencils,h⁻¹[1]),even,1) - for i ∈ 2:Dim - Hᵢ⁻¹ = SbpOperators.volume_operator(grid,scale(inv_inner_stencil,h⁻¹[i]),scale.(inv_closure_stencils,h⁻¹[i]),even,i) - H⁻¹ = H⁻¹∘Hᵢ⁻¹ - end - return H⁻¹ -end -export InverseQuadrature - -""" - InverseDiagonalQuadrature(grid::EquidistantGrid, closure_stencils) - -Creates the inverse of the diagonal quadrature operator defined by the inner stencil -1/h and a set of 1-element closure stencils in `closure_stencils`. Note that -the closure stencils are those of the quadrature operator (and not the inverse). -""" -function InverseDiagonalQuadrature(grid::EquidistantGrid, closure_stencils::NTuple{M,Stencil{T,1}}) where {T,M} - inv_inner_stencil = Stencil(Tuple{T}(1),center=1) - inv_closure_stencils = reciprocal_stencil.(closure_stencils) - return InverseQuadrature(grid, inv_inner_stencil, inv_closure_stencils) -end -export InverseDiagonalQuadrature - -reciprocal_stencil(s::Stencil{T}) where T = Stencil(s.range,one(T)./s.weights)
--- a/src/SbpOperators/volumeops/quadratures/quadrature.jl Sat Feb 06 15:26:14 2021 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,69 +0,0 @@ -""" - quadrature(grid::EquidistantGrid, inner_stencil, closure_stencils) - quadrature(grid::EquidistantGrid, closure_stencils) - -Creates the quadrature operator `H` as a `TensorMapping` - -`H` approximiates the integral operator on `grid` the using the stencil -`inner_stencil` in the interior and a set of stencils `closure_stencils` -for the points in the closure regions. If `inner_stencil` is omitted a central -interior stencil with weight 1 is used. - -On a one-dimensional `grid`, `H` is a `VolumeOperator`. On a multi-dimensional -`grid`, `H` is the outer product of the 1-dimensional quadrature operators in -each coordinate direction. Also see the documentation of -`SbpOperators.volume_operator(...)` for more details. -""" -function quadrature(grid::EquidistantGrid, inner_stencil, closure_stencils) where Dim - h = spacing(grid) - H = SbpOperators.volume_operator(grid, scale(inner_stencil,h[1]), scale.(closure_stencils,h[1]), even, 1) - for i ∈ 2:dimension(grid) - Hᵢ = SbpOperators.volume_operator(grid, scale(inner_stencil,h[i]), scale.(closure_stencils,h[i]), even, i) - H = H∘Hᵢ - end - return H -end -export quadrature - -function quadrature(grid::EquidistantGrid, closure_stencils::NTuple{M,Stencil{T}}) where {M,T} - inner_stencil = Stencil(Tuple{T}(1),center=1) - return quadrature(grid, inner_stencil, closure_stencils) -end - -""" - boundary_quadrature(grid::EquidistantGrid, inner_stencil, closure_stencils, id::CartesianBoundary) - boundary_quadrature(grid::EquidistantGrid{1}, inner_stencil, closure_stencils, id) - boundary_quadrature(grid::EquidistantGrid, closure_stencils, id) - -Creates the lower-dimensional quadrature operator associated with the boundary -of `grid` specified by `id`. The quadrature operator is defined on the grid -spanned by the dimensions orthogonal to the boundary coordinate direction. -If the dimension of `grid` is 1, then the boundary quadrature is the 0-dimensional -`IdentityMapping`. If `inner_stencil` is omitted a central interior stencil with -weight 1 is used. -""" -function boundary_quadrature(grid::EquidistantGrid, inner_stencil, closure_stencils, id::CartesianBoundary) - return quadrature(orthogonal_grid(grid,dim(id)),inner_stencil,closure_stencils) -end -export boundary_quadrature - -function boundary_quadrature(grid::EquidistantGrid{1}, inner_stencil::Stencil{T}, closure_stencils::NTuple{M,Stencil{T}}, id::CartesianBoundary{1}) where {M,T} - return IdentityMapping{T}() -end - -function boundary_quadrature(grid::EquidistantGrid, closure_stencils::NTuple{M,Stencil{T}}, id::CartesianBoundary) where {M,T} - inner_stencil = Stencil(Tuple{T}(1),center=1) - return boundary_quadrature(grid,inner_stencil,closure_stencils,id) -end - -""" - orthogonal_grid(grid,dim) - -Creates the lower-dimensional restriciton of `grid` spanned by the dimensions -orthogonal to `dim`. -""" -function orthogonal_grid(grid,dim) - dims = collect(1:dimension(grid)) - orth_dims = dims[dims .!= dim] - return restrict(grid,orth_dims) -end
--- a/test/testGrids.jl Sat Feb 06 15:26:14 2021 +0100 +++ b/test/testGrids.jl Mon Feb 15 11:30:34 2021 +0100 @@ -13,9 +13,12 @@ @test_throws DomainError EquidistantGrid(1,1.0,-1.0) @test EquidistantGrid(4,0.0,1.0) == EquidistantGrid((4,),(0.0,),(1.0,)) - # size - @test size(EquidistantGrid(4,0.0,1.0)) == (4,) - @test size(EquidistantGrid((5,3), (0.0,0.0), (2.0,1.0))) == (5,3) + @testset "Base" begin + @test eltype(EquidistantGrid(4,0.0,1.0)) == Float64 + @test eltype(EquidistantGrid((4,3),(0,0),(1,3))) == Int + @test size(EquidistantGrid(4,0.0,1.0)) == (4,) + @test size(EquidistantGrid((5,3), (0.0,0.0), (2.0,1.0))) == (5,3) + end # dimension @test dimension(EquidistantGrid(4,0.0,1.0)) == 1 @@ -63,6 +66,39 @@ @test boundary_identifiers(g) == bids @inferred boundary_identifiers(g) end + + @testset "boundary_grid" begin + @testset "1D" begin + g = EquidistantGrid(5,0.0,2.0) + (id_l, id_r) = boundary_identifiers(g) + @test boundary_grid(g,id_l) == EquidistantGrid{Float64}() + @test boundary_grid(g,id_r) == EquidistantGrid{Float64}() + @test_throws DomainError boundary_grid(g,CartesianBoundary{2,Lower}()) + @test_throws DomainError boundary_grid(g,CartesianBoundary{0,Lower}()) + end + @testset "2D" begin + g = EquidistantGrid((5,3),(0.0,0.0),(1.0,3.0)) + (id_w, id_e, id_s, id_n) = boundary_identifiers(g) + @test boundary_grid(g,id_w) == restrict(g,2) + @test boundary_grid(g,id_e) == restrict(g,2) + @test boundary_grid(g,id_s) == restrict(g,1) + @test boundary_grid(g,id_n) == restrict(g,1) + @test_throws DomainError boundary_grid(g,CartesianBoundary{4,Lower}()) + end + @testset "3D" begin + g = EquidistantGrid((2,5,3), (0.0,0.0,0.0), (2.0,1.0,3.0)) + (id_w, id_e, + id_s, id_n, + id_t, id_b) = boundary_identifiers(g) + @test boundary_grid(g,id_w) == restrict(g,[2,3]) + @test boundary_grid(g,id_e) == restrict(g,[2,3]) + @test boundary_grid(g,id_s) == restrict(g,[1,3]) + @test boundary_grid(g,id_n) == restrict(g,[1,3]) + @test boundary_grid(g,id_t) == restrict(g,[1,2]) + @test boundary_grid(g,id_b) == restrict(g,[1,2]) + @test_throws DomainError boundary_grid(g,CartesianBoundary{4,Lower}()) + end + end end end
--- a/test/testSbpOperators.jl Sat Feb 06 15:26:14 2021 +0100 +++ b/test/testSbpOperators.jl Mon Feb 15 11:30:34 2021 +0100 @@ -24,9 +24,12 @@ @test eltype(s) == Float64 @test SbpOperators.scale(s, 2) == Stencil((-2,2), (2.,4.,4.,6.,8.)) - @test Stencil((1,2,3,4), center=1) == Stencil((0, 3),(1,2,3,4)) - @test Stencil((1,2,3,4), center=2) == Stencil((-1, 2),(1,2,3,4)) - @test Stencil((1,2,3,4), center=4) == Stencil((-3, 0),(1,2,3,4)) + @test Stencil(1,2,3,4; center=1) == Stencil((0, 3),(1,2,3,4)) + @test Stencil(1,2,3,4; center=2) == Stencil((-1, 2),(1,2,3,4)) + @test Stencil(1,2,3,4; center=4) == Stencil((-3, 0),(1,2,3,4)) + + @test CenteredStencil(1,2,3,4,5) == Stencil((-2, 2), (1,2,3,4,5)) + @test_throws ArgumentError CenteredStencil(1,2,3,4) end @testset "parse_rational" begin @@ -67,40 +70,40 @@ parsed_toml = TOML.parse(toml_str) @testset "get_stencil" begin - @test get_stencil(parsed_toml, "order2", "D1", "inner_stencil") == Stencil((-1/2, 0., 1/2), center=2) - @test get_stencil(parsed_toml, "order2", "D1", "inner_stencil", center=1) == Stencil((-1/2, 0., 1/2); center=1) - @test get_stencil(parsed_toml, "order2", "D1", "inner_stencil", center=3) == Stencil((-1/2, 0., 1/2); center=3) + @test get_stencil(parsed_toml, "order2", "D1", "inner_stencil") == Stencil(-1/2, 0., 1/2, center=2) + @test get_stencil(parsed_toml, "order2", "D1", "inner_stencil", center=1) == Stencil(-1/2, 0., 1/2; center=1) + @test get_stencil(parsed_toml, "order2", "D1", "inner_stencil", center=3) == Stencil(-1/2, 0., 1/2; center=3) - @test get_stencil(parsed_toml, "order2", "H", "inner") == Stencil((1.,), center=1) + @test get_stencil(parsed_toml, "order2", "H", "inner") == Stencil(1.; center=1) @test_throws AssertionError get_stencil(parsed_toml, "meta", "type") @test_throws AssertionError get_stencil(parsed_toml, "order2", "D1", "closure_stencils") end @testset "get_stencils" begin - @test get_stencils(parsed_toml, "order2", "D1", "closure_stencils", centers=(1,)) == (Stencil((-1., 1.), center=1),) - @test get_stencils(parsed_toml, "order2", "D1", "closure_stencils", centers=(2,)) == (Stencil((-1., 1.), center=2),) - @test get_stencils(parsed_toml, "order2", "D1", "closure_stencils", centers=[2]) == (Stencil((-1., 1.), center=2),) + @test get_stencils(parsed_toml, "order2", "D1", "closure_stencils", centers=(1,)) == (Stencil(-1., 1., center=1),) + @test get_stencils(parsed_toml, "order2", "D1", "closure_stencils", centers=(2,)) == (Stencil(-1., 1., center=2),) + @test get_stencils(parsed_toml, "order2", "D1", "closure_stencils", centers=[2]) == (Stencil(-1., 1., center=2),) @test get_stencils(parsed_toml, "order4", "D2", "closure_stencils",centers=[1,1,1,1]) == ( - Stencil(( 2., -5., 4., -1., 0., 0.), center=1), - Stencil(( 1., -2., 1., 0., 0., 0.), center=1), - Stencil(( -4/43, 59/43, -110/43, 59/43, -4/43, 0.), center=1), - Stencil(( -1/49, 0., 59/49, -118/49, 64/49, -4/49), center=1), + Stencil( 2., -5., 4., -1., 0., 0., center=1), + Stencil( 1., -2., 1., 0., 0., 0., center=1), + Stencil( -4/43, 59/43, -110/43, 59/43, -4/43, 0., center=1), + Stencil( -1/49, 0., 59/49, -118/49, 64/49, -4/49, center=1), ) @test get_stencils(parsed_toml, "order4", "D2", "closure_stencils",centers=(4,2,3,1)) == ( - Stencil(( 2., -5., 4., -1., 0., 0.), center=4), - Stencil(( 1., -2., 1., 0., 0., 0.), center=2), - Stencil(( -4/43, 59/43, -110/43, 59/43, -4/43, 0.), center=3), - Stencil(( -1/49, 0., 59/49, -118/49, 64/49, -4/49), center=1), + Stencil( 2., -5., 4., -1., 0., 0., center=4), + Stencil( 1., -2., 1., 0., 0., 0., center=2), + Stencil( -4/43, 59/43, -110/43, 59/43, -4/43, 0., center=3), + Stencil( -1/49, 0., 59/49, -118/49, 64/49, -4/49, center=1), ) @test get_stencils(parsed_toml, "order4", "D2", "closure_stencils",centers=1:4) == ( - Stencil(( 2., -5., 4., -1., 0., 0.), center=1), - Stencil(( 1., -2., 1., 0., 0., 0.), center=2), - Stencil(( -4/43, 59/43, -110/43, 59/43, -4/43, 0.), center=3), - Stencil(( -1/49, 0., 59/49, -118/49, 64/49, -4/49), center=4), + Stencil( 2., -5., 4., -1., 0., 0., center=1), + Stencil( 1., -2., 1., 0., 0., 0., center=2), + Stencil( -4/43, 59/43, -110/43, 59/43, -4/43, 0., center=3), + Stencil( -1/49, 0., 59/49, -118/49, 64/49, -4/49, center=4), ) @test_throws AssertionError get_stencils(parsed_toml, "order4", "D2", "closure_stencils",centers=(1,2,3)) @@ -116,8 +119,8 @@ end @testset "VolumeOperator" begin - inner_stencil = Stencil(1/4 .* (1.,2.,1.),center=2) - closure_stencils = (Stencil(1/2 .* (1.,1.),center=1),Stencil((0.,1.),center=2)) + inner_stencil = CenteredStencil(1/4, 2/4, 1/4) + closure_stencils = (Stencil(1/2, 1/2; center=1), Stencil(0.,1.; center=2)) g_1D = EquidistantGrid(11,0.,1.) g_2D = EquidistantGrid((11,12),(0.,0.),(1.,1.)) g_3D = EquidistantGrid((11,12,10),(0.,0.,0.),(1.,1.,1.)) @@ -238,13 +241,13 @@ @testset "Constructors" begin @testset "1D" begin - Dₓₓ = SecondDerivative(g_1D,op.innerStencil,op.closureStencils) - @test Dₓₓ == SecondDerivative(g_1D,op.innerStencil,op.closureStencils,1) + Dₓₓ = second_derivative(g_1D,op.innerStencil,op.closureStencils) + @test Dₓₓ == second_derivative(g_1D,op.innerStencil,op.closureStencils,1) @test Dₓₓ isa VolumeOperator end @testset "2D" begin - Dₓₓ = SecondDerivative(g_2D,op.innerStencil,op.closureStencils,1) - D2 = SecondDerivative(g_1D,op.innerStencil,op.closureStencils) + Dₓₓ = second_derivative(g_2D,op.innerStencil,op.closureStencils,1) + D2 = second_derivative(g_1D,op.innerStencil,op.closureStencils) I = IdentityMapping{Float64}(size(g_2D)[2]) @test Dₓₓ == D2⊗I @test Dₓₓ isa TensorMapping{T,2,2} where T @@ -269,7 +272,7 @@ # implies that L*v should be exact for monomials up to order 2. @testset "2nd order" begin op = read_D2_operator(sbp_operators_path()*"standard_diagonal.toml"; order=2) - Dₓₓ = SecondDerivative(g_1D,op.innerStencil,op.closureStencils) + Dₓₓ = second_derivative(g_1D,op.innerStencil,op.closureStencils) @test Dₓₓ*monomials[1] ≈ zeros(Float64,size(g_1D)...) atol = 5e-10 @test Dₓₓ*monomials[2] ≈ zeros(Float64,size(g_1D)...) atol = 5e-10 @test Dₓₓ*monomials[3] ≈ monomials[1] atol = 5e-10 @@ -280,7 +283,7 @@ # implies that L*v should be exact for monomials up to order 3. @testset "4th order" begin op = read_D2_operator(sbp_operators_path()*"standard_diagonal.toml"; order=4) - Dₓₓ = SecondDerivative(g_1D,op.innerStencil,op.closureStencils) + Dₓₓ = second_derivative(g_1D,op.innerStencil,op.closureStencils) # NOTE: high tolerances for checking the "exact" differentiation # due to accumulation of round-off errors/cancellation errors? @test Dₓₓ*monomials[1] ≈ zeros(Float64,size(g_1D)...) atol = 5e-10 @@ -306,7 +309,7 @@ # implies that L*v should be exact for binomials up to order 2. @testset "2nd order" begin op = read_D2_operator(sbp_operators_path()*"standard_diagonal.toml"; order=2) - Dyy = SecondDerivative(g_2D,op.innerStencil,op.closureStencils,2) + Dyy = second_derivative(g_2D,op.innerStencil,op.closureStencils,2) @test Dyy*binomials[1] ≈ zeros(Float64,size(g_2D)...) atol = 5e-9 @test Dyy*binomials[2] ≈ zeros(Float64,size(g_2D)...) atol = 5e-9 @test Dyy*binomials[3] ≈ evalOn(g_2D,(x,y)->1.) atol = 5e-9 @@ -317,7 +320,7 @@ # implies that L*v should be exact for binomials up to order 3. @testset "4th order" begin op = read_D2_operator(sbp_operators_path()*"standard_diagonal.toml"; order=4) - Dyy = SecondDerivative(g_2D,op.innerStencil,op.closureStencils,2) + Dyy = second_derivative(g_2D,op.innerStencil,op.closureStencils,2) # NOTE: high tolerances for checking the "exact" differentiation # due to accumulation of round-off errors/cancellation errors? @test Dyy*binomials[1] ≈ zeros(Float64,size(g_2D)...) atol = 5e-9 @@ -338,21 +341,21 @@ @testset "1D" begin # Create all tensor mappings included in Laplace Δ = laplace(g_1D, op.innerStencil, op.closureStencils) - H = quadrature(g_1D, op.quadratureClosure) - Hi = InverseDiagonalQuadrature(g_1D, op.quadratureClosure) + H = inner_product(g_1D, op.quadratureClosure) + Hi = inverse_inner_product(g_1D, op.quadratureClosure) (id_l, id_r) = boundary_identifiers(g_1D) - e_l = BoundaryRestriction(g_1D,op.eClosure,id_l) - e_r = BoundaryRestriction(g_1D,op.eClosure,id_r) + e_l = boundary_restriction(g_1D,op.eClosure,id_l) + e_r = boundary_restriction(g_1D,op.eClosure,id_r) e_dict = Dict(Pair(id_l,e_l),Pair(id_r,e_r)) - d_l = NormalDerivative(g_1D,op.dClosure,id_l) - d_r = NormalDerivative(g_1D,op.dClosure,id_r) + d_l = normal_derivative(g_1D,op.dClosure,id_l) + d_r = normal_derivative(g_1D,op.dClosure,id_r) d_dict = Dict(Pair(id_l,d_l),Pair(id_r,d_r)) - H_l = boundary_quadrature(g_1D,op.quadratureClosure,id_r) - H_r = boundary_quadrature(g_1D,op.quadratureClosure,id_r) + H_l = inner_product(boundary_grid(g_1D,id_l),op.quadratureClosure) + H_r = inner_product(boundary_grid(g_1D,id_r),op.quadratureClosure) Hb_dict = Dict(Pair(id_l,H_l),Pair(id_r,H_r)) # TODO: Not sure why this doesnt work? Comparing the fields of @@ -372,37 +375,37 @@ @testset "3D" begin # Create all tensor mappings included in Laplace Δ = laplace(g_3D, op.innerStencil, op.closureStencils) - H = quadrature(g_3D, op.quadratureClosure) - Hi = InverseDiagonalQuadrature(g_3D, op.quadratureClosure) + H = inner_product(g_3D, op.quadratureClosure) + Hi = inverse_inner_product(g_3D, op.quadratureClosure) (id_l, id_r, id_s, id_n, id_b, id_t) = boundary_identifiers(g_3D) - e_l = BoundaryRestriction(g_3D,op.eClosure,id_l) - e_r = BoundaryRestriction(g_3D,op.eClosure,id_r) - e_s = BoundaryRestriction(g_3D,op.eClosure,id_s) - e_n = BoundaryRestriction(g_3D,op.eClosure,id_n) - e_b = BoundaryRestriction(g_3D,op.eClosure,id_b) - e_t = BoundaryRestriction(g_3D,op.eClosure,id_t) + e_l = boundary_restriction(g_3D,op.eClosure,id_l) + e_r = boundary_restriction(g_3D,op.eClosure,id_r) + e_s = boundary_restriction(g_3D,op.eClosure,id_s) + e_n = boundary_restriction(g_3D,op.eClosure,id_n) + e_b = boundary_restriction(g_3D,op.eClosure,id_b) + e_t = boundary_restriction(g_3D,op.eClosure,id_t) e_dict = Dict(Pair(id_l,e_l),Pair(id_r,e_r), Pair(id_s,e_s),Pair(id_n,e_n), Pair(id_b,e_b),Pair(id_t,e_t)) - d_l = NormalDerivative(g_3D,op.dClosure,id_l) - d_r = NormalDerivative(g_3D,op.dClosure,id_r) - d_s = NormalDerivative(g_3D,op.dClosure,id_s) - d_n = NormalDerivative(g_3D,op.dClosure,id_n) - d_b = NormalDerivative(g_3D,op.dClosure,id_b) - d_t = NormalDerivative(g_3D,op.dClosure,id_t) + d_l = normal_derivative(g_3D,op.dClosure,id_l) + d_r = normal_derivative(g_3D,op.dClosure,id_r) + d_s = normal_derivative(g_3D,op.dClosure,id_s) + d_n = normal_derivative(g_3D,op.dClosure,id_n) + d_b = normal_derivative(g_3D,op.dClosure,id_b) + d_t = normal_derivative(g_3D,op.dClosure,id_t) d_dict = Dict(Pair(id_l,d_l),Pair(id_r,d_r), Pair(id_s,d_s),Pair(id_n,d_n), Pair(id_b,d_b),Pair(id_t,d_t)) - H_l = boundary_quadrature(g_3D,op.quadratureClosure,id_r) - H_r = boundary_quadrature(g_3D,op.quadratureClosure,id_r) - H_s = boundary_quadrature(g_3D,op.quadratureClosure,id_s) - H_n = boundary_quadrature(g_3D,op.quadratureClosure,id_n) - H_b = boundary_quadrature(g_3D,op.quadratureClosure,id_b) - H_t = boundary_quadrature(g_3D,op.quadratureClosure,id_t) + H_l = inner_product(boundary_grid(g_3D,id_l),op.quadratureClosure) + H_r = inner_product(boundary_grid(g_3D,id_r),op.quadratureClosure) + H_s = inner_product(boundary_grid(g_3D,id_s),op.quadratureClosure) + H_n = inner_product(boundary_grid(g_3D,id_n),op.quadratureClosure) + H_b = inner_product(boundary_grid(g_3D,id_b),op.quadratureClosure) + H_t = inner_product(boundary_grid(g_3D,id_t),op.quadratureClosure) Hb_dict = Dict(Pair(id_l,H_l),Pair(id_r,H_r), Pair(id_s,H_s),Pair(id_n,H_n), Pair(id_b,H_b),Pair(id_t,H_t)) @@ -426,14 +429,15 @@ op = read_D2_operator(sbp_operators_path()*"standard_diagonal.toml"; order=4) @testset "1D" begin L = laplace(g_1D, op.innerStencil, op.closureStencils) - @test L == SecondDerivative(g_1D, op.innerStencil, op.closureStencils) + @test L == second_derivative(g_1D, op.innerStencil, op.closureStencils) @test L isa TensorMapping{T,1,1} where T end @testset "3D" begin L = laplace(g_3D, op.innerStencil, op.closureStencils) - Dxx = SecondDerivative(g_3D, op.innerStencil, op.closureStencils,1) - Dyy = SecondDerivative(g_3D, op.innerStencil, op.closureStencils,2) - Dzz = SecondDerivative(g_3D, op.innerStencil, op.closureStencils,3) + @test L isa TensorMapping{T,3,3} where T + Dxx = second_derivative(g_3D, op.innerStencil, op.closureStencils,1) + Dyy = second_derivative(g_3D, op.innerStencil, op.closureStencils,2) + Dzz = second_derivative(g_3D, op.innerStencil, op.closureStencils,3) @test L == Dxx + Dyy + Dzz @test L isa TensorMapping{T,3,3} where T end @@ -470,7 +474,8 @@ # 2nd order interior stencil, 1st order boundary stencil, # implies that L*v should be exact for binomials up to order 2. @testset "2nd order" begin - L = Laplace(g_3D,sbp_operators_path()*"standard_diagonal.toml"; order=2) + op = read_D2_operator(sbp_operators_path()*"standard_diagonal.toml"; order=2) + L = laplace(g_3D,op.innerStencil,op.closureStencils) @test L*polynomials[1] ≈ zeros(Float64, size(g_3D)...) atol = 5e-9 @test L*polynomials[2] ≈ zeros(Float64, size(g_3D)...) atol = 5e-9 @test L*polynomials[3] ≈ polynomials[1] atol = 5e-9 @@ -480,7 +485,8 @@ # 4th order interior stencil, 2nd order boundary stencil, # implies that L*v should be exact for binomials up to order 3. @testset "4th order" begin - L = Laplace(g_3D,sbp_operators_path()*"standard_diagonal.toml"; order=4) + op = read_D2_operator(sbp_operators_path()*"standard_diagonal.toml"; order=4) + L = laplace(g_3D,op.innerStencil,op.closureStencils) # NOTE: high tolerances for checking the "exact" differentiation # due to accumulation of round-off errors/cancellation errors? @test L*polynomials[1] ≈ zeros(Float64, size(g_3D)...) atol = 5e-9 @@ -492,7 +498,7 @@ end end -@testset "Quadrature diagonal" begin +@testset "Diagonal-stencil inner_product" begin Lx = π/2. Ly = Float64(π) Lz = 1. @@ -500,65 +506,37 @@ g_2D = EquidistantGrid((77,66), (0.0, 0.0), (Lx,Ly)) g_3D = EquidistantGrid((10,10, 10), (0.0, 0.0, 0.0), (Lx,Ly,Lz)) integral(H,v) = sum(H*v) - @testset "quadrature" begin + @testset "inner_product" begin op = read_D2_operator(sbp_operators_path()*"standard_diagonal.toml"; order=4) + @testset "0D" begin + H = inner_product(EquidistantGrid{Float64}(),op.quadratureClosure) + @test H == IdentityMapping{Float64}() + @test H isa TensorMapping{T,0,0} where T + end @testset "1D" begin - H = quadrature(g_1D,op.quadratureClosure) - inner_stencil = Stencil((1.,),center=1) - @test H == quadrature(g_1D,inner_stencil,op.quadratureClosure) + H = inner_product(g_1D,op.quadratureClosure) + inner_stencil = CenteredStencil(1.) + @test H == inner_product(g_1D,op.quadratureClosure,inner_stencil) @test H isa TensorMapping{T,1,1} where T end @testset "2D" begin - H = quadrature(g_2D,op.quadratureClosure) - H_x = quadrature(restrict(g_2D,1),op.quadratureClosure) - H_y = quadrature(restrict(g_2D,2),op.quadratureClosure) + H = inner_product(g_2D,op.quadratureClosure) + H_x = inner_product(restrict(g_2D,1),op.quadratureClosure) + H_y = inner_product(restrict(g_2D,2),op.quadratureClosure) @test H == H_x⊗H_y @test H isa TensorMapping{T,2,2} where T end end - @testset "boundary_quadrature" begin - op = read_D2_operator(sbp_operators_path()*"standard_diagonal.toml"; order=4) - @testset "1D" begin - (id_l, id_r) = boundary_identifiers(g_1D) - @test boundary_quadrature(g_1D,op.quadratureClosure,id_l) == IdentityMapping{Float64}() - @test boundary_quadrature(g_1D,op.quadratureClosure,id_r) == IdentityMapping{Float64}() - - end - @testset "2D" begin - (id_w, id_e, id_s, id_n) = boundary_identifiers(g_2D) - H_x = quadrature(restrict(g_2D,1),op.quadratureClosure) - H_y = quadrature(restrict(g_2D,2),op.quadratureClosure) - @test boundary_quadrature(g_2D,op.quadratureClosure,id_w) == H_y - @test boundary_quadrature(g_2D,op.quadratureClosure,id_e) == H_y - @test boundary_quadrature(g_2D,op.quadratureClosure,id_s) == H_x - @test boundary_quadrature(g_2D,op.quadratureClosure,id_n) == H_x - end - @testset "3D" begin - (id_w, id_e, - id_s, id_n, - id_t, id_b) = boundary_identifiers(g_3D) - H_xy = quadrature(restrict(g_3D,[1,2]),op.quadratureClosure) - H_xz = quadrature(restrict(g_3D,[1,3]),op.quadratureClosure) - H_yz = quadrature(restrict(g_3D,[2,3]),op.quadratureClosure) - @test boundary_quadrature(g_3D,op.quadratureClosure,id_w) == H_yz - @test boundary_quadrature(g_3D,op.quadratureClosure,id_e) == H_yz - @test boundary_quadrature(g_3D,op.quadratureClosure,id_s) == H_xz - @test boundary_quadrature(g_3D,op.quadratureClosure,id_n) == H_xz - @test boundary_quadrature(g_3D,op.quadratureClosure,id_t) == H_xy - @test boundary_quadrature(g_3D,op.quadratureClosure,id_b) == H_xy - end - end - @testset "Sizes" begin op = read_D2_operator(sbp_operators_path()*"standard_diagonal.toml"; order=4) @testset "1D" begin - H = quadrature(g_1D,op.quadratureClosure) + H = inner_product(g_1D,op.quadratureClosure) @test domain_size(H) == size(g_1D) @test range_size(H) == size(g_1D) end @testset "2D" begin - H = quadrature(g_2D,op.quadratureClosure) + H = inner_product(g_2D,op.quadratureClosure) @test domain_size(H) == size(g_2D) @test range_size(H) == size(g_2D) end @@ -575,7 +553,7 @@ @testset "2nd order" begin op = read_D2_operator(sbp_operators_path()*"standard_diagonal.toml"; order=2) - H = quadrature(g_1D,op.quadratureClosure) + H = inner_product(g_1D,op.quadratureClosure) for i = 1:2 @test integral(H,v[i]) ≈ v[i+1][end] - v[i+1][1] rtol = 1e-14 end @@ -584,7 +562,7 @@ @testset "4th order" begin op = read_D2_operator(sbp_operators_path()*"standard_diagonal.toml"; order=4) - H = quadrature(g_1D,op.quadratureClosure) + H = inner_product(g_1D,op.quadratureClosure) for i = 1:4 @test integral(H,v[i]) ≈ v[i+1][end] - v[i+1][1] rtol = 1e-14 end @@ -598,13 +576,13 @@ u = evalOn(g_2D,(x,y)->sin(x)+cos(y)) @testset "2nd order" begin op = read_D2_operator(sbp_operators_path()*"standard_diagonal.toml"; order=2) - H = quadrature(g_2D,op.quadratureClosure) + H = inner_product(g_2D,op.quadratureClosure) @test integral(H,v) ≈ b*Lx*Ly rtol = 1e-13 @test integral(H,u) ≈ π rtol = 1e-4 end @testset "4th order" begin op = read_D2_operator(sbp_operators_path()*"standard_diagonal.toml"; order=4) - H = quadrature(g_2D,op.quadratureClosure) + H = inner_product(g_2D,op.quadratureClosure) @test integral(H,v) ≈ b*Lx*Ly rtol = 1e-13 @test integral(H,u) ≈ π rtol = 1e-8 end @@ -612,27 +590,32 @@ end end -@testset "InverseDiagonalQuadrature" begin +@testset "Diagonal-stencil inverse_inner_product" begin Lx = π/2. Ly = Float64(π) g_1D = EquidistantGrid(77, 0.0, Lx) g_2D = EquidistantGrid((77,66), (0.0, 0.0), (Lx,Ly)) - @testset "Constructors" begin + @testset "inverse_inner_product" begin op = read_D2_operator(sbp_operators_path()*"standard_diagonal.toml"; order=4) + @testset "0D" begin + Hi = inverse_inner_product(EquidistantGrid{Float64}(),op.quadratureClosure) + @test Hi == IdentityMapping{Float64}() + @test Hi isa TensorMapping{T,0,0} where T + end @testset "1D" begin - Hi = InverseDiagonalQuadrature(g_1D, op.quadratureClosure); - inner_stencil = Stencil((1.,),center=1) + Hi = inverse_inner_product(g_1D, op.quadratureClosure); + inner_stencil = CenteredStencil(1.) closures = () for i = 1:length(op.quadratureClosure) closures = (closures...,Stencil(op.quadratureClosure[i].range,1.0./op.quadratureClosure[i].weights)) end - @test Hi == InverseQuadrature(g_1D,inner_stencil,closures) + @test Hi == inverse_inner_product(g_1D,closures,inner_stencil) @test Hi isa TensorMapping{T,1,1} where T end @testset "2D" begin - Hi = InverseDiagonalQuadrature(g_2D,op.quadratureClosure) - Hi_x = InverseDiagonalQuadrature(restrict(g_2D,1),op.quadratureClosure) - Hi_y = InverseDiagonalQuadrature(restrict(g_2D,2),op.quadratureClosure) + Hi = inverse_inner_product(g_2D,op.quadratureClosure) + Hi_x = inverse_inner_product(restrict(g_2D,1),op.quadratureClosure) + Hi_y = inverse_inner_product(restrict(g_2D,2),op.quadratureClosure) @test Hi == Hi_x⊗Hi_y @test Hi isa TensorMapping{T,2,2} where T end @@ -641,12 +624,12 @@ @testset "Sizes" begin op = read_D2_operator(sbp_operators_path()*"standard_diagonal.toml"; order=4) @testset "1D" begin - Hi = InverseDiagonalQuadrature(g_1D,op.quadratureClosure) + Hi = inverse_inner_product(g_1D,op.quadratureClosure) @test domain_size(Hi) == size(g_1D) @test range_size(Hi) == size(g_1D) end @testset "2D" begin - Hi = InverseDiagonalQuadrature(g_2D,op.quadratureClosure) + Hi = inverse_inner_product(g_2D,op.quadratureClosure) @test domain_size(Hi) == size(g_2D) @test range_size(Hi) == size(g_2D) end @@ -658,15 +641,15 @@ u = evalOn(g_1D,x->x^3-x^2+1) @testset "2nd order" begin op = read_D2_operator(sbp_operators_path()*"standard_diagonal.toml"; order=2) - H = quadrature(g_1D,op.quadratureClosure) - Hi = InverseDiagonalQuadrature(g_1D,op.quadratureClosure) + H = inner_product(g_1D,op.quadratureClosure) + Hi = inverse_inner_product(g_1D,op.quadratureClosure) @test Hi*H*v ≈ v rtol = 1e-15 @test Hi*H*u ≈ u rtol = 1e-15 end @testset "4th order" begin op = read_D2_operator(sbp_operators_path()*"standard_diagonal.toml"; order=4) - H = quadrature(g_1D,op.quadratureClosure) - Hi = InverseDiagonalQuadrature(g_1D,op.quadratureClosure) + H = inner_product(g_1D,op.quadratureClosure) + Hi = inverse_inner_product(g_1D,op.quadratureClosure) @test Hi*H*v ≈ v rtol = 1e-15 @test Hi*H*u ≈ u rtol = 1e-15 end @@ -676,15 +659,15 @@ u = evalOn(g_2D,(x,y)->x*y + x^5 - sqrt(y)) @testset "2nd order" begin op = read_D2_operator(sbp_operators_path()*"standard_diagonal.toml"; order=2) - H = quadrature(g_2D,op.quadratureClosure) - Hi = InverseDiagonalQuadrature(g_2D,op.quadratureClosure) + H = inner_product(g_2D,op.quadratureClosure) + Hi = inverse_inner_product(g_2D,op.quadratureClosure) @test Hi*H*v ≈ v rtol = 1e-15 @test Hi*H*u ≈ u rtol = 1e-15 end @testset "4th order" begin op = read_D2_operator(sbp_operators_path()*"standard_diagonal.toml"; order=4) - H = quadrature(g_2D,op.quadratureClosure) - Hi = InverseDiagonalQuadrature(g_2D,op.quadratureClosure) + H = inner_product(g_2D,op.quadratureClosure) + Hi = inverse_inner_product(g_2D,op.quadratureClosure) @test Hi*H*v ≈ v rtol = 1e-15 @test Hi*H*u ≈ u rtol = 1e-15 end @@ -705,7 +688,7 @@ @test op_l isa TensorMapping{T,0,1} where T op_r = BoundaryOperator{Upper}(closure_stencil,size(g_1D)[1]) - @test op_r == BoundaryRestriction(g_1D,closure_stencil,Upper()) + @test op_r == BoundaryOperator(g_1D,closure_stencil,Upper()) @test op_r == boundary_operator(g_1D,closure_stencil,CartesianBoundary{1,Upper}()) @test op_r isa TensorMapping{T,0,1} where T end @@ -836,28 +819,28 @@ end -@testset "BoundaryRestriction" begin +@testset "boundary_restriction" begin op = read_D2_operator(sbp_operators_path()*"standard_diagonal.toml"; order=4) g_1D = EquidistantGrid(11, 0.0, 1.0) g_2D = EquidistantGrid((11,15), (0.0, 0.0), (1.0,1.0)) - @testset "Constructors" begin + @testset "boundary_restriction" begin @testset "1D" begin - e_l = BoundaryRestriction(g_1D,op.eClosure,Lower()) - @test e_l == BoundaryRestriction(g_1D,op.eClosure,CartesianBoundary{1,Lower}()) + e_l = boundary_restriction(g_1D,op.eClosure,Lower()) + @test e_l == boundary_restriction(g_1D,op.eClosure,CartesianBoundary{1,Lower}()) @test e_l == BoundaryOperator(g_1D,op.eClosure,Lower()) @test e_l isa BoundaryOperator{T,Lower} where T @test e_l isa TensorMapping{T,0,1} where T - e_r = BoundaryRestriction(g_1D,op.eClosure,Upper()) - @test e_r == BoundaryRestriction(g_1D,op.eClosure,CartesianBoundary{1,Upper}()) + e_r = boundary_restriction(g_1D,op.eClosure,Upper()) + @test e_r == boundary_restriction(g_1D,op.eClosure,CartesianBoundary{1,Upper}()) @test e_r == BoundaryOperator(g_1D,op.eClosure,Upper()) @test e_r isa BoundaryOperator{T,Upper} where T @test e_r isa TensorMapping{T,0,1} where T end @testset "2D" begin - e_w = BoundaryRestriction(g_2D,op.eClosure,CartesianBoundary{1,Upper}()) + e_w = boundary_restriction(g_2D,op.eClosure,CartesianBoundary{1,Upper}()) @test e_w isa InflatedTensorMapping @test e_w isa TensorMapping{T,1,2} where T end @@ -865,8 +848,8 @@ @testset "Application" begin @testset "1D" begin - e_l = BoundaryRestriction(g_1D, op.eClosure, CartesianBoundary{1,Lower}()) - e_r = BoundaryRestriction(g_1D, op.eClosure, CartesianBoundary{1,Upper}()) + e_l = boundary_restriction(g_1D, op.eClosure, CartesianBoundary{1,Lower}()) + e_r = boundary_restriction(g_1D, op.eClosure, CartesianBoundary{1,Upper}()) v = evalOn(g_1D,x->1+x^2) u = fill(3.124) @@ -877,10 +860,10 @@ end @testset "2D" begin - e_w = BoundaryRestriction(g_2D, op.eClosure, CartesianBoundary{1,Lower}()) - e_e = BoundaryRestriction(g_2D, op.eClosure, CartesianBoundary{1,Upper}()) - e_s = BoundaryRestriction(g_2D, op.eClosure, CartesianBoundary{2,Lower}()) - e_n = BoundaryRestriction(g_2D, op.eClosure, CartesianBoundary{2,Upper}()) + e_w = boundary_restriction(g_2D, op.eClosure, CartesianBoundary{1,Lower}()) + e_e = boundary_restriction(g_2D, op.eClosure, CartesianBoundary{1,Upper}()) + e_s = boundary_restriction(g_2D, op.eClosure, CartesianBoundary{2,Lower}()) + e_n = boundary_restriction(g_2D, op.eClosure, CartesianBoundary{2,Upper}()) v = rand(11, 15) u = fill(3.124) @@ -893,25 +876,25 @@ end end -@testset "NormalDerivative" begin +@testset "normal_derivative" begin g_1D = EquidistantGrid(11, 0.0, 1.0) g_2D = EquidistantGrid((11,12), (0.0, 0.0), (1.0,1.0)) - @testset "Constructors" begin + @testset "normal_derivative" begin op = read_D2_operator(sbp_operators_path()*"standard_diagonal.toml"; order=4) @testset "1D" begin - d_l = NormalDerivative(g_1D, op.dClosure, Lower()) - @test d_l == NormalDerivative(g_1D, op.dClosure, CartesianBoundary{1,Lower}()) + d_l = normal_derivative(g_1D, op.dClosure, Lower()) + @test d_l == normal_derivative(g_1D, op.dClosure, CartesianBoundary{1,Lower}()) @test d_l isa BoundaryOperator{T,Lower} where T @test d_l isa TensorMapping{T,0,1} where T end @testset "2D" begin op = read_D2_operator(sbp_operators_path()*"standard_diagonal.toml"; order=4) - d_w = NormalDerivative(g_2D, op.dClosure, CartesianBoundary{1,Lower}()) - d_n = NormalDerivative(g_2D, op.dClosure, CartesianBoundary{2,Upper}()) + d_w = normal_derivative(g_2D, op.dClosure, CartesianBoundary{1,Lower}()) + d_n = normal_derivative(g_2D, op.dClosure, CartesianBoundary{2,Upper}()) Ix = IdentityMapping{Float64}((size(g_2D)[1],)) Iy = IdentityMapping{Float64}((size(g_2D)[2],)) - d_l = NormalDerivative(restrict(g_2D,1),op.dClosure,Lower()) - d_r = NormalDerivative(restrict(g_2D,2),op.dClosure,Upper()) + d_l = normal_derivative(restrict(g_2D,1),op.dClosure,Lower()) + d_r = normal_derivative(restrict(g_2D,2),op.dClosure,Upper()) @test d_w == d_l⊗Iy @test d_n == Ix⊗d_r @test d_w isa TensorMapping{T,1,2} where T @@ -925,10 +908,10 @@ # TODO: Test for higher order polynomials? @testset "2nd order" begin op = read_D2_operator(sbp_operators_path()*"standard_diagonal.toml"; order=2) - d_w = NormalDerivative(g_2D, op.dClosure, CartesianBoundary{1,Lower}()) - d_e = NormalDerivative(g_2D, op.dClosure, CartesianBoundary{1,Upper}()) - d_s = NormalDerivative(g_2D, op.dClosure, CartesianBoundary{2,Lower}()) - d_n = NormalDerivative(g_2D, op.dClosure, CartesianBoundary{2,Upper}()) + d_w = normal_derivative(g_2D, op.dClosure, CartesianBoundary{1,Lower}()) + d_e = normal_derivative(g_2D, op.dClosure, CartesianBoundary{1,Upper}()) + d_s = normal_derivative(g_2D, op.dClosure, CartesianBoundary{2,Lower}()) + d_n = normal_derivative(g_2D, op.dClosure, CartesianBoundary{2,Upper}()) @test d_w*v ≈ v∂x[1,:] atol = 1e-13 @test d_e*v ≈ -v∂x[end,:] atol = 1e-13 @@ -938,10 +921,10 @@ @testset "4th order" begin op = read_D2_operator(sbp_operators_path()*"standard_diagonal.toml"; order=4) - d_w = NormalDerivative(g_2D, op.dClosure, CartesianBoundary{1,Lower}()) - d_e = NormalDerivative(g_2D, op.dClosure, CartesianBoundary{1,Upper}()) - d_s = NormalDerivative(g_2D, op.dClosure, CartesianBoundary{2,Lower}()) - d_n = NormalDerivative(g_2D, op.dClosure, CartesianBoundary{2,Upper}()) + d_w = normal_derivative(g_2D, op.dClosure, CartesianBoundary{1,Lower}()) + d_e = normal_derivative(g_2D, op.dClosure, CartesianBoundary{1,Upper}()) + d_s = normal_derivative(g_2D, op.dClosure, CartesianBoundary{2,Lower}()) + d_n = normal_derivative(g_2D, op.dClosure, CartesianBoundary{2,Upper}()) @test d_w*v ≈ v∂x[1,:] atol = 1e-13 @test d_e*v ≈ -v∂x[end,:] atol = 1e-13