# 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](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 push excitation the sheet is pushed at the bottom-right corner over the ramp time, held with heavy artificial damping until it settles, and released by ramping the finger force to zero over the release time; the recording of audio and movie frames starts at the release. With the drumstick excitation a free mass strikes the sheet at a configurable point and speed through a Hertz contact, and the recording starts at the impact. The view shows the transverse displacement as a color map (2D) or a lit height field (3D; drag to orbit, wheel to zoom), 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 bow (default 3 mm across the width; set the bow shape to Flat for the ideal plate). A negative push amount pushes against the bow. - 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=1` or `?excitation=strike&shape=ellipse`. 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.3 microseconds at 8 mm, so 4 s of sound take about 3 million steps. On an Intel Iris Xe integrated GPU this runs at about 33k steps per second, or roughly 1.5 minutes for 4 s of sound; a discrete GPU is considerably faster. Halving the spacing to 4 mm costs about eight times as much (about 5 minutes for 4 s on the same GPU) and moves the 3 percent point to about 4 kHz. ## Tests `npm test` runs two groups of tests with Node's built-in runner. - `tests/cpuRef.test.ts` checks 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/gpu.test.ts` serves 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, and elliptical sheets (`?selftest=1` in the browser shows the same numbers), and runs a short push and a short strike to completion. It needs Playwright's Chromium (`npx playwright install chromium`) and a machine whose Chromium has WebGPU; `npm run test:cpu` runs only the first group. ## Layout - `src/params.ts`: parameters, grid and mask, material constants, geometry of the excitation, grid dispersion estimate. - `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.ts` and `src/main.ts`: parameter form and the rest of the interface. - `tests/`: the two test files above.