Model#
A Model is the symbolic PDE: state, parameters, closures and boundary
conditions, derived from a vertical ansatz. It has no mesh and no numerics.
What you write: a model family with its options.
from zoomy_core.model.models import SME
model = SME(level=0, dimension=3, closures=[...], boundary_conditions=...)
choice |
options (default) |
|---|---|
family ( |
|
|
number of velocity moments above the depth average ( |
|
spatial dimension including the vertical: 2 = (x, z), 3 = (x, y, z) |
|
stress pieces, one per stress component: |
|
per mesh tag (below) |
|
|
Boundary conditions (zoomy_core.model.boundary_conditions), each on one mesh
tag, collected in BoundaryConditions([...]) or passed as a list:
class |
meaning |
|---|---|
|
reflecting (free-slip) wall; |
|
prescribed value of a field |
|
prescribed normal gradient |
|
zero gradient (transmissive) |
|
prescribe some fields, extrapolate the rest |
|
periodic seam |
|
face values from a user function |
|
preCICE interface (see Backends) |
Every BC feeds three channels, the data structures its value goes to:
channel |
what |
consumed by |
|---|---|---|
|
the state on the boundary face |
the numerical flux (Riemann problem) |
|
the value at the mirror image of the inner cell centre; by default from the face value ( |
gradients, limiters, derivative aux, diffusion |
|
a prescribed dQ/dn on the face (Neumann data; 0 unless set) |
diffusion, the LSQ boundary closure |
Any BC can take any channel from another BC, on the fields of that BC’s on:
Wall(tag="w", ghost=Dirichlet(on="momentum", value=0)) (reflecting Riemann state, no-slip
stencils), Wall(tag="w", normal_gradient=Flux(on="h", gradient=2.0)).
A new BC subclasses BoundaryCondition and implements only what differs:
compute_boundary_condition (the face value; set boundary_value_kind = BoundaryValueKind.face when it is a true face value), compute_ghost_state (only if the
stencils need something else), compute_boundary_gradient (Neumann data). Wall is the
template: about 20 lines building the reflected state from normal and the momentum groups.
The kernels are symbolic, so every backend gets them.
Model parameters are param parameters, like the solver settings (Solvers): the
class declares them, the constructor’s arguments set them, and a misspelt name gets the closest
one (SME(levl=1): TypeError: SME has no setting 'levl'; did you mean 'level'?).
Connects to: SystemModel.from_model(model) (SystemModel).
model.describe() shows what was built. Models without a vertical ansatz
(the compressible Euler equations, zoomy_core.systemmodel.euler.compressible_euler)
are built directly as a SystemModel.
API: zoomy_core.model.