steelsim31#
A browser simulation of the sound of a thin stainless steel sheet, rectangular or elliptical, that hangs from a thread and is either pushed at a corner and released or struck with a drumstick. The sheet rings like a gong, so the simulator solves the geometrically nonlinear (von Karman) plate equations with in-plane inertia retained, stepped explicitly on the GPU through WebGPU. The model and the numerical method are described in THEORY.md.
This is a clean rebuild of steelsim21, reduced to the parts that matter for the sound: the plate model with a stress-free bow, the two excitations, the two-parameter loss model plus an in-plane loss, the Rayleigh listener, and the tests. The sound-matching additions of steelsim21 (the k^4 loss term, the dipole heuristic, the matching scripts) and its command-line renderer and gallery were left out.
The app is deployed by the deploy workflow on every push to main: https://steelsim31--proof-of-concept.vault1-sites.magland.org/
Running#
Requires Node 20 or later and a browser with WebGPU (Chrome or Edge 113+; Firefox and Safari with WebGPU enabled).
npm install
npm run dev # development server
npm run build # static site in dist/
npm test # all tests (see below)
Using the simulator#
Press Start. With the drumstick excitation (the default) a free mass strikes the sheet at a configurable point and speed through a Hertz contact, and the recording of audio and movie frames starts at the impact. The Hits selector turns the single hit into a series: a fixed number of hits at a fixed interval, all at the same speed or rising or falling between the softest and the loudest speed; the Excitation panel reports the schedule and how much ring the recorded duration leaves after the last hit. With the push excitation the sheet is pushed at the bottom-right corner over the ramp time, held with heavy artificial damping until it settles (its kinetic energy drops below the threshold or stops falling), and released by ramping the finger force to zero over the release time; the recording starts at the release. The view shows the shape of the sheet as a color map (2D) or a lit height field (3D; drag to orbit, wheel to zoom): by default the total shape, that is the initial shape plus the vibration, and with Show initial shape unticked only the deviation from the initial shape, which makes a small vibration on a bowed sheet visible. The spectrogram shows the listener signal, and the audio can be played or downloaded as a 16-bit WAV at any time.
- The sheet is a rectangle by default; the Outline selector makes it the ellipse inscribed in the given width and height. Width and height are entered in inches by default, or in millimeters; everything else is metric. Internally all values are SI.
- The sheet has a stress-free initial shape, built from a list of features in the Initial shape panel: parabolic bows across the width or the height (with an optional apex offset), a twist, Gaussian dents, creases (a fold along a line), and a seeded smooth random field. The default is a single 3 mm bow across the width; Clear gives the ideal flat plate. Randomize draws a new combination whose heights are of the order of the scale field, so that the effect of the shape on the sound can be surveyed; the drawn values appear in the panel and can be edited. The panel reports the peak-to-peak height and the largest slope of the shape and warns when the slope leaves the shallow-shell range. Before Start, and after any change of a parameter that takes effect at the next Start, the view shows the initial shape alone; the movie slider or Live returns to the last run. A negative push amount pushes against a bow across the width.
- Copy link puts a URL with every parameter that differs from its default into the clipboard and the address bar, so a configuration (a random shape in particular) can be recovered or shared.
- The Excitation panel shows the parameters of the selected excitation type only. Both excitations are self-equilibrated by inertia relief (the sheet gains no net momentum, as if the thread took it up); the periodic projection of the rigid-body modes during the ring is a Numerics option that is off by default and only removes rounding drift.
- Sheet, initial shape, excitation, and numerics parameters take effect at the next Start. Losses and the listener position can be changed while a simulation runs.
- Pause halts the run temporarily; Stop ends it, keeps the audio and movie, and unlocks the parameter fields. To extend a finished run, raise the duration and press Continue; the state is kept on the GPU.
- Playback level: Absolute maps 1 Pa to full scale, shifted by the gain slider, so different runs can be compared by ear (the peak level in dBFS is shown, with a clipping warning); Loudness and Peak normalize each run instead. The WAV download uses the same setting.
- After the simulation completes, drag the time slider to explore the movie; Play starts the audio from the slider position and moves the movie and the spectrogram cursor with it. Live returns to the running view.
- Any parameter can be preset in the URL in SI units, for example
?spacing=0.006&duration=2&autostart=1or?excitation=push&shape=ellipseor?hitSequence=crescendo&hitCount=6&hitInterval=0.5&duration=6. The initial shape is thefeaturesparameter, a list oftype:valuesentries separated by semicolons with the values in SI in the order of the panel, for example?features=bow:x,0.003,0;twist:0.001;dent:0.3,0.6,0.03,0.0015;noise:11,0.0005,0.05or?features=none; the earlierbowShapeandbowAmplitudeparameters are still read.
The default grid spacing of 8 mm (39 by 58 nodes) keeps the simulation interactive but lowers the bending partials by 3 percent near 1 kHz and by 10 percent near 3.6 kHz through grid dispersion; the Sheet panel reports these two frequencies for the chosen spacing. The stable time step is set by the in-plane wave speed, about 1.4 microseconds at 8 mm, so 4 s of sound take about 2.9 million steps. On an Intel Iris Xe integrated GPU this runs at about 57k steps per second, or roughly 50 s for 4 s of sound plus a few seconds for the push and hold; a discrete GPU is considerably faster. On grids of this size the cost of a step is the latency of one workgroup rather than the arithmetic, so a finer grid costs less than the node count suggests: halving the spacing to 4 mm costs about three times as much (about 2.5 minutes for 4 s on the same GPU) and moves the 3 percent point to about 4 kHz. The Numerics panel also offers an in-plane mass factor that lengthens the time step by its square root at the expense of lowering the in-plane modes of the sheet; see THEORY.md, Section 5.
Tests#
npm test runs two groups of tests with Node's built-in runner.
tests/cpuRef.test.tschecks the float64 reference of the spatial discretization without a GPU: symmetry of the stiffness with exactly three rigid modes per block, forces as the exact gradient of the discrete energy (flat and bowed, rectangle and ellipse), dissipativity of the loss terms, and convergence of the free square and circular plate frequencies to the reference values of Gorman and Leissa.tests/shape.test.tschecks the initial-shape features: the text encoding, the removal of the mean plane, the geometry of each feature, and the random configurations.tests/gpu.test.tsserves the app with Vite and drives a headless Chromium through Playwright. It compares one step of the WGSL kernel with the float64 reference on flat, bowed, elliptical, and randomly imperfect sheets (?selftest=1in the browser shows the same numbers), and runs a short push, a short strike, and a short series of strikes to completion. It needs Playwright's Chromium (npx playwright install chromium) and a machine whose Chromium has WebGPU;npm run test:cpuruns only the first group.
Layout#
src/params.ts: parameters, grid and mask, material constants, geometry of the excitation, grid dispersion estimate.src/shape.ts: the initial-shape features, their evaluation on the grid, their text encoding, and the random configurations.src/sim/cpuRef.ts: float64 reference of the spatial discretization; used for the time-step estimate and the tests.src/sim/shaders/: WGSL kernels (time step, rigid-body projection, listener sum, display extraction).src/sim/simulation.ts: WebGPU driver (buffers, batch encoding, phases, readback).src/selftest.ts: the in-browser GPU-versus-CPU comparison.src/render/: 2D and 3D WebGPU rendering of the displacement field.src/audio/: FFT, spectrogram, WAV encoder, playback, level mapping.src/ui/form.tsandsrc/main.ts: parameter form and the rest of the interface.tests/: the three test files above.