Mercurial > repos > public > sbplib_julia
view src/SbpOperators/volumeops/laplace/laplace.jl @ 873:9929c99754fb laplace_benchmarks
Add some benchmarks using the Laplace Operator Set
author | Vidar Stiernström <vidar.stiernstrom@it.uu.se> |
---|---|
date | Wed, 19 Jan 2022 13:15:45 +0100 |
parents | 1970ebceabe4 |
children | 067a322e4f73 |
line wrap: on
line source
""" Laplace{T, Dim, TMdiffop} <: TensorMapping{T,Dim,Dim} Laplace(grid::AbstractGrid, fn; order) Implements the Laplace operator, approximating ∑d²/xᵢ² , i = 1,...,`Dim` as a `TensorMapping`. Additionally, `Laplace` stores the inner product and boundary operators relevant for constructing a SBP finite difference scheme as `TensorMapping`s. Laplace(grid, fn; order) creates the Laplace operator defined on `grid`, where the operators are read from TOML. The differential operator is created using `laplace(grid::AbstractGrid,...)`. Note that all properties of Laplace, excluding the Differential operator `D`, are abstract types. For performance reasons, they should therefore be accessed via the provided getter functions (e.g `inner_product(::Laplace)`). """ struct Laplace{T, Dim, TMdiffop<:TensorMapping{T,Dim,Dim}} <: TensorMapping{T,Dim,Dim} D::TMdiffop # Differential operator H::TensorMapping # Inner product operator H_inv::TensorMapping # Inverse inner product operator e::StaticDict{<:BoundaryIdentifier,<:TensorMapping} # Boundary restriction operators. d::StaticDict{<:BoundaryIdentifier,<:TensorMapping} # Normal derivative operators H_boundary::StaticDict{<:BoundaryIdentifier,<:TensorMapping} # Boundary quadrature operators # TODO: Boundary inner product? order::Int end export Laplace function Laplace(grid::AbstractGrid, fn; order) # TODO: Removed once we can construct the volume and # boundary operators by op(grid, fn; order,...). # Read stencils op = read_D2_operator(fn; order) D_inner_stecil = op.innerStencil D_closure_stencils = op.closureStencils H_closure_stencils = op.quadratureClosure e_closure_stencil = op.eClosure d_closure_stencil = op.dClosure # Volume operators Δ = laplace(grid, D_inner_stecil, D_closure_stencils) H = inner_product(grid, H_closure_stencils) H⁻¹ = inverse_inner_product(grid, H_closure_stencils) # Boundary operator - id pairs ids = boundary_identifiers(grid) n_ids = length(ids) e_pairs = ntuple(i -> ids[i] => boundary_restriction(grid,e_closure_stencil,ids[i]),n_ids) d_pairs = ntuple(i -> ids[i] => normal_derivative(grid,d_closure_stencil,ids[i]),n_ids) Hᵧ_pairs = ntuple(i -> ids[i] => inner_product(boundary_grid(grid,ids[i]),H_closure_stencils),n_ids) return Laplace(Δ, H, H⁻¹, StaticDict(e_pairs), StaticDict(d_pairs), StaticDict(Hᵧ_pairs), order) end # TODO: Consider pretty printing of the following form # 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, ")") LazyTensors.range_size(L::Laplace) = LazyTensors.range_size(L.D) LazyTensors.domain_size(L::Laplace) = LazyTensors.domain_size(L.D) LazyTensors.apply(L::Laplace, v::AbstractArray, I...) = LazyTensors.apply(L.D,v,I...) """ closure_size(L::Lapalace) Returns the inner product operator associated with `L` """ closure_size(L::Laplace) = closure_size(L.D) export closure_size """ inner_product(L::Lapalace) Returns the inner product operator associated with `L` """ inner_product(L::Laplace) = L.H export inner_product """ inverse_inner_product(L::Lapalace) Returns the inverse of the inner product operator associated with `L` """ inverse_inner_product(L::Laplace) = L.H_inv export inverse_inner_product """ boundary_restriction(L::Lapalace,id::BoundaryIdentifier) boundary_restriction(L::Lapalace,ids::NTuple{N,BoundaryIdentifier}) boundary_restriction(L::Lapalace,ids...) Returns boundary restriction operator(s) associated with `L` for the boundary(s) identified by id(s). """ boundary_restriction(L::Laplace,id::BoundaryIdentifier) = L.e[id] boundary_restriction(L::Laplace,ids::NTuple{N,BoundaryIdentifier}) where N = ntuple(i->L.e[ids[i]],N) boundary_restriction(L::Laplace,ids::Vararg{BoundaryIdentifier,N}) where N = ntuple(i->L.e[ids[i]],N) export boundary_restriction """ normal_derivative(L::Lapalace,id::BoundaryIdentifier) normal_derivative(L::Lapalace,ids::NTuple{N,BoundaryIdentifier}) normal_derivative(L::Lapalace,ids...) Returns normal derivative operator(s) associated with `L` for the boundary(s) identified by id(s). """ normal_derivative(L::Laplace,id::BoundaryIdentifier) = L.d[id] normal_derivative(L::Laplace,ids::NTuple{N,BoundaryIdentifier}) where N = ntuple(i->L.d[ids[i]],N) normal_derivative(L::Laplace,ids::Vararg{BoundaryIdentifier,N}) where N = ntuple(i->L.d[ids[i]],N) export normal_derivative # TODO: boundary_inner_product? """ boundary_quadrature(L::Lapalace,id::BoundaryIdentifier) boundary_quadrature(L::Lapalace,ids::NTuple{N,BoundaryIdentifier}) boundary_quadrature(L::Lapalace,ids...) Returns boundary quadrature operator(s) associated with `L` for the boundary(s) identified by id(s). """ boundary_quadrature(L::Laplace,id::BoundaryIdentifier) = L.H_boundary[id] boundary_quadrature(L::Laplace,ids::NTuple{N,BoundaryIdentifier}) where N = ntuple(i->L.H_boundary[ids[i]],N) boundary_quadrature(L::Laplace,ids::Vararg{BoundaryIdentifier,N}) where N = ntuple(i->L.H_boundary[ids[i]],N) export boundary_quadrature abstract type BoundaryConditionType end struct NeumannBC <: BoundaryConditionType end struct DirichletBC <: BoundaryConditionType end export NeumannBC boundary_condition(L, id, ::NeumannBC) = neumann_bc(L, id) boundary_condition(L, id, ::DirichletBC) = dirichlet_bc(L, id) export boundary_condition function neumann_bc(L::Laplace, id::BoundaryIdentifier) H_inv = inverse_inner_product(L) e = boundary_restriction(L,id) d = normal_derivative(L,id) H_b = boundary_quadrature(L,id) tau = H_inv∘e'∘H_b closure = tau∘d # TODO: Return penalty once we have implemented scalar scaling of the operators. return closure end function dirichlet_bc(L::Laplace, id::BoundaryIdentifier) error("Not implemented") # H_inv = inverse_inner_product(L) # e = boundary_restriction(L,id) # d = normal_derivative(L,id) # H_b = boundary_quadrature(L,id) # gamma = borrowing_parameter(L) # tuning = 1.2 # S = ScalingOperator(tuning * -1.0/gamma) # tau = H_inv∘(S∘e' + d')∘H_b # closure = tau∘e # penalty = ScalingOperator(-1)∘tau # return (closure, penalty) end # function borrowing_parameter(L) # if L.order == 2 # return 0.4 # elseif L.order == 4 # return 0.2508 # elseif L.order == 6 # return 0.1878 # elseif L.order == 8 # return 0.0015 # elseif L.order == 10 # return 0.0351 # end # end """ laplace(grid, inner_stencil, closure_stencils) Creates the Laplace operator operator `Δ` as a `TensorMapping` `Δ` approximates the Laplace operator ∑d²/xᵢ² , i = 1,...,N on the N-dimensional `grid`, using the stencil `inner_stencil` in the interior and a set of stencils `closure_stencils` for the points in the closure regions. On a one-dimensional `grid`, `Δ` is equivalent to `second_derivative`. On a multi-dimensional `grid`, `Δ` is the sum of multi-dimensional `second_derivative`s where the sum is carried out lazily. """ function laplace(grid::AbstractGrid, inner_stencil, closure_stencils) Δ = second_derivative(grid, inner_stencil, closure_stencils, 1) for d = 2:dimension(grid) Δ += second_derivative(grid, inner_stencil, closure_stencils, d) end return Δ end export laplace