zoomy_core.model.boundary_conditions module

zoomy_core.model.boundary_conditions module#

Module zoomy_core.model.boundary_conditions.

class zoomy_core.model.boundary_conditions.BoundaryCondition(*, tag, name)#

Bases: Parameterized

Default implementation. The required data for the ‘ghost cell’ is the data from the interior cell. Can be overwritten e.g. to implement periodic boundary conditions.

tag = 'bc'#
compute_boundary_condition(time, X, dX, Q, Qaux, parameters, normal)#

Symbolic builder for the boundary value — used by BoundaryConditions.get_boundary_condition_function() to assemble the indexed Piecewise BC kernel.

compute_boundary_gradient(time, X, dX, Q, Qaux, parameters, normal)#

Symbolic builder for the boundary normal-direction gradient ∂Q/∂n at the face — used by BoundaryConditions.get_boundary_gradient_function() to assemble the indexed Piecewise boundary-gradient kernel (consumed by the diffusion path).

Default: zero Neumann. Subclasses override when a non-zero gradient is part of the BC (e.g. prescribed-flux Robin BCs).

face_state(Q_face, Qaux_face, normal, parameters)#

Compute the boundary-side Riemann state from the reconstructed face value.

Called at boundary faces inside the flux operator. Q_face is the MUSCL-reconstructed interior state at the face. Returns the state that the Riemann solver sees on the boundary side.

Default: same as Q_face (Neumann / zero-flux).

Deprecated since version Use: face_value instead.

face_value(Q_inner, Qaux_inner, normal, d_face, time, parameters)#

Boundary-side Riemann state for convective flux (ghost-cell-free).

Parameters:
  • Q_inner (ndarray, shape (n_vars,)) – Cell-center values of the adjacent interior cell.

  • Qaux_inner (ndarray, shape (n_aux,)) – Auxiliary variables of the adjacent interior cell.

  • normal (ndarray, shape (dim,)) – Outward unit face normal.

  • d_face (float) – Distance from interior cell center to face center.

  • time (float) – Current simulation time.

  • parameters (ndarray, shape (n_params,)) – Model parameters.

Returns:

The state that the Riemann solver sees on the boundary side.

Return type:

ndarray, shape (n_vars,)

face_gradient(Q_inner, Q_face, Qaux_inner, normal, d_face, time, parameters)#

Face-normal gradient dQ/dn for diffusive flux at boundary.

Parameters:
  • Q_inner (ndarray, shape (n_vars,)) – Cell-center values of the adjacent interior cell.

  • Q_face (ndarray, shape (n_vars,)) – The face_value result (already computed upstream).

  • Qaux_inner (ndarray, shape (n_aux,)) – Auxiliary variables of the adjacent interior cell.

  • normal (ndarray, shape (dim,)) – Outward unit face normal.

  • d_face (float) – Distance from interior cell center to face center.

  • time (float) – Current simulation time.

  • parameters (ndarray, shape (n_params,)) – Model parameters.

Returns:

Face-normal gradient at the boundary face.

Return type:

ndarray, shape (n_vars,)

name = 'BoundaryCondition'#
class zoomy_core.model.boundary_conditions.Extrapolation(*, use_gradient, tag, name)#

Bases: BoundaryCondition

Extrapolation. (class).

use_gradient = True#
compute_boundary_condition(time, X, dX, Q, Qaux, parameters, normal)#

Compute boundary condition.

face_state(Q_face, Qaux_face, normal, parameters)#

Extrapolation: boundary state = interior face state (zero flux).

face_value(Q_inner, Qaux_inner, normal, d_face, time, parameters)#

Extrapolation: boundary state = interior cell state.

face_gradient(Q_inner, Q_face, Qaux_inner, normal, d_face, time, parameters)#

Extrapolation: zero Neumann (no normal gradient).

name = 'Extrapolation'#
class zoomy_core.model.boundary_conditions.InflowOutflow(*, prescribe_fields, tag, name)#

Bases: BoundaryCondition

Inflow / outflow boundary — prescribe selected state fields, extrapolate the rest.

prescribe_fields maps a state index to a spec. A spec is either a bare value (scalar or symbolic expression — the field is replaced by it) or a dict carrying a "mode" key:

  • {"mode": "replace", "value": v}Q_out[k] = v.

  • {"mode": "inlet_outlet", "value": v} — OpenFOAM inletOutlet style: the field takes v where the interior is inflowing (Q[k] >= 0) and keeps the interior value otherwise (so backflow is never overridden): Q_out[k] = conditional(Q[k] >= 0, v, Q[k]). The index k is assumed to be a momentum component whose positive direction points into the domain.

  • {"mode": "blend", "target": t, "weight": w} — a soft inflow: Q_out[k] = Q[k] + max(0, t - Q[k]) * w. w = 0 means “no inflow” (the field stays at its interior value); w = 1 pulls it fully to t.

Every value / target / weight is a scalar or a symbolic expression — typically built by the codegen driver from model parameters (e.g. a piecewise-linear Q(t) timeline interpolated over a fixed block of timeline parameters). The BC plugs the expressions in; it never builds them and it never reads data.

prescribe_fields = {}#
compute_boundary_condition(time, X, dX, Q, Qaux, parameters, normal)#

Compute boundary condition.

face_value(Q_inner, Qaux_inner, normal, d_face, time, parameters)#

InflowOutflow (numpy path): prescribe selected fields, rest from the interior. Supports constant replace specs only — the symbolic inlet_outlet / blend modes and parameter-valued prescriptions flow through the codegen path (compute_boundary_condition).

name = 'InflowOutflow'#
class zoomy_core.model.boundary_conditions.Lambda(*, prescribe_fields, tag, name)#

Bases: BoundaryCondition

Lambda. (class).

prescribe_fields = {}#
compute_boundary_condition(time, X, dX, Q, Qaux, parameters, normal)#

Compute boundary condition.

name = 'Lambda'#
class zoomy_core.model.boundary_conditions.FromData(*, prescribe_fields, timeline, tag, name)#

Bases: BoundaryCondition

FromData. (class).

prescribe_fields = {}#
timeline = None#
compute_boundary_condition(time, X, dX, Q, Qaux, parameters, normal)#

Compute boundary condition.

name = 'FromData'#
class zoomy_core.model.boundary_conditions.CharacteristicReflective(*, D, L, M, R, S, tag, name)#

Bases: BoundaryCondition

CharacteristicReflective. (class).

R = None#
L = None#
D = None#
S = None#
M = None#
compute_boundary_condition(time, X, dX, Q, Qaux, parameters, normal)#

Compute boundary condition.

name = 'CharacteristicReflective'#
class zoomy_core.model.boundary_conditions.Wall(*, blending, momentum_field_indices, permeability, use_gradient, wall_slip, tag, name)#

Bases: BoundaryCondition

Wall. (class).

momentum_field_indices = [[1, 2]]#
permeability = 0.0#
wall_slip = 1.0#
blending = 0.0#
use_gradient = True#
compute_boundary_condition(time, X, dX, Q, Qaux, parameters, normal)#

Compute boundary condition.

face_state(Q_face, Qaux_face, normal, parameters)#

Wall: reflect normal momentum component of the reconstructed face value.

face_value(Q_inner, Qaux_inner, normal, d_face, time, parameters)#

Wall: reflect normal momentum, copy scalars.

Momentum decomposition:

u_wall = slip * u_tangential - (1 - perm) * u_normal

Scalars are extrapolated (copied from interior).

name = 'Wall'#
class zoomy_core.model.boundary_conditions.RoughWall(*, CsW, Ks, blending, momentum_field_indices, permeability, use_gradient, wall_slip, tag, name)#

Bases: Wall

RoughWall. (class).

CsW = 0.5#
Ks = 0.001#
compute_boundary_condition(time, X, dX, Q, Qaux, parameters, normal)#

Compute boundary condition.

face_value(Q_inner, Qaux_inner, normal, d_face, time, parameters)#

RoughWall: Wall reflection with distance-dependent slip.

name = 'RoughWall'#
class zoomy_core.model.boundary_conditions.Periodic(*, periodic_to_physical_tag, tag, name)#

Bases: BoundaryCondition

Periodic. (class).

periodic_to_physical_tag = ''#
compute_boundary_condition(time, X, dX, Q, Qaux, parameters, normal)#

Compute boundary condition.

name = 'Periodic'#
class zoomy_core.model.boundary_conditions.WindStress(*, prescribe_gradients, prescribe_values, tag, name)#

Bases: BoundaryCondition

Mixed Neumann + Dirichlet BC — POM-style wind-stress surface.

Some state rows get a prescribed value (Dirichlet); others get a prescribed face-normal gradient (Neumann). Rows mentioned in neither default to zero-gradient extrapolation. Symbolic specs in state / aux / parameter symbols are supported on the codegen and Firedrake-DG paths (boundary kernels lambdify the resulting expressions); the numpy paths require numeric specs.

Built for the canonical POM surface BC (BM87 §2.15):

ρ_o K_M ∂_z U = τ_o            ← Neumann on the velocity row
∂_z T = 0                       ← Neumann on the tracer row
q² = B₁^(2/3) u_τs²             ← Dirichlet on the q² row
q²ℓ = 0                         ← Dirichlet on the q²ℓ row

For the velocity Neumann gradient ∂_z U = u_*² / K_M the user pulls the symbolic K_M from the model so the BC stays consistent with the interior closure:

sm = SystemModel.from_model(my_col)
K_M_sym = sm.diffusion_matrix[0, 0, 0, 0]
bc = WindStress(
    tag="surface",
    prescribe_gradients={0: sm.parameters.u_star**2 / K_M_sym,
                         1: 0},
    prescribe_values={2: sm.parameters.B1 ** sp.Rational(2, 3)
                        * sm.parameters.u_star**2,
                      3: 0},
)

Same mechanism handles the bottom BC (no-slip + zero heat flux + bottom-stress q² + zero q²ℓ) with different per-row specs.

prescribe_values = {}#
prescribe_gradients = {}#
compute_boundary_condition(time, X, dX, Q, Qaux, parameters, normal)#

Dirichlet rows take the prescribed value; others extrapolate.

compute_boundary_gradient(time, X, dX, Q, Qaux, parameters, normal)#

Neumann rows take the prescribed gradient; others zero.

face_value(Q_inner, Qaux_inner, normal, d_face, time, parameters)#

Numpy: Dirichlet rows get the prescribed value, others extrapolate. Only numeric specs work here; symbolic specs need to flow through the codegen / Firedrake-DG path.

face_gradient(Q_inner, Q_face, Qaux_inner, normal, d_face, time, parameters)#

Numpy: Neumann rows get the prescribed gradient; others zero. Numeric specs only (same caveat as face_value).

name = 'WindStress'#
class zoomy_core.model.boundary_conditions.SystemExtrapolation(tag=None)#

Bases: object

Apply Extrapolation to all equations in the system.

apply_to_system_bcs(system_bcs, tag=None)#
class zoomy_core.model.boundary_conditions.SystemPeriodic(tag=None, periodic_to_physical_tag='')#

Bases: object

Apply Periodic to all equations in the system.

apply_to_system_bcs(system_bcs, tag=None)#
class zoomy_core.model.boundary_conditions.SystemWall(tag=None, permeability=0.0, wall_slip=1.0)#

Bases: object

System-aware wall BC: Extrapolation for scalars, reflection for momentum.

Applied via system.boundary_conditions.apply(SystemWall(), tag="right"). The Wall BC holds a reference to the system and reads its equations to determine scalar vs momentum fields automatically.

Parameters:
  • tag (str) – Boundary tag (e.g. “right”, “bottom”).

  • permeability (float) – 0 = impermeable (default), 1 = fully permeable.

  • wall_slip (float) – 1 = free-slip (default), 0 = no-slip.

apply_to_system_bcs(system_bcs, tag=None, system=None)#
class zoomy_core.model.boundary_conditions.WallMomentumBC(tag, system_bcs, permeability=0.0, wall_slip=1.0, use_gradient=True)#

Bases: object

Wall BC for momentum equations — reads the system to build reflection.

Holds a reference to the SystemBoundaryConditions (and thus knows which equations exist). At compile time, determines the momentum vector grouping automatically from the equation names.

The normal/tangential decomposition works for any system derived from INS: SWE (hu), SME (hu0, hu1, …), VAM (hu, hv, hw moments), full INS.

property momentum_equations#

Momentum equations in the current system.

zoomy_core.model.boundary_conditions.compile_system_bcs(system_bcs, equation_variable_map, dimension)#

Translate system-aware BCs into the legacy BoundaryConditions container.

Reads per-equation, per-tag BCs from system_bcs and produces a BoundaryConditions with one entry per tag. The equation_variable_map maps equation names to variable indices so the Wall BC knows which indices form the momentum vector.

Parameters:
  • system_bcs (SystemBoundaryConditions) –

  • equation_variable_map (dict) – {equation_name: [var_index, ...]}

  • dimension (int) – Model dimension (1 or 2 for horizontal).

Return type:

BoundaryConditions

class zoomy_core.model.boundary_conditions.BoundaryConditions(boundary_conditions=None, **params)#

Bases: Parameterized

BoundaryConditions. (class).

boundary_conditions_list = []#
property list_sorted_function_names#

List sorted function names.

property boundary_conditions_list_dict#

Boundary conditions list dict.

get_boundary_condition_function(time, X, dX, Q, Qaux, parameters, normal, function_name='boundary_conditions')#

Get boundary condition function.

name = 'BoundaryConditions'#
get_boundary_gradient_function(time, X, dX, Q, Qaux, parameters, normal, function_name='boundary_gradients')#

Indexed symbolic kernel for the boundary face-normal gradient ∂Q/∂n.

Same shape and contract as get_boundary_condition_function(): a Function whose first argument is the BC index, with a Piecewise body dispatching to each BC subclass’s BoundaryCondition.compute_boundary_gradient(). The default per BC is zero Neumann (matches Extrapolation’s gradient); subclasses override when a non-zero gradient is part of the BC.