Mercurial > repos > public > sbplib_julia
comparison SbpOperators/src/laplace/laplace.jl @ 293:f63232aeb1c6
Move laplace.jl from DiffOps to SbpOperators. Rename constandlaplace to secondderivative
author | Vidar Stiernström <vidar.stiernstrom@it.uu.se> |
---|---|
date | Mon, 22 Jun 2020 22:08:56 +0200 |
parents | DiffOps/src/laplace.jl@7247e85dc1e8 |
children | b00eea62c78e |
comparison
equal
deleted
inserted
replaced
292:3747e5636eef | 293:f63232aeb1c6 |
---|---|
1 """ | |
2 Laplace{Dim,T<:Real,N,M,K} <: TensorOperator{T,Dim} | |
3 | |
4 Implements the Laplace operator `L` in Dim dimensions as a tensor operator | |
5 The multi-dimensional tensor operator simply consists of a tuple of the 1D | |
6 Laplace tensor operator as defined by ConstantLaplaceOperator. | |
7 """ | |
8 struct Laplace{Dim,T<:Real,N,M,K} <: TensorOperator{T,Dim} | |
9 D2::NTuple(Dim,SecondDerivative{T,N,M,K}) | |
10 #TODO: Write a good constructor | |
11 end | |
12 export Laplace | |
13 | |
14 LazyTensors.domain_size(H::Laplace{Dim}, range_size::NTuple{Dim,Integer}) = range_size | |
15 | |
16 function LazyTensors.apply(L::Laplace{Dim,T}, v::AbstractArray{T,Dim}, I::NTuple{Dim,Index}) where {T,Dim} | |
17 error("not implemented") | |
18 end | |
19 | |
20 # u = L*v | |
21 function LazyTensors.apply(L::Laplace{1,T}, v::AbstractVector{T}, I::NTuple{1,Index}) where T | |
22 return apply(L.D2[1],v,I) | |
23 end | |
24 | |
25 | |
26 @inline function LazyTensors.apply(L::Laplace{2,T}, v::AbstractArray{T,2}, I::NTuple{2,Index}) where T | |
27 # 2nd x-derivative | |
28 @inbounds vx = view(v, :, Int(I[2])) | |
29 @inbounds uᵢ = apply(L.D2[1], vx , (I[1],)) #Tuple conversion here is ugly. How to do it? Should we use indexing here? | |
30 | |
31 # 2nd y-derivative | |
32 @inbounds vy = view(v, Int(I[1]), :) | |
33 @inbounds uᵢ += apply(L.D2[2], vy , (I[2],)) #Tuple conversion here is ugly. How to do it? | |
34 | |
35 return uᵢ | |
36 end | |
37 | |
38 quadrature(L::Laplace) = Quadrature(L.op, L.grid) | |
39 inverse_quadrature(L::Laplace) = InverseQuadrature(L.op, L.grid) | |
40 boundary_value(L::Laplace, bId::CartesianBoundary) = BoundaryValue(L.op, L.grid, bId) | |
41 normal_derivative(L::Laplace, bId::CartesianBoundary) = NormalDerivative(L.op, L.grid, bId) | |
42 boundary_quadrature(L::Laplace, bId::CartesianBoundary) = BoundaryQuadrature(L.op, L.grid, bId) | |
43 export quadrature | |
44 | |
45 # At the moment the grid property is used all over. It could possibly be removed if we implement all the 1D operators as TensorMappings | |
46 """ | |
47 Quadrature{Dim,T<:Real,N,M,K} <: TensorMapping{T,Dim,Dim} | |
48 | |
49 Implements the quadrature operator `H` of Dim dimension as a TensorMapping | |
50 """ | |
51 struct Quadrature{Dim,T<:Real,N,M,K} <: TensorOperator{T,Dim} | |
52 op::D2{T,N,M,K} | |
53 grid::EquidistantGrid{Dim,T} | |
54 end | |
55 export Quadrature | |
56 | |
57 LazyTensors.domain_size(H::Quadrature{Dim}, range_size::NTuple{Dim,Integer}) where Dim = range_size | |
58 | |
59 @inline function LazyTensors.apply(H::Quadrature{2,T}, v::AbstractArray{T,2}, I::NTuple{2,Index}) where T | |
60 N = size(H.grid) | |
61 # Quadrature in x direction | |
62 @inbounds q = apply_quadrature(H.op, spacing(H.grid)[1], v[I] , I[1], N[1]) | |
63 # Quadrature in y-direction | |
64 @inbounds q = apply_quadrature(H.op, spacing(H.grid)[2], q, I[2], N[2]) | |
65 return q | |
66 end | |
67 | |
68 LazyTensors.apply_transpose(H::Quadrature{2,T}, v::AbstractArray{T,2}, I::NTuple{2,Index}) where T = LazyTensors.apply(H,v,I) | |
69 | |
70 | |
71 """ | |
72 InverseQuadrature{Dim,T<:Real,N,M,K} <: TensorMapping{T,Dim,Dim} | |
73 | |
74 Implements the inverse quadrature operator `inv(H)` of Dim dimension as a TensorMapping | |
75 """ | |
76 struct InverseQuadrature{Dim,T<:Real,N,M,K} <: TensorOperator{T,Dim} | |
77 op::D2{T,N,M,K} | |
78 grid::EquidistantGrid{Dim,T} | |
79 end | |
80 export InverseQuadrature | |
81 | |
82 LazyTensors.domain_size(H_inv::InverseQuadrature{Dim}, range_size::NTuple{Dim,Integer}) where Dim = range_size | |
83 | |
84 @inline function LazyTensors.apply(H_inv::InverseQuadrature{2,T}, v::AbstractArray{T,2}, I::NTuple{2,Index}) where T | |
85 N = size(H_inv.grid) | |
86 # Inverse quadrature in x direction | |
87 @inbounds q_inv = apply_inverse_quadrature(H_inv.op, inverse_spacing(H_inv.grid)[1], v[I] , I[1], N[1]) | |
88 # Inverse quadrature in y-direction | |
89 @inbounds q_inv = apply_inverse_quadrature(H_inv.op, inverse_spacing(H_inv.grid)[2], q_inv, I[2], N[2]) | |
90 return q_inv | |
91 end | |
92 | |
93 LazyTensors.apply_transpose(H_inv::InverseQuadrature{2,T}, v::AbstractArray{T,2}, I::NTuple{2,Index}) where T = LazyTensors.apply(H_inv,v,I) | |
94 | |
95 """ | |
96 BoundaryValue{T,N,M,K} <: TensorMapping{T,2,1} | |
97 | |
98 Implements the boundary operator `e` as a TensorMapping | |
99 """ | |
100 struct BoundaryValue{T,N,M,K} <: TensorMapping{T,2,1} | |
101 op::D2{T,N,M,K} | |
102 grid::EquidistantGrid{2} | |
103 bId::CartesianBoundary | |
104 end | |
105 export BoundaryValue | |
106 | |
107 # TODO: This is obviouly strange. Is domain_size just discarded? Is there a way to avoid storing grid in BoundaryValue? | |
108 # Can we give special treatment to TensorMappings that go to a higher dim? | |
109 function LazyTensors.range_size(e::BoundaryValue{T}, domain_size::NTuple{1,Integer}) where T | |
110 if dim(e.bId) == 1 | |
111 return (UnknownDim, domain_size[1]) | |
112 elseif dim(e.bId) == 2 | |
113 return (domain_size[1], UnknownDim) | |
114 end | |
115 end | |
116 LazyTensors.domain_size(e::BoundaryValue{T}, range_size::NTuple{2,Integer}) where T = (range_size[3-dim(e.bId)],) | |
117 # TODO: Make a nicer solution for 3-dim(e.bId) | |
118 | |
119 # TODO: Make this independent of dimension | |
120 function LazyTensors.apply(e::BoundaryValue{T}, v::AbstractArray{T}, I::NTuple{2,Index}) where T | |
121 i = I[dim(e.bId)] | |
122 j = I[3-dim(e.bId)] | |
123 N_i = size(e.grid)[dim(e.bId)] | |
124 return apply_boundary_value(e.op, v[j], i, N_i, region(e.bId)) | |
125 end | |
126 | |
127 function LazyTensors.apply_transpose(e::BoundaryValue{T}, v::AbstractArray{T}, I::NTuple{1,Index}) where T | |
128 u = selectdim(v,3-dim(e.bId),Int(I[1])) | |
129 return apply_boundary_value_transpose(e.op, u, region(e.bId)) | |
130 end | |
131 | |
132 """ | |
133 NormalDerivative{T,N,M,K} <: TensorMapping{T,2,1} | |
134 | |
135 Implements the boundary operator `d` as a TensorMapping | |
136 """ | |
137 struct NormalDerivative{T,N,M,K} <: TensorMapping{T,2,1} | |
138 op::D2{T,N,M,K} | |
139 grid::EquidistantGrid{2} | |
140 bId::CartesianBoundary | |
141 end | |
142 export NormalDerivative | |
143 | |
144 # TODO: This is obviouly strange. Is domain_size just discarded? Is there a way to avoid storing grid in BoundaryValue? | |
145 # Can we give special treatment to TensorMappings that go to a higher dim? | |
146 function LazyTensors.range_size(e::NormalDerivative, domain_size::NTuple{1,Integer}) | |
147 if dim(e.bId) == 1 | |
148 return (UnknownDim, domain_size[1]) | |
149 elseif dim(e.bId) == 2 | |
150 return (domain_size[1], UnknownDim) | |
151 end | |
152 end | |
153 LazyTensors.domain_size(e::NormalDerivative, range_size::NTuple{2,Integer}) = (range_size[3-dim(e.bId)],) | |
154 | |
155 # TODO: Not type stable D:< | |
156 # TODO: Make this independent of dimension | |
157 function LazyTensors.apply(d::NormalDerivative{T}, v::AbstractArray{T}, I::NTuple{2,Index}) where T | |
158 i = I[dim(d.bId)] | |
159 j = I[3-dim(d.bId)] | |
160 N_i = size(d.grid)[dim(d.bId)] | |
161 h_inv = inverse_spacing(d.grid)[dim(d.bId)] | |
162 return apply_normal_derivative(d.op, h_inv, v[j], i, N_i, region(d.bId)) | |
163 end | |
164 | |
165 function LazyTensors.apply_transpose(d::NormalDerivative{T}, v::AbstractArray{T}, I::NTuple{1,Index}) where T | |
166 u = selectdim(v,3-dim(d.bId),Int(I[1])) | |
167 return apply_normal_derivative_transpose(d.op, inverse_spacing(d.grid)[dim(d.bId)], u, region(d.bId)) | |
168 end | |
169 | |
170 """ | |
171 BoundaryQuadrature{T,N,M,K} <: TensorOperator{T,1} | |
172 | |
173 Implements the boundary operator `q` as a TensorOperator | |
174 """ | |
175 struct BoundaryQuadrature{T,N,M,K} <: TensorOperator{T,1} | |
176 op::D2{T,N,M,K} | |
177 grid::EquidistantGrid{2} | |
178 bId::CartesianBoundary | |
179 end | |
180 export BoundaryQuadrature | |
181 | |
182 # TODO: Make this independent of dimension | |
183 function LazyTensors.apply(q::BoundaryQuadrature{T}, v::AbstractArray{T,1}, I::NTuple{1,Index}) where T | |
184 h = spacing(q.grid)[3-dim(q.bId)] | |
185 N = size(v) | |
186 return apply_quadrature(q.op, h, v[I[1]], I[1], N[1]) | |
187 end | |
188 | |
189 LazyTensors.apply_transpose(q::BoundaryQuadrature{T}, v::AbstractArray{T,1}, I::NTuple{1,Index}) where T = LazyTensors.apply(q,v,I) | |
190 | |
191 | |
192 | |
193 | |
194 struct Neumann{Bid<:BoundaryIdentifier} <: BoundaryCondition end | |
195 | |
196 function sat(L::Laplace{2,T}, bc::Neumann{Bid}, v::AbstractArray{T,2}, g::AbstractVector{T}, I::CartesianIndex{2}) where {T,Bid} | |
197 e = boundary_value(L, Bid()) | |
198 d = normal_derivative(L, Bid()) | |
199 Hᵧ = boundary_quadrature(L, Bid()) | |
200 H⁻¹ = inverse_quadrature(L) | |
201 return (-H⁻¹*e*Hᵧ*(d'*v - g))[I] | |
202 end | |
203 | |
204 struct Dirichlet{Bid<:BoundaryIdentifier} <: BoundaryCondition | |
205 tau::Float64 | |
206 end | |
207 | |
208 function sat(L::Laplace{2,T}, bc::Dirichlet{Bid}, v::AbstractArray{T,2}, g::AbstractVector{T}, i::CartesianIndex{2}) where {T,Bid} | |
209 e = boundary_value(L, Bid()) | |
210 d = normal_derivative(L, Bid()) | |
211 Hᵧ = boundary_quadrature(L, Bid()) | |
212 H⁻¹ = inverse_quadrature(L) | |
213 return (-H⁻¹*(tau/h*e + d)*Hᵧ*(e'*v - g))[I] | |
214 # Need to handle scalar multiplication and addition of TensorMapping | |
215 end | |
216 | |
217 # function apply(s::MyWaveEq{D}, v::AbstractArray{T,D}, i::CartesianIndex{D}) where D | |
218 # return apply(s.L, v, i) + | |
219 # sat(s.L, Dirichlet{CartesianBoundary{1,Lower}}(s.tau), v, s.g_w, i) + | |
220 # sat(s.L, Dirichlet{CartesianBoundary{1,Upper}}(s.tau), v, s.g_e, i) + | |
221 # sat(s.L, Dirichlet{CartesianBoundary{2,Lower}}(s.tau), v, s.g_s, i) + | |
222 # sat(s.L, Dirichlet{CartesianBoundary{2,Upper}}(s.tau), v, s.g_n, i) | |
223 # end |