Skip to content

Commit 3489204

Browse files
authored
Remove the use of indices for storage in PerturbationAdvection (#4578)
* remove secret_indices * different index notation * cleanup and improvement of validation scripts * uncomment flat_extrapolation * change notation for setp_left_boundary! * follow nomenclature already in fill_halo_regions_value_gradient.jl * slightly different notation
1 parent 6c2944e commit 3489204

File tree

3 files changed

+54
-60
lines changed

3 files changed

+54
-60
lines changed

src/BoundaryConditions/perturbation_advection_open_boundary_matching_scheme.jl

Lines changed: 24 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -26,13 +26,13 @@ relaxation to the mean velocity (i.e. u′→0) then Fᵤ = -u′ / τ then we c
2626
u′ⁿ⁺¹ = (uⁿ + Ũu′ⁿ⁺¹ᵢ₋₁ - Uⁿ⁺¹) / (1 + Ũ + Δt/τ),
2727
2828
where Ũ = U Δt / Δx, then uⁿ⁺¹ is:
29-
uⁿ⁺¹ = (uᵢⁿ + Ũuᵢ₋₁ⁿ⁺¹ + Uⁿ⁺¹τ̃) / (1 + τ̃ + U)
29+
uⁿ⁺¹ = (uᵢⁿ + Ũuᵢ₋₁ⁿ⁺¹ + Uⁿ⁺¹τ̃) / (1 + τ̃ + )
3030
3131
where τ̃ = Δt/τ.
3232
3333
The same operation can be repeated for left boundaries.
3434
35-
The relaxation timescale ``τ`` can be set to different values depending on whether the
35+
The relaxation timescale ``τ`` can be set to different values depending on whether
3636
``U`` points in or out of the domain (`inflow_timescale`/`outflow_timescale`). Since the
3737
scheme is only valid when the flow is directed out of the domain the boundary condition
3838
falls back to relaxation to the prescribed value. By default this happens instantly but
@@ -64,6 +64,8 @@ details about this method, refer to the docstring for `PerturbationAdvection`.
6464
function PerturbationAdvectionOpenBoundaryCondition(val, FT = defaults.FloatType;
6565
outflow_timescale = Inf,
6666
inflow_timescale = 0, kwargs...)
67+
inflow_timescale = convert(FT, inflow_timescale)
68+
outflow_timescale = convert(FT, outflow_timescale)
6769

6870
classification = Open(PerturbationAdvection(inflow_timescale, outflow_timescale))
6971

@@ -76,45 +78,48 @@ const PAOBC = BoundaryCondition{<:Open{<:PerturbationAdvection}}
7678

7779
@inline function step_right_boundary!(bc::PAOBC, l, m, boundary_indices, boundary_adjacent_indices,
7880
grid, u, clock, model_fields, ΔX)
81+
iᴮ, jᴮ, kᴮ = boundary_indices
82+
iᴬ, jᴬ, kᴬ = boundary_adjacent_indices
7983
Δt = clock.last_stage_Δt
8084
Δt = ifelse(isinf(Δt), 0, Δt)
8185

82-
ūⁿ⁺¹ = getbc(bc, l, m, grid, clock, model_fields)
83-
uᵢⁿ = @inbounds getindex(u, boundary_indices...)
84-
uᵢ₋₁ⁿ⁺¹ = @inbounds getindex(u, boundary_adjacent_indices...)
86+
ūⁿ⁺¹ = getbc(bc, l, m, grid, clock, model_fields)
87+
uᵢⁿ = @inbounds getindex(u, iᴮ, jᴮ, kᴮ)
88+
uᵢ₋₁ⁿ⁺¹ = @inbounds getindex(u, iᴬ, jᴬ, kᴬ)
8589
U = max(0, min(1, Δt / ΔX * ūⁿ⁺¹))
8690

8791
pa = bc.classification.matching_scheme
8892
τ = ifelse(ūⁿ⁺¹ >= 0, pa.outflow_timescale, pa.inflow_timescale)
89-
τ̃ = Δt / τ
93+
τ̃ = Δt / τ # last stage Δt normalized by the inflow/output timescale
9094

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

94-
@inbounds setindex!(u, uᵢⁿ⁺¹, boundary_indices...)
98+
@inbounds setindex!(u, uᵢⁿ⁺¹, iᴮ, jᴮ, kᴮ)
9599

96100
return nothing
97101
end
98102

99-
@inline function step_left_boundary!(bc::PAOBC, l, m, boundary_indices, boundary_adjacent_indices, boundary_secret_storage_indices,
103+
@inline function step_left_boundary!(bc::PAOBC, l, m, boundary_indices, boundary_adjacent_indices,
100104
grid, u, clock, model_fields, ΔX)
105+
iᴮ, jᴮ, kᴮ = boundary_indices
106+
iᴬ, jᴬ, kᴬ = boundary_adjacent_indices
101107
Δt = clock.last_stage_Δt
102108
Δt = ifelse(isinf(Δt), 0, Δt)
103109

104-
ūⁿ⁺¹ = getbc(bc, l, m, grid, clock, model_fields)
105-
uᵢⁿ = @inbounds getindex(u, boundary_secret_storage_indices...)
106-
uᵢ₋₁ⁿ⁺¹ = @inbounds getindex(u, boundary_adjacent_indices...)
110+
ūⁿ⁺¹ = getbc(bc, l, m, grid, clock, model_fields)
111+
uᵢⁿ = @inbounds getindex(u, iᴮ, jᴮ, kᴮ)
112+
uᵢ₋₁ⁿ⁺¹ = @inbounds getindex(u, iᴬ, jᴬ, kᴬ)
107113
U = min(0, max(-1, Δt / ΔX * ūⁿ⁺¹))
108114

109115
pa = bc.classification.matching_scheme
110116
τ = ifelse(ūⁿ⁺¹ <= 0, pa.outflow_timescale, pa.inflow_timescale)
111-
τ̃ = Δt / τ
117+
τ̃ = Δt / τ # last stage Δt normalized by the inflow/output timescale
112118

113119
relaxed_u₁ⁿ⁺¹ = (uᵢⁿ - U * uᵢ₋₁ⁿ⁺¹ + ūⁿ⁺¹ * τ̃) / (1 + τ̃ - U)
114-
u₁ⁿ⁺¹ = ifelse== 0, ūⁿ⁺¹, relaxed_u₁ⁿ⁺¹)
120+
u₁ⁿ⁺¹ = ifelse== 0, ūⁿ⁺¹, relaxed_u₁ⁿ⁺¹)
115121

116-
@inbounds setindex!(u, u₁ⁿ⁺¹, boundary_indices...)
117-
@inbounds setindex!(u, u₁ⁿ⁺¹, boundary_secret_storage_indices...)
122+
@inbounds setindex!(u, u₁ⁿ⁺¹, iᴮ, jᴮ, kᴮ)
118123

119124
return nothing
120125
end
@@ -134,11 +139,9 @@ end
134139
@inline function _fill_west_halo!(j, k, grid, u, bc::PAOBC, ::Tuple{Face, Any, Any}, clock, model_fields)
135140
boundary_indices = (1, j, k)
136141
boundary_adjacent_indices = (2, j, k)
137-
boundary_secret_storage_indices = (0, j, k)
138142

139143
Δx = Δxᶠᶜᶜ(1, j, k, grid)
140-
141-
step_left_boundary!(bc, j, k, boundary_indices, boundary_adjacent_indices, boundary_secret_storage_indices, grid, u, clock, model_fields, Δx)
144+
step_left_boundary!(bc, j, k, boundary_indices, boundary_adjacent_indices, grid, u, clock, model_fields, Δx)
142145

143146
return nothing
144147
end
@@ -149,7 +152,6 @@ end
149152
boundary_adjacent_indices = (i, j-1, k)
150153

151154
Δy = Δyᶜᶠᶜ(i, j, k, grid)
152-
153155
step_right_boundary!(bc, i, k, boundary_indices, boundary_adjacent_indices, grid, u, clock, model_fields, Δy)
154156

155157
return nothing
@@ -158,11 +160,9 @@ end
158160
@inline function _fill_south_halo!(i, k, grid, u, bc::PAOBC, ::Tuple{Any, Face, Any}, clock, model_fields)
159161
boundary_indices = (i, 1, k)
160162
boundary_adjacent_indices = (i, 2, k)
161-
boundary_secret_storage_indices = (i, 0, k)
162163

163164
Δy = Δyᶜᶠᶜ(i, 1, k, grid)
164-
165-
step_left_boundary!(bc, i, k, boundary_indices, boundary_adjacent_indices, boundary_secret_storage_indices, grid, u, clock, model_fields, Δy)
165+
step_left_boundary!(bc, i, k, boundary_indices, boundary_adjacent_indices, grid, u, clock, model_fields, Δy)
166166

167167
return nothing
168168
end
@@ -173,7 +173,6 @@ end
173173
boundary_adjacent_indices = (i, j, k-1)
174174

175175
Δz = Δzᶜᶜᶠ(i, j, k, grid)
176-
177176
step_right_boundary!(bc, i, j, boundary_indices, boundary_adjacent_indices, grid, u, clock, model_fields, Δz)
178177

179178
return nothing
@@ -182,11 +181,9 @@ end
182181
@inline function _fill_bottom_halo!(i, j, grid, u, bc::PAOBC, ::Tuple{Any, Any, Face}, clock, model_fields)
183182
boundary_indices = (i, j, 1)
184183
boundary_adjacent_indices = (i, j, 2)
185-
boundary_secret_storage_indices = (i, j, 0)
186184

187185
Δz = Δzᶜᶜᶠ(i, j, 1, grid)
188-
189-
step_left_boundary!(bc, i, j, boundary_indices, boundary_adjacent_indices, boundary_secret_storage_indices, grid, u, clock, model_fields, Δz)
186+
step_left_boundary!(bc, i, j, boundary_indices, boundary_adjacent_indices, grid, u, clock, model_fields, Δz)
190187

191188
return nothing
192189
end

validation/open_boundaries/cylinder.jl

Lines changed: 9 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -54,49 +54,34 @@ function drag(model;
5454
∂₁uᵣ = Field(∂x(uᶜ), indices = (i₂, j₁:j₂, 1))
5555

5656
∂ₜuᶜ = Field(@at (Center, Center, Center) model.timestepper.Gⁿ.u)
57-
5857
∂ₜu = Field(∂ₜuᶜ, indices = (i₁:i₂, j₁:j₂, 1))
5958

6059
p = model.pressures.pNHS
61-
6260
∫∂ₓp = Field(∂x(p), indices = (i₁:i₂, j₁:j₂, 1))
6361

6462
a_local = Field(Integral(∂ₜu))
65-
6663
a_flux = Field(Integral(uᵣ²)) - Field(Integral(uₗ²)) + Field(Integral(uvᵣ)) - Field(Integral(uvₗ))
67-
6864
a_viscous_stress = 2ν * (Field(Integral(∂₁uᵣ)) - Field(Integral(∂₁uₗ)))
69-
7065
a_pressure = Field(Integral(∫∂ₓp))
7166

7267
return a_local + a_flux + a_pressure - a_viscous_stress
7368
end
7469

7570
function cylinder_model(open_boundaries;
76-
7771
obc_name = "",
78-
7972
u∞ = 1,
8073
r = 1/2,
81-
8274
cylinder = (x, y) -> ((x^2 + y^2) r^2),
83-
8475
stop_time = 100,
85-
8676
arch = GPU(),
87-
8877
Re = 100,
89-
Ny = 512,
78+
Ny = 128,
9079
Nx = Ny,
91-
9280
ϵ = 0, # break up-down symmetry
9381
x = (-6, 12), # 18
9482
y = (-6 + ϵ, 6 + ϵ), # 12
95-
9683
grid_kwargs = (; size=(Nx, Ny), x, y, halo=(6, 6), topology=(Bounded, Bounded, Flat)),
97-
9884
prefix = "flow_around_cylinder_Re$(Re)_Ny$(Ny)_$(obc_name)",
99-
10085
drag_averaging_window = 29)
10186

10287
grid = RectilinearGrid(arch; grid_kwargs...)
@@ -108,9 +93,7 @@ function cylinder_model(open_boundaries;
10893
closure = ScalarDiffusivity=1/Re)
10994

11095
no_slip = ValueBoundaryCondition(0)
111-
11296
u_bcs = FieldBoundaryConditions(immersed=no_slip, east=open_boundaries.east, west=open_boundaries.west)
113-
11497
v_bcs = FieldBoundaryConditions(immersed=no_slip,
11598
east=GradientBoundaryCondition(0),
11699
west=ValueBoundaryCondition(0))
@@ -221,8 +204,8 @@ function cylinder_model(open_boundaries;
221204

222205
supertitle = Label(fig[0, :], title)
223206

224-
CairoMakie.record(fig, prefix"*.mp4", 1:length(u.times), framerate=20) do i
225-
@info "$i"
207+
CairoMakie.record(fig, prefix * ".mp4", 1:length(u.times), framerate=20) do i
208+
i % 50 == 0 && @info "$i"
226209
n[] = i
227210
end
228211

@@ -231,15 +214,16 @@ end
231214

232215
u∞ = 1
233216

234-
feobc = (east = FlatExtrapolationOpenBoundaryCondition(), west = OpenBoundaryCondition(u∞))
217+
feobcs = (west = OpenBoundaryCondition(u∞), east = FlatExtrapolationOpenBoundaryCondition(),)
235218

236-
paobcs = (east = PerturbationAdvectionOpenBoundaryCondition(u∞; inflow_timescale = 1/4, outflow_timescale = Inf),
237-
west = PerturbationAdvectionOpenBoundaryCondition(u∞; inflow_timescale = 0.1, outflow_timescale = 0.1))
219+
paobcs = (west = PerturbationAdvectionOpenBoundaryCondition(u∞; inflow_timescale = 0.1, outflow_timescale = 0.1),
220+
east = PerturbationAdvectionOpenBoundaryCondition(u∞; inflow_timescale = 1/4, outflow_timescale = Inf),
221+
)
238222

239-
obcs = (; flat_extrapolation=feobc,
223+
obcs = (; flat_extrapolation=feobcs,
240224
perturbation_advection=paobcs)
241225

242226
for (obc_name, obc) in pairs(obcs)
243227
@info "Running $(obc_name)"
244-
cylinder_model(obc; obc_name, u∞)
228+
cylinder_model(obc; obc_name, u∞, arch=CPU(), Ny=16)
245229
end

validation/open_boundaries/oscillating_flow.jl

Lines changed: 21 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
# This case also has a stretched grid to validate the matching scheme on a stretched grid.
99

1010
using Oceananigans, CairoMakie
11-
using Oceananigans.BoundaryConditions: FlatExtrapolationOpenBoundaryCondition
11+
using Oceananigans.BoundaryConditions: FlatExtrapolationOpenBoundaryCondition, PerturbationAdvectionOpenBoundaryCondition
1212

1313
@kwdef struct Cylinder{FT}
1414
D :: FT = 1.0
@@ -122,6 +122,7 @@ function run_cylinder(grid, boundary_conditions; plot=true, stop_time = 50, simn
122122
end
123123
end
124124

125+
inflow_timescale = outflow_timescale = 1/4
125126
matching_scheme_name(obc) = string(nameof(typeof(obc.classification.matching_scheme)))
126127
for grid in (xygrid, xzgrid)
127128

@@ -132,14 +133,26 @@ for grid in (xygrid, xzgrid)
132133
u_boundaries_fe = FieldBoundaryConditions(west = u_fe, east = u_fe)
133134
v_boundaries_fe = FieldBoundaryConditions(south = v_fe, north = v_fe)
134135
w_boundaries_fe = FieldBoundaryConditions(bottom = w_fe, top = w_fe)
136+
feobcs = (u = u_boundaries_fe, v = v_boundaries_fe, w = w_boundaries_fe)
135137

136-
if grid isa Oceananigans.Grids.ZFlatGrid
137-
boundary_conditions = (u = u_boundaries_fe, v = v_boundaries_fe)
138-
simname = "xy_" * matching_scheme_name(u_boundaries_fe.east)
139-
elseif grid isa Oceananigans.Grids.YFlatGrid
140-
boundary_conditions = (u = u_boundaries_fe, w = w_boundaries_fe)
141-
simname = "xz_" * matching_scheme_name(u_boundaries_fe.east)
138+
u_boundaries_pa = FieldBoundaryConditions(west = PerturbationAdvectionOpenBoundaryCondition(u∞; parameters = (; U, T), inflow_timescale, outflow_timescale),
139+
east = PerturbationAdvectionOpenBoundaryCondition(u∞; parameters = (; U, T), inflow_timescale, outflow_timescale))
140+
v_boundaries_pa = FieldBoundaryConditions(south = PerturbationAdvectionOpenBoundaryCondition(v∞; parameters = (; U, T), inflow_timescale, outflow_timescale),
141+
north = PerturbationAdvectionOpenBoundaryCondition(v∞; parameters = (; U, T), inflow_timescale, outflow_timescale))
142+
w_boundaries_pa = FieldBoundaryConditions(bottom = PerturbationAdvectionOpenBoundaryCondition(v∞; parameters = (; U, T), inflow_timescale, outflow_timescale),
143+
top = PerturbationAdvectionOpenBoundaryCondition(v∞; parameters = (; U, T), inflow_timescale, outflow_timescale))
144+
paobcs = (u = u_boundaries_pa, v = v_boundaries_pa, w = w_boundaries_pa)
145+
146+
for obcs in (feobcs, paobcs,)
147+
if grid isa Oceananigans.Grids.ZFlatGrid
148+
boundary_conditions = (u = obcs.u, v = obcs.v)
149+
simname = "xy_" * matching_scheme_name(boundary_conditions.u.east)
150+
elseif grid isa Oceananigans.Grids.YFlatGrid
151+
boundary_conditions = (u = obcs.u, w = obcs.w)
152+
simname = "xz_" * matching_scheme_name(boundary_conditions.u.east)
153+
end
154+
@info "Running $simname"
155+
run_cylinder(grid, boundary_conditions, simname = simname, stop_time = T)
142156
end
143-
run_cylinder(grid, boundary_conditions, simname = simname, stop_time = T)
144157
end
145158

0 commit comments

Comments
 (0)