Skip to content

Milestone 8 — Cruise M import completeness

A coverage-driven roadmap. The acceptance criterion for each phase is "this Cruise M element type imports cleanly into a runnable aeolus1d case." Where Milestone 7 has a parallel feature-driven phase, this doc cross-references it; the two are scheduled together but tracked separately so we can see Cruise M parity specifically.

The driver: a typical engine + aftertreatment Cruise M .proj contains 15-25 element types. The current importer (post-Phases A21–A26) covers aftertreatment_pipe / TWCTopology / mass_flow_boundary / boundary / monitor plus the supporting catalogues — that's ~5 of the 15-25. Everything else falls into lossy_components even when aeolus1d already has the physics. This milestone closes that gap.

Update 2026-07: this roadmap has since been largely executed and is retained as a historical planning record. Nearly every phase has shipped, though a few landed under different names/shapes than proposed below (the plan predates the final implementation): 8b DOC/SCR + 8a breathing-path recognition (src/aeolus1d/io/interop/avl_cruise_m/); 8c multi-injector cylinders (InjectorSpec / CylinderSpec.injectors, ADR-0009); 8d heat-exchanger ε-NTU as EGR-cooler / charge-air-cooler heat kinds (closures/heat.py); 8e urea as [pipe.urea] kind="urea_spray" + the hnco_hydrolysis reaction (not a urea_decomposition kind); 8f DPF as a [pipe.filter] kind="diesel_particulate_filter" block with a per-cell soot_loading accumulator (closures/filter.py), which also covers 8i; 8g wastegate control (control/wastegate_controller.py); 8z FMI 2.0 export scaffolding (src/aeolus1d/fmi.py). The scope boundary was also superseded: rather than deferring everything to FMI, aeolus1d grew native vehicle/powertrain models — vehicle.py, driveline.py, transmission_shift.py, hybrid.py, coolant.py, drive_cycles.py, driver.py. Treat the per-phase approach text below as the original design intent, not the as-built implementation.

Scope boundary. Vehicle dynamics, transmission, hybrid drive (electric machine, battery, inverter), cooling system, and ECU controller logic are explicitly out of scope — those belong in a coupled-simulation tool that calls aeolus1d via FMI. Phase 8z covers the FMI-export surface for that hand-off.

Importer-side gaps (aeolus1d has the physics)

These phases are pure plumbing — no new aeolus1d closures needed; the importer's element-recognition list just needs extending. Roughly 3-5 days for the whole bucket.

Phase 8a — Engine breathing-path elements

Goal. Recognise cylinder.Topology, injector.Topology, valve.Topology, compressor.Topology, turbine.Topology, shaft.Topology, intake / exhaust manifold elements; map each to its existing aeolus1d model.

Mappings (existing aeolus1d):

Cruise M element aeolus1d model
cylinder.Topology Cylinder (slider-crank + Wiebe + ports)
injector.Topology injection schedule on Cylinder (or [[cylinder.injector]] after 8b ships)
valve.Topology CylinderPort valve windows
compressor.Topology Compressor with TurboMap
turbine.Topology Turbine with TurboMap
shaft.Topology Shaft (I·dω/dt = (Ẇ_T − Ẇ_C)/ω)
Intake / exhaust manifold Junction (plenum)

Effort. ~3-4 days. Per-element parameter extraction is the work; the dispatch shape is the same as the existing aftertreatment_pipe / TWCTopology branches.

Risk. Medium. Cruise M's per-template parameter layouts vary; the existing gt_suite_native importer's parameter mapping is the cautionary tale. Some parameters (cylinder bore / stroke / clearance volume) live in well-known fields; others (valve lift schedules, turbine map data) may live in referenced sub-objects we'd need to graph-walk to.

Done when. A Cruise M .proj with a single-cylinder naturally-aspirated engine imports as a runnable aeolus1d network without lossy-element warnings for the breathing path.

Phase 8b — DOC / SCR catalyst topology recognition

Goal. Extend the catalyst-pipe branch to recognise DOCTopology and SCRTopology alongside the existing TWCTopology. The _closure_for_class dispatcher already maps each to the right aeolus1d reaction kind (doc_oxidation / nh3_scr_kinetics); the topology parser just needs to add the elements to its recognition list.

Effort. ~1 day. Mostly testing — the dispatcher already handles the catalyst-kind selection.

Done when. A Cruise M case with a DOC + SCR + TWC chain imports with each catalyst pipe carrying the right aeolus1d reaction kind.

Aeolus-feature gaps (new physics needed)

Phase 8c — Multi-injector cylinders (same as Phase 7a sub-1)

Goal. Per-cylinder [[cylinder.injector]] blocks for split injection (pilot + main of the same fuel) and dual-fuel (H₂ pilot + NH₃ main, or diesel pilot + NG main). Each injector carries its own (cad, rate, m_fuel_per_cycle, T_fuel, cv_fuel, fuel_species_name).

Approach. Schema: InjectorSpec dataclass + CylinderSpec.injectors: list[InjectorSpec]. Runtime: Cylinder.injectors: list[dict] with cached cycle integral per injector; rates sum into composite ṁ_fuel; Wiebe uses the summed m_fuel_per_cycle. Per-injector fuel_species_name writes to the matching pipe inflow channel during open-valve windows.

Effort. ~3-4 days. Already started — partial work in git stash@{0} (schema + parser + half of cylinder runtime).

Risk. Medium. The Cylinder runtime touches species- coupling, blowback bookkeeping, and Wiebe heat release — fanning multiple injectors through that needs careful treatment of the cylinder's composite Y_fuel scalar.

Done when. A pilot+main diesel cylinder runs to steady state with per-injector rate shapes summing into the right total fuel mass per cycle; per-fuel species columns at connected pipes show separate H₂ vs NH₃ inflows in a dual-fuel test case.

Cross-ref. Milestone 7, Phase 7a sub-piece "multi-injector cylinders for dual-fuel cases".

Phase 8d — Heat-exchanger ε-NTU component

Goal. A new pipe-mounted closure or standalone component modelling intercooler / EGR cooler / charge-air cooler heat extraction. Effectiveness-NTU formulation:

Q̇ = ε · ṁ · c_p · (T_hot_in − T_cold_in)

with ε and the cold-side conditions (T_coolant) as user inputs. Energy sink on the gas side; coolant side is a prescribed T (no coolant-loop solver — that's out of scope).

Approach. Either a new closure kind on Pipe (similar shape to heat's constant_twall) parameterised by (epsilon, T_coolant, ntu_units), or a new HeatExchanger component sitting between two Junctions. The closure approach is simpler — one new kind in the heat family + parameter packing. Distributed along the pipe length.

Effort. ~1 week.

Done when. A Cruise M case with an intercooler.Topology imports with the imported pipe carrying an ε-NTU heat extraction closure; charge temperature drop matches the project's calibration to ~1 % at a reference operating point.

Cross-ref. Milestone 7, Phase 7d "EGR cooler" piece.

Phase 8e — Urea injector + urea-water spray decomposition

Goal. New BC kind: urea_spray_inlet injecting an NH₃ + HNCO mixture at a specified spray rate. Plus a hydrolysis decomposition reaction HNCO + H₂O → NH₃ + CO₂ that fires on the pipe just downstream of the injector. The combined BC + reaction lets the SCR catalyst downstream see the right NH₃ feed concentration as a function of urea-dosing rate.

Approach. Schema: new BCSpec.kind = "urea_spray_inlet" + extra fields (urea_mass_flow_t / urea_mass_flow_v, droplet_size, evaporation_model). Reaction: new kind urea_decomposition on SpeciesSpec.reaction. Both wire through the existing schema-vs-registry consistency tests.

Effort. ~1-2 weeks. The droplet evaporation model is the chunky part — droplet diameter, residence time, ambient T effect on evaporation rate.

Done when. A Cruise M case with a urea-spray AftertreatmentInjectorTopology imports with the injection BC + decomposition reaction wired correctly; the imported SCR sees an NH₃-feed schedule shaped like the dosing schedule × hydrolysis efficiency.

Cross-ref. Milestone 7, Phase 7b "urea-water spray BC + decomposition".

Phase 8f — DPF (Diesel Particulate Filter)

Goal. New aftertreatment closure modelling soot loading, soot-loading-dependent pressure drop, passive O₂ regeneration (via NO₂), and active T-driven thermal regeneration (above ~600 °C).

Approach. New Pipe.dpf_state per-cell soot-mass array (kg/m³). New reaction kind dpf_soot_burn that consumes soot when local T crosses a threshold or NO₂ is present. Pressure drop via the Phase-A25 darcy_forchheimer_kc closure with K(soot_loading) — i.e. permeability shrinks as soot accumulates. Soot tracked as either a new species column (passive convection through the network) or as a per-cell scalar accumulator (the cleaner choice — soot doesn't really advect like a gas species).

Effort. ~2-3 weeks. Most of the work is the soot-loading calibration + regeneration kinetics. The pressure-drop coupling rides on Phase A25.

Risk. High — DPF physics is genuinely complex and the calibration is fixture-specific. Plan to ship a Tier-1 model matching MIT lit defaults; tuning per project is manual.

Done when. A Cruise M case with a DPFTopology imports with the soot-loaded pipe + regeneration reaction; a hot-exhaust transient triggers active regeneration with visible soot-mass decay.

Cross-ref. Milestone 7, Phase 7b "DPF with soot loading + passive / active regeneration".

Phase 8g — VGT + wastegate + twin-/sequential-turbo topology

Goal. Variable-geometry turbine (vane position as 3rd map axis); wastegate (parallel-pipe bypass with controlled-area orifice); twin / sequential turbo topology.

Approach. VGT: extend TurboMapSpec with a vane_position axis on the lookup. Wastegate: parallel pipe with a valve_orifice BC on the bypass — already supported by the existing aeolus1d components, just needs the importer to recognise the topology.

Effort. ~1 week (VGT) + ~1 week (wastegate); twin / sequential turbo is wiring (no new physics).

Done when. A Cruise M case with a VGT-equipped engine imports with the turbine map carrying a 3rd vane-position axis; wastegate-bypass cases route the right fraction of exhaust around the turbine.

Cross-ref. Milestone 7, Phase 7c "Turbocharger depth".

Phase 8h — Combined SCRF + two-stage SCR

Goal. A single brick that's both an SCR (urea + NH₃ → N₂) and a DPF (soot loading + regen). Two-stage SCR is just two SCR pipes in series — covered by Phase 8b once DOC / SCR topology recognition lands.

Approach. Combined SCRF composes Phase 8e (urea decomposition + NH₃ SCR) and Phase 8f (DPF). Most of the work is fixture validation; the closures already compose when both are attached to the same pipe.

Effort. ~1 week (mostly tests + cross-validation).

Done when. A Cruise M case with an SCRFTopology imports with both SCR reactions and DPF soot loading on the same pipe.

Cross-ref. Milestone 7, Phase 7b "combined SCRF" + "two- stage SCR".

Phase 8i — Particulate matter species column

Goal. First-class species tracking for soot mass — a non-advecting accumulator per cell that the DPF (Phase 8f) reads/writes and that tracer/writer can serialise.

Approach. New Pipe.soot_mass per-cell array, analogous to T_solid for catalysts. Snapshot helper extension so the writer + tracer pick it up automatically. Cruise M's ParticulateMatterSpecie declarations map to this column.

Effort. ~1 week. Mostly persistence + GUI plot integration; the soot accumulator math itself comes with Phase 8f.

Done when. A run with a DPF brick records the per-cell soot mass over time in the HDF5; the GUI plot dock has a soot-loading visualisation; resume-from-HDF5 restores the soot state.

Cross-ref. Milestone 7, Phase 7b context.

Out-of-scope items — go through FMI

Phase 8z — FMI export surface for vehicle / powertrain integration

Goal. Aeolus exports an FMU. Vehicle dynamics, transmission, hybrid drive, cooling system, and ECU controller logic stay out of aeolus1d's native scope; coupled-simulation tools wrap the FMU + their own vehicle / control models.

Approach. Phase 7e in the original roadmap. The Phase A14a _cmd_run decomposition + Phase A17 live-control checkpoint + Phase A19 CI infrastructure all support a clean FMI 2.0 export. Most of the work is the FMU envelope: modelDescription.xml, the C wrapper around the Python solver, signal mapping for inlet ṁ / T / Y(t) and outlet T / p / Y(t).

Effort. ~2-3 weeks for FMI 2.0 co-simulation export. FMI 3.0 (with array signals) is a follow-up.

Done when. An aeolus1d aftertreatment case can be imported into AVL Cruise M as an FMU sub-system and stepped from Cruise M's vehicle solver, with NH₃ / urea / NOx round- tripping correctly across the FMU boundary.

Cross-ref. Milestone 7, Phase 7e "Co-simulation interfaces".

Summary

Phase Effort Cumulative Cruise M coverage delta
8a — engine breathing recognition 3-4 d 4 d Cylinder, valve, compressor, turbine, shaft, manifold
8b — DOC/SCR topology recognition 1 d 5 d DOC, SCR catalyst kinds
8c — multi-injector cylinders 3-4 d 9 d split / dual-fuel injection
8d — heat-exchanger ε-NTU 1 w 16 d intercooler, EGR cooler
8e — urea injector + decomposition 1-2 w 26 d urea dosing, hydrolysis
8f — DPF 2-3 w 47 d soot loading + regen
8g — VGT + wastegate 2 w 61 d modern diesel turbo control
8h — combined SCRF + two-stage SCR 1 w 68 d combined aftertreatment
8i — PM species column 1 w 75 d soot persistence
8z — FMI export 2-3 w 96 d vehicle integration via co-sim

~14-19 weeks for the whole milestone if executed strictly sequentially. Phases 8a / 8b / 8c can run in parallel with 8d-8i; 8z is the natural last step (consumes the rest as a Tier-1 FMU).

Cross-reference

  • The architecture-refactor plan (architecture-refactor-plan.md) ships the foundations Milestone 8 builds on: closure registry (Phase 1) for the new reaction / heat-exchanger / porous kinds, snapshot value type (Phase 2) for the soot state persistence, Component protocol (Phase 5) for any new network components.
  • Milestone 7 (in phase-log.md) covers the same physics from a feature-driven angle. Phases marked "Cross-ref" above show the mapping.