comparison src/SbpOperators/volumeops/laplace/laplace.jl @ 924:12e8e431b43c feature/laplace_opset

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