zoomy_core.fvm.solver_dae_numpy module#
DAE solver (numpy backend) — index-1 DAE-PDE integrator via Ascher-Ruuth-Spiteri IMEX-Runge-Kutta time stepping.
Sits next to HyperbolicSolver and IMEXSolver in
zoomy_core.fvm and reuses every shared piece of the framework:
SystemModelis the single symbolic source-of-truth;SystemModel.from_modelauto-scans all non-state Function and Derivative atoms intoaux_state+ a structuredSystemModel.aux_registry.NumpyRuntimeModellambdifies the operator matrices into(Q, Qaux, p) → ndarraycallables.ensure_lsq_mesh()promotes the input mesh toLSQMesh, exposingcompute_derivativesfor the registry- drivenupdate_qauxwalker.Boundary-condition objects (
Extrapolation,Lambda,InflowOutflow, …) supply face values viaface_value.Solver.update_q/Solver.update_qaux(registry-aware default) fire after every step.
Time integration: Ascher-Ruuth-Spiteri IMEX-Runge-Kutta (ARS232 / ARS343)
on the singular DAE M(Q)·∂_t Q = R(Q, Qaux, p). Aux is updated
once per step (lagged through the Newton iteration), keeping the
Jacobian small and reusing the standard Solver.update_qaux hook.
Spatial scheme: Rusanov flux + non-conservative path-integral
fluctuations, mirroring NonconservativeRusanov but driven by
the SystemModel runtime (so derivative-aux entries like ∂_x h flow
through as ordinary Qaux components, no special-casing). Boundary
faces use BC.face_value(Q_inner, Qaux_inner, normal, d_face, time,
parameters).
- class zoomy_core.fvm.solver_dae_numpy.DAESolver(**kwargs)#
Bases:
SolverIndex-1 DAE-PDE solver with IMEX-RK time stepping.
At
reconstruction_order=1this solver is the validated correctness reference for the VAM chain: lake-at-rest is preserved to machine precision and a perturbation propagates with bounded mass loss.At
reconstruction_order=2the spatial scheme is also correct — lake-at-rest over a bump is well-balanced to ~1e-14 (the η = h+bSurfaceReconstruction+ the cell-interior non-conservative integral telescope exactly), and the slope limiter is frozen through the Newton iteration sof_Iis a smooth function of the stage unknown. But the time integration does not converge: the monolithic IMEX-ARK stage Jacobian is ill-conditioned (cond ~1e7), concentrated in the algebraic pressure-constraint rows. At that conditioning the finite-difference Jacobian (step ~1e-7) is unreliable, so the stage Newton degrades from quadratic to slow linear convergence and does not reachnewton_tolwithinnewton_maxit.This is structural, not a bug: the monolithic DAE couples a well-conditioned hyperbolic evolution block and an ill-conditioned elliptic pressure-constraint block into a single FD Jacobian. The fix is the Chorin / projection split — an explicit hyperbolic predictor (where the order-2 reconstruction lives, no Jacobian needed) plus a separate linear elliptic pressure solve (which can be preconditioned properly). The split solver is the supported home for order 2; this class stays the order-1 reference.
- time_end = 0.1#
- method = 'ars343'#
- newton_tol = 1e-09#
- newton_maxit = 30#
- h_index = 0#
- nc_integration_order = 3#
- reconstruction_order = 1#
- limiter = 'venkatakrishnan'#
- well_balanced = True#
- jacobian_mode = 'sparse_fd'#
- compute_dt = None#
- setup_simulation(mesh, model, *, write_output=False)#
Build operators + state once, including BC plumbing, output infrastructure, and the registry-driven Qaux walker.
- f_E(t, Y)#
- f_I(t, Y)#
Implicit RHS: per-cell
M_evol⁻¹·R_evolon evolution rows; constraint residual on algebraic rows.Aux is held fixed at
self._sim_Qaux(refreshed once per timestep) — the lagged-aux Newton convention.
- J_I(t, Y)#
- project_to_manifold(Q, *, time=0.0, tol=1e-10, maxit=20)#
Newton-project
Qonto the algebraic constraint manifoldf_I[alg] = 0by adjusting algebraic state entries.Aborts (returns the original
Q) if the Newton residual does not decrease or if any iterate becomes non-finite — the caller can then proceed with the un-projected IC and let the IMEX-ARK Newton (which uses a more conservative update) do the projection.
- step(dt)#
One IMEX-ARK step on the stored state.
Convention: refresh
self._sim_Qauxviaupdate_qauxonce per step (lagged through the Newton iteration), applyupdate_qto the new state after. The slope-limiter coefficients are frozen the same way — computed once from the lagged state sof_Istays smooth in the Newton unknown.
- run_simulation()#
- solve(mesh, model, *, write_output=True)#
- export_vtk(*, field_names=None, aux_field_names=None, filename='dae_output', skip_aux=False)#
Post-process HDF5 snapshots to a VTK time series for Paraview. Requires
write_output=Trueat setup time.
- name = 'DAESolver'#