Skip to content

Validation dossier

This page is the credibility artefact for aeolus1d's parity claims. It collects, in one place, the parity workflows that define "GT-POWER / AVL Cruise M standard" for this project, the checked-in case that exercises each, the reference dataset it is validated against, the current pass/fail verdict, and the wall-clock budget it runs inside.

Citable, frozen snapshot. This page is a living document and its numbers move as the code does. For a citation that will not move, use the frozen per-release report validation-report-v0.3.0.md — it pins the verdicts, meshes, reference types, and uncertainty classes at the v0.3.0 tag. Cite the report, not this page.

The thesis behind the project (see roadmap.md) is that parity is not feature-count parity with a 30-year funded Fortran product. It is validated competence on the core workflows at an acceptable wall-clock, every claim reproducible from a checked-in, text-defined case. This page is where that claim is made auditable: every row points at a file in the repository that you can run.

How to read the status column. ✅ banked means the suite's TOML grid runs green under its run_validation.py against the committed pass_criteria.toml on a fresh checkout. ⏳ pending means the case exists but the reference data or a closed-loop element is not yet in place. The honest, un-rounded numbers are in the per-workflow sections below — including the corners that fail and why.

The parity workflows

# Workflow Reference case Reference type Status Wall-clock
W1 Engine breathing / manifold tuning examples/validation/ricardo_ktm/, examples/validation/mendeley_ethanol_water/ mixed — see note. mendeley_ethanol_water: experiment (DOI 10.17632/yvb7khhbrj.1). ricardo_ktm: code-to-code vs Ricardo WAVE (IMECE2017-70638), reclassified 2026-08-30 ⚠️ breathing physics verified; quantitative match re-cal owed (orifice default, ADR-0008) seconds/operating-point
W1b HD-diesel engine, full breathing + turbo examples/validation/avl_epw_diesel_steady/ code-to-code (AVL Cruise M EPW steady sweep; vendor CSV no-derivatives, never committed) ⚠️ 3/3 ops PASS in ANCHORED mode; CV-A + CV-B both close; u_num on T_EXH. CORRECTED 2026-09-10 — this cell read "3/3 ops PASS both modes". The predictive mode does not gate T_EXH: the channel is report-only and NOT VALIDATED there, reading −44.9 / −113.4 / −80.9 K at 1200 / 1500 / 1800 (measured 2026-09-07). Predictive is the mode a user without the vendor CSV runs, so the shipped default is the ungated one. See run_validation.py::PREDICTIVE_REPORT_ONLY and docs/scope-and-limitations.md. ~10 min / 3 ops
W2 Turbo matching examples/validation/turbo_match/ (over examples/59_wastegate_boost_ctrl.toml) self-consistency (shaft power-balance + map fidelity — not external data) ✅ self-consistency check, 3/3 ~2.5 min / 3 points
W3 Aftertreatment drive cycle examples/avl_cruise_m/c02006_dpf_csf_regen_trans.toml code-to-code vs AVL Cruise M C02006 (DPF-CSF regen transient) ✅ runs end-to-end (numeric promotion in progress; co_conv_cat structurally blocked) ~6.5 min / 500 s cycle
W4 Acoustics / NVH examples/ muffler TL cases + aeolus1d acoustics CLI + examples/validation/gt_tmm_pipe/ + examples/validation/gt_acoustics_tl/ experiment (measured muffler TL), plus analytic + code-to-code vs GT-Suite TMM ✅ experiment-referenced since 2026-08-29 — RMS 0.92 dB below 1.2 kHz and 1.26 dB below 2 kHz over 122 measured points, with no fitted parameter; maintainer-run, data never committed seconds
W5 Electrified drive cycle examples/86_electrified_drive_cycle.toml (aeolus1d drive-cycle) self-consistency (parallel-hybrid SoC + energy bookkeeping) ✅ self-consistency check (energy-balance) seconds

Reference-type honesty (the W2/W4/W5 relabel, and the 2026-08-30 W1 split). This paragraph used to open "Only W1 is validated against experimental data". Both halves of that have since changed and the sentence is kept here, struck, because it was the basis of a maturity headline.

W1 is mixed, not experiment (corrected 2026-08-30 by reading the paper). Its ricardo_ktm half compares against the OEM column of Tables 2 + 3 of IMECE2017-70638, which is Ricardo WAVE's own simulated baseline — the thing the paper's tuning study computes a percentage gain over. The suite's README had asserted the opposite, that those numbers were "validated against the engine's chassis-dyno test … to within a few percent"; the paper's Figs. 3 + 4 show WAVE running 15-25 % above the dyno and attribute the gap to drivetrain and roller losses the simulation omits. A citation naming a simulation code as the source of an experimental reference should have been the tell. Detail and evidence in examples/validation/ricardo_ktm/README.md. The paper's dyno curves are real measured data and are digitisable; that is filed there as the route to an actual experimental reference, not claimed as one.

W1's experimental claim therefore rests on mendeley_ethanol_water alone (DOI 10.17632/yvb7khhbrj.1, 39/60), and the KTM's 6/10 is a code-to-code score. The headline it fed — the 2026-08-29 sweep's "of the five parity workflows exactly one carries an experimental reference, and it scores 6/10 and 39/60" — needs the 6/10 removed from it. The count of experiment-referenced suites is unchanged at three, because W4's gt_acoustics_tl and the DD13 suite both landed on 2026-08-29 and neither depended on this.

Its quantitative match is separately mid-re-calibration after the ADR-0008 breathing fix (see below). W2 and W5 are self-consistency checks — the solver is shown to agree with itself (conservation, energy bookkeeping), not with an external dataset. W4 is experiment-referenced as of 2026-08-29: examples/validation/gt_acoustics_tl/ compares the transfer-matrix transmission loss against a measured expansion chamber (191 points, 0-3202 Hz) and matches to 0.88 dB RMS below 1.2 kHz. Two caveats stated rather than buried. (a) Nothing is fitted as of 2026-08-29. It briefly was: the chamber length was recovered acoustically because gt_suite_native read it 10x too small, and that importer defect is now FIXED — it ignored GT's unitID and assumed millimetres, so files in cm/inch/m came out wrong by that unit's ratio, uniformly and therefore invisibly to an area-ratio check. The file's own 0.53996 m and the acoustically recovered 0.538 m agree to 0.36 %, which is what confirms the fix. Going blind cost 0.88 -> 0.92 dB RMS. (b) The suite is maintainer-run — the measurements are a vendor example distribution, never committed, and the harness skips cleanly without them, so this upgrades the reference type but not third-party reproducibility. The analytic and GT-Suite TMM checks are retained alongside. AVL traces. These are real evidence of different strength; the report states the type beside every number so a reader never mistakes a self-check for an experimental validation.

v1.0 = all parity workflows pass inside their wall-clock budget, plus this dossier and the perf baselines checked in, plus a Zenodo DOI minted on the release tag (see release.md). W5 (electrified) is included now that the hybrid drive-cycle deliverable runs.

W1 — Engine breathing / manifold tuning

What it proves. The Cylinder + WiebeCombustion + WoschniHeatTransfer cycle physics, the runner/manifold tuning that sets volumetric efficiency, and the per-cycle IMEP / ISFC reduction in aeolus1d.analysis.engine_metrics — validated against published experimental engine data, not against another simulator.

Ricardo WAVE KTM 510 cc SI — examples/validation/ricardo_ktm/

  • Reference: Aradhye & Bari (2017), Continuously Varying Exhaust Pipe Length and Diameter…, IMECE2017-70638. OEM brake-torque / power column of Tables 2 + 3, ten operating points 1000–10000 RPM.
  • Run: python examples/validation/ricardo_ktm/run_validation.py
  • Verdict — re-validated 2026-06-09 against the default orifice valve coupling (ADR-0008). Read in two regimes:
  • Breathing physics: verified correct. The compressible-orifice cylinder↔runner coupling conserves mass across the valve to <1e-10 (tests/integration/test_cylinder_valve_conservation.py), replacing a legacy coupling that lost ~(1 − Cd·lift) of the charge every valve event — a deficit that grew with RPM (same-build motoring A/B: trapped-air ratio 1.05 at 5000 RPM → 1.56 at 9000 RPM).
  • Quantitative match: 6/10 at the 25 % gate with the recommended --throttle --wall-heat invocation (3/10 bare), down from the legacy coupling's 8/10 on the same invocation. The single TOML is calibrated at one point (7000 RPM) with a textbook polydyne valve lift and no port-flow losses; with physically-correct breathing this idealised geometry now over-breathes (η_v 0.87–1.18, peaking 1.18 at 8000 RPM), so the fixed calibration over-predicts torque at every point — most at the 1000–2000 (cam over-admits at low RPM: 1000 RPM 48 vs 29 N·m) and 8000–9000 (runner ram peak misplaced vs the paper's 7000) corners. This is a case-calibration limitation, not a solver regression — bare-default reproduces the post-!188 numbers exactly, so breathing is unchanged across !189–!203; closing the match needs a per-RPM cam / fuel / spark table (a 10-point case, not the single-case demonstration this is), which is owed and tracked. The legacy 8/10 was a partly-fortuitous cancellation between the under-breathing leak and the idealised over-breathing cam.

The honest takeaway: the breathing solver is now trustworthy and conservation-pinned; the KTM case needs a per-RPM re-calibration (gated on proprietary OEM cam geometry) before its quantitative match is re-quoted.

Mendeley ethanol/water blends — examples/validation/mendeley_ethanol_water/

  • Reference: Mendeley Data, CC BY 4.0, DOI 10.17632/yvb7khhbrj.1 — single-cylinder Otto SI, ethanol/water blends across a compression-ratio sweep.
  • Run: python examples/validation/mendeley_ethanol_water/run_validation.py
  • ⚠️ 2026-08-15 note on the numbers and the diagnosis below. The same invocation scores 39/60 on the 2026-08-15 tree — and the same-day bisect attributed the difference to 643fc3fb (2026-07-01): until that fix the Livengood-Wu knock integral silently ratcheted a 10° timing retard on this scaffold, deflating predicted IMEP and flattering five gate-edge points, so the 44/60 was bug-flattered and 39/60 is the honest score (closure with the measured mechanism in BACKLOG_HISTORY.md, "Mendeley baseline drifted 44→39"). And the "charge-cooling + single-γ" structural diagnosis was implemented, measured over all 60 points, and retracted: charge cooling moves the prediction away from the data (39/60 → 36/60; predicted BMEP 9.27 → 9.55 bar against a measured 5.73 at 50 % water). The measured gap is combustion deterioration under water dilution — see the suite README's retraction. The verdict below is kept as written for the tree it measured.
  • Verdict — re-validated 2026-06-09 against the shipped-default orifice coupling (ADR-0008). 44/60 under both the legacy and the orifice coupling, at the 20/25/25 % tolerance bands (no re-tuning). The orifice is near-neutral here (~1 % on BMEP) because the suite is fixed-fuel: per-cycle fuel is prescribed from the paper's measured fuel-mass-flow, so the Wiebe heat release dominates indicated work and trapped air only moves the compression/pumping loop ~1 %. (Contrast the fuel-from-air Ricardo KTM suite, where the same coupling change swung breathing 5–56 % and moved the gate 8/10 → 6/10 — the fueling mode, not the coupling, is why one suite is sensitive and the other isn't.) The ~1 % nudge reshuffles gate-edge points without changing the count: the 0–30 % w/w band reads 40/40 under orifice (37/40 under legacy) — gate-edge realignment (it pulls three borderline CR-9.44 eta_i points that sat at 25.2–26 % rel error under the 25 % gate), not a model-physics gain — and an equal number of high-water passes tip out (40–50 %: 7/20 → 4/20), where aeolus1d already over-predicts BMEP. The 40–50 % corner is the documented structural gap: charge-cooling from the water fraction + the bulk single-γ Volume mapping, unaffected by the breathing coupling.
  • ✅ The suite now runs on the shipped-default orifice coupling (cylinder_orifice_valve_flow=True in the harness). Correction: earlier notes here called the Mendeley data "local-only (gitignored, not in CI)" — that was wrong. data/operating_points.csv is committed (allow-listed in data/.gitignore) and the suite is CI-reproducible; the legacy closure (2026-05-17) simply predated the orifice default (2026-06-07), which only changed the TOML build path and never reached the scaffold this suite uses.

U-Michigan heavy-duty diesel cylinder pressure — examples/validation/umich_diesel/

  • Reference: heavy-duty diesel single-cylinder pressure trace; the harness builds an aeolus1d cylinder via aeolus1d.scaffold.scaffold_single_cylinder_engine and compares CA50 (crank angle of 50 % mass-burned) and the pressure trace.
  • Status: ✅ LIVE — 9/9 measured operating points on the predictive path, 8/9 on the calibrated one. Corrected 2026-08-29: this row read "⏳ scaffolded, pending data fetch" and was stale. The suite's own README has recorded it as Active since the dataset was staged; the row here reasoned from umich_diesel/data/ being empty, which stopped being evidence once the harness gained $AEOLUS_DD13_DIR and the data was placed outside the tree. Same README-current / dossier-stale shape as the EPW IMEP_High row. Reference type: experiment, and — unlike every other maintainer-run suite here — the dataset is publicly obtainable at a stable handle (Deep Blue 2027.42/116203), so a third party can reproduce this by fetching it themselves. Licence permits research redistribution but no derivative works, which is why data/ stays empty and nothing is transcribed into the repository.

  • The predictive path is the result worth quoting. --predictive computes start of combustion and premixed fraction from the charge state (Hardenberg-Hase ignition delay + Watson premixed fraction) under one global calibration, with only the measured injector commands as per-point input — no per-point phasing tuning. It passes 9/9 on peak pressure, CA50 and gross IMEP, and beats the hand-calibrated Wiebe path on phasing.

  • One systematic bias, recorded rather than banded away. Gross IMEP is over-predicted at 9 of 9 points in the predictive path, mean +0.53 bar, and the offset falls monotonically with speed — +0.85 / +0.53 / +0.22 bar at 750 / 1100 / 1400 rpm. It survives the change of combustion model (calibrated: +0.74 / +0.36 / +0.18), so it sits in the closed-cycle thermodynamics rather than the burn, and peak pressure shows no matching structure. Consistent with under-modelled in-cylinder heat loss; the test is a Woschni hA sweep on these same points. In BACKLOG.md, not acted on.

Directly validates the multi-stage two-zone Wiebe + Woschni cylinder physics against a compression-ignition trace, the diesel complement to the SI KTM / Mendeley suites above.

AVL EPW heavy-duty diesel, steady sweep — examples/validation/avl_epw_diesel_steady/

  • Reference: AVL Cruise M EPW, a 12.9 L 6-cylinder turbocharged HD diesel: 6 cylinders on a split intake/exhaust manifold, compressor + VGT turbine on a shared shaft, charge-air cooler, HP-EGR leg. Code-to-code against AVL's own steady-state operating-point CSV.
  • The vendor CSV is no-derivatives and is never committed. The harness skips cleanly without it, so this row describes a maintainer-run suite.
  • Status: ✅ 3/3 operating points PASS, exit 0, in both modes (predictive and --anchor-bcs), re-measured 2026-08-08.

What is gated, and what is not. T_EXH, BMEP, IMEP_High, IMEP_Low, PFP, MFB50 and SOC are gated, each declaring scale, band_basis, floor, delta_min and band_op_set alongside exactly one tolerance. NOX and Q_WHT are report-only with measured reasons — the honest form of "not validated", as opposed to a tolerance too wide to fail.

Energy closure (the reason to believe the rest).

Control volume Result
CV-A — cylinder, [IVC, EVO) closes within max(1 %, 3×floor)
CV-B — whole network, full cycle 1.302 / 0.808 / 0.701 % of fuel against a 3 % threshold. Re-measured 2026-10-10 on the v0.4.0 tree: 0.001 % at all three ops, each half (cylinders / rest-of-network) under 3 % on its own.

CV-B did not close until 2026-08-08. The 4.3 % residual was the charge-air cooler: a 7–27 kW heat sink the audit enumerated as nothing, because its refusal for pipe heat closures probed attribute names the builder never sets. Confirmed by timestep refinement — the residual is invariant under CFL (4.317 → 4.316 → 4.316 %), so it was a missing term and not a sampling artefact — and the split localised it to the non-cylinder half of the network.

Numerical uncertainty. T_EXH carries u_num = ±0.035 °C from a three-level uniform mesh study (scale 1.0/1.5/2.25, observed order p = 1.286, asymptotic ratio 0.99996; re-measured 2026-10-10 on the v0.4.0 tree: ±0.015 °C, p = 2.28, ratio 0.99996, against anchored errors of −10.5 / −35.9 / −29.3 °C). Against a +20.5 °C model error that is negligible: the gap is model form, not mesh. u_val is not claimed — the AVL CSV documents no instrument uncertainty.

CI coverage without the vendor data. The golden row epw_diesel_engine pins the whole network state at t_end = 0.05 s (past heat release), screened bit-reproducible across 3 processes × NUMBA_NUM_THREADS ∈ {1,2,4}; tests/validation/test_epw_engine_selfconsistency.py checks CV-A closure, the valve specific-enthalpy identity, closed-period species conservation and the temperature clamp.

Open gaps, stated: the plenum wall term is PARTIALLY CLOSED (plenum_wall_fraction 0.0837, re-measured 2026-09-11 from 0.1646 — the sink has halved, two of three ops are now under the 0.08 "closed" line, and the max misses it by 0.0037; still not the dominant error sink, still not proven physical, and the halving did not move the T_EXH residual); NOX is report-only. Re-measured 2026-10-11 (--ops 3 predictive, main 56dad407): the compared value is now the core-zone model, reading 892.5 / 620.7 / 1229.2 ppm against AVL 293.1 / 240.4 / 509.4, a 2.67× over-prediction that does reproduce AVL's 1500 rpm dip. Peak flame T is 2648 / 2617 / 2755 K. The rest of this paragraph is the 2026-08-26 well-mixed account, kept as history. The core-zone model it calls for is the one now compared (docs/release-readiness.md). In that account the channel read 17.8 / 3964.9 / 5875.2 ppm against AVL 293 / 240 / 509 (2026-08-26). The N₂O kinetics defect that used to pin this channel to a constant is FIXED — the total rate is now 0.99–1.81× Heywood eq. 11.1, NO freezes kinetically, and moving the T_active_min gate 1500→1900 K shifts the answer by 0.08 % where it once shifted it 9.5×. What the flatness was hiding is a single quantity: the peak burnt-zone temperature runs 1995 / 2429 / 2577 K against the 2200–2800 K a diesel flame sheet holds at every load, because a well-mixed burnt zone sits near the global φ (0.41 → 0.67). exp(−38370/T) turns that 582 K swing into 330×. Closing it needs a local-φ / stoichiometric-core burnt zone; see docs/release-readiness.md and pass_criteria.toml for the measurement and for the new compensating pair (equilibrium_NO_ppm currently caps the 1800 rpm op) that must not be "fixed" first. The species pool does not close during gas exchange (~12 %, localised to valve-flow bookkeeping — closed-period accounting is exact).

W2 — Turbo matching

What it proves. Off-design compressor/turbine operation: corrected speed/flow scaling away from the map reference gas, near-surge behaviour, and shaft mechanical losses.

  • Reference case: examples/validation/turbo_match/ (run_validation.py + pass_criteria.toml), driving the examples/59_wastegate_boost_ctrl.toml turbo-shaft topology at three fixed wastegate settings. Exercises the v0.5 robustness pack in components/turbo.py (γ/R off-test-gas correction, near-surge damping, shaft mechanical efficiency).
  • What is validated. This is a physics-conservation + map-fidelity check (like W4's analytic transmission loss), not an external-dataset comparison — there is no open turbo map + transient reference to ship, and we do not fabricate one. The validated property is turbo matching: at steady state the solver must find the shaft-speed equilibrium where turbine power == compressor power (independently computed; conservation forces them equal), with the compressor above surge and inside its PR map.
  • Verdict (2026-05-22): ✅ banked, 3/3. Power balance holds to ~1e-7 relative across bypass_open ∈ {0.0, 0.2, 0.4}; the matched power is monotone in the wastegate (5767 → 4258 → 3017 W as it opens — the physically-correct response); surge margin and PR stay on-map at every point.

W3 — Aftertreatment drive cycle (the locked wedge)

What it proves. The keystone workflow: a transient aftertreatment drive cycle that GT-POWER and AVL Cruise M both target. This is where the project's existential constraint lived — at the acoustic-CFL floor a 500 s cycle was ~84 M steps (~4.6 h), impractical for unattended use.

  • Reference case: examples/avl_cruise_m/c02006_dpf_csf_regen_trans.toml — the AVL Cruise M C02006 DPF + catalysed-soot-filter regeneration transient.
  • What was needed. The v0.3 keystone: the low-Mach / quasi-steady solver mode (solver = "quasi_steady", pressure-projection SIMPLE with Rhie–Chow), transient inlet BCs, a steady gas-phase energy solve, and the JIT'd SIMPLE kernel (~75× per solve). See low-mach-at-plan.md and perf-history.md.
  • Verdict: the full 500 s cycle runs end-to-end in ~6.5 min, stable through regen ignition, soot burning down to completion — on the merged main. The acoustic-CFL floor that made this impractical is gone. W3's wall-clock gate, which the roadmap originally listed as failing (existential), now passes.
  • Code-to-code numeric promotion in progress. Seven Tier-A AVL EAT cases (C02001 DOC light-off · C02002 SCRT ads/des · C02004 DPF ash filt · C02005 DPF back-diff · C02006 DPF CSF regen · C02007 DPF filt soot classes · C02022 DPF user-filter) now ship as scaffolded validation suites under examples/validation/avl_c020*/. Each auto-skips with exit 0 until a user populates data/ with curves digitized from the AVL screenshots via WebPlotDigitizer, then runs the full code-to-code comparison automatically. The Tier-A audit + digitization workflow lives at examples/avl_cruise_m/validation_audit.md (in the repo, outside the docs tree); C02001 is the canonical worked example. Numeric promotion of C02006 is the highest-value follow-up — it lifts the W3 keystone from "runs end-to-end" to "matches AVL numerically".
  • Aeolus-authored catalyst suites, and TWO OF THEM ARE EXPERIMENT-REFERENCED. Beyond the AVL Cruise-M imports, four harnesses exercise the generic twc_brinkmeier catalyst kinetics against published behaviour. They ship self-contained — no vendor data — and all four are CI-gated and passing.

This heading said "code-to-literature" for all of them until 2026-08-30, and that is wrong for two. Literature here meant a published correlation or band; but heliyon_twc_co_oxidation compares against measured durations from an open-access synthetic-gas-bench study, and ornl_passive_scr against measured selectivity from ORNL CLEERS. Those are experiments. The mislabel mattered: it sat below the W1-W5 table, so every summary claim drawn from that table — including docs/scope-and-limitations.md's "Not validated against lab / synthetic-gas-bench data", and release criterion EC-Q12, which asked for an open synthetic-gas-bench set as future work — was written as though these suites did not exist. Per-suite type is now stated on each entry: - ORNL passive-SCR NH₃ generation — reference type: experiment (trend-level); the comparison is against measured selectivity bands, not point values (examples/validation/ornl_passive_scr/): NO→NH₃ selectivity-vs-λ over a rich TWC via the opt-in A_nh3_form_brnk channel — >80 % rich, 7–40 % near-stoich, matching the ORNL CLEERS 2014 / SAE 2016-01-0934 open trend. - DOC propylene (C₃H₆) light-off — reference type: code-to-literature, correctly: the reference is a 200-280 °C T50 band from a 1973 correlation, not a dataset (examples/validation/doc_propylene_lightoff/): the opt-in A_c3h6_ox_brnk C₃H₆-oxidation channel run on a CO-free, oxygen-storage-off DOC-like brick over an inlet-temperature sweep; the light-off T50 ≈ 240 °C lands in the 200–280 °C literature band for propylene over a noble-metal oxidation catalyst (Voltz-Morgan-Liederman 1973). Code-to-literature: the single pre-exponential is the fitted handle, the model form (a sharp Voltz knee) is what is validated. run_validation.py + plot_results.py + @slow CI gate.

- **Heliyon 2024 TWC CO-oxidation / oxygen-storage (OSC)** — *reference
  type:* **experiment**, and **obtainable**: open access CC BY, with every
  number quoted from the paper's tables and text rather than digitised
  from a figure, so a third party can reproduce it exactly
  (`examples/validation/heliyon_twc_co_oxidation/`): a CO-step OSC
  titration at 300 °C over a Pd/CZ three-way catalyst, gated by the opt-in
  `Omega_OSC_brnk` oxygen-storage capacity. ✅ **banked** — it reproduces
  the paper's Table-11 discharge durations across three ageing states
  (Fresh CZ 25.4 s vs ≈25 s · Mild 16.5 s vs ≈15 s · Severe 7.7 s vs
  <10 s, `|Δ| ≤ 6 s` band). `Omega_OSC_brnk` is calibrated on the *fresh*
  state only; the mild/severe capacities follow from the *independent*
  Table-13 OSC site-density ratio (1 : 0.637 : 0.308), so reproducing all
  three durations from a single scale is predictive content, not a
  three-point fit. Independent of the un-packaged AVL SC630 TWC reference.
- **Passive-SCR system (TWC NH₃ source + underfloor SCR)** — *reference
  type:* **self-consistency / characterization**, against
  necessary-condition bands rather than external data
  (`examples/validation/passive_scr_system/`): the system-level companion
  to `ornl_passive_scr` — a rich TWC excursion generates NH₃ that an
  underfloor SCR brick then consumes to reduce NOₓ. ✅ **characterization
  (validated)** against necessary-condition bands (system NOₓ conversion
  ≥70 % with stored reductant → ~100 %; ≤5 % baseline with no NH₃ → ~0 %),
  isolating each leg of the passive-SCR mechanism.

All are gated by their opt-in pre-exponential / capacity (default 0 → inert → bit-identical), so they add coverage without perturbing the shipped defaults.

W4 — Acoustics / NVH

What it proves. Muffler/silencer transmission loss and the post-processing NVH chain (SPL / dB(A) / dB(C) / octave bands / order tracks / Campbell diagram). This workflow is GT-unique among the reference tools — AVL Cruise M is not an acoustics package.

  • Transmission loss. Three TL paths ship, with different correctness envelopes — be precise about which one a number came from. (1) The time-domain naïve amplitude-ratio transmission_loss is what aeolus1d acoustics --probe-out reports; it is correct only for reflection-free (anechoic-terminated) setups and carries a warning docstring + CLI note to that effect. (2) The Chung–Blaser two-microphone wave-decomposition transmission_loss_decomposed is correct in the presence of reflections; it is available through the Python API but not wired into the CLI (it needs two probes per side + a probe spacing). (3) The frequency-domain transfer-matrix solver (analysis/acoustics_tm.py) reproduces the analytic TL notch of a side-branch / quarter-wave / Helmholtz element at its resonance to within tolerance — that analytic agreement is the validated check.
  • Post-processing. aeolus1d acoustics CLI emits SPL/dB(A)/dB(C) + octave bands (Butterworth analyzer roll-off) + the naïve TL from a trace HDF5; Campbell-diagram critical-speed crossings come from an order-track RPM sweep.
  • Code-to-code: GT-Suite TMM uniform pipe. New suite examples/validation/gt_tmm_pipe/ compares aeolus1d's analytic duct_four_pole against GT-Suite's TMM-computed transfer matrix for the same pipe (from the GT acoustics TMM demo at gt_suite/Acoustics/Other_Analysis/Transfer_Matrix_Method/tm-pipe.tm). Geometry recovered by least-squares (L≈0.52 m, D≈97 mm). Verdict: ✅ TL agrees to <0.5 dB across 10–200 Hz (the ideal-plane-wave regime); above ~200 Hz GT adds viscothermal / higher-mode physics aeolus1d doesn't model, reported as an informational model-fidelity gap (5.45 dB at 990 Hz).
  • Measured transmission loss (added 2026-08-29). examples/validation/gt_acoustics_tl/ compares acoustics_tm's expansion-chamber TL against a measured curve — 191 points, 0-3202 Hz, provenance Source - Measured checked per sheet rather than assumed. RMS 1.02 / 0.88 / 1.18 dB over bands of 600 / 1200 / 2000 Hz, gated at 2.0 dB. Widening to 3300 Hz takes RMS to 4.92 dB and max |err| to 25.29 dB — the plane-wave limit, measured for the first time, and report-only for that reason. One fitted parameter (chamber length; the importer reads it 10x small) and maintainer-run data — both stated in the suite README and in the honesty note above.
  • Status: ✅ the analytic checks pass, with a code-to-code GT-Suite cross-check banked. Note the CLI's --probe-out TL is the naïve (anechoic-only) metric; the reflection-correct wave-decomposition TL is API-only (see above). A measured-muffler dataset would upgrade this from analytic + code-to-code to experimental validation (future).

W5 — Electrified drive cycle

What it proves. The Cruise-M-derived electrified workflow: a hybrid/EV reporting state-of-charge + energy consumption + tailpipe over a drive cycle within the wall-clock budget.

  • Reference case: examples/86_electrified_drive_cycle.toml, run by aeolus1d drive-cycle. It extends the W-vehicle case format (the v0.7 aeolus1d.io.vehicle_case layer) with a [powertrain] block that builds a parallel hybrid (aeolus1d.hybrid.ParallelHybrid: envelope e-motor + coulomb-counted battery + power-split controller). Each step the closed- loop driver's torque demand is split between engine and motor; the battery SoC is integrated; the engine-share fuel comes from the BSFC.
  • What is validated. Like W2, this is an energy-bookkeeping consistency check, not an external-dataset comparison: the run reports a coherent SoC trajectory, electrical-energy-used vs regen-recovered split, and engine-share fuel + CO₂ — and the battery responds correctly (drive discharges, braking regenerates, SoC clamps to [0, 1]). Unit- tested in tests/unit/test_vehicle_case.py.
  • Status: ✅ the deliverable runs in seconds (longitudinal dynamics, not CFD). A measured hybrid drive-cycle dataset would upgrade this from a functional/energy-balance check to experimental validation (future, and the deep electrochemical battery tier is FMU-import territory).
  • Toward experimental drive-cycle data — examples/validation/argonne_d3/. A scaffolded vehicle drive-cycle suite (Phase H4d, ⏳ pending data fetch) compares the aeolus1d driveline + vehicle model against published Argonne D3 vehicle-test traces. The first pass stays in conventional-only mode (a non-hybrid SI car) because the driveline/vehicle MVP does not yet model the e-motor + battery side on the validated path; it becomes runnable once data/<vehicle_name>/ is populated.

Cross-driver agreement

The quasi-steady driver runs W3's anchor case, so how far it sits from the compressible drivers matters. Measured 2026-09-22 (EC-C2 Phase C), the gap is grid error and nothing else. On the reacting parity case (tests/integration/test_driver_reacting_parity.py), the QS − strang temperature band is 0.58 / 0.30 / 0.15 K at 10 / 20 / 40 cells. Conversion stays at 0.402–0.403 and the state is settled at every level. The band halves per doubling and extrapolates to ~0 K. On the non-reacting sibling it is flat in Mach from 0.032 down to 0.004, so the low-Mach model term is below 0.02 K there. This is self-consistency evidence, code against code. It says the drivers solve the same equations, not that either matches an engine. Tables and harness: docs/roadmap.md §1.

Performance baselines

The wall-clock budgets above are anchored to checked-in baselines so a regression is caught in CI, not in production:

  • benchmarks-baseline.md — per-kernel latency table, regenerated by python tests/benchmarks/run_baseline.py. The regression guard is tests/benchmarks/test_baseline_regression.py.
  • perf-history.md — the Perf-1 → Perf-7 audit trajectory and the low-Mach / QS-JIT collapse, with the empirical-vs-speculative record (which optimizations were rejected after profiling, so they are not re-attempted).

The system the current baseline was captured on (Python 3.10, 16-core WSL2, NumPy 2.2.6, Numba 0.64.0) is recorded in the baseline doc; absolute numbers are machine-relative, the ratios and the step-count collapse are the portable result.

Reproducing the dossier

Every row is runnable from a fresh checkout:

# W1 — published-data engine validation (slow; per-RPM sweep)
python examples/validation/ricardo_ktm/run_validation.py
python examples/validation/mendeley_ethanol_water/run_validation.py

# W2 — turbo matching (shaft power balance, ~2.5 min)
python examples/validation/turbo_match/run_validation.py

# W3 — AVL C02006 aftertreatment drive cycle (~6.5 min)
aeolus1d run examples/avl_cruise_m/c02006_dpf_csf_regen_trans.toml

# W4 — acoustics post-processing from a trace
aeolus1d acoustics --help

# W4 code-to-code: aeolus1d duct_four_pole vs GT-Suite TMM (uniform pipe)
python examples/validation/gt_tmm_pipe/run_validation.py

# W5 — electrified (parallel-hybrid) drive cycle
aeolus1d drive-cycle examples/86_electrified_drive_cycle.toml

# Perf baseline (regeneration + regression guard)
python tests/benchmarks/run_baseline.py
pytest tests/benchmarks/test_baseline_regression.py

The validation suites carry their dataset licences verbatim in each suite's DATA_LICENSE; only fair-use published numerical reference points are committed, raw datasets are fetched into the (gitignored) data/ subdirectories per each suite README.