comparison DiffOps/src/laplace.jl @ 247:ed29ee13e92e boundary_conditions

Restructure laplace.jl
author Vidar Stiernström <vidar.stiernstrom@it.uu.se>
date Thu, 27 Jun 2019 09:43:44 +0200
parents a827568fc251
children 05e7bbe0af97
comparison
equal deleted inserted replaced
244:a827568fc251 247:ed29ee13e92e
1 """ 1 struct Laplace{Dim,T<:Real,N,M,K} <: DiffOpCartesian{Dim}
2 NormalDerivative{T,N,M,K} <: TensorMapping{T,2,1} 2 grid::EquidistantGrid{Dim,T}
3 3 a::T
4 Implements the boundary operator `d` as a TensorMapping 4 op::D2{Float64,N,M,K}
5 """ 5 # e::BoundaryValue
6 struct NormalDerivative{T,N,M,K} <: TensorMapping{T,2,1} 6 # d::NormalDerivative
7 op::D2{T,N,M,K}
8 grid::EquidistantGrid
9 bId::CartesianBoundary
10 end
11 export NormalDerivative
12
13 # TODO: This is obviouly strange. Is domain_size just discarded? Is there a way to avoid storing grid in BoundaryValue?
14 # Can we give special treatment to TensorMappings that go to a higher dim?
15 LazyTensors.range_size(e::NormalDerivative{T}, domain_size::NTuple{1,Integer}) where T = size(e.grid)
16 LazyTensors.domain_size(e::NormalDerivative{T}, range_size::NTuple{2,Integer}) where T = (range_size[3-dim(e.bId)],)
17
18 # Not correct abstraction level
19 # TODO: Not type stable D:<
20 function LazyTensors.apply(d::NormalDerivative, v::AbstractArray, I::NTuple{2,Int})
21 i = I[dim(d.bId)]
22 j = I[3-dim(d.bId)]
23 N_i = size(d.grid)[dim(d.bId)]
24
25 if region(d.bId) == Lower
26 # Note, closures are indexed by offset. Fix this D:<
27 return d.grid.inverse_spacing[dim(d.bId)]*d.op.dClosure[i-1]*v[j]
28 elseif region(d.bId) == Upper
29 return -d.grid.inverse_spacing[dim(d.bId)]*d.op.dClosure[N_i-i]*v[j]
30 end
31 end 7 end
32 8
33 function LazyTensors.apply_transpose(d::NormalDerivative, v::AbstractArray, I::NTuple{1,Int}) 9 function apply(L::Laplace{Dim}, v::AbstractArray{T,Dim} where T, I::CartesianIndex{Dim}) where Dim
34 u = selectdim(v,3-dim(d.bId),I[1]) 10 error("not implemented")
35 return apply_d(d.op, d.grid.inverse_spacing[dim(d.bId)], u, region(d.bId))
36 end 11 end
12
13 # u = L*v
14 function apply(L::Laplace{1}, v::AbstractVector, i::Int)
15 uᵢ = L.a * SbpOperators.apply(L.op, L.grid.spacing[1], v, i)
16 return uᵢ
17 end
18
19 @inline function apply(L::Laplace{2}, v::AbstractArray{T,2} where T, I::Tuple{Index{R1}, Index{R2}}) where {R1, R2}
20 # 2nd x-derivative
21 @inbounds vx = view(v, :, Int(I[2]))
22 @inbounds uᵢ = L.a*SbpOperators.apply(L.op, L.grid.inverse_spacing[1], vx , I[1])
23 # 2nd y-derivative
24 @inbounds vy = view(v, Int(I[1]), :)
25 @inbounds uᵢ += L.a*SbpOperators.apply(L.op, L.grid.inverse_spacing[2], vy, I[2])
26 # NOTE: the package qualifier 'SbpOperators' can problably be removed once all "applying" objects use LazyTensors
27 return uᵢ
28 end
29
30 # Slow but maybe convenient?
31 function apply(L::Laplace{2}, v::AbstractArray{T,2} where T, i::CartesianIndex{2})
32 I = Index{Unknown}.(Tuple(i))
33 apply(L, v, I)
34 end
35
37 36
38 37
39 """ 38 """
40 BoundaryValue{T,N,M,K} <: TensorMapping{T,2,1} 39 BoundaryValue{T,N,M,K} <: TensorMapping{T,2,1}
41 40
71 return apply_e(e.op, u, region(e.bId)) 70 return apply_e(e.op, u, region(e.bId))
72 end 71 end
73 72
74 73
75 74
76 struct Laplace{Dim,T<:Real,N,M,K} <: DiffOpCartesian{Dim} 75 """
77 grid::EquidistantGrid{Dim,T} 76 NormalDerivative{T,N,M,K} <: TensorMapping{T,2,1}
78 a::T 77
79 op::D2{Float64,N,M,K} 78 Implements the boundary operator `d` as a TensorMapping
80 # e::BoundaryValue 79 """
81 # d::NormalDerivative 80 struct NormalDerivative{T,N,M,K} <: TensorMapping{T,2,1}
81 op::D2{T,N,M,K}
82 grid::EquidistantGrid
83 bId::CartesianBoundary
84 end
85 export NormalDerivative
86
87 # TODO: This is obviouly strange. Is domain_size just discarded? Is there a way to avoid storing grid in BoundaryValue?
88 # Can we give special treatment to TensorMappings that go to a higher dim?
89 LazyTensors.range_size(e::NormalDerivative{T}, domain_size::NTuple{1,Integer}) where T = size(e.grid)
90 LazyTensors.domain_size(e::NormalDerivative{T}, range_size::NTuple{2,Integer}) where T = (range_size[3-dim(e.bId)],)
91
92 # Not correct abstraction level
93 # TODO: Not type stable D:<
94 function LazyTensors.apply(d::NormalDerivative, v::AbstractArray, I::NTuple{2,Int})
95 i = I[dim(d.bId)]
96 j = I[3-dim(d.bId)]
97 N_i = size(d.grid)[dim(d.bId)]
98
99 if region(d.bId) == Lower
100 # Note, closures are indexed by offset. Fix this D:<
101 return d.grid.inverse_spacing[dim(d.bId)]*d.op.dClosure[i-1]*v[j]
102 elseif region(d.bId) == Upper
103 return -d.grid.inverse_spacing[dim(d.bId)]*d.op.dClosure[N_i-i]*v[j]
104 end
82 end 105 end
83 106
84 function apply(L::Laplace{Dim}, v::AbstractArray{T,Dim} where T, I::CartesianIndex{Dim}) where Dim 107 function LazyTensors.apply_transpose(d::NormalDerivative, v::AbstractArray, I::NTuple{1,Int})
85 error("not implemented") 108 u = selectdim(v,3-dim(d.bId),I[1])
109 return apply_d(d.op, d.grid.inverse_spacing[dim(d.bId)], u, region(d.bId))
86 end 110 end
87 111
88 # u = L*v
89 function apply(L::Laplace{1}, v::AbstractVector, i::Int)
90 uᵢ = L.a * SbpOperators.apply(L.op, L.grid.spacing[1], v, i)
91 return uᵢ
92 end
93
94 @inline function apply(L::Laplace{2}, v::AbstractArray{T,2} where T, I::Tuple{Index{R1}, Index{R2}}) where {R1, R2}
95 # 2nd x-derivative
96 @inbounds vx = view(v, :, Int(I[2]))
97 @inbounds uᵢ = L.a*SbpOperators.apply(L.op, L.grid.inverse_spacing[1], vx , I[1])
98 # 2nd y-derivative
99 @inbounds vy = view(v, Int(I[1]), :)
100 @inbounds uᵢ += L.a*SbpOperators.apply(L.op, L.grid.inverse_spacing[2], vy, I[2])
101 # NOTE: the package qualifier 'SbpOperators' can problably be removed once all "applying" objects use LazyTensors
102 return uᵢ
103 end
104
105 # Slow but maybe convenient?
106 function apply(L::Laplace{2}, v::AbstractArray{T,2} where T, i::CartesianIndex{2})
107 I = Index{Unknown}.(Tuple(i))
108 apply(L, v, I)
109 end
110 112
111 113
112 struct Neumann{Bid<:BoundaryIdentifier} <: BoundaryCondition end 114 struct Neumann{Bid<:BoundaryIdentifier} <: BoundaryCondition end
113 115
114 function sat(L::Laplace{2,T}, bc::Neumann{Bid}, v::AbstractArray{T,2}, g::AbstractVector{T}, I::CartesianIndex{2}) where {T,Bid} 116 function sat(L::Laplace{2,T}, bc::Neumann{Bid}, v::AbstractArray{T,2}, g::AbstractVector{T}, I::CartesianIndex{2}) where {T,Bid}