Mercurial > repos > public > sbplib_julia
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 |
