all of the changes

This commit is contained in:
grillkol committed 2026-10-23 18:29:51 +02:00
1 parent 4c435fdd76
commit 5607dcf2b5
73 files changed
+4365 -2059

No files matched your search

+205 -55
View File
@@ -83,10 +83,11 @@ installed Windows or Linux system fonts. To bundle another font, add
headless build, add `-DFLUIDSIM_BUILD_DESKTOP=OFF`; this skips SFML and the
desktop's graphics/audio dependencies.
Controls: hold `W` for throttle, `C` for clutch, `A` / `D` to shift, `Z` for
neutral, up/down to adjust throttle target, left/right to adjust engine load,
`M` toggles mechanical engine noise, mouse wheel changes simulation playback
speed, and Space toggles real time.
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.
The command-line runner is useful for repeatable checks:
@@ -118,8 +119,11 @@ it performs no simulation, allocation or waiting. An underrun fades out and
recovery crossfades over 64 samples rather than stepping abruptly to silence.
The callback never advances physical time to conceal missing samples.
The source is a linear compact-monopole approximation,
`p(r,t) = (d mass_flow/dt)/(4*pi*r)`. Intake and exhaust have separate static
The primary source is a linear compact-monopole approximation,
`p(r,t) = rho_ambient * (d volume_flow/dt)/(4*pi*r)`. Mouth volume flow
comes from the boundary face velocity and area. Fluid conservation retains the
actual mass flux; hot/cold density changes are excluded from the acoustic source.
Intake and exhaust have separate static
positions, fractional-sample propagation delays, inverse-distance spreading,
and left/right ear paths. Playback calibration is 200 Pa per device full scale;
this is not calibrated speaker SPL. A second-order 6 kHz monitoring filter
@@ -128,19 +132,27 @@ A roughly 3.5 Hz device DC blocker and final PCM clipping protection remain.
Use 1x playback for acoustic evaluation.
The default environment is a nearby wall. Press **R** to cycle dry, field,
wall and woodland. Ground/wall image paths provide early reflections; the
woodland scatterers and decaying feedback-delay tail are approximate effects,
not validated outdoor acoustics. Synthetic mechanical noise remains optional.
The compact source does not implement pipe-end radiation impedance, validated
directivity, or exhaust afterfire chemistry. Filtering cannot recover aliased
wall, woodland, and tunnel. Ground/wall image paths provide early reflections;
the live eight-line feedback-delay network supplies a scene-dependent late
tail. Woodland scatterers and the hard-surface tunnel images are approximate.
These are listening profiles, not validated acoustics. Mechanical sounds are
not implemented.
Open pipe mouths now use a causal unflanged radiation boundary with frequency-
dependent reflection and end correction. Intake mouths draw fresh ambient gas
directly, replacing the fixed atmosphere component and its inlet orifice.
The model assumes plane waves and low mean flow; strong jet and vortex effects
remain unmodeled. The compact source does not implement validated directivity
or exhaust afterfire chemistry. Filtering cannot recover aliased
source information. See [audio verification](verification/AUDIO_RENDERING.md)
for tests, capture commands, limitations and measured transient reductions.
for capture commands, current renderer details and limitations.
Launching `fluidsim_desktop` without `--scenario` opens a small scenario menu.
Click the twin, YZ125 or Saab B205 card to start, or select with Up/Down and press Enter.
Choose the twin, YZ125, Saab B205, or American V8 card, or select with Up/Down
and press Enter.
Escape closes the menu. Simulation and audio start after selection. Passing
`--scenario twin`, `--scenario two-stroke` or `--scenario b205` bypasses the menu; `--scene` and
`--exhaust` options also apply when choosing through the menu.
`--scenario twin`, `--scenario two-stroke`, `--scenario b205`, or `--scenario v8`
bypasses the menu; `--scene` and `--exhaust` options also apply
when choosing through the menu.
To test the two desktop engines from the repository root:
@@ -151,7 +163,8 @@ cmake --build build-desktop --target fluidsim_desktop -j 4
./build-desktop/fluidsim_desktop --scenario twin --scene field
```
Hold **W** for throttle, use **Up/Down** to adjust the persistent pedal request,
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
the existing 125 cc configuration; its dimensions and calibrations must be
adapted before it represents a particular engine. Both scenarios use the same
@@ -214,6 +227,13 @@ seconds per simulated second here, including coast-down (previously up to
repairs. The CFL limit remains enforced; other operating points may still
require subdivisions. The desktop retains the 4x playback gain.
The V8 uses the same per-pipe resolution policy as other scenarios. Uniform
mesh benchmarks found that 35 cells/m was near real time under one pedal
workload and 33 cells/m was near real time at steady 4500 RPM on the tested
machine; denser uniform meshes ran slower than real time. The existing
per-pipe mesh is faster and remains in use. See [V8 performance notes](verification/V8_PIPE_PERFORMANCE.md)
for measurements and reproduction commands.
Benchmark or capture with:
```sh
@@ -222,36 +242,9 @@ Benchmark or capture with:
./build-desktop/fluidsim_audio_capture --scenario v8 --seconds 6 --throttle .3 --out /tmp/v8
```
## Twin with a VZ21-size turbo
Choose **600 cc twin + VZ21-size turbo** in the startup menu, or bypass it:
```sh
./build-desktop/fluidsim_desktop --scenario twin --turbo vz21 --scene field
./build-audit/fluidsim_cpp --scenario twin --turbo vz21 --seconds 5 --throttle 0.7
```
`Turbocharger` connects to four existing pipe ends and couples turbine and
compressor work through a rigid rotor. Small housing volumes preserve unsteady
exhaust pressure. Backpressure, charge temperature and spool speed emerge from
flow restrictions and energy exchange. A pressure-can/spring wastegate opens a
bypass; no boost pressure is imposed. HUD pressures are absolute. The default
unboosted twin is unchanged unless `--turbo vz21` is selected.
This is an estimated VZ21-size model, not a measured turbo map. Engine exhaust
pulses are implemented; blade-passing whistle/wakes are still pending. The
seven-second twin transient and all nine CTest suites passed. The optimized
7,000-RPM workload takes about 0.65 wall seconds per simulated second on the audit
machine; actual playback headroom depends on the computer. See
[turbo verification](verification/TURBO_VZ21.md) for assumptions and results.
## Saab B205 / 9-5 wagon baseline
The Saab menu entry now includes an estimated GT17 turbo and ECU wastegate boost
control (up to 0.45 bar gauge). Launch with `--scenario b205 --turbo gt17`, or use
`--turbo none` for the naturally aspirated baseline. See [GT17 verification](verification/SAAB_GT17.md)
for controller behavior, assumptions and tests. Charge heating and backpressure
are simulated; an intercooler is not yet included.
The Saab menu entry models the naturally aspirated B205 baseline.
Select **Saab B205 / 9-5 wagon** from the desktop menu, or launch directly:
@@ -266,10 +259,8 @@ cylinder and 1-3-4-2 firing order. Four intake runners and four exhaust headers
connect shared plenums and a tailpipe. The vehicle approximates a 9-5 wagon:
1675 kg with driver, five-speed manual, FM55 B05 overall ratios
13.70 / 7.12 / 4.77 / 3.62 / 2.67, and 4.05 final drive. No sixth gear is offered.
Controls and dyno match the other scenarios. The original atmospheric-breathing
geometry baseline remains available with `--turbo none`. Pipe/cam dimensions,
Controls and dyno match the other scenarios. Pipe/cam dimensions,
friction, idle/ignition maps, clutch, drag and loaded tire radius are estimates.
Turbo calibration and acoustics are approximate; factory power is not validated.
See [B205 verification](verification/B205_BASELINE.md) for sources and checks.
## Current port status
@@ -280,8 +271,8 @@ configurable 0-D volume components (including thermal relaxation and moving
volume work), profiled compressible 1-D pipes and boundaries, adaptive solver
stepping, the impulse-clutch motorcycle/road-load model, and the active 600 cc
twin topology. Audio includes the flow-derivative source, spatialized
intake/exhaust radiation, outdoor feedback-delay reverb, optional mechanical
noise, a lock-free simulation audio buffer, a `SoundEngine` lifecycle wrapper,
intake/exhaust radiation, outdoor feedback-delay reverb, a lock-free simulation
audio buffer, a `SoundEngine` lifecycle wrapper,
and an SFML desktop frontend. The shared 50-RPM-bin dyno history and graph are
also ported. A crankcase-scavenged 125 cc two-stroke scenario is available in
the core and desktop, with an ECU, finite-response throttle and dynamic reed.
@@ -313,15 +304,17 @@ 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).
Extra gain is capped at 12x above the existing fixed 4x playback gain, with
linked stereo peak protection. Silence does not request additional boost and
linked stereo peak protection. Silence does not change the engine controls and
underruns freeze the detector. Disabling smoothly returns to fixed playback
gain. Simulation pressures and WAV capture levels are unaffected.
Both desktop engines use `Ecu` (`include/FluidSim/Ecu.hpp`). The desktop and
CLI throttle values are pedal requests; the actual throttle is advanced every
simulation sample, independently of rendering. Opening and closing use an
80 ms first-order actuator response and a maximum travel rate of two full
travels per second. The four-stroke uses an ideal butterfly projection; the
1 ms first-order throttle-body response capped at 1000 full travels per second.
The two-stroke carb slide uses 0.2 ms and 5000 full travels per second.
Only the keyboard pedal request ramps over 0.5 seconds; the UI slider is direct.
Physical fuel-film and mixture transport dynamics remain in the carburetor. The four-stroke uses an ideal butterfly projection; the
two-stroke uses the circular-segment aperture uncovered by a translating slide.
Shaft obstruction and edge leakage are not modeled.
@@ -352,13 +345,19 @@ is transported out through the exhaust without pipe combustion. No sound
samples are mixed in.
All ECU parameters are accessible calibrations, not measured engine maps.
There is no starter motor, automatic restart, knock sensor, lambda sensor,
Holding V applies configurable constant starter torque at the crankshaft in every
scenario; release or loss of window focus disengages it. This is a torque source,
without battery, motor electrical, or starter gearing models. There is no
automatic restart, knock sensor, lambda sensor,
catalyst, cold-start temperature model or injector electrical model. Idle
control can still stall under excessive load and does not impose crankshaft
speed or add artificial sustaining torque. Existing combustion/thermal models
remain approximations; ECU changes do not establish their physical accuracy.
The two-stroke targets 3000 RPM idle and uses idle ignition trim in addition to
throttle control. Its
The two-stroke uses a fixed mechanical carb slide stop instead of RPM-controlled
idle throttle or idle ignition trim. Each carb scenario config sets
`TwoStrokeConfig::idle_slide_opening` (normalized 0..1); the default is 0.045,
or 4.5% slide travel. Pedal demand above that stop opens the slide further.
The resulting idle RPM depends on the simulation and load. Its
reed is a damped lumped cantilever model with finite opening time and seating
contacts. Cylinder and crankcase moving-volume work use adiabatic energy changes.
Jet dimensions are effective flow calibrations rather than measured Mikuni
@@ -396,3 +395,154 @@ The twin intake is supplied by an explicit 300 K atmospheric reservoir rather
than a pressure-only boundary with extrapolated entropy. The repeated-blip
`fluidsim_intake_regression` checks fresh-air supply and pressure/idle recovery.
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
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.
Each method currently uses the same first-order spatial discretization and CFL
limit. HLLC resolves contact transport with less diffusion and uses HLLE when
its intermediate states are invalid. These are solver experiments; sharper
signals do not by themselves prove more accurate combustion or sound.
For repeatable comparisons, WAV capture accepts `--solver`, `--rpm` (an ideal
speed-holding dyno) and `--warmup` in seconds. Capture gains are identical across
solvers and do not include desktop automatic gain. For example:
```sh
./build-desktop/fluidsim_desktop --scenario v8 --scene dry --solver hllc
./build-desktop/fluidsim_desktop --scenario two-stroke --scene dry --solver hllc
./build-desktop/fluidsim_scenario_benchmark 8 loaded v8 0 hllc
./build-desktop/fluidsim_scenario_benchmark 8 loaded two-stroke-racing 0 hllc
./build-desktop/fluidsim_audio_capture --scenario v8 --solver hllc --scene dry --rpm 4500 --warmup 2 --seconds 6 --throttle .7 --out /tmp/v8-hllc
```
The benchmark's fourth argument is the existing optional uniform V8 cells/m
setting (0 keeps the scenario mesh); its fifth argument selects the pipe solver.
See [solver measurements](verification/SOLVER_COMPARISON.md) for results.
## Desktop workspace and 3D view
The desktop has a neutral black/gray workspace: a left telemetry and control
panel, an engine viewport, a dyno panel, and a cylinder inspector. Resize or
maximize the window to give the engine view more space. All desktop engine
presets use the OpenGL 3D renderer by default. Tab switches to the existing
schematic view. Left drag orbits, right/middle drag pans, the wheel zooms, and
Home fits the engine again. Camera gestures are confined to the engine viewport.
The spring-return pedal slider sends a pedal request to the ECU. W/S pedal
travel takes 0.5 seconds in either direction; releasing W returns toward zero
at the same speed. End releases the pedal immediately. Zero pedal lets the ECU
operate its idle throttle opening. Solver cycling is now F3; S lowers the pedal.
Pipes are continuous indexed tube meshes with smooth bends, physical diameters
from the simulated area profile, and per-vertex pressure colors. Route points
are keyed by distance along the simulated pipe, in metres. Moving those drawing
points changes the schematic route, not the fluid solver lengths. The fixed
pressure scale is blue at vacuum, green at 101325 Pa and red at/above 1 MPa.
Volumes and cylinder gas use the same pressure scale. Pistons and rods animate
from snapshot piston positions and crank phases. Geometry is schematic rather
than a dimensionally complete engine CAD model.
Code responsibilities are split into `DesktopUi`/`WorkspaceLayout`, `OrbitCamera`,
`PedalControl`, `PipePath`, `EngineRenderer3D`, `EngineSchematic` and `DynoRenderer`.
The renderer consumes snapshots and reuses meshes; it does not step the solver.
OpenGL is linked through CMake's `OpenGL::GL`. This first renderer uses indexed
client arrays, lighting and a depth buffer in an OpenGL compatibility context,
with SFML's GL state preservation around the viewport pass. It is not a core
profile shader renderer. Windows runtime still needs verification on Windows.
### Saab exhaust silencers
The B205 exhaust now includes a 6 L straight-through resonator and an 18 L
straight-through rear muffler, separated by 0.8 m of pipe and followed by a
radiating tailpipe. Saab uses two minimum fluid substeps per audio sample; the
acoustic CFL condition can request more. These are estimated large
passenger-car silencers, not measured Saab internals. `ExhaustConfig` and
`SilencerConfig` in `include/FluidSim/Silencer.hpp` configure length, nominal body
volume, core diameter, chamber count, baffle passage diameter, linear resistance
(1/s), and quadratic loss coefficient. Pass an `ExhaustConfig` as the third
`FourStrokeScenario` constructor argument; `enabled=false` bypasses the silencers.
Expansion and chambered silencers use resolved variable-area passages. Body
radius is derived from volume and length; tapered transitions reduce actual gas
volume below the nominal cylindrical body volume. Straight-through mode retains
a constant core through the housing and uses a linear resistance surrogate for
packing. It does not yet resolve perforation coupling or porous-material acoustics.
Loss coefficients are tuning inputs, not calibrated predictions from body geometry.
Momentum losses retain total gas energy, converting kinetic energy into heat.
The renderer draws round housings with their configured lengths and diameters.
### N-port junctions and V8 4-2-1 exhaust
`BoundarySystem::add_junction({{pipe_index, left_end}, ...})` connects any number
of pipe faces without a storage volume. A shared stationary Rusanov state is computed algebraically from all connected
faces. Integrated mass, total energy and species fluxes sum to zero at each node. Setup claims every endpoint;
updates allocate no memory. This is a dissipative one-dimensional numerical coupling, not a
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
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.
`V8ExhaustConfig` configures primary length/diameter and 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.
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.
### Example browser and small port-coupled junctions
The startup browser now scrolls with the mouse wheel, Up/Down, Page Up/Down,
Home and End. It adapts to the window size and shows a scroll indicator. Click
an example or press Enter to start it. The examples are defined in
`ScenarioCatalog.hpp`, grouped into categories with selectable variants. These are configuration comparisons of
the existing engine models, not measurements of additional production engines.
The V8 currently uses port-coupled finite-volume fittings, configured by
`V8ExhaustConfig::junction_volume` (default 50 cc per fitting). They use the
existing conservative component/port exchange and have no volume boxes in the
renderer. The earlier zero-storage Rusanov junction remains available for
comparison through `BoundarySystem::add_junction`, but is not used by the V8.
The 4-2-1 piping and the H crossover geometry remain the same.
### Engine families and inspired builds
The browser opens at engine categories; click a category to see variants, then
click a variant or press Enter to start. Backspace, Left, Escape or the
`< Categories` header returns to categories. Both levels support wheel and
keyboard scrolling.
`EngineConfig` supplies cylinder count (up to 12), inline/V/boxer layout,
bank angle, bore/stroke/rod, compression, firing phases, rev limit and fueling.
The catalog includes four-stroke singles, parallel and V twins, inline 3/4/5/6,
V6/V8/V10/V12 and flat 4/6 examples. Inspired builds include F20C, Audi five,
RB26, Busso V6, EJ20, 911 flat-six, 916 V-twin and 250 V12 concepts. These use
estimated calibrations and simplified common-plenum/exhaust networks: they are
not factory replicas, measured torque curves, or turbocharged configurations.
The 8.0 L big-block variant transports carburetor fuel through its intake into
the cylinders. Its fixed idle stop is configured with `EngineConfig::idle_opening`.
It reuses the lumped carb model with scaled effective jets; multiple carb barrels,
floats and cylinder-specific fuel distribution are not resolved. Larger engine
geometry requires its own mixture and idle calibration.
Two-stroke families include 50, 125 and 500 cc singles. The 125 variants compare
standard, straight, long, short and wide chambers. The 50/500 concepts scale
bore/stroke, rod, crankcase clearance, port widths, flywheel inertia and chamber
geometry; they retain estimated carb and combustion calibrations. A different
chamber is a geometry experiment, not a guaranteed RPM or power improvement.
Launch a specific variant directly with `--example big-carb`, `--example flat6`,
`--example fifty` or another catalog ID. Carb jet scaling is configurable per
engine (`EngineConfig::carb_jet_scale`, `carb_pilot_scale`, or
`TwoStrokeConfig::jet_scale`).