Mercurial > repos > public > sbplib_julia
changeset 356:0844069ab5ff refactor/remove_dynamic_size_tensormapping
Reinclude SbpOperators and fix most of the code and tests there.
author | Jonatan Werpers <jonatan@werpers.com> |
---|---|
date | Sun, 27 Sep 2020 22:51:31 +0200 |
parents | 5c9212a8ee4f |
children | e22b061f5299 |
files | src/SbpOperators/SbpOperators.jl src/SbpOperators/laplace/laplace.jl src/SbpOperators/laplace/secondderivative.jl src/SbpOperators/quadrature/diagonal_inner_product.jl src/SbpOperators/quadrature/inverse_diagonal_inner_product.jl src/SbpOperators/quadrature/inverse_quadrature.jl src/SbpOperators/quadrature/quadrature.jl src/Sbplib.jl test/testSbpOperators.jl |
diffstat | 9 files changed, 91 insertions(+), 55 deletions(-) [+] |
line wrap: on
line diff
--- a/src/SbpOperators/SbpOperators.jl Sun Sep 27 21:08:18 2020 +0200 +++ b/src/SbpOperators/SbpOperators.jl Sun Sep 27 22:51:31 2020 +0200 @@ -2,6 +2,7 @@ using Sbplib.RegionIndices using Sbplib.LazyTensors +using Sbplib.Grids include("stencil.jl") include("constantstenciloperator.jl")
--- a/src/SbpOperators/laplace/laplace.jl Sun Sep 27 21:08:18 2020 +0200 +++ b/src/SbpOperators/laplace/laplace.jl Sun Sep 27 22:51:31 2020 +0200 @@ -1,18 +1,27 @@ export Laplace """ - Laplace{Dim,T<:Real,N,M,K} <: TensorOperator{T,Dim} + Laplace{Dim,T<:Real,N,M,K} <: TensorMapping{T,Dim,Dim} Implements the Laplace operator `L` in Dim dimensions as a tensor operator The multi-dimensional tensor operator consists of a tuple of 1D SecondDerivative tensor operators. """ #export quadrature, inverse_quadrature, boundary_quadrature, boundary_value, normal_derivative -struct Laplace{Dim,T,N,M,K} <: TensorOperator{T,Dim} +struct Laplace{Dim,T,N,M,K} <: TensorMapping{T,Dim,Dim} D2::NTuple{Dim,SecondDerivative{T,N,M,K}} - #TODO: Write a good constructor end -LazyTensors.domain_size(L::Laplace{Dim}, range_size::NTuple{Dim,Integer}) where {Dim} = range_size +function Laplace(g::EquidistantGrid{Dim}, innerStencil, closureStencils) where Dim + D2 = () + for i ∈ 1:Dim + D2 = (D2..., SecondDerivative(subgrid(g,i), innerStencil, closureStencils)) + end + + return Laplace(D2) +end + +LazyTensors.range_size(L::Laplace) = getindex.(range_size.(L.D2),1) +LazyTensors.domain_size(L::Laplace) = getindex.(domain_size.(L.D2),1) function LazyTensors.apply(L::Laplace{Dim,T}, v::AbstractArray{T,Dim}, I::Vararg{Index,Dim}) where {T,Dim} error("not implemented")
--- a/src/SbpOperators/laplace/secondderivative.jl Sun Sep 27 21:08:18 2020 +0200 +++ b/src/SbpOperators/laplace/secondderivative.jl Sun Sep 27 22:51:31 2020 +0200 @@ -9,11 +9,17 @@ innerStencil::Stencil{T,N} closureStencils::NTuple{M,Stencil{T,K}} parity::Parity - #TODO: Write a nice constructor + size::NTuple{1,Int} end export SecondDerivative -LazyTensors.domain_size(D2::SecondDerivative, range_size::NTuple{1,Integer}) = range_size +function SecondDerivative(grid::EquidistantGrid{1}, innerStencil, closureStencils) + h_inv = grid.inverse_spacing[1] + return SecondDerivative(h_inv, innerStencil, closureStencils, even, size(grid)) +end + +LazyTensors.range_size(D2::SecondDerivative) = D2.size +LazyTensors.domain_size(D2::SecondDerivative) = D2.size #TODO: The 1D tensor mappings should not have to dispatch on 1D tuples if we write LazyTensor.apply for vararg right?!?! # Currently have to index the Tuple{Index} in each method in order to call the stencil methods which is ugly.
--- a/src/SbpOperators/quadrature/diagonal_inner_product.jl Sun Sep 27 21:08:18 2020 +0200 +++ b/src/SbpOperators/quadrature/diagonal_inner_product.jl Sun Sep 27 22:51:31 2020 +0200 @@ -4,13 +4,18 @@ Implements the diagnoal norm operator `H` of Dim dimension as a TensorMapping """ -struct DiagonalInnerProduct{T,M} <: TensorOperator{T,1} - h::T # The grid spacing could be included in the stencil already. Preferable? +struct DiagonalInnerProduct{T,M} <: TensorMapping{T,1,1} + h::T closure::NTuple{M,T} - #TODO: Write a nice constructor + size::Tuple{Int} end -LazyTensors.domain_size(H::DiagonalInnerProduct, range_size::NTuple{1,Integer}) = range_size +function DiagonalInnerProduct(g::EquidistantGrid{1}, closure) + return DiagonalInnerProduct(spacing(g)[1], closure, size(g)) +end + +LazyTensors.range_size(H::DiagonalInnerProduct) = H.size +LazyTensors.domain_size(H::DiagonalInnerProduct) = H.size function LazyTensors.apply(H::DiagonalInnerProduct{T}, v::AbstractVector{T}, I::Index) where T return @inbounds apply(H, v, I)
--- a/src/SbpOperators/quadrature/inverse_diagonal_inner_product.jl Sun Sep 27 21:08:18 2020 +0200 +++ b/src/SbpOperators/quadrature/inverse_diagonal_inner_product.jl Sun Sep 27 22:51:31 2020 +0200 @@ -1,22 +1,30 @@ export InverseDiagonalInnerProduct, closuresize """ - InverseDiagonalInnerProduct{Dim,T<:Real,M} <: TensorOperator{T,1} + InverseDiagonalInnerProduct{Dim,T<:Real,M} <: TensorMapping{T,1,1} Implements the inverse diagonal inner product operator `Hi` of as a 1D TensorOperator """ -struct InverseDiagonalInnerProduct{T<:Real,M} <: TensorOperator{T,1} - h_inv::T # The reciprocl grid spacing could be included in the stencil already. Preferable? - closure::NTuple{M,T} - #TODO: Write a nice constructor +struct InverseDiagonalInnerProduct{T<:Real,M} <: TensorMapping{T,1,1} + h_inv::T + inverseQuadratureClosure::NTuple{M,T} + size::Tuple{Int} end +function InverseDiagonalInnerProduct(g::EquidistantGrid{1}, quadratureClosure) + return InverseDiagonalInnerProduct(inverse_spacing(g)[1], 1 ./ quadratureClosure, size(g)) +end + +LazyTensors.range_size(Hi::InverseDiagonalInnerProduct) = Hi.size +LazyTensors.domain_size(Hi::InverseDiagonalInnerProduct) = Hi.size + + function LazyTensors.apply(Hi::InverseDiagonalInnerProduct{T}, v::AbstractVector{T}, I::Index{Lower}) where T - return @inbounds Hi.h_inv*Hi.closure[Int(I)]*v[Int(I)] + return @inbounds Hi.h_inv*Hi.inverseQuadratureClosure[Int(I)]*v[Int(I)] end function LazyTensors.apply(Hi::InverseDiagonalInnerProduct{T}, v::AbstractVector{T}, I::Index{Upper}) where T N = length(v); - return @inbounds Hi.h_inv*Hi.closure[N-Int(I)+1]v[Int(I)] + return @inbounds Hi.h_inv*Hi.inverseQuadratureClosure[N-Int(I)+1]v[Int(I)] end function LazyTensors.apply(Hi::InverseDiagonalInnerProduct{T}, v::AbstractVector{T}, I::Index{Interior}) where T
--- a/src/SbpOperators/quadrature/inverse_quadrature.jl Sun Sep 27 21:08:18 2020 +0200 +++ b/src/SbpOperators/quadrature/inverse_quadrature.jl Sun Sep 27 22:51:31 2020 +0200 @@ -2,14 +2,27 @@ """ InverseQuadrature{Dim,T<:Real,M,K} <: TensorMapping{T,Dim,Dim} -Implements the inverse quadrature operator `Qi` of Dim dimension as a TensorOperator +Implements the inverse quadrature operator `Qi` of Dim dimension as a TensorMapping The multi-dimensional tensor operator consists of a tuple of 1D InverseDiagonalInnerProduct tensor operators. """ -struct InverseQuadrature{Dim,T<:Real,M} <: TensorOperator{T,Dim} +struct InverseQuadrature{Dim,T<:Real,M} <: TensorMapping{T,Dim,Dim} Hi::NTuple{Dim,InverseDiagonalInnerProduct{T,M}} end + +function InverseQuadrature(g::EquidistantGrid{Dim}, quadratureClosure) where Dim + Hi = () + for i ∈ 1:Dim + Hi = (Hi..., InverseDiagonalInnerProduct(subgrid(g,i), quadratureClosure)) + end + + return InverseQuadrature(Hi) +end + +LazyTensors.range_size(Hi::InverseQuadrature) = getindex.(range_size.(Hi.Hi),1) +LazyTensors.domain_size(Hi::InverseQuadrature) = getindex.(domain_size.(Hi.Hi),1) + LazyTensors.domain_size(Qi::InverseQuadrature{Dim}, range_size::NTuple{Dim,Integer}) where Dim = range_size function LazyTensors.apply(Qi::InverseQuadrature{Dim,T}, v::AbstractArray{T,Dim}, I::Vararg{Index,Dim}) where {T,Dim}
--- a/src/SbpOperators/quadrature/quadrature.jl Sun Sep 27 21:08:18 2020 +0200 +++ b/src/SbpOperators/quadrature/quadrature.jl Sun Sep 27 22:51:31 2020 +0200 @@ -6,11 +6,21 @@ The multi-dimensional tensor operator consists of a tuple of 1D DiagonalInnerProduct H tensor operators. """ -struct Quadrature{Dim,T<:Real,M} <: TensorOperator{T,Dim} +struct Quadrature{Dim,T<:Real,M} <: TensorMapping{T,Dim,Dim} H::NTuple{Dim,DiagonalInnerProduct{T,M}} end -LazyTensors.domain_size(Q::Quadrature{Dim}, range_size::NTuple{Dim,Integer}) where {Dim} = range_size +function Quadrature(g::EquidistantGrid{Dim}, quadratureClosure) where Dim + H = () + for i ∈ 1:Dim + H = (H..., DiagonalInnerProduct(subgrid(g,i), quadratureClosure)) + end + + return Quadrature(H) +end + +LazyTensors.range_size(H::Quadrature) = getindex.(range_size.(H.H),1) +LazyTensors.domain_size(H::Quadrature) = getindex.(domain_size.(H.H),1) function LazyTensors.apply(Q::Quadrature{Dim,T}, v::AbstractArray{T,Dim}, I::Vararg{Index,Dim}) where {T,Dim} error("not implemented")
--- a/src/Sbplib.jl Sun Sep 27 21:08:18 2020 +0200 +++ b/src/Sbplib.jl Sun Sep 27 22:51:31 2020 +0200 @@ -3,7 +3,7 @@ include("RegionIndices/RegionIndices.jl") include("LazyTensors/LazyTensors.jl") include("Grids/Grids.jl") -# include("SbpOperators/SbpOperators.jl") +include("SbpOperators/SbpOperators.jl") # include("DiffOps/DiffOps.jl") export RegionIndices
--- a/test/testSbpOperators.jl Sun Sep 27 21:08:18 2020 +0200 +++ b/test/testSbpOperators.jl Sun Sep 27 22:51:31 2020 +0200 @@ -33,7 +33,7 @@ g = EquidistantGrid((101,), (0.0,), (L,)) h_inv = inverse_spacing(g) h = 1/h_inv[1]; - Dₓₓ = SecondDerivative(h_inv[1],op.innerStencil,op.closureStencils,op.parity) + Dₓₓ = SecondDerivative(g,op.innerStencil,op.closureStencils) f0(x::Float64) = 1. f1(x::Float64) = x @@ -50,7 +50,7 @@ v4 = evalOn(g,f4) v5 = evalOn(g,f5) - @test Dₓₓ isa TensorOperator{T,1} where T + @test Dₓₓ isa TensorMapping{T,1,1} where T @test Dₓₓ' isa TensorMapping{T,1,1} where T # TODO: Should perhaps set tolerance level for isapporx instead? @@ -77,12 +77,8 @@ Lx = 1.5 Ly = 3.2 g = EquidistantGrid((102,131), (0.0, 0.0), (Lx,Ly)) + L = Laplace(g, op.innerStencil, op.closureStencils) - h_inv = inverse_spacing(g) - h = spacing(g) - D_xx = SecondDerivative(h_inv[1],op.innerStencil,op.closureStencils,op.parity) - D_yy = SecondDerivative(h_inv[2],op.innerStencil,op.closureStencils,op.parity) - L = Laplace((D_xx,D_yy)) f0(x::Float64,y::Float64) = 2. f1(x::Float64,y::Float64) = x+y @@ -100,7 +96,7 @@ v5 = evalOn(g,f5) v5ₓₓ = evalOn(g,f5ₓₓ) - @test L isa TensorOperator{T,2} where T + @test L isa TensorMapping{T,2,2} where T @test L' isa TensorMapping{T,2,2} where T # TODO: Should perhaps set tolerance level for isapporx instead? @@ -118,6 +114,8 @@ @test all(abs.((collect(L*v3) - v1)) .<= equalitytol) e4 = collect(L*v4) - v2 e5 = collect(L*v5) - v5ₓₓ + + h = spacing(g) @test sqrt(prod(h)*sum(collect(e4.^2))) <= accuracytol @test sqrt(prod(h)*sum(collect(e5.^2))) <= accuracytol end @@ -126,11 +124,10 @@ op = readOperator(sbp_operators_path()*"d2_4th.txt",sbp_operators_path()*"h_4th.txt") L = 2.3 g = EquidistantGrid((77,), (0.0,), (L,)) - h = spacing(g) - H = DiagonalInnerProduct(h[1],op.quadratureClosure) + H = DiagonalInnerProduct(g,op.quadratureClosure) v = ones(Float64, size(g)) - @test H isa TensorOperator{T,1} where T + @test H isa TensorMapping{T,1,1} where T @test H' isa TensorMapping{T,1,1} where T @test sum(collect(H*v)) ≈ L @test collect(H*v) == collect(H'*v) @@ -142,14 +139,11 @@ Ly = 5.2 g = EquidistantGrid((77,66), (0.0, 0.0), (Lx,Ly)) - h = spacing(g) - Hx = DiagonalInnerProduct(h[1],op.quadratureClosure); - Hy = DiagonalInnerProduct(h[2],op.quadratureClosure); - Q = Quadrature((Hx,Hy)) + Q = Quadrature(g, op.quadratureClosure) v = ones(Float64, size(g)) - @test Q isa TensorOperator{T,2} where T + @test Q isa TensorMapping{T,2,2} where T @test Q' isa TensorMapping{T,2,2} where T @test sum(collect(Q*v)) ≈ (Lx*Ly) @test collect(Q*v) == collect(Q'*v) @@ -159,14 +153,11 @@ op = readOperator(sbp_operators_path()*"d2_4th.txt",sbp_operators_path()*"h_4th.txt") L = 2.3 g = EquidistantGrid((77,), (0.0,), (L,)) - h = spacing(g) - H = DiagonalInnerProduct(h[1],op.quadratureClosure) - - h_i = inverse_spacing(g) - Hi = InverseDiagonalInnerProduct(h_i[1],1 ./ op.quadratureClosure) + H = DiagonalInnerProduct(g, op.quadratureClosure) + Hi = InverseDiagonalInnerProduct(g,op.quadratureClosure) v = evalOn(g, x->sin(x)) - @test Hi isa TensorOperator{T,1} where T + @test Hi isa TensorMapping{T,1,1} where T @test Hi' isa TensorMapping{T,1,1} where T @test collect(Hi*H*v) ≈ v @test collect(Hi*v) == collect(Hi'*v) @@ -178,20 +169,13 @@ Ly = 8.2 g = EquidistantGrid((77,66), (0.0, 0.0), (Lx,Ly)) - h = spacing(g) - Hx = DiagonalInnerProduct(h[1], op.quadratureClosure); - Hy = DiagonalInnerProduct(h[2], op.quadratureClosure); - Q = Quadrature((Hx,Hy)) - - hi = inverse_spacing(g) - Hix = InverseDiagonalInnerProduct(hi[1], 1 ./ op.quadratureClosure); - Hiy = InverseDiagonalInnerProduct(hi[2], 1 ./ op.quadratureClosure); - Qinv = InverseQuadrature((Hix,Hiy)) + Q = Quadrature(g, op.quadratureClosure) + Qinv = InverseQuadrature(g, op.quadratureClosure) v = evalOn(g, (x,y)-> x^2 + (y-1)^2 + x*y) - @test Qinv isa TensorOperator{T,2} where T + @test Qinv isa TensorMapping{T,2,2} where T @test Qinv' isa TensorMapping{T,2,2} where T - @test collect(Qinv*Q*v) ≈ v + @test collect(Qinv*(Q*v)) ≈ v @test collect(Qinv*v) == collect(Qinv'*v) end #