Add machine workshop, typed logic, mechanics and sensor-driven ECUs

This commit is contained in:
max
2026-11-02 07:27:13 +01:00
parent eb2b6366c2
commit abfcce0f46
99 changed files with 28835 additions and 145 deletions

View File

@@ -0,0 +1,9 @@
scenario,runtime,frames,rpm,pedal,cells,min_cell_mm,substeps_per_frame,us_per_frame,wall_per_sim,positivity_repairs
single-450,native,32768,3000,0.35,44,43.7834,1,2.89427,0.127637,0
single-450,workshop,32768,3000,0.35,44,36.6667,1,3.54769,0.156453,0
twin,native,32768,3000,0.35,59,18.9302,1.70621,6.11425,0.269638,0
twin,workshop,32768,3000,0.35,58,15,1.71796,6.89146,0.303913,0
flat6,native,32768,3000,0.35,98,34.1958,1.03406,8.42729,0.371643,0
flat6,workshop,32768,3000,0.35,98,34.1958,1.02969,8.79167,0.387713,0
v8-h,native,32768,3000,0.35,176,36.3695,1,16.5588,0.730241,0
v8-h,workshop,32768,3000,0.35,175,36.3695,1,16.0058,0.705858,0
1 scenario runtime frames rpm pedal cells min_cell_mm substeps_per_frame us_per_frame wall_per_sim positivity_repairs
2 single-450 native 32768 3000 0.35 44 43.7834 1 2.89427 0.127637 0
3 single-450 workshop 32768 3000 0.35 44 36.6667 1 3.54769 0.156453 0
4 twin native 32768 3000 0.35 59 18.9302 1.70621 6.11425 0.269638 0
5 twin workshop 32768 3000 0.35 58 15 1.71796 6.89146 0.303913 0
6 flat6 native 32768 3000 0.35 98 34.1958 1.03406 8.42729 0.371643 0
7 flat6 workshop 32768 3000 0.35 98 34.1958 1.02969 8.79167 0.387713 0
8 v8-h native 32768 3000 0.35 176 36.3695 1 16.5588 0.730241 0
9 v8-h workshop 32768 3000 0.35 175 36.3695 1 16.0058 0.705858 0

View File

@@ -0,0 +1,8 @@
single-450 native: cells=44 min_cell_mm=43.7834 substeps/frame=1 us/frame=3.17636 realtime_ratio=0.140078
single-450 workshop: cells=56 min_cell_mm=5 culprit=Inlet metering stub substeps/frame=4 us/frame=12.6059 realtime_ratio=0.555921 slowdown=3.96866
twin native: cells=59 min_cell_mm=18.9302 substeps/frame=1.70621 us/frame=6.21104 realtime_ratio=0.273907
twin workshop: cells=67 min_cell_mm=5 culprit=Inlet metering stub substeps/frame=4 us/frame=16.9562 realtime_ratio=0.747767 slowdown=2.73001
flat6 native: cells=98 min_cell_mm=34.1958 substeps/frame=1.03406 us/frame=9.63491 realtime_ratio=0.424899
flat6 workshop: cells=161 min_cell_mm=1.7773 culprit=Pipe 12 / flat6 substeps/frame=12.3495 us/frame=104.441 realtime_ratio=4.60584 slowdown=10.8398
v8-h native: cells=176 min_cell_mm=36.3695 substeps/frame=1 us/frame=15.5274 realtime_ratio=0.684757
v8-h workshop: cells=318 min_cell_mm=4.99998 culprit=Inlet metering stub substeps/frame=4.08749 us/frame=67.5066 realtime_ratio=2.97704 slowdown=4.34759

View File

@@ -0,0 +1,9 @@
scenario,runtime,frames,rpm,pedal,cells,min_cell_mm,substeps_per_frame,us_per_frame,wall_per_sim,positivity_repairs
single-450,native,32768,6000,0.7,44,43.7834,1,2.9588,0.130483,0
single-450,workshop,32768,6000,0.7,44,36.6667,1,3.56339,0.157145,0
twin,native,32768,6000,0.7,59,18.9302,2.03198,7.14645,0.315158,0
twin,workshop,32768,6000,0.7,58,15,1.98846,8.3636,0.368835,0
flat6,native,32768,6000,0.7,98,34.1958,1.04791,9.21917,0.406565,0
flat6,workshop,32768,6000,0.7,98,34.1958,1.04437,9.31432,0.410762,0
v8-h,native,32768,6000,0.7,176,36.3695,1.0159,16.3243,0.719902,0
v8-h,workshop,32768,6000,0.7,175,36.3695,1,16.1124,0.710557,0
1 scenario runtime frames rpm pedal cells min_cell_mm substeps_per_frame us_per_frame wall_per_sim positivity_repairs
2 single-450 native 32768 6000 0.7 44 43.7834 1 2.9588 0.130483 0
3 single-450 workshop 32768 6000 0.7 44 36.6667 1 3.56339 0.157145 0
4 twin native 32768 6000 0.7 59 18.9302 2.03198 7.14645 0.315158 0
5 twin workshop 32768 6000 0.7 58 15 1.98846 8.3636 0.368835 0
6 flat6 native 32768 6000 0.7 98 34.1958 1.04791 9.21917 0.406565 0
7 flat6 workshop 32768 6000 0.7 98 34.1958 1.04437 9.31432 0.410762 0
8 v8-h native 32768 6000 0.7 176 36.3695 1.0159 16.3243 0.719902 0
9 v8-h workshop 32768 6000 0.7 175 36.3695 1 16.1124 0.710557 0

View File

@@ -0,0 +1,3 @@
scenario,frames,wall_seconds,sim_seconds,sim_per_wall,underruns,buffered
flat6,120,2.00608,2.02014,1.00701,0,4096
v8-h,120,2.0706,2.08181,1.00541,0,4096
1 scenario frames wall_seconds sim_seconds sim_per_wall underruns buffered
2 flat6 120 2.00608 2.02014 1.00701 0 4096
3 v8-h 120 2.0706 2.08181 1.00541 0 4096

View File

@@ -0,0 +1,3 @@
scenario,frames,ms_per_frame,render_fps
flat6,120,0.696523,1435.7
v8-h,120,0.963612,1037.76
1 scenario frames ms_per_frame render_fps
2 flat6 120 0.696523 1435.7
3 v8-h 120 0.963612 1037.76

View File

@@ -0,0 +1,3 @@
scenario,frames,ms_per_frame,render_fps
flat6,120,1.40442,712.035
v8-h,120,1.77209,564.305
1 scenario frames ms_per_frame render_fps
2 flat6 120 1.40442 712.035
3 v8-h 120 1.77209 564.305

View File

@@ -0,0 +1,95 @@
# Workshop performance, 2026-10-30
The flat-six workshop now runs within the real-time audio budget. The measured
simulation cost fell from 104.44 to 8.79 microseconds per sample (11.9 times faster).
At 44,100 Hz the available budget is 22.68 microseconds per sample.
## Cause and changes
The workshop used a different assembly path from the native scenarios. It split
fluid sections at every visual pipe knot, inserted 5 mm inlet stubs, required at
least four fluid substeps per sample, and repeated mechanical/control work in
each substep. Flat6 consequently had a 1.78 mm cell and averaged 12.35 substeps
per sample. Its native scenario had a 34.20 mm minimum cell and about one substep.
- Mesh each pipe by total arclength and its diameter profile. Visual knots remain
in the editor and renderer; exact frustum averages preserve gas volume.
- Advance shaft, ECU, cams, combustion, carburetors and pump displacement at the
audio sample rate, matching native engine scheduling. Keep CFL stepping for
fluid transport and pressure-operated check valves. Compile active part/gate
lists and cache fixed restriction areas.
- Place the importer's metering assembly farther upstream within its existing
inlet segment, allowing a sensible outlet stub. The inlet endpoints, route
length, diameter and total gas volume stay the same. Existing custom pipes are
never lengthened automatically; actual short pipes still constrain CFL steps.
- Cache local pipe vertices, normals and indices, shared primitive meshes, and
the part-picker icon atlas. Transforms and pressure updates reuse geometry;
route/diameter edits rebuild the affected pipe.
Untouched stock imports in `machines/` were compared against the previous
importer's canonical output before replacement. User files, including
`paralell-twin.machine.toml`, were preserved.
## Simulation results
Windows GCC RelWithDebInfo, Rusanov, preset density 20 cells/m, 44,100 Hz,
512 warm-up samples and 32,768 measured samples, motor-driven at 3,000 RPM,
35% pedal. Timings include audio synthesis but exclude editor rendering and
snapshot collection. Paired native/workshop measurements use the same process;
before/after runs have normal timing variation.
| Preset | Workshop before, us/sample | Workshop after | Native after | Workshop cells before / after | Substeps before / after |
| --- | ---: | ---: | ---: | ---: | ---: |
| Single 450 | 12.61 | 3.55 | 2.89 | 56 / 44 | 4.00 / 1.00 |
| Twin | 16.96 | 6.89 | 6.11 | 67 / 58 | 4.00 / 1.72 |
| Flat6 | 104.44 | 8.79 | 8.43 | 161 / 98 | 12.35 / 1.03 |
| V8 H-pipe | 67.51 | 16.01 | 16.56 | 318 / 175 | 4.09 / 1.00 |
At 6,000 RPM and 70% pedal, flat6 measured 9.31 us/sample and V8 16.11.
All benchmark cases reported zero positivity repairs and finite audio.
See [baseline](workshop-before.txt), [after](workshop-after.csv) and
[higher-load results](workshop-high-load.csv).
These are performance comparisons, not claims of identical combustion or sound.
The workshop has explicit metering-body storage, connections and editable
calibration; the native scenarios assemble that hardware differently. Arbitrary
large or finely meshed custom machines can still exceed the audio budget.
## Rendering and playback
Hidden 1440 x 900 OpenGL window, 120 static frames, `glFinish`, no vsync or
simulation: flat6 fell from 1.40 to 0.70 ms/frame; V8 from 1.77 to 0.96 ms/frame.
This measures CPU/GPU render cost, not the displayed frame rate.
See [before](workshop-render-before.csv) and [after](workshop-render-after.csv).
The combined workshop/audio check ran at 60 display frames/s with a held
3,000 RPM shaft, 16 warm-up frames and 120 measured frames per machine:
| Preset | Wall seconds | Simulated seconds | Audio underruns | Buffered samples |
| --- | ---: | ---: | ---: | ---: |
| Flat6 | 2.006 | 2.020 | 0 | 4,096 |
| V8 H-pipe | 2.071 | 2.082 | 0 | 4,096 |
Simulation time includes producer buffering and snapshot timing, so a small
offset from wall time is expected. This is a short playback check, not a long
session guarantee. Raw output: [playback](workshop-playback.csv).
## Validation and reproduction
All 22 CTest cases passed. Machine tests cover import length/volume preservation,
route-knot-independent meshes, a real 5 mm pipe retaining its CFL constraint,
explicit fuel sources, cold starting and ECU cutoff. Pump pressure agreed within
1% between 44.1 and 88.2 kHz. Builder checks cover geometry-cache reuse and
invalidation, pressure coloring, transforms, deletion/ID reuse and the icon atlas.
Editor preview images were visually inspected.
From the repository root after `cmake --build --preset windows`:
```powershell
ctest --preset windows -j 8 --output-on-failure
.\out\build\windows-gcc\fluidsim_machine_benchmark.exe 32768 3000 0.35
.\out\build\windows-gcc\fluidsim_machine_benchmark.exe 32768 6000 0.7
.\out\build\windows-gcc\fluidsim_machine_render_benchmark.exe 120
.\out\build\windows-gcc\fluidsim_machine_render_benchmark.exe 120 --play
.\out\build\windows-gcc\fluidsim_machine_builder_tests.exe --preview out/workshop-performance-preview
```

View File

@@ -0,0 +1,3 @@
scenario,speed,frames,wall_seconds,sim_seconds,sim_per_wall,underruns,buffered
flat6,0.01,120,1.94593,0.0196145,0.0100798,0,41
v8-h,0.01,120,1.96952,0.0198639,0.0100857,0,41
1 scenario speed frames wall_seconds sim_seconds sim_per_wall underruns buffered
2 flat6 0.01 120 1.94593 0.0196145 0.0100798 0 41
3 v8-h 0.01 120 1.96952 0.0198639 0.0100857 0 41

View File

@@ -0,0 +1,3 @@
scenario,speed,frames,wall_seconds,sim_seconds,sim_per_wall,underruns,buffered
flat6,0.1,120,1.95923,0.198458,0.101294,0,407
v8-h,0.1,120,1.96564,0.19737,0.10041,0,409
1 scenario speed frames wall_seconds sim_seconds sim_per_wall underruns buffered
2 flat6 0.1 120 1.95923 0.198458 0.101294 0 407
3 v8-h 0.1 120 1.96564 0.19737 0.10041 0 409

View File

@@ -0,0 +1,3 @@
scenario,speed,frames,wall_seconds,sim_seconds,sim_per_wall,underruns,buffered
flat6,1,120,1.96809,1.98531,1.00875,0,4096
v8-h,1,120,2.0466,2.04989,1.0016,0,3872
1 scenario speed frames wall_seconds sim_seconds sim_per_wall underruns buffered
2 flat6 1 120 1.96809 1.98531 1.00875 0 4096
3 v8-h 1 120 2.0466 2.04989 1.0016 0 3872

View File

@@ -0,0 +1,99 @@
# Workshop instruments, slow playback and live tuning
Implemented on 2026-10-31. The workshop now supports eight nonintrusive instrument
channels, simulation-time traces, CSV export, slow playback down to 1%, paused
10 ms stepping, and live adjustment of safe component settings.
## Measurement model
Pressure, temperature and mass-flow taps read the compiled simulation. Pipe taps
sample the cell at a chosen fraction of arclength. Lumped-part flow is net into
the part; pipe flow is signed Start-to-End. RPM is instantaneous shaft speed;
torque and power use the shaft model's running averages.
Bulk AFR/lambda use a passive conserved fuel-origin tracer. Combustion does not
erase that tracer, so downstream instruments include fuel that has already burned.
It travels through pipe fluxes, component ports, storage volumes and junctions.
The extra tracer does not feed back into gas pressure, energy or mass.
Bulk AFR = (gas mass - fuel-origin mass) / fuel-origin mass; lambda divides that
by the channel's stoichiometric AFR reference, default 14.7. Fresh-charge AFR on a
cylinder instead reads its remaining unburned fresh-air/fuel mass ratio.
Undefined readings are gaps on the graph and empty cells in CSV. Sensor heating,
response lag, oxygen chemistry and fuel-specific combustion chemistry are not
added by this change. Initially clean exhaust pipes can read very lean until
purged. A probe after a collector measures the gas mixture that actually reaches
that collector's outlet, including dilution and backflow.
Channels sample every 16 physics samples: 2,756.25 Hz at a 44,100 Hz simulation
rate. The bounded capture retains 32,768 records (about 11.9 simulated seconds).
Graph compression preserves sampled min/max envelopes and leaves undefined
intervals disconnected. Frequencies above 1,378.125 Hz cannot be resolved by this
capture rate. This is not an audio-rate acquisition mode.
## Playback and tuning
Slow playback resamples audio without changing the physics timestep. Producer
batch size, prefill and target queue depth scale with playback speed. Pause stops
both audio and physics; switching speed discards queued audio while both threads
are stopped, preserving the machine's state. A paused step advances exactly 441
samples (10 ms). Graph timestamps remain simulated seconds.
Live edits are validated and applied under the simulation mutex between batches.
Carb calibration, ECU settings, throttle opening, cracking pressure, combustion
settings and shaft/load settings retain gas state, fuel film, controller state and
simulation time. Geometry, initial conditions, mesh/solver settings, cam/valve
mechanics and compiled boundary settings remain locked. The API rejects structural
changes even if a caller bypasses the UI. Live edits support undo/redo and saving.
Probes/taps can change live; changing the capture schema clears the trace.
Machine files now use version 4 for probe definitions. Versions 1 through 3 remain
readable; recordings are exported separately. Existing user machine files were
not rewritten.
## Playback checks
Windows GCC RelWithDebInfo; hidden 1440 x 900 window at a 60 Hz display target;
16 warm-up display frames, 120 measured display frames; motor-driven at 3,000 RPM.
All eight channels were active, including cylinder pressure, downpipe AFR/lambda,
fresh-charge AFR, mass flow and shaft gauges, with the scope visible.
| Machine | Requested speed | Measured simulated / wall time | Audio underruns | Buffered input samples |
| --- | ---: | ---: | ---: | ---: |
| Flat6 | 1.0 | 1.00875 | 0 | 4,096 |
| V8 H-pipe | 1.0 | 1.00160 | 0 | 3,872 |
| Flat6 | 0.1 | 0.101294 | 0 | 407 |
| V8 H-pipe | 0.1 | 0.100410 | 0 | 409 |
| Flat6 | 0.01 | 0.0100798 | 0 | 41 |
| V8 H-pipe | 0.01 | 0.0100857 | 0 | 41 |
The small offsets reflect queue depth, snapshot timing and short-run measurement
variation. These are short playback checks, not a sustained-session guarantee.
Raw results: [1x](instruments-playback-1.csv), [0.1x](instruments-playback-0.1.csv),
[0.01x](instruments-playback-0.01.csv).
## Verification
The full 22-test CTest suite passed. Targeted checks additionally cover conserved
burned-fuel transport in all four solvers, characteristic/legacy junction mixing,
finite exhaust AFR after combustion, lambda normalization, undefined dry readings,
probe persistence, live tuning without state/time reset, rejected geometry edits,
increased fuel delivery after live carb jet changes, pause/step/slow playback,
live undo/redo, CSV units and independently selectable overlapping probe markers.
Builder preview mode verifies rendered UI pixels after OpenGL scene/icon rendering
and captures pressure, downpipe lambda and live carb-tuning views. Those images
were visually inspected. Extremely small passive tracer tails are flushed like
the existing species tails to avoid subnormal arithmetic overhead; total gas mass
and energy are unchanged.
Reproduce from the repository root:
```powershell
cmake --build --preset windows
ctest --preset windows -j 8 --output-on-failure
.\out\build\windows-gcc\fluidsim_machine_builder_tests.exe --preview out/workshop-instruments-preview
.\out\build\windows-gcc\fluidsim_machine_render_benchmark.exe 120 --play 1
.\out\build\windows-gcc\fluidsim_machine_render_benchmark.exe 120 --play 0.1
.\out\build\windows-gcc\fluidsim_machine_render_benchmark.exe 120 --play 0.01
```