Mercurial > repos > public > sbplib_julia
changeset 1163:c9fdfb1efba8 feature/boundary_conditions
Merge with default
author | Vidar Stiernström <vidar.stiernstrom@it.uu.se> |
---|---|
date | Wed, 12 Oct 2022 10:45:47 +0200 |
parents | 6757cc9ba22e (diff) 0aa8ce9f30e2 (current diff) |
children | d26aef8a5987 |
files | |
diffstat | 8 files changed, 181 insertions(+), 0 deletions(-) [+] |
line wrap: on
line diff
--- a/Notes.md Wed Oct 12 10:44:44 2022 +0200 +++ b/Notes.md Wed Oct 12 10:45:47 2022 +0200 @@ -1,5 +1,23 @@ # Notes +## Boundary Conditions and SATs + +Types for boundary conditions: + + * abstract type `BoundaryDataType` + * abstract type `BoundaryCondition{T<:BoundaryDataType}` + * concrete types `ConstantBoundaryData <: BoundaryDataType` and similar + * concrete types `NeumannCondition{BDT<:BoundaryDataType} <: BoundaryCondition{BDT}` and similar +The concrete `BoundaryDataType` subtypes are "thin types" wrapping the boundary data, and are used to indicate how the boundary data should be used in e.g. sat routines. The concrete `BoundaryCondition{BDT}` subtypes are used for assembling the tensors used to construct e.g. a SAT. + +SAT methods: +There are multiple options for what the SAT methods could return. +* (Current) a function which returns a `LazyTensorApplication`, e.g. `f = sat(grid,op,bc)`. The the resulting `LazyTensorApplication` can then be added to scheme i.e. `scheme = op*u + f(u)`. This is how one typically would write the SAT in the litterature. Depdending on the type of data in the BC, e.g. time-depdendent etc one can return f(u,t). +* `LazyTensor`s `closure, penalty = sat(grid,op,bc)` like in the matlab version. Probably the most general one. Up to the user to make use of the returned `LazyTensor`s. One can for example then easily include the closures to the operator and have eg. `D = (op + closure)*u`. +* A `LazyTensor` for closure, and a `LazyArray` for `penalty*data`. Mix of the above. + +It is not clear if any of these are preferable as it currently stands. + ## Reading operators Jonatan's suggestion is to add methods to `Laplace`, `SecondDerivative` and
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/BoundaryConditions/BoundaryConditions.jl Wed Oct 12 10:45:47 2022 +0200 @@ -0,0 +1,24 @@ +module BoundaryConditions + +export BoundaryDataType +export ConstantBoundaryData +export SpaceDependentBoundaryData +export TimeDependentBoundaryData +export SpaceDependentBoundaryData + +export BoundaryCondition +export NeumannCondition +export DirichletCondition +export RobinCondition + +export data +export sat +export sat_tensors + +using Sbplib.Grids +using Sbplib.LazyTensors + +include("boundary_condition.jl") +include("sat.jl") + +end # module
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/BoundaryConditions/boundary_condition.jl Wed Oct 12 10:45:47 2022 +0200 @@ -0,0 +1,52 @@ +""" + BoundaryDataType + +A type for storing boundary data, e.g. constant, space-dependent, time-dependent etc. +Subtypes of `BoundaryDataType` should store the boundary data in a field `val`, i.e. +`struct MyBoundaryDataType{T} <: BoundaryDataType val::T end`. +""" +abstract type BoundaryDataType end + +struct ConstantBoundaryData{T} <: BoundaryDataType + val::T +end + +struct SpaceDependentBoundaryData{T} <: BoundaryDataType + val::T +end + +struct TimeDependentBoundaryData{T} <: BoundaryDataType + val::T +end + +struct SpaceTimeDependentBoundaryData{T} <: BoundaryDataType + val::T +end + +""" + BoundaryCondition + +A type for implementing data needed in order to impose a boundary condition. +Subtypes refer to perticular types of boundary conditions, e.g. Neumann conditions. +""" +# TODO: Parametrize the boundary id as well? +abstract type BoundaryCondition{T<:BoundaryDataType} end + +data(bc::BoundaryCondition) = bc.data.val + +struct NeumannCondition{BDT<:BoundaryDataType} <: BoundaryCondition{BDT} + id::BoundaryIdentifier + data::BDT +end + +struct DirichletCondition{BDT<:BoundaryDataType} <: BoundaryCondition{BDT} + id::BoundaryIdentifier + data::BDT +end + +struct RobinCondition{BDT<:BoundaryDataType,T<:Real} <: BoundaryCondition{BDT} + id::BoundaryIdentifier + data::BDT + α::T + β::T +end \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/BoundaryConditions/sat.jl Wed Oct 12 10:45:47 2022 +0200 @@ -0,0 +1,62 @@ +""" + sat_tensors(op, grid, bc::BoundaryCondition{T}, params...) + +Returns the `LazyTensor`s used to construct a SAT for the SBP operator `op` on +`grid` associated with the boundary condition `bc`. +""" +function sat_tensors end + +""" + sat(op, grid, bc::BoundaryCondition{ConstantBoundaryData{T}}, params...) + +Simultaneous-Approximation-Term for constant boundary data. f = sat(op, grid, bc) returns +an anonymous function, such that f(u) is a `LazyTensorApplication` weakly imposing the BC. +""" +function sat(op, grid, bc::BoundaryCondition{ConstantBoundaryData{T}}, params...) where T + closure, penalty = sat_tensors(op, grid, bc, params...) + b_sz = size(boundary_grid(grid, bc.id)) + g = fill(data(bc), b_sz) + if iszero(g) + return u -> closure(u) + else + return u -> closure(u) + penalty(g) + end +end + +""" + sat(op, grid, bc::BoundaryCondition{SpaceDependentBoundaryData{T}}, params...) + +Simultaneous-Approximation-Term for space-dependent boundary data. f = sat(op, grid, bc) returns +an anonymous function, such that f(u) is a `LazyTensorApplication` weakly imposing the BC. +""" +function sat(op, grid, bc::BoundaryCondition{SpaceDependentBoundaryData{T}}, params...) where T + closure, penalty = sat_tensors(op, grid, bc, params...) + g = data(bc) + return u -> closure(u) + penalty(g) +end + +""" + sat(op, grid, bc::BoundaryCondition{SpaceDependentBoundaryData{T}}, params...) + +Simultaneous-Approximation-Term for time-dependent boundary data. f = sat(op, grid, bc) returns +an anonymous function, such that f(u,t) is a `LazyTensorApplication` weakly imposing the BC at time t. +""" +function sat(op, grid, bc::BoundaryCondition{TimeDependentBoundaryData{T}}, params...) where T + closure, penalty = sat_tensors(op, grid, bc, params...) + b_sz = size(boundary_grid(grid, bc.id)) + b_vec = ones(eltype(grid), b_sz) + g = data(bc) + return (u,t) -> closure(u) + g(t)*penalty(b_vec) +end + +""" + sat(op, grid, bc::BoundaryCondition{SpaceDependentBoundaryData{T}}, params...) + +Simultaneous-Approximation-Term for space-time-dependent boundary data. f = sat(op, grid, bc) returns +an anonymous function, such that f(u,t) is a `LazyTensorApplication` weakly imposing the BC at time t. +""" +function sat(op, grid, bc::BoundaryCondition{SpaceTimeDependentBoundaryData{T}}, params...) where T + closure, penalty = sat_tensors(op, grid, bc, params...) + g = data(bc) + return (u,t) -> closure(u) + penalty(g(t)) +end \ No newline at end of file
--- a/src/LazyTensors/lazy_tensor_operations.jl Wed Oct 12 10:44:44 2022 +0200 +++ b/src/LazyTensors/lazy_tensor_operations.jl Wed Oct 12 10:45:47 2022 +0200 @@ -121,6 +121,7 @@ Base.:*(a::T, tm::LazyTensor{T}) where T = TensorComposition(ScalingTensor{T,range_dim(tm)}(a,range_size(tm)), tm) Base.:*(tm::LazyTensor{T}, a::T) where T = a*tm +Base.:-(tm::LazyTensor{T}) where T = (-one(T))*tm """ InflatedTensor{T,R,D} <: LazyTensor{T,R,D}
--- a/src/SbpOperators/SbpOperators.jl Wed Oct 12 10:44:44 2022 +0200 +++ b/src/SbpOperators/SbpOperators.jl Wed Oct 12 10:45:47 2022 +0200 @@ -23,6 +23,7 @@ using Sbplib.RegionIndices using Sbplib.LazyTensors using Sbplib.Grids +using Sbplib.BoundaryConditions @enum Parity begin odd = -1
--- a/src/SbpOperators/volumeops/laplace/laplace.jl Wed Oct 12 10:44:44 2022 +0200 +++ b/src/SbpOperators/volumeops/laplace/laplace.jl Wed Oct 12 10:45:47 2022 +0200 @@ -53,3 +53,24 @@ end return Δ end + +""" + sat_tensors(Δ::Laplace, g::EquidistantGrid, bc::NeumannCondition) + +Returns anonymous functions for construction the `LazyTensorApplication`s +recuired in order to impose a Neumann boundary condition. + +See also: [`sat`,`NeumannCondition`](@ref). +""" +function BoundaryConditions.sat_tensors(Δ::Laplace, g::EquidistantGrid, bc::NeumannCondition) + id = bc.id + set = Δ.stencil_set + H⁻¹ = inverse_inner_product(g,set) + Hᵧ = inner_product(boundary_grid(g, id), set) + e = boundary_restriction(g, set, id) + d = normal_derivative(g, set, id) + + closure(u) = H⁻¹*e'*Hᵧ*d*u + penalty(g) = -H⁻¹*e'*Hᵧ*g + return closure, penalty +end
--- a/src/Sbplib.jl Wed Oct 12 10:44:44 2022 +0200 +++ b/src/Sbplib.jl Wed Oct 12 10:45:47 2022 +0200 @@ -4,6 +4,7 @@ include("RegionIndices/RegionIndices.jl") include("LazyTensors/LazyTensors.jl") include("Grids/Grids.jl") +include("BoundaryConditions/BoundaryConditions.jl") include("SbpOperators/SbpOperators.jl") include("DiffOps/DiffOps.jl") @@ -12,5 +13,6 @@ export Grids export SbpOperators export DiffOps +export BoundaryConditions end