changeset 282:ce6a2f3f732a boundary_conditions

Make Laplace a TensorOperator and add tests. NOTE: Two of the tests for Laplace2D are currently failing.
author Vidar Stiernström <vidar.stiernstrom@it.uu.se>
date Thu, 09 Jan 2020 10:54:24 +0100
parents 1eefaefdd0c7
children 12a12a5cd973
files DiffOps/src/DiffOps.jl DiffOps/src/laplace.jl DiffOps/test/runtests.jl
diffstat 3 files changed, 58 insertions(+), 25 deletions(-) [+]
line wrap: on
line diff
--- a/DiffOps/src/DiffOps.jl	Thu Jan 09 10:53:03 2020 +0100
+++ b/DiffOps/src/DiffOps.jl	Thu Jan 09 10:54:24 2020 +0100
@@ -98,7 +98,5 @@
 
 
 include("laplace.jl")
-export Laplace
-
 
 end # module
--- a/DiffOps/src/laplace.jl	Thu Jan 09 10:53:03 2020 +0100
+++ b/DiffOps/src/laplace.jl	Thu Jan 09 10:54:24 2020 +0100
@@ -1,36 +1,33 @@
-struct Laplace{Dim,T<:Real,N,M,K} <: DiffOpCartesian{Dim}
+struct Laplace{Dim,T<:Real,N,M,K} <: TensorOperator{T,Dim}
     grid::EquidistantGrid{Dim,T}
-    a::T
-    op::D2{Float64,N,M,K}
+    a::T # TODO: Better name?
+    op::D2{T,N,M,K}
 end
+export Laplace
 
-function apply(L::Laplace{Dim}, v::AbstractArray{T,Dim} where T, I::CartesianIndex{Dim}) where Dim
+LazyTensors.domain_size(H::Laplace{Dim}, range_size::NTuple{Dim,Integer}) where Dim = size(L.grid)
+
+function LazyTensors.apply(L::Laplace{Dim,T}, v::AbstractArray{T,Dim}, I::NTuple{Dim,Index}) where {T,Dim}
     error("not implemented")
 end
 
 # u = L*v
-function apply(L::Laplace{1}, v::AbstractVector, i::Int)
-    uᵢ = L.a * SbpOperators.apply_2nd_derivative(L.op, inverse_spacing(L.grid)[1], v, i)
+function LazyTensors.apply(L::Laplace{1,T}, v::AbstractVector{T}, I::NTuple{1,Index}) where T
+    uᵢ = L.a*apply_2nd_derivative(L.op, inverse_spacing(L.grid)[1], v, I[1])
     return uᵢ
 end
 
-@inline function apply(L::Laplace{2}, v::AbstractArray{T,2} where T, I::Tuple{Index{R1}, Index{R2}}) where {R1, R2}
+
+@inline function LazyTensors.apply(L::Laplace{2,T}, v::AbstractArray{T,2}, I::NTuple{2,Index}) where T
     # 2nd x-derivative
     @inbounds vx = view(v, :, Int(I[2]))
-    @inbounds uᵢ = L.a*SbpOperators.apply_2nd_derivative(L.op, inverse_spacing(L.grid)[1], vx , I[1])
+    @inbounds uᵢ = L.a*apply_2nd_derivative(L.op, inverse_spacing(L.grid)[1], vx , I[1])
     # 2nd y-derivative
     @inbounds vy = view(v, Int(I[1]), :)
-    @inbounds uᵢ += L.a*SbpOperators.apply_2nd_derivative(L.op, inverse_spacing(L.grid)[2], vy, I[2])
-    # NOTE: the package qualifier 'SbpOperators' can problably be removed once all "applying" objects use LazyTensors
+    @inbounds uᵢ += L.a*apply_2nd_derivative(L.op, inverse_spacing(L.grid)[2], vy, I[2])
     return uᵢ
 end
 
-# Slow but maybe convenient?
-function apply(L::Laplace{2}, v::AbstractArray{T,2} where T, i::CartesianIndex{2})
-    I = Index{Unknown}.(Tuple(i))
-    apply(L, v, I)
-end
-
 quadrature(L::Laplace) = Quadrature(L.op, L.grid)
 inverse_quadrature(L::Laplace) = InverseQuadrature(L.op, L.grid)
 boundary_value(L::Laplace, bId::CartesianBoundary) = BoundaryValue(L.op, L.grid, bId)
--- a/DiffOps/test/runtests.jl	Thu Jan 09 10:53:03 2020 +0100
+++ b/DiffOps/test/runtests.jl	Thu Jan 09 10:54:24 2020 +0100
@@ -5,6 +5,44 @@
 using RegionIndices
 using LazyTensors
 
+@testset "Laplace2D" begin
+    op = readOperator(sbp_operators_path()*"d2_4th.txt",sbp_operators_path()*"h_4th.txt")
+    Lx = 3.5
+    Ly = 7.2
+    g = EquidistantGrid((21,42), (0.0, 0.0), (Lx,Ly))
+    L = Laplace(g, 1., op)
+
+    f0(x::Float64,y::Float64) = 2.
+    f1(x::Float64,y::Float64) = x+y
+    f2(x::Float64,y::Float64) = 1/2*x^2 + 1/2*y^2
+    f3(x::Float64,y::Float64) = 1/6*x^3 + 1/6*y^3
+    f4(x::Float64,y::Float64) = 1/24*x^4 + 1/24*y^4
+    f5(x::Float64,y::Float64) = x^5 + 2*y^3 + 3/2*x^2 + y + 7
+    f5ₓₓ(x::Float64,y::Float64) = 20*x^3 + 12*y + 3
+
+    v0 = evalOn(g,f0)
+    v1 = evalOn(g,f1)
+    v2 = evalOn(g,f2)
+    v3 = evalOn(g,f3)
+    v4 = evalOn(g,f4)
+    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
+    # TODO: Should perhaps set tolerance level for isapporx instead?
+    equalitytol = 0.5*1e-11
+    accuracytol = 1e-4
+    @test all(collect(L*v0) .<= equalitytol)
+    @test all(collect(L*v1) .<= equalitytol)
+    @test all(collect(L*v2) .≈ v0) # Seems to be more accurate
+    @test all((collect(L*v3) - v1) .<= equalitytol)
+    @show maximum(abs.(collect(L*v4) - v2))
+    @show maximum(abs.(collect(L*v5) - v5ₓₓ))
+    @test_broken all((collect(L*v4) - v2) .<= accuracytol) #TODO: Should be equality?
+    @test_broken all((collect(L*v5) - v5ₓₓ) .<= accuracytol) #TODO: This is just wrong
+end
+
 @testset "Quadrature" begin
     op = readOperator(sbp_operators_path()*"d2_4th.txt",sbp_operators_path()*"h_4th.txt")
     Lx = 2.3
@@ -13,7 +51,7 @@
     H = Quadrature(op,g)
     v = ones(Float64, size(g))
 
-    @test H isa TensorMapping{T,2,2} where T
+    @test H isa TensorOperator{T,2} where T
     @test H' isa TensorMapping{T,2,2} where T
     @test sum(collect(H*v)) ≈ (Lx*Ly)
     @test collect(H*v) == collect(H'*v)
@@ -28,7 +66,7 @@
     Hinv = InverseQuadrature(op,g)
     v = evalOn(g, (x,y)-> x^2 + (y-1)^2 + x*y)
 
-    @test Hinv isa TensorMapping{T,2,2} where T
+    @test Hinv isa TensorOperator{T,2} where T
     @test Hinv' isa TensorMapping{T,2,2} where T
     @test collect(Hinv*H*v)  ≈ v
     @test collect(Hinv*v) == collect(Hinv'*v)
@@ -141,7 +179,7 @@
         d_y_u[i] = -op.dClosure[length(d_y_u)-i]
     end
 
-    function ❓(x,y)
+    function prod_matrix(x,y)
         G = zeros(Float64, length(x), length(y))
         for I ∈ CartesianIndices(G)
             G[I] = x[I[1]]*y[I[2]]
@@ -153,10 +191,10 @@
     g_x = [1,2,3,4.0,5]
     g_y = [5,4,3,2,1.0,11]
 
-    G_w = ❓(d_x_l, g_y)
-    G_e = ❓(d_x_u, g_y)
-    G_s = ❓(g_x, d_y_l)
-    G_n = ❓(g_x, d_y_u)
+    G_w = prod_matrix(d_x_l, g_y)
+    G_e = prod_matrix(d_x_u, g_y)
+    G_s = prod_matrix(g_x, d_y_l)
+    G_n = prod_matrix(g_x, d_y_u)
 
 
     @test size(d_w*g_y) == (5,6)