Improve physical geometry, fluid solvers, audio, and profiling

This commit is contained in:
max
2026-10-30 18:57:56 +01:00
parent bf8621ad39
commit eb2b6366c2
130 changed files with 14649 additions and 862 deletions

137
README.md
View File

@@ -87,7 +87,9 @@ Controls: W/S raise/lower the pedal over 0.5 seconds, C disengages the clutch,
V applies starter torque while held,
A/D shift, Z selects neutral, and left/right adjust engine load. The on-screen
pedal is direct and springs back on release; zero pedal retains ECU idle control.
Page Up/Down change playback speed; Space toggles real time.
Space toggles real-time and manual playback. In manual mode, Shift+scroll or
Page Up/Down changes speed; ordinary scrolling zooms the view. Rendering uses
display VSync independently of simulation speed, including 0.01x slow motion.
The command-line runner is useful for repeatable checks:
@@ -113,7 +115,8 @@ cmake --build build-msvc --target fluidsim_parity_trace
Desktop playback starts at real time: one solver output frame per 44.1 kHz
stereo device frame. A simulation worker fills a bounded 8192-frame queue in
512-frame batches with a 4096-frame startup reserve (about 93 ms). The device
up to 128-frame batches with a 4096-frame startup reserve (about 93 ms). Batches
shrink with playback speed so 0.01x does not advance in large bursts. The device
callback only reads samples, removes DC, converts to PCM and handles underruns;
it performs no simulation, allocation or waiting. An underrun fades out and
recovery crossfades over 64 samples rather than stepping abruptly to silence.
@@ -155,10 +158,18 @@ or exhaust afterfire chemistry. Filtering cannot recover aliased
source information. See [audio verification](verification/AUDIO_RENDERING.md)
for capture commands, current renderer details and limitations.
Use the **Cells/m - / +** control in the sidebar to change the active scenario's
pipe resolution. Changes rebuild the mesh in the background and restart the
engine, retaining solver, listener, scene and driving-control inputs. Values are
remembered separately per scenario until the app closes. Set persistent defaults
in each engine TOML's `[simulation] cells_per_meter`. The desktop engine editor
has been removed; edit engine calibration in TOML.
Launching `fluidsim_desktop` without `--scenario` opens a small scenario menu.
Choose the twin, YZ125, Saab B205, or American V8 card, or select with Up/Down
and press Enter.
Escape returns from a running scenario to the menu, stopping its simulation and
Escape returns from the scenario to the menu, stopping its simulation and
audio so another scenario can be selected. Escape closes the menu at the category
screen. Simulation and audio start after selection. Passing
`--scenario twin`, `--scenario two-stroke`, `--scenario b205`, or `--scenario v8`
@@ -176,7 +187,9 @@ cmake --build build-desktop --target fluidsim_desktop -j 4
Hold **W** to raise the pedal and **S** to lower it. Releasing the keyboard
returns the pedal over 0.5 seconds. The UI lever is direct and springs back. Use
**Space** to restore real-time playback and **R** to change environment. The two-stroke desktop uses
**Space** to toggle real-time/manual playback and **R** to change environment.
In manual mode use **Shift+scroll** or **Page Up/Down** to adjust speed;
ordinary scrolling continues to zoom the view. The two-stroke desktop uses
the existing 125 cc configuration; its dimensions and calibrations must be
adapted before it represents a particular engine. Both scenarios use the same
motorcycle test model, dashboard and rolling peak dyno graph (kW and Nm versus
@@ -310,7 +323,7 @@ runs for every scenario, and finite audio/reverb output.
## Fuel and throttle control
Desktop playback has automatic gain enabled by default for every scenario.
Desktop playback has automatic gain disabled by default for every scenario.
Press **G** to toggle it; the dashboard shows its state. It tracks stereo RMS
and peaks after DC removal, lifting quiet idle audio gradually (1.5-second
gain-rise time constant) and reducing gain faster for loud revs (30 ms).
@@ -410,8 +423,8 @@ Manifold vacuum at closed throttle remains part of the simulated pumping cycle.
## Pipe solver comparisons
The desktop accepts `--solver rusanov|hlle|hllc`. Press **F3** during playback to
cycle Rusanov, HLLE and HLLC; the dashboard shows the current solver. All pipes
The desktop accepts `--solver rusanov|hlle|hllc|muscl`. Press **F3** during playback to
cycle Rusanov, HLLE, HLLC and MUSCL; the dashboard shows the current solver. All pipes
switch together between simulation samples. Rusanov remains the startup default.
Changing solver affects the ongoing engine state; allow several cycles and the
audio queue to settle before judging it. Use the same scene and auto-gain setting.
@@ -499,16 +512,20 @@ geometry-resolving junction model. Momentum changes
are reacted by the fitting. Branch angle losses are not modeled. The separate
`Junction` class remains available for explicit finite-volume chambers.
Each V8 bank now has a 4-2-1 header: four equal 750 mm x 38 mm primaries feed two
equal 400 mm x 45 mm secondaries, then a 50 mm exhaust. Pairings are 1+2 / 3+4
Each V8 bank has a 4-2-1 header: four primaries feed two secondaries, then a
50 mm exhaust. Pairings are 1+2 / 3+4
and 5+7 / 6+8 with this simulation's bank numbering and firing order. Two T
junctions and a 780 mm x 38 mm tube form the H-pipe. Small configurable port-coupled junction volumes are used by the V8. The intake
plenum also remains a storage volume.
The TOML `primaries` pipe group configures primary length/diameter, while
The TOML `primaries` pipe group configures diameter; measured
`geometry.pipes` centerlines configure length and position. Headers now use
direct swept bends with revised lengths, and the short/long variants have
distinct physical layouts. See [geometry definitions](docs/ENGINE_CONFIG.md).
The
`[junctions] h_pipe` enables the H crossover;
pass it as the fourth `FourStrokeScenario` constructor argument. The renderer
routes the primary pairs into Y merges, then the final Y collectors and H-pipe,
using local pipe diameter and pressure colors without collector boxes.
uses the same centerlines, cross-sections and active storage-volume dimensions
as the fluid system, with local pressure colors and mitered hard corners.
The previous header optimization measurements applied to the earlier finite-volume
4-1 layout and do not establish an optimum for this new 4-2-1 network.
@@ -619,3 +636,99 @@ The tool also prints CSV diagnostics: run without arguments for the four main
operating points, or use `--sweep single-450` for a denser sweep of one scenario.
See [carb calibration results](verification/CARB_CALIBRATION.md) for operating
conditions, AFR values and the distinction between carb and recirculated charge.
### Source-separated audio diagnostics
The capture tool writes `-intake.wav`, `-exhaust.wav`, `-exhaust-2.wav`, and
`-valve-contact.wav` alongside the existing rendered, dry, and unfiltered mixes.
Source stems contain direct sound and early reflections, before the shared diffuse
reverb; `-tail.wav` contains that shared tail. With all sources enabled, the four
stems plus the tail reconstruct the rendered mix before WAV quantization/clipping.
Absent sources produce silent files. Peak, RMS, maximum sample delta, and clipping
counts are reported for every stem, in device full-scale units, without normalization.
Use `--solo intake`, `--solo exhaust`, `--solo exhaust-2`, or
`--solo valve-contact` to select a source in the output mix (default: `--solo all`).
All diagnostic stems remain active during soloing. These controls affect audio only;
they do not change the fluid simulation. Source controls are simulation-thread APIs.
```powershell
.\out\build\windows-gcc\fluidsim_audio_capture.exe --example single-450 --rpm 3000 --throttle .3 --warmup 1 --seconds 2 --scene dry --out out/audio/single-450-baseline
```
For intake-only listening, repeat with `--solo intake` and a different output prefix.
The shared tail can retain decay when controls change during playback.
Captures use 32-bit IEEE float WAV to preserve very quiet sources without clipping.
For audible, individually peak-normalized PCM16 listening copies, run:
```powershell
py tools/audio_preview.py out/audio/single-450-baseline
```
Previews appear in `out/audio/previews/`, with gain reported for each file.
Silent sources are skipped. Preview loudness does not represent relative source
strength; use the original captures and metrics for calibration.
### Acoustic pulse diagnostics
The `fluidsim_acoustic_benchmark` target compares straight connections, idealized
three-way junctions, and finite-volume fittings across meshes, timesteps, and
all three flux solvers. It exports pressure/velocity traces and acoustic energy
ratios, with conservation and numerical-repair diagnostics. See
[the benchmark guide and initial findings](docs/ACOUSTIC_BENCHMARK.md).
### Listening comparison: limited second-order pipes
Desktop auto gain now starts **off**. Press **G** to enable it if desired.
For a direct comparison on the current engine, keep throttle and master volume
fixed and press **F3** to cycle `rusanov ? hlle ? hllc ? muscl`.
The dashboard shows the selected solver. Rusanov remains the startup default.
To start directly in the new mode:
```powershell
.\out\build\windows-gcc\fluidsim_desktop.exe --example single-450 --solver muscl --scene dry
```
`muscl` uses minmod-limited primitive MUSCL-Hancock reconstruction with HLLC
fluxes on uniform pipe sections. Matching direct connections share reconstruction
stencils. Component boundaries and area/profile transitions retain first-order
coupling; nonphysical predicted edges fall back to cell averages, and HLLC keeps
its existing HLLE fallback. Reconstruction buffers are allocated at construction.
This is a listening candidate, not a calibrated real-engine sound model.
At 3000 RPM / 0.3 pedal, four-second dry captures are in
`out/audio/pipe-ab-rusanov-rendered.wav` and `out/audio/pipe-ab-muscl-rendered.wav`.
They preserve the actual level difference. New wave resolution can also change
cylinder filling, combustion, and torque. Restart in each solver for clean
comparisons; live switching retains the engine's current state.
For a comparison at equal RMS loudness, use
`out/audio/pipe-ab-rusanov-level-matched.wav` and
`out/audio/pipe-ab-muscl-level-matched.wav`. Both are PCM16 listening copies;
original float captures keep their physical output scale. Equal RMS does not
imply identical perceived loudness or identical engine state.
In one local loaded V8 check, MUSCL took 1.23 wall seconds per simulated second,
versus 0.78 for Rusanov. Large engines may underrun in real-time playback;
use the single-450 for the first listening comparison.
### Direction-aware characteristic junctions
A nonlinear zero-storage exhaust junction solver is now available separately
from the pipe solver. Start with Rusanov pipes to isolate the junction change:
```powershell
.\out\build\windows-gcc\fluidsim_desktop.exe --example v8-h --solver rusanov --junctions characteristic --junction-loss 0.5 --scene dry
```
Use `--junctions volume` to compare against the original volume fittings.
`--junctions legacy` selects the old dissipative zero-storage Rusanov node.
Default engine behavior still uses volume fittings. Direction losses use local
route tangents, with explicit TOML branch direction overrides supported. The
loss coefficient is an uncalibrated engineering parameter; zero disables angle
losses. Auto gain still defaults off.
The single-450 also supports these switches, but its two-port collector cannot
exercise multi-branch turning. Selecting a zero-storage node there removes its
collector-volume resonance. See [junction details](docs/JUNCTION_SOLVER.md).