comparison src/SbpOperators/volumeops/laplace/laplace.jl @ 875:067a322e4f73 laplace_benchmarks

Merge with feature/laplace_opset
author Vidar Stiernström <vidar.stiernstrom@it.uu.se>
date Thu, 27 Jan 2022 10:55:08 +0100
parents 9929c99754fb 86776d06b883
children
comparison
equal deleted inserted replaced
874:7e9ebd572deb 875:067a322e4f73
1 export Laplace
2 export laplace
3 # REVIEW: Makes more sense to me to have the exports at the top of the file.
4 # Might as well start fixing that.
5
6 # REVIEW: The style of name `Laplace` might clash with other concepts. When
7 # thinking about implementing the variable second derivative I think I will
8 # have to create it as a full TM for the full dimensional problem instead of
9 # building it as a 1D operator and then use that with outer products. The
10 # natural name there would be `VariableSecondDerivative` (or something
11 # similar). But the similarity of the two names would suggest that `Laplace`
12 # and `VariableSecondDerivative` are the same kind of thing, which they
13 # wouldn't be.
14 #
15 # How do we distinguish the kind of type we are implementing here and what we
16 # could potentially do for the variable second derivative?
17 #
18 # I see two ways out:
19 # * Come up with a name for these sets of operators and change `Laplace` accordingly.
20 # * Come up with a name for the bare operators and change `VariableSecondDerivative` accordingly.
21
1 """ 22 """
2 Laplace{T, Dim, TMdiffop} <: TensorMapping{T,Dim,Dim} 23 Laplace{T, Dim, TMdiffop} <: TensorMapping{T,Dim,Dim}
3 Laplace(grid::AbstractGrid, fn; order) 24 Laplace(grid, filename; order)
4 25
5 Implements the Laplace operator, approximating ∑d²/xᵢ² , i = 1,...,`Dim` as a 26 Implements the Laplace operator, approximating ∑d²/xᵢ² , i = 1,...,`Dim` as a
6 `TensorMapping`. Additionally, `Laplace` stores the inner product and boundary 27 `TensorMapping`. Additionally, `Laplace` stores the inner product and boundary
7 operators relevant for constructing a SBP finite difference scheme as `TensorMapping`s. 28 operators relevant for constructing a SBP finite difference scheme as a `TensorMapping`.
8 29
9 Laplace(grid, fn; order) creates the Laplace operator defined on `grid`, 30 `Laplace(grid, filename; order)` creates the Laplace operator defined on `grid`,
10 where the operators are read from TOML. The differential operator is created 31 where the operators are read from TOML. The differential operator is created
11 using `laplace(grid::AbstractGrid,...)`. 32 using `laplace(grid,...)`.
12 33
13 Note that all properties of Laplace, excluding the Differential operator `D`, are 34 Note that all properties of Laplace, excluding the differential operator `Laplace.D`, are
14 abstract types. For performance reasons, they should therefore be 35 abstract types. For performance reasons, they should therefore be
15 accessed via the provided getter functions (e.g `inner_product(::Laplace)`). 36 accessed via the provided getter functions (e.g `inner_product(::Laplace)`).
16
17 """ 37 """
18 struct Laplace{T, Dim, TMdiffop<:TensorMapping{T,Dim,Dim}} <: TensorMapping{T,Dim,Dim} 38 struct Laplace{T, Dim, TMdiffop<:TensorMapping{T,Dim,Dim}} <: TensorMapping{T,Dim,Dim}
19 D::TMdiffop # Differential operator 39 D::TMdiffop # Differential operator
20 H::TensorMapping # Inner product operator 40 H::TensorMapping # Inner product operator
21 H_inv::TensorMapping # Inverse inner product operator 41 H_inv::TensorMapping # Inverse inner product operator
22 e::StaticDict{<:BoundaryIdentifier,<:TensorMapping} # Boundary restriction operators. 42 e::StaticDict{<:BoundaryIdentifier,<:TensorMapping} # Boundary restriction operators.
23 d::StaticDict{<:BoundaryIdentifier,<:TensorMapping} # Normal derivative operators 43 d::StaticDict{<:BoundaryIdentifier,<:TensorMapping} # Normal derivative operators
24 H_boundary::StaticDict{<:BoundaryIdentifier,<:TensorMapping} # Boundary quadrature operators # TODO: Boundary inner product? 44 H_boundary::StaticDict{<:BoundaryIdentifier,<:TensorMapping} # Boundary quadrature operators
25 order::Int
26 end 45 end
27 export Laplace
28 46
29 function Laplace(grid::AbstractGrid, fn; order) 47 function Laplace(grid, filename; order)
48
49 # Read stencils
50 stencil_set = read_stencil_set(filename; order)
30 # TODO: Removed once we can construct the volume and 51 # TODO: Removed once we can construct the volume and
31 # boundary operators by op(grid, fn; order,...). 52 # boundary operators by op(grid, read_stencil_set(fn; order,...)).
32 # Read stencils 53 D_inner_stecil = parse_stencil(stencil_set["D2"]["inner_stencil"])
33 op = read_D2_operator(fn; order) 54 D_closure_stencils = parse_stencil.(stencil_set["D2"]["closure_stencils"])
34 D_inner_stecil = op.innerStencil 55 H_inner_stencils = parse_scalar(stencil_set["H"]["inner"])
35 D_closure_stencils = op.closureStencils 56 H_closure_stencils = parse_tuple(stencil_set["H"]["closure"])
36 H_closure_stencils = op.quadratureClosure 57 e_closure_stencil = parse_stencil(stencil_set["e"]["closure"])
37 e_closure_stencil = op.eClosure 58 d_closure_stencil = parse_stencil(stencil_set["d1"]["closure"])
38 d_closure_stencil = op.dClosure 59 # REVIEW: Do we add the methods to get rid of this in this branch or a new one?
39 60
40 # Volume operators 61 # Volume operators
41 Δ = laplace(grid, D_inner_stecil, D_closure_stencils) 62 Δ = laplace(grid, D_inner_stecil, D_closure_stencils)
42 H = inner_product(grid, H_closure_stencils) 63 H = inner_product(grid, H_inner_stencils, H_closure_stencils)
43 H⁻¹ = inverse_inner_product(grid, H_closure_stencils) 64 H⁻¹ = inverse_inner_product(grid, H_inner_stencils, H_closure_stencils)
44 65
45 # Boundary operator - id pairs 66 # Boundary operator - id pairs
46 ids = boundary_identifiers(grid) 67 ids = boundary_identifiers(grid)
47 n_ids = length(ids) 68 # REVIEW: Change suggestion: Seems more readable to me but pretty subjective so feel free to ignore
48 e_pairs = ntuple(i -> ids[i] => boundary_restriction(grid,e_closure_stencil,ids[i]),n_ids) 69 e_pairs = map(id -> Pair(id, boundary_restriction(grid, e_closure_stencil, id)), ids)
49 d_pairs = ntuple(i -> ids[i] => normal_derivative(grid,d_closure_stencil,ids[i]),n_ids) 70 d_pairs = map(id -> Pair(id, normal_derivative(grid, d_closure_stencil, id)), ids)
50 Hᵧ_pairs = ntuple(i -> ids[i] => inner_product(boundary_grid(grid,ids[i]),H_closure_stencils),n_ids) 71 Hᵧ_pairs = map(id -> Pair(id, inner_product(boundary_grid(grid, id), H_inner_stencils, H_closure_stencils)), ids)
51 72
52 return Laplace(Δ, H, H⁻¹, StaticDict(e_pairs), StaticDict(d_pairs), StaticDict(Hᵧ_pairs), order) 73 return Laplace(Δ, H, H⁻¹, StaticDict(e_pairs), StaticDict(d_pairs), StaticDict(Hᵧ_pairs), order)
53 end 74 end
54 75
55 # TODO: Consider pretty printing of the following form 76 # TODO: Consider pretty printing of the following form
56 # Base.show(io::IO, L::Laplace{T, Dim}) where {T,Dim,TM} = print(io, "Laplace{$T, $Dim, $TM}(", L.D, L.H, L.H_inv, L.e, L.d, L.H_boundary, ")") 77 # Base.show(io::IO, L::Laplace{T, Dim}) where {T,Dim,TM} = print(io, "Laplace{$T, $Dim, $TM}(", L.D, L.H, L.H_inv, L.e, L.d, L.H_boundary, ")")
78 # REVIEW: Should leave a todo here to update this once we have some pretty printing for tensor mappings in general.
57 79
58 LazyTensors.range_size(L::Laplace) = LazyTensors.range_size(L.D) 80 LazyTensors.range_size(L::Laplace) = LazyTensors.range_size(L.D)
59 LazyTensors.domain_size(L::Laplace) = LazyTensors.domain_size(L.D) 81 LazyTensors.domain_size(L::Laplace) = LazyTensors.domain_size(L.D)
60 LazyTensors.apply(L::Laplace, v::AbstractArray, I...) = LazyTensors.apply(L.D,v,I...) 82 LazyTensors.apply(L::Laplace, v::AbstractArray, I...) = LazyTensors.apply(L.D,v,I...)
61 83
67 """ 89 """
68 closure_size(L::Laplace) = closure_size(L.D) 90 closure_size(L::Laplace) = closure_size(L.D)
69 export closure_size 91 export closure_size
70 92
71 """ 93 """
72 inner_product(L::Lapalace) 94 inner_product(L::Laplace)
73 95
74 Returns the inner product operator associated with `L` 96 Returns the inner product operator associated with `L`
75
76 """ 97 """
77 inner_product(L::Laplace) = L.H 98 inner_product(L::Laplace) = L.H
78 export inner_product
79 99
80 100
81 """ 101 """
82 inverse_inner_product(L::Lapalace) 102 inverse_inner_product(L::Laplace)
83 103
84 Returns the inverse of the inner product operator associated with `L` 104 Returns the inverse of the inner product operator associated with `L`
85
86 """ 105 """
87 inverse_inner_product(L::Laplace) = L.H_inv 106 inverse_inner_product(L::Laplace) = L.H_inv
88 export inverse_inner_product
89 107
90 108
91 """ 109 """
92 boundary_restriction(L::Lapalace,id::BoundaryIdentifier) 110 boundary_restriction(L::Laplace, id::BoundaryIdentifier)
93 boundary_restriction(L::Lapalace,ids::NTuple{N,BoundaryIdentifier}) 111 boundary_restriction(L::Laplace, ids::Tuple)
94 boundary_restriction(L::Lapalace,ids...) 112 boundary_restriction(L::Laplace, ids...)
95 113
96 Returns boundary restriction operator(s) associated with `L` for the boundary(s) 114 Returns boundary restriction operator(s) associated with `L` for the boundary(s)
97 identified by id(s). 115 identified by id(s).
116 """
117 boundary_restriction(L::Laplace, id::BoundaryIdentifier) = L.e[id]
118 boundary_restriction(L::Laplace, ids::Tuple) = map(id-> L.e[id], ids)
119 boundary_restriction(L::Laplace, ids...) = boundary_restriction(L, ids)
120 # REVIEW: I propose changing the following implementations according to the
121 # above. There are some things we're missing with regards to
122 # `BoundaryIdentifier`, for example we should be able to handle groups of
123 # boundaries as a single `BoundaryIdentifier`. I don't know if we can figure
124 # out the interface for that now or if we save it for the future but either
125 # way these methods will be affected.
98 126
99 """
100 boundary_restriction(L::Laplace,id::BoundaryIdentifier) = L.e[id]
101 boundary_restriction(L::Laplace,ids::NTuple{N,BoundaryIdentifier}) where N = ntuple(i->L.e[ids[i]],N)
102 boundary_restriction(L::Laplace,ids::Vararg{BoundaryIdentifier,N}) where N = ntuple(i->L.e[ids[i]],N)
103 export boundary_restriction
104 127
105 128
106 """ 129 """
107 normal_derivative(L::Lapalace,id::BoundaryIdentifier) 130 normal_derivative(L::Laplace, id::BoundaryIdentifier)
108 normal_derivative(L::Lapalace,ids::NTuple{N,BoundaryIdentifier}) 131 normal_derivative(L::Laplace, ids::NTuple{N,BoundaryIdentifier})
109 normal_derivative(L::Lapalace,ids...) 132 normal_derivative(L::Laplace, ids...)
110 133
111 Returns normal derivative operator(s) associated with `L` for the boundary(s) 134 Returns normal derivative operator(s) associated with `L` for the boundary(s)
112 identified by id(s). 135 identified by id(s).
136 """
137 normal_derivative(L::Laplace, id::BoundaryIdentifier) = L.d[id]
138 normal_derivative(L::Laplace, ids::NTuple{N,BoundaryIdentifier}) where N = ntuple(i->L.d[ids[i]],N)
139 normal_derivative(L::Laplace, ids::Vararg{BoundaryIdentifier,N}) where N = ntuple(i->L.d[ids[i]],N)
140
113 141
114 """ 142 """
115 normal_derivative(L::Laplace,id::BoundaryIdentifier) = L.d[id] 143 boundary_quadrature(L::Laplace, id::BoundaryIdentifier)
116 normal_derivative(L::Laplace,ids::NTuple{N,BoundaryIdentifier}) where N = ntuple(i->L.d[ids[i]],N) 144 boundary_quadrature(L::Laplace, ids::NTuple{N,BoundaryIdentifier})
117 normal_derivative(L::Laplace,ids::Vararg{BoundaryIdentifier,N}) where N = ntuple(i->L.d[ids[i]],N) 145 boundary_quadrature(L::Laplace, ids...)
118 export normal_derivative
119
120
121 # TODO: boundary_inner_product?
122 """
123 boundary_quadrature(L::Lapalace,id::BoundaryIdentifier)
124 boundary_quadrature(L::Lapalace,ids::NTuple{N,BoundaryIdentifier})
125 boundary_quadrature(L::Lapalace,ids...)
126 146
127 Returns boundary quadrature operator(s) associated with `L` for the boundary(s) 147 Returns boundary quadrature operator(s) associated with `L` for the boundary(s)
128 identified by id(s). 148 identified by id(s).
129
130 """ 149 """
131 boundary_quadrature(L::Laplace,id::BoundaryIdentifier) = L.H_boundary[id] 150 boundary_quadrature(L::Laplace, id::BoundaryIdentifier) = L.H_boundary[id]
132 boundary_quadrature(L::Laplace,ids::NTuple{N,BoundaryIdentifier}) where N = ntuple(i->L.H_boundary[ids[i]],N) 151 boundary_quadrature(L::Laplace, ids::NTuple{N,BoundaryIdentifier}) where N = ntuple(i->L.H_boundary[ids[i]],N)
133 boundary_quadrature(L::Laplace,ids::Vararg{BoundaryIdentifier,N}) where N = ntuple(i->L.H_boundary[ids[i]],N) 152 boundary_quadrature(L::Laplace, ids::Vararg{BoundaryIdentifier,N}) where N = ntuple(i->L.H_boundary[ids[i]],N)
134 export boundary_quadrature
135 153
136 abstract type BoundaryConditionType end 154 abstract type BoundaryConditionType end
137 struct NeumannBC <: BoundaryConditionType end 155 struct NeumannBC <: BoundaryConditionType end
138 struct DirichletBC <: BoundaryConditionType end 156 struct DirichletBC <: BoundaryConditionType end
139 export NeumannBC 157 export NeumannBC
151 closure = tau∘d 169 closure = tau∘d
152 # TODO: Return penalty once we have implemented scalar scaling of the operators. 170 # TODO: Return penalty once we have implemented scalar scaling of the operators.
153 return closure 171 return closure
154 end 172 end
155 173
156 function dirichlet_bc(L::Laplace, id::BoundaryIdentifier)
157 error("Not implemented")
158 # H_inv = inverse_inner_product(L)
159 # e = boundary_restriction(L,id)
160 # d = normal_derivative(L,id)
161 # H_b = boundary_quadrature(L,id)
162 # gamma = borrowing_parameter(L)
163 # tuning = 1.2
164 # S = ScalingOperator(tuning * -1.0/gamma)
165 # tau = H_inv∘(S∘e' + d')∘H_b
166 # closure = tau∘e
167 # penalty = ScalingOperator(-1)∘tau
168 # return (closure, penalty)
169 end
170
171 # function borrowing_parameter(L)
172 # if L.order == 2
173 # return 0.4
174 # elseif L.order == 4
175 # return 0.2508
176 # elseif L.order == 6
177 # return 0.1878
178 # elseif L.order == 8
179 # return 0.0015
180 # elseif L.order == 10
181 # return 0.0351
182 # end
183 # end
184
185 """ 174 """
186 laplace(grid, inner_stencil, closure_stencils) 175 laplace(grid::EquidistantGrid{Dim}, inner_stencil, closure_stencils)
187 176
188 Creates the Laplace operator operator `Δ` as a `TensorMapping` 177 Creates the Laplace operator operator `Δ` as a `TensorMapping`
189 178
190 `Δ` approximates the Laplace operator ∑d²/xᵢ² , i = 1,...,N on the N-dimensional 179 `Δ` approximates the Laplace operator ∑d²/xᵢ² , i = 1,...,`Dim` on `grid`, using
191 `grid`, using the stencil `inner_stencil` in the interior and a set of stencils 180 the stencil `inner_stencil` in the interior and a set of stencils `closure_stencils`
192 `closure_stencils` for the points in the closure regions. 181 for the points in the closure regions.
193 182
194 On a one-dimensional `grid`, `Δ` is equivalent to `second_derivative`. On a 183 On a one-dimensional `grid`, `Δ` is equivalent to `second_derivative`. On a
195 multi-dimensional `grid`, `Δ` is the sum of multi-dimensional `second_derivative`s 184 multi-dimensional `grid`, `Δ` is the sum of multi-dimensional `second_derivative`s
196 where the sum is carried out lazily. 185 where the sum is carried out lazily.
197 """ 186 """
198 function laplace(grid::AbstractGrid, inner_stencil, closure_stencils) 187 function laplace(grid::EquidistantGrid, inner_stencil, closure_stencils)
199 Δ = second_derivative(grid, inner_stencil, closure_stencils, 1) 188 Δ = second_derivative(grid, inner_stencil, closure_stencils, 1)
200 for d = 2:dimension(grid) 189 for d = 2:dimension(grid)
201 Δ += second_derivative(grid, inner_stencil, closure_stencils, d) 190 Δ += second_derivative(grid, inner_stencil, closure_stencils, d)
202 end 191 end
203 return Δ 192 return Δ
204 end 193 end
205 export laplace