15 KiB
Fluid physics audit — 23 October 2026
This pass repairs conservation and boundary coupling, establishes repeatable physical tests, and measures kernel and threading performance. It is not a certification that every engine or acoustic subsystem is physically validated.
Findings and changes
- Pipe–volume mass/energy mismatch. Previously, the volume used an orifice's requested discharge while the pipe used a different Rusanov ghost-cell flux. Each boundary now supplies one integrated mass, energy and fresh-air flux; the volume receives the exact opposite exchange. Stationary walls transfer momentum but no mass or energy. Open-end audio reports the mass flux actually applied by the finite-volume update.
- Substep integration. Components previously received only the final boundary flow after several pipe substeps. Every component now updates after every pipe substep. CFL is recalculated as the solution evolves.
- Profiled pipes. Geometry was stored but absent from the conservation
update. Shared face fluxes now include face area and divide by cell volume;
momentum includes the quasi-1D pressure source
p dA/dx. Constant-pressure rest remains stationary while closed profiled pipes conserve mass/energy. - Orifice choking. The old formula used the upstream sound speed with throat Mach number, overestimating discharge. The nozzle calculation now uses the isentropic throat temperature and satisfies the sonic-flow test.
- Unstable small-signal boundary. Evaluating
sqrt(dp)using only the adjacent cell-centre pressure destabilized a small Helmholtz excitation. The nozzle discharge is now matched to the outgoing duct characteristic using a safeguarded analytic Newton solve of a squared-flow residual. Bisection remains the fallback. Subsonic, isentropic characteristic and quasi-steady nozzle assumptions still limit this model. - Inertance units. For mass flow,
d(mdot)/dt = A dp/L, notA dp/(rho L). Dimensionless quadratic resistance is integrated with a dissipative semi-implicit term. Removed the additional lumped inertance in the Helmholtz scenario: its resolved neck already carries inertance. - Moving volumes. Volume0D previously applied work without changing its
geometric volume. Closed adiabatic work now follows
E V^(gamma-1)=constantand updates volume. Crankcase geometry work is applied once per geometry change rather than again for each solver substep. Removed its five-bar cap, which silently deleted gas during high compression. - Invalid configurations. Reject invalid geometry, timesteps, duplicate or missing endpoints and incompatible gas constants. A pressure-only boundary cannot specify a supersonic inlet; that case now fails explicitly. Direct pipe joints support equal endpoint areas and all orientation combinations; unequal-area direct joints are rejected. Use a profiled transition instead.
- Performance. Cache primitive states/wave speeds, evaluate each shared interior face once, and hoist uniform relaxation outside the cell loop. Compiler SIMD is enabled without fast-math. No per-step allocations were introduced into the pipe/boundary kernels.
Validation
fluidsim_fluid_validation contains 29 named cases, in addition to the existing
physics/audio/ECU regression executable. Coverage includes:
- Closed pipes, variable-area equilibrium/conservation, stationary hot contacts.
- Sealed volume–pipe exchange, several volumes and a shared tiny donor.
- Direct joints in four orientations and split/unsplit equivalence.
- Fresh-air species conservation, actual open-end mass accounting on both ends.
- Sonic choking against the analytic ideal-gas formula; inertance units and steady quadratic resistance.
- Adiabatic moving volumes, thermal exponential relaxation and sealed crankcase compression beyond five bar without mass deletion.
- Closed/open acoustic reflection signs, closed-duct mode frequencies at 50/100/200 cells, and small-signal cavity resonance.
- Sod shock-tube density error at 100/200/400 cells, strong pressure pulses, expanding-flow near-vacuum states, positivity-repair checks.
- Invalid geometry/configuration, incompatible gas coupling, unsupported supersonic inlet and missing/duplicate endpoint rejection.
Representative measured results:
| Check | Result |
|---|---|
| Sod density L1, 100 / 200 / 400 cells | 0.02332 / 0.01595 / 0.01052 |
| Closed-duct fundamental | approximately 171.9 Hz; analytic 171.91 Hz |
| Cavity fundamental | approximately 136.2 Hz; lumped estimate 138.51 Hz |
| Closed mass/energy relative tolerances | 2e-5 to 5e-5, depending on case |
| Cavity frequency tolerance | 5%, with growth and positivity checks |
| Closed-duct frequency tolerance | 1% across three resolutions |
The cavity estimate assumes a compact, lossless neck without radiation end correction; the discretized model includes neck compressibility and numerical losses. These comparisons are verification of stated assumptions, not a comparison with measured engine hardware.
Benchmarks and SIMD
Machine: Intel Core i5-12600K, GCC 16.2.1, Linux x86-64, Release. These are local wall-clock microbenchmarks; CPU frequency and background load affect timings. The pipe benchmark advances an equilibrium lossless duct with reflected ends; the twin benchmark runs one simulated second including its nonlinear boundaries.
Before this audit, isolated kernels measured about 49–52 million cell updates/s and the twin about 3.84 times real time. Cached shared-face evaluation raised pipe throughput to roughly 110–140 million updates/s. The final twin is around 1.7 times real time: it does substantially more boundary work than the original, physically inconsistent solver. Early faster twin numbers from before the characteristic/nozzle correction must not be treated as final results.
A SIMD comparison measured roughly 111–139 million updates/s with compiler
vectorization versus 84–102 million with vectorization disabled. GCC's
vectorization report confirms 16-byte SIMD in the primitive-state and face-flux
loops. FLUIDSIM_ENABLE_SIMD=ON permits vectorization and disables math errno;
it does not enable fast-math, approximate reciprocal/square-root intrinsics,
or machine-specific instruction sets. OFF disables compiler vectorization for
repeatable comparison. Scalar and SIMD builds run the same physics tests.
Windows/MSVC settings are provided but were not executed in this Linux audit.
Multithreading investigation
fluidsim_thread_benchmark measures persistent workers with two barriers per
iteration. Boundaries/components must remain in ordered phases; pipes can be
advanced independently only after all boundary fluxes are resolved.
| Independent pipe workload, 1000 steps | Serial | 2 workers | 4 workers |
|---|---|---|---|
| 6 pipes × 10 cells | 0.00093 s | 0.00272 s | 0.00625 s |
| 64 pipes × 256 cells | 0.1275 s | 0.0700 s | 0.0410 s |
This is an optimistic stage-only benchmark with equilibrium data, excluding worker startup and a real graph's serial boundary work. It supports further work on persistent pools for large networks; it does not justify threading the current small twin. No fluid worker pool is enabled in production. The existing simulation/audio/UI separation remains.
Reproduce
cmake -S . -B build-audit -DFLUIDSIM_BUILD_DESKTOP=OFF -DCMAKE_BUILD_TYPE=Release
cmake --build build-audit -j 4
ctest --test-dir build-audit --output-on-failure
./build-audit/fluidsim_physics_benchmark 44100
./build-audit/fluidsim_thread_benchmark
For a scalar comparison configure a separate directory with
-DFLUIDSIM_ENABLE_SIMD=OFF. On GCC/Clang, use another directory with
-DCMAKE_CXX_FLAGS="-fsanitize=address,undefined -fno-omit-frame-pointer" to
reproduce the sanitizer run. Final Linux desktop regressions, all 29 scalar fluid cases, and both test
executables under AddressSanitizer/UndefinedBehaviorSanitizer passed. The final
sanitizer run completed in about 13 seconds.
Compiler vectorization diagnostics can be produced
with GCC -fopt-info-vec-optimized.
Remaining limits and next work
- First-order Rusanov flux is dissipative. Spatial/time resolution convergence and attenuation across the full audible band are not yet established. A higher-order limited scheme is a separate change, not silently enabled here.
- The default four-substep floor was retained: removing it failed a tiny-volume
stress case. CFL alone is not a positivity guarantee for arbitrary stiff
pipe/volume networks. Conservative donor budgets can limit transfer; inspect
BoundarySystem::limited_fluxesand refine time resolution when they activate. Budgets for shared donors are allocated in registration order. Pipe positivity repairs are counted byPipe1D::positivity_repairs; a nonzero count invalidates a claim of exact conservation for that run. - Pipe geometry/cell storage remains public for initialization. Changing its topology or resizing cells after connections have been built is unsupported.
- The pressure-only open boundary extrapolates interior entropy. It is an ideal pressure-release model, not a complete external atmosphere, anechoic boundary, or frequency-dependent radiation impedance. Strong inlet flows need richer thermodynamic boundary data.
- Junctions and orifices are quasi-1D approximations. Jet separation, vena contracta, discharge coefficients and strong multidimensional area changes need validation; equal-area joint tests do not validate arbitrary fittings.
- The optional lumped inertance law is dimensionally checked, but its stored neck kinetic energy is not a separately tracked thermodynamic state. Use resolved pipe cells when evaluating physical neck acoustics and energy.
- Core pipe damping and volume thermal relaxation default to zero. Explicit scenario damping/relaxation still represents empirical source terms and must be calibrated before claiming real dissipation or heat transfer.
- Engine cylinders retain pressure/temperature safety clamps, approximate combustion/species bookkeeping and unvalidated mechanical work integration. ECU behavior and the broader engine model are not certified by this audit.
- Sound radiation remains the documented compact-source approximation. These fluid tests do not establish microphone SPL, high-frequency radiation, thermoviscous losses or full mechanical/chemical energy conservation.
Physical references
- Clawpack: approximate Euler Riemann solvers — conservative Euler fluxes and total-energy equation of state.
- Clawpack: Euler equations and exact Riemann solutions — shock/contact/rarefaction verification and the Sod problem.
- NASA Glenn: mass-flow choking — isentropic throat relations and maximum mass flow at Mach one.
- EPFL: quasi-1D Laval nozzle model — variable-area Euler fluxes and geometric pressure source.
Sustained-load follow-up
A one-second run missed a runtime deadline problem: at full throttle the heated gas raised average CFL work from 4 to approximately 7 substeps per audio frame. By simulated second 5, each second needed about 1.04 seconds of CPU time, so a finite startup buffer could not prevent eventual underruns. Idle stayed near 0.6 seconds per simulated second.
The solver now reuses its CFL primitive-state/wave-speed preparation in the
finite-volume update. Boundary Newton residual tolerance is matched to the
single-precision conserved state (4e-7 in the normalized squared-flow
residual), rather than solving to 1e-12 relative residual each time. The same
CFL limits and four-substep floor remain. On the same machine, a nine-second
full-throttle run measured approximately 0.74–0.81 seconds per simulated second
in the hot portion; idle measured approximately 0.49–0.52 seconds. All 29 fluid
cases and existing regressions still pass. This is measured headroom, not a
hard real-time guarantee on other workloads or machines.
Reproduce sustained-load timings with:
./build-audit/fluidsim_physics_benchmark --soak 12
The benchmark reports each simulated second, average substeps/frame and boundary iterations/frame. Desktop audio also counts underrun blocks; the counter is shown with the audio-buffer status when a UI font is available.
Intake reservoir and repeated-blip regression
The twin's upstream pressure-only boundary inherited pipe entropy during
inflow. Repeated blips could therefore admit progressively hotter gas rather
than fresh ambient air: a captured sequence reached approximately 1140 K in
the plenum at wide-open throttle and lost fresh charge density. The intake now
connects to an explicit infinite Atmosphere reservoir (101325 Pa, 300 K,
fresh-air fraction one), updated on every fluid substep. Intake radiation uses
that reservoir's actual signed mass exchange. The remaining pressure-release
open-end index now refers only to the exhaust.
The twin also disables pipe relaxation toward ambient pressure energy. That source can heat low-density evacuated cells without a physical wall heat transfer law. This does not impose any pressure floor or artificial manifold refill. Hot residual-gas reversion, closed-throttle pumping and pressure waves remain possible; their engine-model accuracy still needs further validation.
fluidsim_intake_regression runs 16 simulated seconds: idle, an 80% blip,
recovery, a full-throttle opening, and return to idle. It checks pressure
recovery, fresh-air temperature/composition, finite audio, zero pipe positivity
repairs and final idle recovery. Representative results after the fix:
- Before the second opening: 35.76 kPa manifold absolute pressure.
- After opening: 85.45 kPa near 9950 RPM; manifold 298.96 K, inlet 296.92 K.
- After return to idle: 34.51 kPa at 1820 RPM.
Manifold vacuum at small/closed throttle is expected and is not removed by the fix. An actual obstruction/regression is distinguished by failure to recover pressure and fresh-charge density when reopening the throttle. The inlet reservoir controls the upstream gas state; it does not thermostat the manifold. See AEM's engine-management manual for the qualitative throttle-angle/manifold-pressure relationship. These are scenario regression bounds, not universal pressure limits for real engines.
All three CTest executables pass after this change (existing regressions, 29-case fluid suite, and the new intake transient). A six-second sustained full-throttle follow-up stayed at four substeps/frame and approximately 0.51–0.53 seconds of wall time per simulated second, with RPM around the ECU rev limit. This also identifies the earlier hot-gas CFL growth as a consequence of the incorrect inlet thermodynamic state, not solely an unavoidable engine workload increase. The earlier timing sections are historical measurements of those intermediate implementations.