Explicit network step¶
The default network driver (advance_network): an SSP-RK2 or SSP-RK3 step
of every pipe, junction volume and closure state at the acoustic CFL step,
with the operator-split sources applied once after the last stage.
strang=True routes the same entry point to the Strang-split reacting
integrator, the third chart. The contracts of every function below are in
their docstrings (the standard is
Function contracts and flow charts).
One step¶
What enters: the built pipes, junctions and far boundary conditions, t_end,
the CFL and the optional Δt controls (dt_fixed, dt_hrr_fraction,
dt_heat_fraction). The junctions' neck pipes join the pipe list once, at
the start (network_pipes).
flowchart TD
IN["pipes, junctions, far BCs, t_end, cfl, rk, dt knobs"] --> S{"strang?"}
S -- yes --> STR["_advance_network_strang_impl (third chart)"]
S -- no --> B["_ExplicitNetwork.build: necks added, packed first-order pipes, SoA rows, orifice cylinders tagged"]
B --> RK{"_check_network_rk"}
RK -- "not ssp_rk2 / ssp_rk3" --> X1["ValueError"]
RK --> T{"t < t_end?"}
T -- "no" --> OUT["t reached; every state advanced in place; clock.t = t"]
T -- "budget spent short of t_end" --> X2["RuntimeError: max_steps exhausted"]
T -- yes --> LC{"poll_live_control"}
LC -- stop --> OUT
LC --> G["refresh_network_gamma, then fill_ghosts (far BCs and ports)"]
G --> DT{"step_dt: packed / per-pipe CFL step, or dt_fixed; HRR cap; wall-heat cap"}
DT -- "NaN or 1e300-sentinel step on any pipe" --> X3["_raise_nonfinite_network_dt: RuntimeError naming the pipe (cell diagnostic for a lone rho <= 0 or p <= 0)"]
DT -- "dt <= 0 or non-finite, before the t_end clamp" --> X4["assert_advancing_dt: NonAdvancingStepError"]
DT --> SN["snapshot: start-of-step copies"]
SN --> E1["euler_stage: stage_rates at weight 1, forward Euler of every state; soot, housing and port u_n advance here only"]
E1 --> K{"rk"}
K -- ssp_rk2 --> S2["ssp_stage rk2_stage2 at t + dt"]
K -- ssp_rk3 --> S3["ssp_stage rk3_stage2 at t + dt, then rk3_stage3 at t + dt/2 (weight 4)"]
S2 --> P["post_rk: regen species fold, CSF, urea spray at t, fuel step"]
S3 --> P
P --> TH["advance_thermal_couplings: coolant and walls"]
TH --> H["hrr_next_dt_limit (when dt_hrr_fraction > 0); t += dt"]
H --> T
One stage's rates¶
stage_rates is the same for every stage. The order matters: the species
flux is recovered from the mass row of the residual, so every source that
lands on that row (the DPF trap, the valve) comes after it.
flowchart TD
R0["residuals"] --> SOA["_soa_into: compiled MUSCL rows"]
R0 --> PK["_packed_into: packed first-order rows"]
R0 --> PP["_pipe_residual: the rest, closure cached per pipe"]
SOA -- "kernel fault" --> XR["the pipe re-run alone: _bad_residual_state_error names it; no single pipe -> RuntimeError on the buffers"]
PK -- "kernel fault" --> XR
PP -- "ZeroDivisionError / FloatingPointError" --> XR
SOA --> CL["catalyst, DPF cake, regen and substrate-wall sources onto R[:, 1:3]"]
PK --> CL
PP --> CL
CL --> SP["_species_rate: ghost pads (feeds), telescoped face flux anchored on _left_boundary_mass_flux, advection, reaction, DPF trap (debits R[:, 0])"]
SP --> J["_accumulate_at_weight: junction volume rates at the stage weight"]
J --> V["_valve_sources_into: cylinder valve mass, momentum, energy and species off the runner cell"]
V --> OUT["_StageRates"]
The Strang-split step¶
advance_network(..., strang=True): T(Δt/2) ∘ C(Δt) ∘ T(Δt/2), where T
is the plain loop above with the reaction and the doser off, sub-cycled at
the acoustic step, and C the stiff per-cell chemistry. With
chem_every_n > 1 it is a Lie super-cycle: T(Δt) every step, C over the
accumulated window every n-th step.
flowchart TD
IN["as above, plus chem_substeps, chem_every_n, chem_interval"] --> V{"chem_every_n >= 1 and chem_substeps >= 1?"}
V -- no --> X1["ValueError"]
V --> T{"t < t_end?"}
T -- "budget spent short of t_end" --> X2["RuntimeError"]
T -- no --> OUT["t reached; clock.t = t"]
T -- yes --> C{"_strang_step_cfl: live control and CFL ramp"}
C -- "stop" --> FL["pending super-cycle chemistry reacted, then stop"]
FL --> OUT
C --> DT{"fill_network_ghosts, then _strang_step_dt"}
DT -- "non-finite pipe step, dt <= 0" --> X3["RuntimeError / NonAdvancingStepError"]
DT --> TR["_StrangTransport with the run's clock: each sub-call's BCs see the run time"]
TR --> N{"chem_every_n == 1?"}
N -- yes --> SYM["_strang_symmetric_step: T(dt/2), _strang_chem_burst(dt), T(dt/2)"]
N -- no --> SC["_strang_supercycle_step: T(dt); C over the window on the n-th step, the last step, or the interval gate"]
SYM --> END["_strang_end_of_step: coolant and walls once, urea at the true t"]
SC --> END
END --> H["hrr_next_dt_limit; t += dt"]
H --> T
Functions¶
src/aeolus1d/solver/network_timeloop.py::advance_networksrc/aeolus1d/solver/solver_ops.py::network_pipessrc/aeolus1d/solver/network_timeloop.py::_ExplicitNetwork.buildsrc/aeolus1d/solver/network_timeloop.py::_soa_residual_rowssrc/aeolus1d/solver/network_timeloop.py::_check_network_rksrc/aeolus1d/solver/solver_ops.py::poll_live_control@3src/aeolus1d/solver/solver_ops.py::refresh_network_gammasrc/aeolus1d/solver/network_timeloop.py::_ExplicitNetwork.fill_ghostssrc/aeolus1d/bc/base.py::fill_network_ghostssrc/aeolus1d/solver/network_timeloop.py::_ExplicitNetwork.step_dtsrc/aeolus1d/solver/timeloop.py::pipe_min_dt_dispatchsrc/aeolus1d/solver/network_timeloop.py::_heat_transfer_dt_limitsrc/aeolus1d/solver/network_timeloop.py::_raise_nonfinite_network_dtsrc/aeolus1d/solver/solver_ops.py::assert_advancing_dtsrc/aeolus1d/solver/network_timeloop.py::_ExplicitNetwork.snapshotsrc/aeolus1d/solver/network_timeloop.py::_snapshot_rhoYsrc/aeolus1d/solver/network_timeloop.py::_ExplicitNetwork.euler_stagesrc/aeolus1d/solver/network_timeloop.py::_ExplicitNetwork.ssp_stagesrc/aeolus1d/solver/network_timeloop.py::_ssp_mixsrc/aeolus1d/solver/network_timeloop.py::_combine_port_u_nsrc/aeolus1d/solver/network_timeloop.py::_advance_port_u_nsrc/aeolus1d/solver/network_timeloop.py::advance_shaft_housingsrc/aeolus1d/solver/network_timeloop.py::_clip_T_cake_maxsrc/aeolus1d/solver/network_timeloop.py::_ExplicitNetwork.post_rksrc/aeolus1d/closures/filter.py::regen_species_foldsrc/aeolus1d/closures/filter.py::apply_csf_transientsrc/aeolus1d/solver/solver_ops.py::apply_urea_spray_to_pipesrc/aeolus1d/solver/solver_ops.py::advance_thermal_couplingssrc/aeolus1d/solver/solver_ops.py::hrr_next_dt_limitsrc/aeolus1d/solver/network_timeloop.py::_ExplicitNetwork.stage_ratessrc/aeolus1d/solver/network_timeloop.py::_ExplicitNetwork.residualssrc/aeolus1d/solver/network_timeloop.py::_ExplicitNetwork._soa_intosrc/aeolus1d/solver/network_timeloop.py::_ExplicitNetwork._packed_intosrc/aeolus1d/solver/network_timeloop.py::_pipe_residualsrc/aeolus1d/solver/network_timeloop.py::_build_pipe_residual_fnsrc/aeolus1d/solver/timeloop.py::make_pipe_residual_fnsrc/aeolus1d/solver/network_timeloop.py::_bad_residual_state_errorsrc/aeolus1d/closures/catalyst.py::catalyst_rates_intosrc/aeolus1d/closures/filter.py::cake_intosrc/aeolus1d/closures/filter.py::regen_intosrc/aeolus1d/closures/filter.py::substrate_wall_intosrc/aeolus1d/solver/network_timeloop.py::_species_ratesrc/aeolus1d/solver/network_timeloop.py::_species_ghost_pad_primarysrc/aeolus1d/solver/network_timeloop.py::_species_ghost_pad_extrassrc/aeolus1d/solver/network_timeloop.py::_inflow_ghost_extrassrc/aeolus1d/solver/network_timeloop.py::_species_flux_needs_telescopingsrc/aeolus1d/solver/network_timeloop.py::_telescoped_face_mass_fluxsrc/aeolus1d/solver/network_timeloop.py::_telescoped_face_mass_flux_quasi1dsrc/aeolus1d/solver/network_timeloop.py::_left_boundary_mass_fluxsrc/aeolus1d/solver/network_timeloop.py::_species_advection_ratessrc/aeolus1d/solver/network_timeloop.py::_overlay_species_reactionsrc/aeolus1d/solver/network_timeloop.py::_species_reaction_temperaturesrc/aeolus1d/solver/network_timeloop.py::_overlay_filter_trapsrc/aeolus1d/solver/network_timeloop.py::_accumulate_at_weightsrc/aeolus1d/solver/network_timeloop.py::_valve_sources_intosrc/aeolus1d/solver/network_timeloop.py::_valve_species_intosrc/aeolus1d/solver/network_timeloop.py::_advance_network_strang_implsrc/aeolus1d/solver/network_timeloop.py::_strang_step_cflsrc/aeolus1d/solver/network_timeloop.py::_strang_step_dtsrc/aeolus1d/solver/solver_ops.py::HRRSnapshot.takesrc/aeolus1d/solver/network_timeloop.py::_StrangTransport.advancesrc/aeolus1d/solver/network_timeloop.py::_OffsetClock.t@2src/aeolus1d/solver/network_timeloop.py::_transport_max_stepssrc/aeolus1d/solver/network_timeloop.py::_strang_symmetric_stepsrc/aeolus1d/solver/network_timeloop.py::_strang_supercycle_stepsrc/aeolus1d/solver/network_timeloop.py::_strang_chem_burstsrc/aeolus1d/solver/chemistry_ops.py::chemistry_step_on_pipessrc/aeolus1d/solver/network_timeloop.py::_strang_end_of_step