Skip to content

Small improvements to PerturbationAdvectionOpenBoundaryCondition interface #4394

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 23 commits into from
May 15, 2025
Merged
Changes from 7 commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
93aea21
move docstring ti user-faacing method
tomchor Apr 9, 2025
f454ce6
Merge branch 'main' into tc/perturb-adv-obc-tweaks
tomchor Apr 9, 2025
44a1544
add docstring
tomchor Apr 9, 2025
29ac05a
Merge branch 'main' into tc/perturb-adv-obc-tweaks
tomchor Apr 15, 2025
a9a9b38
Merge branch 'main' into tc/perturb-adv-obc-tweaks
tomchor Apr 17, 2025
e438a01
guard agaisnt infinity for backward step
tomchor Apr 17, 2025
5567f28
remove extra lines
tomchor Apr 18, 2025
71d0c4a
use ifelse function
tomchor Apr 18, 2025
40560f1
Merge branch 'main' into tc/perturb-adv-obc-tweaks
tomchor Apr 18, 2025
dc35ff0
Merge branch 'main' into tc/perturb-adv-obc-tweaks
tomchor May 14, 2025
b3234b9
Update perturbation_advection_open_boundary_matching_scheme.jl
tomchor May 14, 2025
3951467
Update perturbation_advection_open_boundary_matching_scheme.jl
jagoosw May 14, 2025
3776a48
remove forward step
tomchor May 14, 2025
06f1dce
don't hardcode float type
tomchor May 14, 2025
16c3e89
move intuitive testing
tomchor May 14, 2025
ae598c6
avoid calculations inside ifelse statements
tomchor May 14, 2025
9daa752
typo andf clarification
tomchor May 14, 2025
004f420
Merge branch 'main' into tc/perturb-adv-obc-tweaks
tomchor May 14, 2025
b1519c4
Merge branch 'main' into tc/perturb-adv-obc-tweaks
tomchor May 15, 2025
a814987
import defaults first
tomchor May 15, 2025
5b45568
Merge branch 'tc/perturb-adv-obc-tweaks' of github.com:CliMA/Oceanani…
tomchor May 15, 2025
2ecdb37
bugfix
tomchor May 15, 2025
dd4b0f6
Merge branch 'main' into tc/perturb-adv-obc-tweaks
tomchor May 15, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -37,15 +37,25 @@ struct PerturbationAdvection{VT, FT}
outflow_timescale :: FT
end

Adapt.adapt_structure(to, pe::PerturbationAdvection) =
Adapt.adapt_structure(to, pe::PerturbationAdvection) =
PerturbationAdvection(adapt(to, pe.backward_step),
adapt(to, pe.inflow_timescale),
adapt(to, pe.outflow_timescale))

function PerturbationAdvectionOpenBoundaryCondition(val, FT = Float64;
"""
PerturbationAdvectionOpenBoundaryCondition(val, FT = Float64;
backward_step = true,
outflow_timescale = Inf,
inflow_timescale = 0.0, kwargs...)

Creates a `PerturbationAdvectionOpenBoundaryCondition` with a given `outflow_timescale` and
`inflow_timescale`. `backward_step` determines whether we assume a backward and forward time
discretization. For details about this method, refer to the docstring for `PerturbationAdvection`.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the docstring doesn't describe what val is. I'm also confused, would a better name than val help?

Copy link
Collaborator Author

@tomchor tomchor May 14, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

val is the exterior value of the normal valocity. The one we're relaxing the flow to (with inflow_timescale during inflow and with outflow_timescale with during outflow). I agree it isn't a very intuitive name. Maybe just exterior_value?

"""
function PerturbationAdvectionOpenBoundaryCondition(val, FT = Float64;
backward_step = true,
outflow_timescale = Inf,
inflow_timescale = 300.0, kwargs...)
outflow_timescale = Inf,
inflow_timescale = 0, kwargs...)

classification = Open(PerturbationAdvection(Val(backward_step), inflow_timescale, outflow_timescale))

Expand All @@ -62,23 +72,18 @@ const FPAOBC = BoundaryCondition{<:Open{<:PerturbationAdvection{Val{false}}}}
@inline function step_right_boundary!(bc::BPAOBC, l, m, boundary_indices, boundary_adjacent_indices,
grid, u, clock, model_fields, ΔX)
Δt = clock.last_stage_Δt

Δt = ifelse(isinf(Δt), 0, Δt)

ūⁿ⁺¹ = getbc(bc, l, m, grid, clock, model_fields)

uᵢⁿ = @inbounds getindex(u, boundary_indices...)
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@jagoosw this isn't critical but I'd appreciate some clarity here. In your derivation you arrive at the equation

uⁿ⁺¹ = (uᵢⁿ + Ũuᵢ₋₁ⁿ⁺¹ + Uⁿ⁺¹τ̃) / (1 + τ̃ + U)

and from it, I understand that uᵢⁿ is the normal velocity at the previous time-step. However, here you're defining uᵢⁿ using the current time-step, no? Am I misunderstanding something?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is where we get the previous value of the boundary point since it hasn't been stepped yet so its still at the previous time step, and then put uⁿ⁺¹ in the same place to bring the whole field to the current time step.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah I see, thanks for the clarification. Just to clarify even further, the way time-stepping works is that the interior of the flow is time-stepped first, then we do the boundaries?

uᵢ₋₁ⁿ⁺¹ = @inbounds getindex(u, boundary_adjacent_indices...)

U = max(0, min(1, Δt / ΔX * ūⁿ⁺¹))

pa = bc.classification.matching_scheme

τ = ifelse(ūⁿ⁺¹ >= 0, pa.outflow_timescale, pa.inflow_timescale)

τ̃ = Δt / τ

uᵢⁿ⁺¹ = (uᵢⁿ + U * uᵢ₋₁ⁿ⁺¹ + ūⁿ⁺¹ * τ̃) / (1 + τ̃ + U)
uᵢⁿ⁺¹ = isinf(τ̃) ? ūⁿ⁺¹ : (uᵢⁿ + U * uᵢ₋₁ⁿ⁺¹ + ūⁿ⁺¹ * τ̃) / (1 + τ̃ + U)

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

Expand All @@ -88,23 +93,18 @@ end
@inline function step_left_boundary!(bc::BPAOBC, l, m, boundary_indices, boundary_adjacent_indices, boundary_secret_storage_indices,
grid, u, clock, model_fields, ΔX)
Δt = clock.last_stage_Δt

Δt = ifelse(isinf(Δt), 0, Δt)

ūⁿ⁺¹ = getbc(bc, l, m, grid, clock, model_fields)

uᵢⁿ = @inbounds getindex(u, boundary_secret_storage_indices...)
uᵢ₋₁ⁿ⁺¹ = @inbounds getindex(u, boundary_adjacent_indices...)

U = min(0, max(-1, Δt / ΔX * ūⁿ⁺¹))

pa = bc.classification.matching_scheme

τ = ifelse(ūⁿ⁺¹ <= 0, pa.outflow_timescale, pa.inflow_timescale)

τ̃ = Δt / τ

u₁ⁿ⁺¹ = (uᵢⁿ - U * uᵢ₋₁ⁿ⁺¹ + ūⁿ⁺¹ * τ̃) / (1 + τ̃ - U)
u₁ⁿ⁺¹ = isinf(τ̃) ? ūⁿ⁺¹ : (uᵢⁿ - U * uᵢ₋₁ⁿ⁺¹ + ūⁿ⁺¹ * τ̃) / (1 + τ̃ - U)

@inbounds setindex!(u, u₁ⁿ⁺¹, boundary_indices...)
@inbounds setindex!(u, u₁ⁿ⁺¹, boundary_secret_storage_indices...)
Expand All @@ -116,20 +116,15 @@ end
@inline function step_right_boundary!(bc::FPAOBC, l, m, boundary_indices, boundary_adjacent_indices,
grid, u, clock, model_fields, ΔX)
Δt = clock.last_stage_Δt

Δt = ifelse(isinf(Δt), 0, Δt)

ūⁿ⁺¹ = getbc(bc, l, m, grid, clock, model_fields)

uᵢⁿ = @inbounds getindex(u, boundary_indices...)
uᵢ₋₁ⁿ⁺¹ = @inbounds getindex(u, boundary_adjacent_indices...)

U = max(0, min(1, Δt / ΔX * ūⁿ⁺¹))

pa = bc.classification.matching_scheme

τ = ifelse(ūⁿ⁺¹ >= 0, pa.outflow_timescale, pa.inflow_timescale)

τ̃ = Δt / τ

uᵢⁿ⁺¹ = uᵢⁿ + U * (uᵢ₋₁ⁿ⁺¹ - ūⁿ⁺¹) + (ūⁿ⁺¹ - uᵢⁿ) * τ̃
Expand All @@ -142,20 +137,15 @@ end
@inline function step_left_boundary!(bc::FPAOBC, l, m, boundary_indices, boundary_adjacent_indices, boundary_secret_storage_indices,
grid, u, clock, model_fields, ΔX)
Δt = clock.last_stage_Δt

Δt = ifelse(isinf(Δt), 0, Δt)

ūⁿ⁺¹ = getbc(bc, l, m, grid, clock, model_fields)

uᵢⁿ = @inbounds getindex(u, boundary_secret_storage_indices...)
uᵢ₋₁ⁿ⁺¹ = @inbounds getindex(u, boundary_adjacent_indices...)

U = min(0, max(-1, Δt / ΔX * ūⁿ⁺¹))

pa = bc.classification.matching_scheme

τ = ifelse(ūⁿ⁺¹ <= 0, pa.outflow_timescale, pa.inflow_timescale)

τ̃ = Δt / τ

u₁ⁿ⁺¹ = uᵢⁿ - U * (uᵢ₋₁ⁿ⁺¹ - ūⁿ⁺¹) + (ūⁿ⁺¹ - uᵢⁿ) * τ̃
Expand Down