Mercurial > repos > public > sbplib_julia
changeset 286:7247e85dc1e8 tensor_mappings
Start separating ConstantStencilOp into multiple 1D tensor mappings, e.g. ConstantLaplaceOp. Sketch an implementation of the multi-D laplace tensor operator as a tuple of 1D laplace tensor operators.
author | Vidar Stiernström <vidar.stiernstrom@it.uu.se> |
---|---|
date | Mon, 22 Jun 2020 19:47:20 +0200 |
parents | e21dcda55163 |
children | dd621017b695 |
files | DiffOps/src/laplace.jl SbpOperators/src/constantlaplace.jl |
diffstat | 2 files changed, 70 insertions(+), 10 deletions(-) [+] |
line wrap: on
line diff
--- a/DiffOps/src/laplace.jl Fri Jun 19 12:20:31 2020 +0200 +++ b/DiffOps/src/laplace.jl Mon Jun 22 19:47:20 2020 +0200 @@ -1,13 +1,18 @@ +#TODO: move to sbpoperators.jl +""" + Laplace{Dim,T<:Real,N,M,K} <: TensorOperator{T,Dim} + +Implements the Laplace operator `L` in Dim dimensions as a tensor operator +The multi-dimensional tensor operator simply consists of a tuple of the 1D +Laplace tensor operator as defined by ConstantLaplaceOperator. +""" struct Laplace{Dim,T<:Real,N,M,K} <: TensorOperator{T,Dim} - grid::EquidistantGrid{Dim,T} # TODO: Should this be here? Should probably be possible to applay a Laplace object to any size grid function - a::T # TODO: Better name? - op::D2{T,N,M,K} + tensorOps::NTuple(Dim,ConstantLaplaceOperator{T,N,M,K}) + #TODO: Write a good constructor end export Laplace -# At the moment the grid property is used all over. It could possibly be removed if we implement all the 1D operators as TensorMappings - -LazyTensors.domain_size(H::Laplace{Dim}, range_size::NTuple{Dim,Integer}) where Dim = range_size +LazyTensors.domain_size(H::Laplace{Dim}, range_size::NTuple{Dim,Integer}) = range_size function LazyTensors.apply(L::Laplace{Dim,T}, v::AbstractArray{T,Dim}, I::NTuple{Dim,Index}) where {T,Dim} error("not implemented") @@ -15,18 +20,19 @@ # u = L*v 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ᵢ + return apply(L.tensorOps[1],v,I) end @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*apply_2nd_derivative(L.op, inverse_spacing(L.grid)[1], vx , I[1]) + @inbounds uᵢ = apply(L.tensorOps[1], vx , (I[1],)) #Tuple conversion here is ugly. How to do it? Should we use indexing here? + # 2nd y-derivative @inbounds vy = view(v, Int(I[1]), :) - @inbounds uᵢ += L.a*apply_2nd_derivative(L.op, inverse_spacing(L.grid)[2], vy, I[2]) + @inbounds uᵢ += apply(L.tensorOps[2], vy , (I[2],)) #Tuple conversion here is ugly. How to do it? + return uᵢ end @@ -37,6 +43,7 @@ boundary_quadrature(L::Laplace, bId::CartesianBoundary) = BoundaryQuadrature(L.op, L.grid, bId) export quadrature +# At the moment the grid property is used all over. It could possibly be removed if we implement all the 1D operators as TensorMappings """ Quadrature{Dim,T<:Real,N,M,K} <: TensorMapping{T,Dim,Dim}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/SbpOperators/src/constantlaplace.jl Mon Jun 22 19:47:20 2020 +0200 @@ -0,0 +1,53 @@ +#TODO: Naming?! What is this? It is a 1D tensor operator but what is then the +# potentially multi-D laplace tensor mapping then? +# Ideally I would like the below to be the laplace operator in 1D, while the +# multi-D operator is a a tuple of the 1D-operator. Possible via recursive +# definitions? Or just bad design? +""" + ConstantLaplaceOperator{T<:Real,N,M,K} <: TensorOperator{T,1} +Implements the Laplace tensor operator `L` with constant grid spacing and coefficients +in 1D dimension +""" +struct ConstantLaplaceOperator{T<:Real,N,M,K} <: TensorOperator{T,1} + h_inv::T # The grid spacing could be included in the stencil already. Preferable? + a::T # TODO: Better name? + innerStencil::Stencil{T,N} + closureStencils::NTuple{M,Stencil{T,K}} + parity::Parity +end + +@enum Parity begin + odd = -1 + even = 1 +end + +LazyTensors.domain_size(L::ConstantLaplaceOperator, range_size::NTuple{1,Integer}) = range_size + +function LazyTensors.apply(L::ConstantLaplaceOperator{T}, v::AbstractVector{T}, I::NTuple{1,Index}) where T + return L.a*apply_2nd_derivative(L, L.h_inv, v, I[1]) +end + +# Apply for different regions Lower/Interior/Upper or Unknown region +@inline function apply_2nd_derivative(L::ConstantLaplaceOperator, h_inv::Real, v::AbstractVector, i::Index{Lower}) + return @inbounds h_inv*h_inv*apply_stencil(L.closureStencils[Int(i)], v, Int(i)) +end + +@inline function apply_2nd_derivative(L::ConstantLaplaceOperator, h_inv::Real, v::AbstractVector, i::Index{Interior}) + return @inbounds h_inv*h_inv*apply_stencil(L.innerStencil, v, Int(i)) +end + +@inline function apply_2nd_derivative(L::ConstantLaplaceOperator, h_inv::Real, v::AbstractVector, i::Index{Upper}) + N = length(v) # Can we use range_size here instead? + return @inbounds h_inv*h_inv*Int(L.parity)*apply_stencil_backwards(L.closureStencils[N-Int(i)+1], v, Int(i)) +end + +@inline function apply_2nd_derivative(L::ConstantLaplaceOperator, h_inv::Real, v::AbstractVector, index::Index{Unknown}) + N = length(v) # Can we use range_size here instead? + r = getregion(Int(index), closuresize(L), N) + i = Index(Int(index), r) + return apply_2nd_derivative(op, h_inv, v, i) +end + +function closuresize(L::ConstantLaplaceOperator{T<:Real,N,M,K})::Int + return M +end