Skip to content

Commit 1f47ee0

Browse files
tomchorjagoosw
andauthored
Small improvements to PerturbationAdvectionOpenBoundaryCondition interface (#4394)
* move docstring ti user-faacing method * add docstring * guard agaisnt infinity for backward step * remove extra lines * use ifelse function * Update perturbation_advection_open_boundary_matching_scheme.jl * Update perturbation_advection_open_boundary_matching_scheme.jl * remove forward step * don't hardcode float type * move intuitive testing * avoid calculations inside ifelse statements * typo andf clarification * import defaults first * bugfix --------- Co-authored-by: Jago Strong-Wright <[email protected]>
1 parent 55b1170 commit 1f47ee0

File tree

2 files changed

+34
-71
lines changed

2 files changed

+34
-71
lines changed

src/BoundaryConditions/perturbation_advection_open_boundary_matching_scheme.jl

+32-69
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using Oceananigans.Operators: Δxᶠᶜᶜ, Δyᶜᶠᶜ, Δzᶜᶜᶠ, Ax_qᶠᶜᶜ, Ay_qᶜᶠᶜ, Az_qᶜᶜᶠ
2+
using Oceananigans: defaults
23

34
"""
45
PerturbationAdvection
@@ -30,24 +31,41 @@ where Ũ = U Δt / Δx, then uⁿ⁺¹ is:
3031
where τ̃ = Δt/τ.
3132
3233
The same operation can be repeated for left boundaries.
34+
35+
The relaxation timescale ``τ`` can be set to different values depending on whether the
36+
``U`` points in or out of the domain (`inflow_timescale`/`outflow_timescale`). Since the
37+
scheme is only valid when the flow is directed out of the domain the boundary condition
38+
falls back to relaxation to the prescribed value. By default this happens instantly but
39+
if the direction varies this may not be preferable. It is beneficial to relax the outflow
40+
(i.e. non-zero `outflow_timescale`) to reduce the shock when the flow changes direction
41+
to point into the domain.
42+
43+
The ideal value of the timescales probably depend on the grid spacing and details of the
44+
boundary flow.
3345
"""
34-
struct PerturbationAdvection{VT, FT}
35-
backward_step :: VT
46+
struct PerturbationAdvection{FT}
3647
inflow_timescale :: FT
3748
outflow_timescale :: FT
3849
end
3950

4051
Adapt.adapt_structure(to, pe::PerturbationAdvection) =
41-
PerturbationAdvection(adapt(to, pe.backward_step),
42-
adapt(to, pe.inflow_timescale),
52+
PerturbationAdvection(adapt(to, pe.inflow_timescale),
4353
adapt(to, pe.outflow_timescale))
4454

45-
function PerturbationAdvectionOpenBoundaryCondition(val, FT = Float64;
46-
backward_step = true,
55+
"""
56+
PerturbationAdvectionOpenBoundaryCondition(val, FT = defaults.FloatType;
57+
outflow_timescale = Inf,
58+
inflow_timescale = 0, kwargs...)
59+
60+
Creates a `PerturbationAdvectionOpenBoundaryCondition` with a given exterior value `val`, to which
61+
the flow is forced with an `outflow_timescale` for outflow and `inflow_timescale` for inflow. For
62+
details about this method, refer to the docstring for `PerturbationAdvection`.
63+
"""
64+
function PerturbationAdvectionOpenBoundaryCondition(val, FT = defaults.FloatType;
4765
outflow_timescale = Inf,
48-
inflow_timescale = 300.0, kwargs...)
66+
inflow_timescale = 0, kwargs...)
4967

50-
classification = Open(PerturbationAdvection(Val(backward_step), inflow_timescale, outflow_timescale))
68+
classification = Open(PerturbationAdvection(inflow_timescale, outflow_timescale))
5169

5270
@warn "`PerturbationAdvection` open boundaries matching scheme is experimental and un-tested/validated"
5371

@@ -56,100 +74,45 @@ end
5674

5775
const PAOBC = BoundaryCondition{<:Open{<:PerturbationAdvection}}
5876

59-
const BPAOBC = BoundaryCondition{<:Open{<:PerturbationAdvection{Val{true}}}}
60-
const FPAOBC = BoundaryCondition{<:Open{<:PerturbationAdvection{Val{false}}}}
61-
62-
@inline function step_right_boundary!(bc::BPAOBC, l, m, boundary_indices, boundary_adjacent_indices,
77+
@inline function step_right_boundary!(bc::PAOBC, l, m, boundary_indices, boundary_adjacent_indices,
6378
grid, u, clock, model_fields, ΔX)
6479
Δt = clock.last_stage_Δt
65-
6680
Δt = ifelse(isinf(Δt), 0, Δt)
6781

6882
ūⁿ⁺¹ = getbc(bc, l, m, grid, clock, model_fields)
69-
7083
uᵢⁿ = @inbounds getindex(u, boundary_indices...)
7184
uᵢ₋₁ⁿ⁺¹ = @inbounds getindex(u, boundary_adjacent_indices...)
72-
7385
U = max(0, min(1, Δt / ΔX * ūⁿ⁺¹))
7486

7587
pa = bc.classification.matching_scheme
76-
7788
τ = ifelse(ūⁿ⁺¹ >= 0, pa.outflow_timescale, pa.inflow_timescale)
78-
7989
τ̃ = Δt / τ
8090

81-
uᵢⁿ⁺¹ = (uᵢⁿ + U * uᵢ₋₁ⁿ⁺¹ + ūⁿ⁺¹ * τ̃) / (1 + τ̃ + U)
91+
relaxed_uᵢⁿ⁺¹ = (uᵢⁿ + U * uᵢ₋₁ⁿ⁺¹ + ūⁿ⁺¹ * τ̃) / (1 + τ̃ + U)
92+
uᵢⁿ⁺¹ = ifelse== 0, ūⁿ⁺¹, relaxed_uᵢⁿ⁺¹)
8293

8394
@inbounds setindex!(u, uᵢⁿ⁺¹, boundary_indices...)
8495

8596
return nothing
8697
end
8798

88-
@inline function step_left_boundary!(bc::BPAOBC, l, m, boundary_indices, boundary_adjacent_indices, boundary_secret_storage_indices,
99+
@inline function step_left_boundary!(bc::PAOBC, l, m, boundary_indices, boundary_adjacent_indices, boundary_secret_storage_indices,
89100
grid, u, clock, model_fields, ΔX)
90101
Δt = clock.last_stage_Δt
91-
92102
Δt = ifelse(isinf(Δt), 0, Δt)
93103

94104
ūⁿ⁺¹ = getbc(bc, l, m, grid, clock, model_fields)
95-
96105
uᵢⁿ = @inbounds getindex(u, boundary_secret_storage_indices...)
97106
uᵢ₋₁ⁿ⁺¹ = @inbounds getindex(u, boundary_adjacent_indices...)
98-
99107
U = min(0, max(-1, Δt / ΔX * ūⁿ⁺¹))
100108

101109
pa = bc.classification.matching_scheme
102-
103110
τ = ifelse(ūⁿ⁺¹ <= 0, pa.outflow_timescale, pa.inflow_timescale)
104-
105-
τ̃ = Δt / τ
106-
107-
u₁ⁿ⁺¹ = (uᵢⁿ - U * uᵢ₋₁ⁿ⁺¹ + ūⁿ⁺¹ * τ̃) / (1 + τ̃ - U)
108-
109-
@inbounds setindex!(u, u₁ⁿ⁺¹, boundary_indices...)
110-
@inbounds setindex!(u, u₁ⁿ⁺¹, boundary_secret_storage_indices...)
111-
112-
return nothing
113-
end
114-
115-
116-
@inline function step_right_boundary!(bc::FPAOBC, l, m, boundary_indices, boundary_adjacent_indices,
117-
grid, u, clock, model_fields, ΔX)
118-
Δt = clock.last_stage_Δt
119-
Δt = ifelse(isinf(Δt), 0, Δt)
120-
121-
ūⁿ⁺¹ = getbc(bc, l, m, grid, clock, model_fields)
122-
uᵢⁿ = @inbounds getindex(u, boundary_indices...)
123-
uᵢ₋₁ⁿ⁺¹ = @inbounds getindex(u, boundary_adjacent_indices...)
124-
125-
U = max(0, min(1, Δt / ΔX * ūⁿ⁺¹))
126-
pa = bc.classification.matching_scheme
127-
128-
τ = ifelse(ūⁿ⁺¹ >= 0, pa.outflow_timescale, pa.inflow_timescale)
129111
τ̃ = Δt / τ
130112

131-
uᵢⁿ⁺¹ = uᵢⁿ + U * (uᵢ₋₁ⁿ⁺¹ - ūⁿ⁺¹) + (ūⁿ⁺¹ - uᵢⁿ) * τ̃
132-
@inbounds setindex!(u, uᵢⁿ⁺¹, boundary_indices...)
133-
134-
return nothing
135-
end
136-
137-
@inline function step_left_boundary!(bc::FPAOBC, l, m, boundary_indices, boundary_adjacent_indices, boundary_secret_storage_indices,
138-
grid, u, clock, model_fields, ΔX)
139-
Δt = clock.last_stage_Δt
140-
Δt = ifelse(isinf(Δt), 0, Δt)
141-
142-
ūⁿ⁺¹ = getbc(bc, l, m, grid, clock, model_fields)
143-
uᵢⁿ = @inbounds getindex(u, boundary_secret_storage_indices...)
144-
uᵢ₋₁ⁿ⁺¹ = @inbounds getindex(u, boundary_adjacent_indices...)
145-
146-
U = min(0, max(-1, Δt / ΔX * ūⁿ⁺¹))
147-
pa = bc.classification.matching_scheme
148-
149-
τ = ifelse(ūⁿ⁺¹ <= 0, pa.outflow_timescale, pa.inflow_timescale)
150-
τ̃ = Δt / τ
113+
relaxed_u₁ⁿ⁺¹ = (uᵢⁿ - U * uᵢ₋₁ⁿ⁺¹ + ūⁿ⁺¹ * τ̃) / (1 + τ̃ - U)
114+
u₁ⁿ⁺¹ = ifelse== 0, ūⁿ⁺¹, relaxed_u₁ⁿ⁺¹)
151115

152-
u₁ⁿ⁺¹ = uᵢⁿ - U * (uᵢ₋₁ⁿ⁺¹ - ūⁿ⁺¹) + (ūⁿ⁺¹ - uᵢⁿ) * τ̃
153116
@inbounds setindex!(u, u₁ⁿ⁺¹, boundary_indices...)
154117
@inbounds setindex!(u, u₁ⁿ⁺¹, boundary_secret_storage_indices...)
155118

test/test_boundary_conditions_integration.jl

+2-2
Original file line numberDiff line numberDiff line change
@@ -176,7 +176,7 @@ velocity_forcing(::Val{1}, forcing) = (; u = forcing)
176176
velocity_forcing(::Val{2}, forcing) = (; v = forcing)
177177
velocity_forcing(::Val{3}, forcing) = (; w = forcing)
178178

179-
function test_pertubation_advection_open_boundary_conditions(arch, FT)
179+
function test_perturbation_advection_open_boundary_conditions(arch, FT)
180180
for orientation in 1:3
181181
topology = tuple(map(n -> ifelse(n == orientation, Bounded, Flat), 1:3)...)
182182

@@ -447,7 +447,7 @@ test_boundary_conditions(C, FT, ArrayType) = (integer_bc(C, FT, ArrayType),
447447
A = typeof(arch)
448448
@info " Testing open boundary conditions [$A, $FT]..."
449449
test_flat_extrapolation_open_boundary_conditions(arch, FT)
450-
test_pertubation_advection_open_boundary_conditions(arch, FT)
450+
test_perturbation_advection_open_boundary_conditions(arch, FT)
451451
end
452452
end
453453
end

0 commit comments

Comments
 (0)