zoomy_core.fvm.solver_numpy module

zoomy_core.fvm.solver_numpy module#

FVM solver for hyperbolic PDE systems (numpy backend).

Uses the symbolic Riemann solver (riemann_solvers.py) for flux computation. No dependency on legacy flux.py or nonconservative_flux.py.

Solver hierarchy:
Solver (base: init, create_runtime, BCs)
-> HyperbolicSolver (explicit time stepping + symbolic Riemann flux)

-> setup_simulation(mesh, model) -> run_simulation() -> Q, Qaux -> step(dt): apply_bcs -> reconstruct -> flux -> ode_step -> update_state

class zoomy_core.fvm.solver_numpy.Solver(**kwargs)#

Bases: Parameterized

Base solver class: initialization, runtime creation, boundary conditions.

settings = None#
initialize(mesh, model)#
create_runtime(Q, Qaux, mesh, model)#

Build the numpy runtime from a SystemModel.

Contract: model is a SystemModel — the self-contained numerical model. Every setup_simulation normalises its input to a SystemModel before reaching here. The runtime comes from NumpyRuntimeModel.from_system_model(); the numeric parameter array from parameter_values. Numerical regularisation, if wanted, is a separate SystemModel SystemModel pass applied before this point.

update_q(Q, Qaux, mesh, model, parameters)#

Apply model.update_variables (h-clamp, momentum ramp) at each cell.

update_variables is carried through the SystemModel and exposed on the runtime — the identity for models with no per-cell transform. It is None only for SystemModels assembled directly without one (e.g. split sub-systems); then this is a genuine no-op, not a legacy fallback.

update_qaux(Q, Qaux, Qold, Qauxold, mesh, model, parameters, time, dt)#

Default: walk model._chain_systemmodel.aux_registry (or self._sm.aux_registry if set up that way) and fill every kind == 'derivative' row via LSQMesh.compute_derivatives on the underlying source field (state Q for state derivatives, Qaux for derivatives of function-aux entries).

Subclasses override to supply the kind == 'function' rows (e.g. user-supplied bathymetry, time-dependent forcing) and call super().update_qaux(...) to handle the derivative part.

No-op if no SystemModel / registry is attached.

name = 'Solver'#
class zoomy_core.fvm.solver_numpy.HyperbolicSolver(**kwargs)#

Bases: Solver

Explicit time-stepping solver using the symbolic Riemann solver.

Core methods:

setup_simulation(mesh, model) – build all operators once run_simulation() – time loop: compute_dt -> step -> output step(dt) – one timestep (readable, no if-clauses) solve(mesh, model) – convenience: setup + run

time_end = 0.1#
min_dt = 1e-06#
compute_dt = None#
initialize(mesh, model)#
get_compute_max_abs_eigenvalue(mesh, model)#
get_flux_operator(mesh, model)#
get_compute_source(mesh, model)#

Compound source operator: evaluates both the implicit source slot and the explicit source_explicit slot at the current state and sums them.

This backend is explicit-only (FE/SSP-RK), so the IMEX split a Firedrake backend respects is collapsed here — all source contributions go to the RHS evaluated at the current state. Backends that genuinely support IMEX (e.g. Firedrake) keep source in the source-step Newton and source_explicit in the convective step.

get_compute_source_jacobian_wrt_variables(mesh, model)#
setup_simulation(mesh, model, write_output=True)#

Build all operators once. Stores simulation state on self.

model may be a Model, a SystemModel, or a NumericalSystemModel. Plain models are auto-promoted through Model → SystemModel → NSM internally; when an NSM is passed directly its numerical slots (reconstruction order, limiter, regularization) seed the solver attributes and its auto-resolved LSQ degree drives the mesh stencil.

step(dt)#

One explicit timestep (ghost-cell-free).

BCs are evaluated inline inside the flux operator — no separate ghost-cell filling step. Loops are split into interior/boundary.

O1 (RK1): flux → advance O2 (RK2/Heun): flux → advance → flux → average

run_simulation()#

Time loop: compute_dt -> step -> post_step -> output.

solve(mesh, model, write_output=True)#

Convenience: setup_simulation + run_simulation.

name = 'HyperbolicSolver'#
class zoomy_core.fvm.solver_numpy.FreeSurfaceFlowSolver(**kwargs)#

Bases: HyperbolicSolver

Explicit FVM for free-surface flows (SWE, SME, VAM).

Uses positive (hydrostatic reconstruction) Rusanov with wet/dry handling. Requires model variables ‘b’ and ‘h’.

name = 'FreeSurfaceFlowSolver'#