ADR-0004 — Implicit-upwind transport for quasi-steady species¶
Status: Accepted
Context¶
The quasi-steady (QS) solver removes the acoustic-CFL floor so a long transient
(e.g. a 6000 s aftertreatment ads/des run) fast-forwards at a macro step set by
qs_cfl_adv, which is routinely > 1. The QS species transport originally
advanced the gas-species mass fractions with an explicit forward-Euler upwind
update. Forward-Euler upwind advection is only stable for CFL ≤ 1, so at the QS
macro step it went unstable and blew up the tracer fields — any past QS run at
qs_cfl_adv > 1 has suspect species output.
Decision¶
QS species transport uses an unconditionally-stable implicit-upwind march
(_qs_implicit_species / _qs_implicit_species_kernel in
src/aeolus1d/solver/quasi_steady_network.py) — a single downstream sweep
analogous to the QS steady-energy march, solving the implicit upwind update
rather than stepping it explicitly. This is gated by species_implicit_upwind
(default on for the QS driver).
Consequences¶
- QS species are stable at the large macro steps the QS driver exists to take;
the tracer blow-up at
qs_cfl_adv > 1is fixed. - Implicit upwind is first-order and adds numerical diffusion at large CFL — acceptable for the slowly-varying QS composition fields it transports, but it means a QS species profile is not a high-accuracy advection result (consistent with the QS driver's whole premise).
- Provenance caveat worth remembering: results from before this fix, run
under the QS driver at
qs_cfl_adv > 1, cannot be trusted for species/tracer channels and should be re-run.
References¶
src/aeolus1d/solver/quasi_steady_network.py:650—_qs_implicit_species(kernel_qs_implicit_species_kernelat:720).species_implicit_upwind([case]knob) — see the update note below.
Update 2026-07: The QS driver now applies the implicit-upwind species march
unconditionally (_qs_implicit_species is called directly in the QS advance
loop; the flag is never read on the QS path), so the decision above still holds
but is no longer gated per case. The species_implicit_upwind [case] knob
(schema default False) today governs a different path: whether the
implicit-Euler / Radau driver reuses this same backward-Euler march in place
of its explicit, acoustic-CFL-bound species sub-stepping
(src/aeolus1d/solver/implicit_network.py). The QS transport decision recorded
here is unchanged.