changeset 1614:13063028d604 feature/boundary_conditions

Merge heads
author Vidar Stiernström <vidar.stiernstrom@gmail.com>
date Sun, 09 Jun 2024 16:53:03 -0700
parents 15488c889a50 (diff) df1856b0e2f0 (current diff)
children b74e1a21265f
files
diffstat 6 files changed, 22 insertions(+), 68 deletions(-) [+]
line wrap: on
line diff
--- a/Notes.md	Sun Jun 09 23:03:04 2024 +0200
+++ b/Notes.md	Sun Jun 09 16:53:03 2024 -0700
@@ -1,23 +1,5 @@
 # Notes
 
-## Boundary Conditions and SATs
-
-Types for boundary conditions:
-
- * abstract type `BoundaryData`
- * abstract type `BoundaryCondition{T<:BoundaryData}`
- * concrete types `ConstantBoundaryData <: BoundaryData` and similar
- * concrete types `NeumannCondition{BD<:BoundaryData} <: BoundaryCondition{BD}` and similar
-The concrete `BoundaryData` 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{BD}` 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)`.  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.
-* Same as first but of  the  form sat = `sat_op*(L*u-g)`. This is how one typically would write the SAT in the litterature. The function `sat_tensors` would return `sat_op` and `L`. Need to get compositions working before we can implement this approach.
-
-
 ## Reading operators
 
 Jonatan's suggestion is to add methods to `Laplace`, `SecondDerivative` and
--- a/src/SbpOperators/SbpOperators.jl	Sun Jun 09 23:03:04 2024 +0200
+++ b/src/SbpOperators/SbpOperators.jl	Sun Jun 09 16:53:03 2024 -0700
@@ -8,11 +8,9 @@
 export parse_nested_stencil
 export parse_scalar
 export parse_tuple
-export parse_named_tuple
 export sbp_operators_path
 
 # Operators
-export boundary_quadrature
 export boundary_restriction
 export inner_product
 export inverse_inner_product
--- a/src/SbpOperators/stencil_set.jl	Sun Jun 09 23:03:04 2024 +0200
+++ b/src/SbpOperators/stencil_set.jl	Sun Jun 09 16:53:03 2024 -0700
@@ -166,17 +166,6 @@
     return Tuple(parse_scalar.(parsed_toml))
 end
 
-"""
-    parse_named_tuple(parsed_toml)
-
-Parse the keys (names) and values (scalars) into a named tuple of rationals.
-
-See also [`parse_scalar`](@ref).
-"""
-function parse_named_tuple(parsed_toml)
-    NamedTuple(Symbol(key) => parse_scalar(val) for (key, val) in parsed_toml)
-end
-
 
 """
     parse_rational(parsed_toml)
--- a/src/SbpOperators/volumeops/laplace/laplace.jl	Sun Jun 09 23:03:04 2024 +0200
+++ b/src/SbpOperators/volumeops/laplace/laplace.jl	Sun Jun 09 16:53:03 2024 -0700
@@ -62,14 +62,14 @@
 
 See also: [`sat`,`DirichletCondition`, `positivity_decomposition`](@ref).
 """
-function sat_tensors(Δ::Laplace, g::Grid, bc::DirichletCondition; tuning = (1., 1.))
+function sat_tensors(Δ::Laplace, g::Grid, bc::DirichletCondition; H_tuning = 1., R_tuning = 1.)
     id = boundary(bc)
     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)
-    B = positivity_decomposition(Δ, g, bc, tuning)
+    B = positivity_decomposition(Δ, g, bc; H_tuning, R_tuning)
     penalty_tensor = H⁻¹∘(d' - B*e')∘Hᵧ
     return penalty_tensor, e
 end
@@ -94,33 +94,26 @@
     return penalty_tensor, d
 end
 
-# TODO: We should consider implementing a proper BoundaryIdentifier for EquidistantGrid and then
-# change bc::BoundaryCondition to id::BoundaryIdentifier
 
-function positivity_decomposition(Δ::Laplace, g::EquidistantGrid, bc::BoundaryCondition, tuning)
-    pos_prop = positivity_properties(Δ)
-    h = spacing(g)
-    θ_H = pos_prop.theta_H
-    τ_H = tuning[1]*ndims(g)/(h*θ_H)
-    θ_R = pos_prop.theta_R
-    τ_R = tuning[2]/(h*θ_R)
-    B = τ_H + τ_R
-    return B
+function positivity_decomposition(Δ::Laplace, g::Grid, bc::DirichletCondition; H_tuning, R_tuning)
+    Nτ_H, τ_R = positivity_limits(Δ,g,bc)
+    return H_tuning*Nτ_H + R_tuning*τ_R
 end
 
-function positivity_decomposition(Δ::Laplace, g::TensorGrid, bc::BoundaryCondition, tuning)
-    pos_prop = positivity_properties(Δ)
-    h = spacing(g.grids[grid_id(boundary(bc))]) # grid spacing of the 1D grid normal to the boundary
-    θ_H = pos_prop.theta_H
-    τ_H = tuning[1]*ndims(g)/(h*θ_H)
-    θ_R = pos_prop.theta_R
-    τ_R = tuning[2]/(h*θ_R)
-    B = τ_H + τ_R
-    return B
+
+# TODO: We should consider implementing a proper BoundaryIdentifier for EquidistantGrid and then
+# change bc::BoundaryCondition to id::BoundaryIdentifier
+function positivity_limits(Δ::Laplace, g::EquidistantGrid, bc::DirichletCondition)
+    h = spacing(g)
+    θ_H = parse_scalar(Δ.stencil_set["H"]["closure"][1])
+    θ_R = parse_scalar(Δ.stencil_set["D2"]["positivity"]["theta_R"])
+
+    τ_H = 1/(h*θ_H)
+    τ_R = 1/(h*θ_R)
+    return τ_H, τ_R
 end
 
-function positivity_properties(Δ::Laplace)
-    D2_pos_prop = parse_named_tuple(Δ.stencil_set["D2"]["positivity"])
-    H_closure = parse_tuple(Δ.stencil_set["H"]["closure"])
-    return merge(D2_pos_prop, (theta_H = H_closure[1],))
+function positivity_limits(Δ::Laplace, g::TensorGrid, bc::DirichletCondition)
+    τ_H, τ_R = positivity_limits(Δ, g.grids[grid_id(boundary(bc))], bc)
+    return τ_H*ndims(g), τ_R
 end
--- a/test/SbpOperators/stencil_set_test.jl	Sun Jun 09 23:03:04 2024 +0200
+++ b/test/SbpOperators/stencil_set_test.jl	Sun Jun 09 16:53:03 2024 -0700
@@ -152,14 +152,6 @@
         @test_throws ArgumentError parse_tuple(toml["e3"])
         @test_throws ArgumentError parse_tuple(toml["e4"])
     end
-
-    @testset "parse_named_tuple" begin
-        toml = TOML.parse("""
-            NamedTuple = {a = "17/48", b = "0.2505765857"}
-        """)
-        @test parse_named_tuple(toml["NamedTuple"]) == (b = Rational(0.2505765857), a = 17//48)
-    end
-
 end
 
 @testset "parse_rational" begin
--- a/test/SbpOperators/volumeops/laplace/laplace_test.jl	Sun Jun 09 23:03:04 2024 +0200
+++ b/test/SbpOperators/volumeops/laplace/laplace_test.jl	Sun Jun 09 16:53:03 2024 -0700
@@ -129,11 +129,11 @@
                 H = inner_product(g, stencil_set)
                 u = collect(eval_on(g, (x,y) -> cos(π*x)cos(2*π*y)))
                 Δu = collect(eval_on(g, (x,y) -> -5*π^2*cos(π*x)cos(2*π*y)))
-                op = Δ 
+                D = Δ 
                 for id ∈ boundary_identifiers(g)
-                    op = op + foldl(∘, sat_tensors(Δ, g, NeumannCondition(0., id)))
+                    D = D + foldl(∘, sat_tensors(Δ, g, NeumannCondition(0., id)))
                 end
-                e = op*u .- Δu
+                e = D*u .- Δu
                 # Accuracy
                 @test sqrt(sum(H*e.^2)) ≈ 0 atol = tol
                 # Symmetry