Add turbocharged twin scenario and cross-platform test harness

This commit is contained in:
grillkol committed 2026-10-23 02:27:03 +02:00
1 parent a859740a95
commit 589d22aa5e
63 files changed
+4903 -771

No files matched your search

+97
View File
@@ -0,0 +1,97 @@
# Static outdoor audio and two-stroke verification
Verified on Linux in Release mode, 2026-10-23. The target remains fluid-derived
sound at 44.1 kHz. No synthetic bang, saturation, or combustion event is added
by the audio renderer. Acoustic processing does not feed energy into the solver.
## Renderer
`OutdoorAudio` replaces the active twin and two-stroke legacy reverb paths.
Each intake/exhaust mass-flow derivative drives a compact monopole. Separate
left/right paths use inverse distance and fractional-sample delays at 343 m/s.
The listener and sources are static. Default listener position is (1.6, 1, 2) m;
intake is (-0.2, .7, 0), exhaust (.55, .5, 0), ground y=0, wall x=-1.5.
Ground and wall reflection coefficients are .35 and .65. These are configurable
assumptions rather than measurements of a particular location.
A second-order 6 kHz monitoring low-pass reduces sharp acquisition transients;
it is linear and does not create afterfire. Early ground/wall reflections use
image paths. Woodland uses six approximate scatterers. A stable four-line
feedback-delay network supplies an empirical diffuse tail; it does not solve
outdoor wave propagation or vegetation scattering. Scene changes smooth over
20 ms. The old `OutdoorExhaustReverb` remains for legacy tests but is inactive
in both engine scenarios.
Pipe-end radiation impedance, calibrated directivity, alias-free acquisition,
and exhaust afterfire chemistry remain unresolved. PCM output is not calibrated
speaker SPL. The monitoring filter cannot recover information lost to aliasing.
## Measured captures
Four seconds at full pedal, wall environment, 44.1 kHz stereo. Each row's raw
and rendered signals come from the same simulation run. Measurements are
before PCM clipping; the raw signal includes direct spatial propagation.
| Engine | Raw maximum adjacent-sample change | Rendered change | Rendered peak | Clipping samples |
| --- | ---: | ---: | ---: | ---: |
| Twin | .569144 | .0881295 | .119947 | 0 |
| Two-stroke | .412956 | .138741 | .390789 | 0 |
These measurements establish transient reduction, not a subjective judgment
that limiter events sound like realistic bangs. Listening on the target audio
device is still required. Reproduce from the repository root:
```sh
cmake --build build-audit --target fluidsim_audio_capture -j 4
./build-audit/fluidsim_audio_capture --scenario twin --out build/audio/twin-wall --seconds 4 --throttle 1 --scene wall
./build-audit/fluidsim_audio_capture --scenario two-stroke --out build/audio/two-stroke-wall --seconds 4 --throttle 1 --scene wall
```
Each produces `-rendered.wav`, `-dry.wav` (filtered direct paths) and
`-unfiltered.wav` for comparison. Capture files are build artifacts.
## Two-stroke and regression checks
The existing 125 cc geometry now uses the shared ECU and finite-response
throttle, fuel dosing after the last scavenging port closes, 3000 RPM idle
control with ignition trim, and a dynamic damped cantilever reed with contacts.
Cylinder/crankcase geometry work uses adiabatic energy differences. An active
charge finishes combustion when a fuel cut begins. Ignition event crossing
handles wraparound without spuriously firing retarded ignition at zero degrees.
Reed parameters, combustion, scavenging and controller calibrations have not
been validated against a measured engine.
Both desktop engines share `MotorcycleTest` for clutch/vehicle integration,
common control dispatch and a common dashboard/dyno renderer. The two-stroke
limiter is disabled explicitly in the ECU and cylinder; the twin limiter is
unchanged. Idle and overrun controls remain enabled. The motorcycle and gearing
reuse the existing twin test configuration, not a measured 125 cc motorcycle.
The rolling peak dyno reports crank power and torque versus RPM.
All five CTest suites passed: basic physics/control, fluid boundary validation,
intake regression, outdoor audio, and two-stroke regression. Audio tests cover
fractional direct arrival, image reflection arrival, stereo ordering, distance
gain, linearity, filtering, causal decaying tails, and reed static compliance
and seating. The two-stroke sequence idles for two seconds, holds .6 pedal for
four, then releases for eight. It checks fuel stays enabled at open pedal above
the old limit, reed opening/seating, positive states, finite audio and idle
recovery, with no pipe positivity repairs. It then launches the motorcycle for
six seconds and checks shifting, neutral and positive dyno power/torque.
Latest Release results: free-rev maximum 22471.3 RPM, recovered idle 3236.08 RPM,
free-rev audio peak .512784, motorcycle speed 51.3773 km/h after launch. The high
unloaded RPM exposes the uncalibrated high-speed friction/combustion behavior;
removing the limiter does not validate this as realistic engine performance.
Unit checks also verify disabling an already latched limiter restores fueling.
The earlier four-second capture table above predates limiter removal and is
retained as an audio-renderer measurement, not a current engine baseline.
Windows execution of the latest changes is pending.
## Reference basis
- [Image source geometry](https://www.acs.psu.edu/noahparker/acs/img-src/img-src.html)
- [Feedback delay networks](https://msp.ucsd.edu/techniques/latest/book-html/node111.html)
- [Beam theory](https://mechanics.ju.se/SolidMechanics/BeamTheory.html), including uniform-load cantilever deflection used for reed compliance.
The later YZ125 baseline changes these engine calibrations and measurements; see
[YZ125 baseline verification](YZ125_BASELINE.md) for current results.
+56
View File
@@ -0,0 +1,56 @@
# Saab B205 / 9-5 wagon baseline
Linux Release, 2026-10-23. This quick preset reuses the four-stroke scenario,
ECU, compressible pipes/volumes, vehicle coupling, spatial audio and dyno.
The original twin remains available through its backward-compatible type alias.
There are four actual cylinders and ten pipes, not copies of an audio waveform.
## References and assumptions
[Saab WIS B205 general data](https://saabwisonline.com/9-3-9400/2001/2-engine/basic-engine-4-cylinder-petrol/technical-data/general-data)
supplies 90 mm bore, 78 mm stroke, approximately 1985 cc, 8.8:1 compression,
four valves per cylinder and 1-3-4-2 firing order. Cylinder phases in physical
1/2/3/4 order are 0/180/540/360 degrees; pistons 1/4 move together and 2/3 move
together. Phased cylinders initialize at their actual piston positions.
[Saab WIS 9-5 gearbox data](https://saabwisonline.com/9-5-9600/2005/4-transmission/manual-gearbox/technical-data/gear-ratio)
supplies FM55 B05 overall reductions 13.70, 7.12, 4.77, 3.62 and 2.67 with
4.05 final reduction. The vehicle configuration factors out final reduction
and has five selectable forward gears, no motorcycle primary reduction.
Other settings are estimates: 1600 kg wagon + 75 kg driver, .317 m loaded tire
radius, Cd .32, frontal area 2.2 square metres, wheel-equivalent rotational
inertia 3.6 kg m^2, 300 Nm clutch capacity, crank inertia .18 kg m^2, and
12 Nm constant + .012 Nm/(rad/s) viscous friction. Road rolling resistance
retains the shared .015 coefficient. No attempt is made to identify a particular
year/trim with these estimates.
The intake uses a 3 litre plenum, estimated 52 mm throttle, four 32 mm x 250 mm
runners, 34 mm x 280 mm headers, .6 litre collector, and a 60 mm x 1.4 m open
tailpipe. Estimated valves are 32/28 mm intake/exhaust, 8.5/8 mm lift, two each.
Cams/combustion retain the shared four-stroke model. The ideal ECU targets
850 RPM idle, with estimated 6500/6250 RPM cut/resume and 2000/1300 overrun
thresholds. These are scenario calibrations, not a factory Trionic map.
There is no compressor, turbine, intercooler, wastegate, catalyst or muffler in
this first version. Intake boundary pressure is ambient. Consequently factory
turbo torque/power and factory exhaust sound are not reproduced. Thermal,
combustion and single-zone mixing limitations from the fluid audit still apply.
## Verification
The six existing suites passed after the shared four-stroke/vehicle changes.
The added B205 regression passed independently: it checks engine displacement,
valve count, cylinder positivity, ten-pipe topology, firing order/cadence, wagon
launch, five-gear selection, final ratio, idle recovery, finite audio and zero
pipe positivity repairs. A prescribed 2000 RPM dyno counted 33 firings in half a
second, consistent with two firing events per revolution. The eight-second
sequence reached 56.57 km/h in first under load, recovered to 1311 RPM after
three seconds of unloaded release, and peaked at .18645 audio full scale.
It cost 7.26 wall seconds while another headless run was also active. Idle
convergence and engine calibration still need refinement; these checks establish
basic operation, not measured Saab performance. Windows runtime remains untested.
Run `fluidsim_desktop --scenario b205` or select the third startup card.
Headless CLI and WAV capture also accept `--scenario b205`. The graph reports
crankshaft power, not power measured at the wheels.
+261
View File
@@ -0,0 +1,261 @@
# 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
1. **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.
2. **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.
3. **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.
4. **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.
5. **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.
6. **Inertance units.** For mass flow, `d(mdot)/dt = A dp/L`, not
`A 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.
7. **Moving volumes.** Volume0D previously applied work without changing its
geometric volume. Closed adiabatic work now follows `E V^(gamma-1)=constant`
and 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.
8. **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.
9. **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
```sh
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_fluxes` and refine time resolution when they activate.
Budgets for shared donors are allocated in registration order. Pipe positivity
repairs are counted by `Pipe1D::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](https://www.clawpack.org/riemann_book/html/Euler_approximate.html)
— conservative Euler fluxes and total-energy equation of state.
- [Clawpack: Euler equations and exact Riemann solutions](https://www.clawpack.org/riemann_book/html/Euler.html)
— shock/contact/rarefaction verification and the Sod problem.
- [NASA Glenn: mass-flow choking](https://www.grc.nasa.gov/www/k-12/BGP/mflchk.html)
— isentropic throat relations and maximum mass flow at Mach one.
- [EPFL: quasi-1D Laval nozzle model](https://www.epfl.ch/labs/mathicse/wp-content/uploads/2018/10/25.2016_MP-FN-PL.pdf)
— 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:
```sh
./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](https://documents.aemelectronics.com/techlibrary_30-6905_universal_programmable_engine_management_system.pdf)
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.
+109
View File
@@ -0,0 +1,109 @@
# VZ21-size turbo prototype
Linux Release, 2026-10-23. Core is ready for an early interactive test. Further
map fitting, acoustic work and performance tuning are deferred at the user's
request so testing can start. No blade-passing whistle has been implemented yet.
## Model
Four finite 0-D gas volumes connect compressor inlet/outlet and turbine
inlet/outlet to existing `BoundarySystem` pipe orifices. Register the turbo once
with `Solver`; do not separately register its internal volumes. Internal flows
are bidirectional and choked where appropriate. Donor budgets preserve positive
mass/energy. Compensated 0-D volume accumulation prevents sub-ulp mass drift.
The compressor's estimated Euler head is psi*(omega*R)^2. Efficiency maps this
to a virtual stagnation pressure; a compressible restriction determines actual
flow against the downstream pressure. The turbine flow follows an effective
nozzle. Its torque uses a mean-line speed-ratio efficiency parabola, with finite
starting torque. Reverse flow is passive; deep surge/reverse-wheel aerodynamics
are not validated. These correlations are not a measured compressor/turbine map.
A rigid shaft obeys I*domega/dt = turbine torque - compressor torque - bearing
and windage torque. Implicit midpoint work balances the exact change in rotor
kinetic energy, including starting from rest. Adaptive shaft steps prevent
large timesteps from reversing the rotor numerically. Turbine work is removed
from gas enthalpy; compressor work is added to charge enthalpy. Bearing loss is
tracked as heat outside the gas circuits. No shaft-speed or boost clamp is used.
Estimated default parameters: inertia 4e-6 kg m^2, compressor effective radius
18 mm, turbine mean effective radius 13.5 mm, efficiencies .65, compressor head
coefficient .6, effective compressor/turbine flow areas 110/100 mm^2. Housing
volumes are 20/30/30/20 cc. Connection bores are 24/24/25/26 mm. Viscous bearing
coefficient is 1e-7 Nm/(rad/s), windage coefficient 2e-11 Nm/(rad/s)^2.
The estimated wastegate has an 800 mm^2 pressure diaphragm, 40 N preload,
6000 N/m spring, 120 Ns/m overdamped linkage, 14 mm valve and 4 mm maximum lift.
Compressor delivery gauge pressure drives its opening. Bypass gas transfers
enthalpy without delivering turbine shaft work. The actuator is an idealized
external pressure-control linkage; its mechanical/thermal energy is outside the
audited gas/rotor system. There is no intercooler, blow-off valve, oil-temperature
model, knock model or thermal/wheel failure model.
## Reference basis
[Ecotrons VZ21 specification](https://ecotrons.com/files/ECOTRONS%20Turbo%20VZ21%20technical%20specl.pdf)
provides rough applications and casing dimensions; its performance illustrations
explicitly refer to a similar IHI family rather than measured VZ21 maps. Those
figures cannot validate the coefficients used here. A
[supplier's VZ21 listing](https://www.maxpeedingrods.nl/en/products/rhb31-vz21-turbocharger-junta-100ps-for-motor-pequeno-rhino-motocicleta-at-vz21-npvl)
lists 24.2/37.1 mm compressor and 35/26.7 mm turbine inducer/exducer diameters.
The model's effective radii remain estimates.
[NASA compressor/turbine work relations](https://www.grc.nasa.gov/WWW/K-12/BGP/ctmatch.html)
provide the ideal-gas thermodynamic basis. Conservation checks establish
numerical consistency, not predictive accuracy for a real VZ21.
## Verification
All nine CTest suites passed after the changes. New checks cover stationary
equilibrium, startup, closed mass/energy balance, a pre-spun rotor, large shaft
timestep passivity, reverse flow, choking, subcritical backpressure response,
wastegate bypass, hot pulsing pipe coupling and twin throttle/limiter/release.
Closed 10 ms runs: measured mass drift zero; energy error -0.16 microjoule from
rest and -0.71 microjoule with an initially 120000 RPM shaft. Energy totals
include all gas, rotor and bearing heat. A hot 80 Hz pulsing pipe bench reached
189122 RPM, delivered .03067 kg/s charge at 376 K, and retained turbine power
pulses of 1189..4022 W. No internal transfer limiting or pipe repairs occurred.
The seven-second twin transient reached 236218 RPM, peak charge pressure
181.46 kPa absolute, peak instantaneous turbine-inlet pressure 674.10 kPa and
2.78 mm gate lift. It coasted down to 151755 RPM after release. Audio peak was
.02933 full scale, with no clipping; accumulated turbo energy residual was
-8.8 microjoules. High shaft speeds are model output, not validated operating
limits or evidence that a real VZ21 would survive them.
Same-engine-speed dyno comparison, .7 pedal, averaging the last half-second of
each two-second run:
| RPM | Turbo | MAP kPa | Exhaust collector kPa | Shaft kW | Charge K | Shaft turbo RPM |
| ---: | :---: | ---: | ---: | ---: | ---: | ---: |
| 4000 | no | 93.30 | 110.00 | 23.54 | — | — |
| 4000 | yes | 151.31 | 172.99 | 24.01 | 387.58 | 194130 |
| 7000 | no | 84.56 | 115.02 | 40.64 | — | — |
| 7000 | yes | 147.13 | 226.09 | 39.69 | 397.86 | 214361 |
Pressure and temperature costs are retained: boost does not guarantee more
shaft power. There is no forced power gain. Effective area/efficiency, gas
properties and the base engine's approximate combustion/overlap affect these
numbers strongly. They are prototype comparisons, not real engine predictions.
The benchmark used four solver substeps per output frame. The turbo cost .81
CPU seconds per simulated second at 4000 RPM and 1.28 at 7000 RPM, versus .53
for the unboosted twin. Sustained high-load real-time playback is an open issue;
monitor underruns. The mixed transient cost .84 wall seconds per simulated
second. Tests run headlessly; latest Windows runtime is unverified.
## Run
```sh
cmake --build build-desktop --target fluidsim_desktop -j 4
./build-desktop/fluidsim_desktop --scenario twin --turbo vz21 --scene field
cmake --build build-audit --target fluidsim_turbo_benchmark -j 4
./build-audit/fluidsim_turbo_benchmark
```
The startup menu also offers the turbo twin. WAV capture accepts
`--scenario twin --turbo vz21`. Blade-passing acoustics are the next requested
part: they must follow rotor geometry/loading and be filtered before 44.1 kHz
sampling, rather than adding an arbitrary sound or aliased pressure ripple.
+108
View File
@@ -0,0 +1,108 @@
# YZ125 baseline verification
Linux Release checks, 2026-10-23. All six CTest suites passed. This is a
YZ125-sized simulation baseline, not a measured replica of a particular year.
## Changes and physical basis
Pipes already supported per-cell areas/lengths and the geometric momentum
source for varying area. The earlier exhaust was a small expansion chamber,
but the UI drew all pipes with pressure-dependent thickness. The display now
uses physical diameter and axial cell length. A shared profile builder preserves
exact conical-frustum volume across mesh refinements.
The new estimated racing pipe has these dimensions (metres):
| Section | Length | Inlet diameter | Outlet diameter |
| --- | ---: | ---: | ---: |
| Header | .160 | .036 | .036 |
| First diffuser | .180 | .036 | .060 |
| Second diffuser | .190 | .060 | .105 |
| Belly | .130 | .105 | .105 |
| Baffle cone | .210 | .105 | .022 |
| Stinger | .240 | .022 | .022 |
Default mesh maximum length is 10 mm. The straight comparison has the same
total length and a uniform 36 mm bore. These are design estimates, not Yamaha
factory pipe dimensions. The test pulse returned -34.33 Pa from a diffuser and
+27.52 Pa from a convergent, with no positivity repairs. The intended negative
scavenging pulse and later positive plugging pulse follow the mechanism in
[SAE 680469](https://saemobilus.sae.org/papers/investigation-tuning-exhaust-system-small-two-stroke-cycle-engines-680469).
Two-stroke port areas now come from piston travel past rectangular port roofs,
replacing the poppet-style curtain-area curve. Assumed transfer/exhaust durations
are 130/190 degrees and aggregate widths 50/36 mm. Trapped compression is 8.2:1;
clearance volume is derived at exhaust closure, rather than confusing this with
full-stroke geometric compression. The exhaust power valve remains fixed open.
These port dimensions and compression interpretation require measured validation.
Combustion has an estimated .8 ms minimum burn duration; timing and duration are
frozen for each active charge. The estimated ignition curve retards above 6000
RPM rather than continuing to advance toward 40 degrees. Neither is a measured
factory CDI/flame model. Fuel remains ideally calculated at port closure.
Mechanical friction now includes a quadratic windage term. The two-stroke uses
FMEP [bar] = .4 + .09*mean_piston_speed + .0009*mean_piston_speed^2, converted to
crank torque with one revolution per cycle. Coefficients are generic estimates
within the ranges discussed in this
[Chalmers engine-model study](https://publications.lib.chalmers.se/records/fulltext/147782.pdf),
not a YZ125 coast-down fit. Crankcase pumping work is already modeled separately.
No speed clamp or rev limiter was added.
Drivetrain ratios use Yamaha's
[2022 YZ125 specification](https://global.yamaha-motor.com/jp/news/2021/0730/yz125.html):
primary 64/19, final 49/13, and six ratios approximately 2.384, 1.933, 1.588,
1.352, 1.176, 1.055. Nominal rear radius is .3313 m from the 100/90-19 tire;
loaded rolling radius is unmeasured. Test mass is 95 kg plus an assumed 75 kg
rider. First/sixth overall reductions are 30.276/13.402, replacing the twin's
much taller drivetrain. Other road-load/clutch parameters remain estimates.
The dyno now records brake shaft torque/power before external load reaction;
previously it displayed acceleration torque/power, which becomes zero at loaded
steady speed. An analytic load-balance test checks 10 Nm and 1 kW at 100 rad/s.
## Measurements and limits
The fixed-speed benchmark imposes speed as an ideal motoring/absorbing dyno and
records shaft output. It runs one simulated second per point and averages the
last half. All points fired approximately once per revolution, had zero pipe
positivity repairs, and cost about .53-.58 wall seconds per simulated second.
| RPM | Straight kW | Racing kW |
| ---: | ---: | ---: |
| 6000 | 4.02 | 6.27 |
| 8000 | .63 | 5.53 |
| 10000 | 2.43 | 10.53 |
| 12000 | 3.96 | 14.32 |
| 14000 | 3.60 | 12.38 |
| 17000 | -.80 | -3.94 |
This coarse sweep peaks near 12000 RPM; it is not a validated Yamaha dyno curve.
Negative power at 17000 means the virtual dyno must motor the engine. Free-rev
speed differs from peak-power speed: full pedal with the straight pipe still
approaches 16950 RPM after eight seconds. This remains an unresolved calibration
limit. The standard transient reached 16128 RPM, recovered idle at 3159 RPM,
and launched the motorcycle to 61.3 km/h without repairs or nonfinite output.
Six-second .6-pedal field captures had no clipping: racing rendered peak .201,
straight .554. Firing cadence, port timing and geometry are improved, but exact
YZ125 sound still requires listening and further combustion/scavenging work.
The first-order pipe flux damps high-frequency content; the compact source,
constant-gamma gas, ideal fueling, fixed power valve, single-zone mixing and
empirical monitoring/environment filters limit fidelity. No engine sound sample
or synthetic two-stroke firing track has been added.
## Run and compare
```sh
cmake --build build-desktop --target fluidsim_desktop -j 4
./build-desktop/fluidsim_desktop --scenario two-stroke --exhaust racing --scene field
./build-desktop/fluidsim_desktop --scenario two-stroke --exhaust straight --scene field
cmake --build build-audit --target fluidsim_two_stroke_benchmark -j 4
./build-audit/fluidsim_two_stroke_benchmark
```
Hold C, shift to first with D, apply W, then release C. A/D shift, Z selects
neutral. Up/down adjusts persistent pedal request; R changes environment.
The capture tool accepts the same exhaust option. Current captures are under
`build/audio/yz125-{racing,straight}-{rendered,dry,unfiltered}.wav`.