06 · Simulation · Native AOT

An engine does not run at one speed.

DynoForge couples mechanical kinematics, compressible flow, crank-locked audio, and diagnostics without forcing every domain into the display frame rate.

Multi-rate kernel

Different physics need different clocks.

Crank and piston mechanics step at 10 kHz, the fluid network at 40 kHz, and audio synthesis at 48 kHz. The rates follow the signals: gas-flow transients need finer resolution than the rotating assembly, while audio must produce the device sample stream. Running all three at 48 kHz would waste mechanical work; running all three at 10 kHz would alias the audio and undersample flow.

Independent accumulators catch each domain up to elapsed time, with a clamp after debugger pauses to prevent a spiral of death. The domains still share causality: piston geometry and crank angle affect cylinder volume; manifold mass balance and combustion create pressure; pressure over piston area and crank geometry produces torque; cylinder pressure and firing phase drive exhaust pulses.

Hot state is shaped for the runtime

The simulation state uses blittable structs, fixed-size arrays, ref access, stackalloc, and no LINQ or boxing in the hot path. Native AOT analyzers police compatibility. A 100 Hz flattened snapshot is the UI boundary, so rendering never locks or walks the live solver’s arrays. Commands travel back through an explicit queue.

Audio has one handoff: a power-of-two single-producer/single-consumer ring buffer. The kernel writes crank-locked samples; the OpenAL-facing device drains them. Misfires and limiter cuts are audible because they alter cylinder events, not because the UI selects a “rough engine” sound.

Engines are data, not subclasses

Engine packs are directories of JSON describing geometry, rotating assembly, heads, cam, fuel, ignition, exhaust, accessories, and calibration. EngineFactory discovers and validates packs into solver inputs. New naturally aspirated configurations do not require recompiling a new class hierarchy.

Diagnostics are part of stability

Step counters, timing, kernel jitter, buffer health, pressures, temperatures, wear, torque, power, and dyno sweep data are exposed through snapshots and diagnostic views. Sweeps dwell at each operating point before sampling and can export CSV. Health feeds back into physics: ring-seal loss reduces effective compression, bearing wear adds drag, and detonation can retard timing.

Current limits: forced induction and dynamic cam switching are not implemented; two alternate combustion modes remain stubs; the exhaust sound is a pressure-driven synthesizer, not a physical pipe propagation model. Native AOT and zero-allocation design reduce runtime overhead, not modelling error.