zoomy_core.systemmodel.system_model#
Symbolic operator-form PDE system (SystemModel) extracted from a Model: flux,
nonconservative matrix, source, diffusion, eigenvalues and boundary conditions in operator
slots.
Sits between Model and NumericalSystemModel; also holds the system-level operations that
repack operators in place.
Module Contents#
Classes#
How a Riemann solver bounds the wave speed rho(A_n) when no closed-form eigenvalues exist. |
|
Operator-form PDE system |
|
Row view of a |
|
Markdown (Jupyter |
|
System-level op: substitute the mass equation into every row with a nonzero |
|
System-level op: repack the gravity term |
|
System-level op: divide each evolution row by its diagonal mass entry |
Functions#
Canonical outward face-normal symbols |
|
Route the derivation function group |
|
Context manager permitting a build to return a |
Data#
API#
- zoomy_core.systemmodel.system_model.face_normal_symbols(n_dim)#
Canonical outward face-normal symbols
n0 ... n_{n_dim-1}, the one naming convention shared bySystemModel.normaland the derivations.
- zoomy_core.systemmodel.system_model.OPERATOR_ARG_SLOTS#
None
- zoomy_core.systemmodel.system_model.register_function_slot(group_name: str, sm_attr: str) None#
Route the derivation function group
group_nameto theSystemModelattributesm_attr(e.g. a derived wall BC to a boundary-condition slot).
- class zoomy_core.systemmodel.system_model.SpectralRadius#
Bases:
zoomy_core.misc.options.OptionHow a Riemann solver bounds the wave speed rho(A_n) when no closed-form eigenvalues exist.
Initialization
Initialize self. See help(type(self)) for accurate signature.
- eig#
‘eig’
- power#
‘power’
- bound#
‘bound’
- class zoomy_core.systemmodel.system_model.SystemModel#
Operator-form PDE system
M dQ/dt + div(F + P) + sum_d B[:,:,d] d_d Q - S = 0with operators indexed(equation_row, state_col[, dim]). It may be rectangular (equation_to_state_indexmaps equations to state entries); derived operators are cached or refreshed byrefresh_derived_operators.- time: sympy.Symbol#
None
- space: List[sympy.Symbol]#
None
- state: List[Any]#
None
- aux_state: List[Any]#
None
- parameters: zoomy_core.misc.misc.Zstruct#
None
- flux: zoomy_core.misc.misc.ZArray#
None
- hydrostatic_pressure: zoomy_core.misc.misc.ZArray#
None
- nonconservative_matrix: zoomy_core.misc.misc.ZArray#
None
- source: zoomy_core.misc.misc.ZArray#
None
- mass_matrix: zoomy_core.misc.misc.ZArray#
None
- eigenvalues: Optional[zoomy_core.misc.misc.ZArray]#
None
- eigenvalues_cfl: Optional[zoomy_core.misc.misc.ZArray]#
None
- source_jacobian_wrt_variables: Optional[zoomy_core.misc.misc.ZArray]#
None
- source_jacobian_wrt_aux_variables: Optional[zoomy_core.misc.misc.ZArray]#
None
- flux_jacobian_wrt_aux_variables: Optional[zoomy_core.misc.misc.ZArray]#
None
- derive_jacobians: bool#
False
- derive_source_jacobians: bool#
‘field(…)’
- normal: Optional[zoomy_core.misc.misc.Zstruct]#
None
- parameter_values: Optional[zoomy_core.misc.misc.Zstruct]#
None
- equation_to_state_index: Optional[List[int]]#
None
- boundary_conditions: Optional[Any]#
None
- aux_boundary_conditions: Optional[Any]#
None
- boundary_gradients: Optional[Any]#
None
- initial_conditions: Optional[Any]#
None
- aux_initial_conditions: Optional[Any]#
None
- update_variables: Optional[zoomy_core.misc.misc.ZArray]#
None
- update_aux_variables: Optional[zoomy_core.misc.misc.ZArray]#
None
- diffusion_matrix: Optional[zoomy_core.misc.misc.ZArray]#
None
- diffusion_matrix_explicit: Optional[zoomy_core.misc.misc.ZArray]#
None
- source_explicit: Optional[zoomy_core.misc.misc.ZArray]#
None
- reconstruction_variables: Optional[zoomy_core.misc.misc.ZArray]#
None
- state_from_reconstruction: Optional[zoomy_core.misc.misc.ZArray]#
None
- interpolate_to_3d: Optional[zoomy_core.misc.misc.ZArray]#
None
- project_from_3d: Optional[zoomy_core.misc.misc.ZArray]#
None
- position: Optional[Any]#
None
- equilibrium_reconstruction: str#
‘none’
- state_function_map: Optional[Dict]#
None
- vertical: Optional[Any]#
None
- unclassified_terms: List#
‘field(…)’
- history: List[Dict[str, str]]#
‘field(…)’
- admissible: Optional[zoomy_core.misc.misc.ZArray]#
None
- property n_equations: int#
Number of equations (rows of the operators).
- property n_state: int#
Number of state entries.
- property n_dim: int#
Number of space dimensions.
- property depth_scaled_state_indices: list#
State rows carrying one factor of the depth, i.e. every row except depth and bed, which a hydrostatic reconstruction must rescale by
h*/h.References
Audusse et al. 2004, https://doi.org/10.1137/S1064827503431090
- property discharge_state_indices: list#
Per horizontal direction, the state row that is the depth-integrated mass flux (
hu,q_x_0), read off the mass balance;-1where no unique row exists.
- property n_variables: int#
Number of state variables (equal to
n_equations).
- property n_aux_variables: int#
Number of aux variables.
- property n_parameters: int#
Number of parameters.
- property dimension: int#
Number of space dimensions (
ModelAPI alias ofn_dim).
- property variables: zoomy_core.misc.misc.Zstruct#
Zstruct view
name -> state Symbol(mirrorsModel.variables).
- update_variables_or_identity() zoomy_core.misc.misc.ZArray#
update_variablesas an explicit(n_eq, 1)expression, the identitystate[equation_to_state_index[i]]when the model has none; the C-family printers emit from this.
- property aux_variables: zoomy_core.misc.misc.Zstruct#
Zstruct view
name -> aux Symbol(mirrorsModel.aux_variables).
- position_struct() zoomy_core.misc.misc.Zstruct#
The length-3 position group
(x, y, z)that printers and analysis read; a bare system resolves the canonical symbols.
- operator_signature(name: str) zoomy_core.misc.misc.Zstruct#
The declared
argsZstruct of operatorname, built from this system’s symbols inOPERATOR_ARG_SLOTSorder; the single source every backend reads.
- operator(name: str) Any#
Operator
nameas abasefunction.Functionwhoseargsis the declared signature and whosedefinitionis the live array; backends only translate syntax.
- property eigenvalue_mode: str#
"symbolic"when a symbolic spectrum is carried,"numerical"when it was skipped (eigenvalues is None).
- attach_boundary_conditions(bcs, aux_bcs=None)#
Build the indexed symbolic BC kernels (
boundary_conditions,boundary_gradients,aux_boundary_conditions) from existingBoundaryConditionsobjects.Args
bcs: aBoundaryConditionscontainer (or list).aux_bcs: aux BCs; defaults to per-tag Extrapolation.
- property roles#
The declared state roles resolved against the current state (
systemmodel.roles.Roles).
- property tags#
The declared model tags (see
systemmodel/tags.py).
- declare_tags(*tags)#
Record model tags; returns
self.
- declare_roles(**roles)#
Record a role declaration (see
systemmodel.roles.declare_roles); returnsself.
- declare_admissible(constraints)#
Declare the admissibility list, expressions in
(Q, Qaux, p)that must stay>= 0(empty: every state admissible); returnsself.
- boundary_ghost_kernel()#
The ghost-state boundary kernel
(function, branches), built on demand (seebuild_boundary_ghost_kernel).
- admissible_constraints() list#
The admissibility list as sympy expressions: the declared one, else
[depth]for a free-surface system, else[].
- property is_square: bool#
True when
n_equations == n_stateand equations map identity-style.
- property stationary_indices: frozenset#
State indices whose row vanishes in every transport, source and diffusion slot, i.e. fields stationary by construction (e.g. the bed).
- field_index(field) int#
Integer state index of a field handle (Symbol or name matched by name, or an int bounds-checked); raises
ValueErrorotherwise.
- property quasilinear_matrix#
Flux Jacobian
dF/dQ + dP/dQ + B, computed lazily from the primaries on first access and cached; assigning re-seeds the cache.
- ensure_jacobians()#
Derive the source and flux jacobians now if absent (off by default, see
derive_jacobians); call before the runtime is lowered, since printers emit what is present.
- property eigensystem: zoomy_core.misc.misc.ZArray#
Opaque eigendecomposition of the normal-projected quasilinear matrix
A_n = sum_d n_d quasilinear_matrix[:, :, d].Returns
Flat row-major array
[lambda (n), R (n*n), L = R^-1 (n*n)].
- property numerical_eigenvalues: zoomy_core.misc.misc.ZArray#
Eigenvalues of
A_nasncalls to the opaque eigenvalue kernel, used for the wave speed when the model has no closed-formeigenvalues(SME, VAM).
- spectral_bound_iterations#
2
- use_spectral_radius_bound#
False
- spectral_radius_method#
None
- spectral_power_steps#
10
- spectral_power_safety#
1.06
- property spectral_radius_bound#
Closed-form scalar upper bound on
rho(A_n), theMinoverk <= iterationsof(max_i (|A_n|^k 1)_i)^(1/k), so the CFL needs no eigen-decomposition. Every candidate is an upper bound on its own, soiterationsbuys tightness only and the CFL cannot become unsafe.References
Golub, Van Loan 2013, https://doi.org/10.56021/9781421407944
- refresh_derived_operators(*, eigenvalues: bool = False)#
Recompute
quasilinear_matrixand the source jacobians from the current (possibly mutated) primaries;eigenvalues=Truealso re-derives the spectrum.
- assert_diagonal_mass_matrix()#
Check that
mass_matrixis diagonal and nonzero on every evolution row and zero on every algebraic row; raises otherwise.
- apply(operation, *, name: Optional[str] = None, description: Optional[str] = None)#
Apply a system-level operation in place; returns
self.
- has_active_source() bool#
True if any source row is nonzero at the configured parameter values (matched by symbol name).
- has_higher_moments() bool#
True if the system carries moment rows beyond the depth-averaged one.
- resolve_equilibrium_kernel(*, force_steady_ode: bool = False) str#
Which concrete well-balanced kernel a backend must run:
none/audussepass through, the Bernoulli family resolves tosteady_ode(friction, higher moments orforce_steady_ode) orbernoulli_closed_form.References
Pimentel-Garcia et al. 2022, https://doi.org/10.1016/j.jcp.2022.111152
- is_vertical_dependent(symbol) bool#
True if state
symbolis a vertical-dependent field such asu(t,x,zeta), False for depth-collapsed fields or when no vertical is known.
- classmethod from_model(model, Q=None, Qaux=None, canonical_source=None, dae=False, derive_source_jacobians=None) zoomy_core.systemmodel.system_model.SystemModel#
Build a
SystemModelfrom aModel; the single entry point. Production models with a_system_model_kinddispatch to their builder inmodel_builders, others go through_from_model_impl.Args
Q: state fields of a declarative model (required there).Qaux: aux fields; auto-populated whenNone.canonical_source: user-facing model that owns the source and explicit-diffusion overrides.dae: retain a non-diagonal or singular mass matrix (index-1 DAE) instead of requiring unit diagonal.derive_source_jacobians: override of the field of the same name.
- reconstruct_residuals()#
Re-assemble the row-wise residuals
M d_t Q + d_x F + d_x P + B d_x Q - Sas sympy expressions, with aux symbols back-substituted to their original atoms.
- expose_aux_atoms()#
Route every non-state symbolic input (bare Functions such as the bed, and Derivative atoms) of the operators into
aux_stateand record each inaux_registry.
- expose_functions_as_aux(function_names=None)#
Replace bare Function atoms (those named in
function_names, else all) by aux Symbols of the same name appended toaux_state.
- expose_derivatives_as_aux()#
Replace every
Derivative(target, axes...)atom in the operators by an aux Symbol{target}_{axes}and record it inaux_derivative_mapfor the solver to fill.
- change_state_variables(new_state, transform)#
Change the state variables in place, updating every state-dependent field (operators, derived operators, reconstruction pair, BC kernels, aux registry by the chain rule).
Args
new_state: new state vector of the same length.transform: maps each replaced OLD state entry to its expression in the new variables.
- remove_non_diagonal_h(**kwargs)#
Apply
RemoveNonDiagonalHto this system.
- assert_all_classified()#
Raise if any equation row carries an operator term the structural extractor could not classify into a slot; the strict counterpart of the build-time warning.
- describe_unclosed() str#
List the aux rows nothing computes (the model’s open terms), classifying each aux slot as computed, external or open.
- describe(full: bool = False) zoomy_core.systemmodel.system_model.SystemModelDescription#
A
SystemModelDescriptionrendering the core operators;full=Trueadds the derived slots.
- class zoomy_core.systemmodel.system_model.SystemModelRow(parent: zoomy_core.systemmodel.system_model.SystemModel, i: int)#
Row view of a
SystemModel: rowiof every stored matrix.Initialization
View row
iofparent.- property flux#
Row
iof the flux.
- property hydrostatic_pressure#
Row
iof the hydrostatic pressure.
- property source#
Entry
iof the source.
- property mass_matrix_row#
Row
iof the mass matrix.
- property nonconservative_matrix_row#
Row
iof the nonconservative matrix as an(n_eq, n_dim)array.
- class zoomy_core.systemmodel.system_model.SystemModelDescription(sm: zoomy_core.systemmodel.system_model.SystemModel, *, full: bool = False)#
Markdown (Jupyter
_repr_markdown_) and plain-text description of aSystemModel.Initialization
Describe
sm;fulladds the derived slots.
- class zoomy_core.systemmodel.system_model.RemoveNonDiagonalH#
System-level op: substitute the mass equation into every row with a nonzero
hentry in the mass matrix, moving theM[i,h] d_t hterm into the NCP matrix and source. The mass row must satisfyM[m,h] = 1and zero elsewhere; other mass-matrix entries are left alone.- name#
‘remove_non_diagonal_h’
- description#
‘Substitute mass equation into rows with non-zero ∂_t h coupling; clear M[i, h] for those rows.’
- class zoomy_core.systemmodel.system_model.HydrostaticReconstruction#
System-level op: repack the gravity term
g h d_x etafrom the chain’s(P, B)form to the standard SWEP = g h^2/2form that hydrostatic-reconstruction Riemann solvers expect. The bathymetry term is then supplied at runtime by the Audusse fluctuation.References
Audusse et al. 2004, https://doi.org/10.1137/S1064827503431090
- name#
‘hydrostatic_reconstruction’
- description#
“Convert chain’s g·h·η in (P, B) to standard SWE P = g·h²/2 for Audusse HR compatibility (drops -g·h·…”
- class zoomy_core.systemmodel.system_model.InvertMassMatrix#
System-level op: divide each evolution row by its diagonal mass entry
M_iiand setM_ii = 1. Requires a diagonal mass matrix on evolution rows and zero on algebraic rows (check withassert_diagonal_mass_matrix); state-dependent entries give a symbolic1/M_ii.- name#
‘invert_mass_matrix’
- description#
‘Divide each evolution row by its diagonal mass entry to reach canonical ∂_t Q form.’
- zoomy_core.systemmodel.system_model.allow_unclosed()#
Context manager permitting a build to return a
SystemModelthat still has unclosed terms, an explicit and greppable opt-in for inspecting open full-stress models.
- exception zoomy_core.systemmodel.system_model.UnclosedClosureError(unclosed, model_name='', system_model=None)#
Bases:
RuntimeErrorA declared closure reached the
SystemModelwith nothing closing it; carries the builtsystem_model.Initialization
Store the unclosed terms, the model name and the built system.
- describe() str#
The open-term listing (see
SystemModel.describe_unclosed).