Bow a metal plate covered in sand and the grains flee the vibrating regions, collecting along the silent nodal lines. This is the same experiment as a driven modal superposition: sweep the frequency, move the driver, and watch thousands of grains assemble the resonant geometry.
Independent research instrument — not claimed as MakerPortal shipped product code. Methods, equations, assumptions, and limitations are disclosed so you can inspect what the page does and does not establish.
Sound made visible
Running. Drag anywhere on the plate to move the driver; grains re-settle onto the new nodal lines.
Cosines, resonance denominators, and gradient drift — every grain of sand follows the same three equations. Here they are in full, the same expressions the solver evaluates every 1/120th of a second.
The driven modal superposition
A plate driven at a point (x0,y0) responds as a weighted sum of its standing-wave modes. The weight is the product of the mode shape at the drive point and a resonance curve — enormous when the drive frequency sits on that mode's eigenfrequency, tiny elsewhere:
Where ϕmn(x,y)=cos(mπx)cos(nπy), the mode shapes of a membrane or cavity with zero slope at the edges (Neumann conditions). The frequencies below are a different law, borrowed from bending plates, so this is a simplified model rather than the exact free-edge plate. The drive point (x0,y0) sets each mode's coupling: placing the driver on a mode's nodal line zeroes that mode entirely. Moving the driver genuinely re-weights the sum.
Plate-like dispersion and the logarithmic slider
f1fmn=2m2+n2
Bending waves in a stiff plate obey ω∝k2, unlike a membrane's ω∝k. Resonances spread quadratically: the gap from mode (1,0) to (2,0) is smaller than from (7,0) to (8,0). The unit f1 is the (1,1) mode, so (1,0) sits at 0.5f1. Every frequency here is a whole-number multiple of the (1,0) frequency, which a real free-edge plate does not satisfy. The slider is a log2 scale because each resonance is about γfmn wide, a fixed fraction of its frequency, so on a log scale every resonance takes the same width on the slider.
Two modes like (4,2) and (2,4) share an eigenfrequency on a square plate because m2+n2 is symmetric. At resonance they respond together, and with equal weights their sum is unchanged by swapping x and y, which gives the diagonal symmetry of the Star preset. The tie comes from the square shape, so it is a property of the model and not a coding shortcut.
How the sand actually moves
The grains are not decoration; they are the measurement. Vibrating regions kick grains into a random walk whose step size grows with local amplitude, while the time-averaged bounce drifts them down the amplitude gradient:
Stochastic grain transport (Grabec-style)
dx=−μ∇(u2)dt+σ∣u∣dW
Deterministic drift down the squared-amplitude gradient (μ=0.12) plus amplitude-scaled jitter (σ=0.006), capped at 0.004 per step in plate-normalized units. Integrated at a fixed 1201 s timestep independent of display frame rate — the same timestep the grid solver uses.
Why it works everywhere at once
Both effects — jitter and gradient drift — vanish exactly where u=0 (the nodal lines) and scale with ∣u∣. That is why the silent curves are the only places grains can come to rest: any grain that lands on a node experiences zero kick and zero drift, so it stays. Any grain off a node gets pushed. After a few seconds thousands of grains self-organize into the eigenfunction geometry — no pattern database, no lookup table.
Separable evaluation
Because ϕmn(x,y)=cos(mπx)cos(nπy) is separable, the 144×144 grid is rebuilt from pre-computed cosine tables — each cell is a pure multiply-add with no trig calls. The 16 strongest modes per frequency are kept, and a smoothstep blend fades discrete jumps over 0.7 s so the grains never teleport.
The response amplitude is auto-normalized so patterns stay visible between resonances. Grain–grain collisions are ignored (the real physics involves avalanche-like piling at nodes, which is visually interesting but computationally separate). The cosine shapes are the modes of a membrane or cavity with zero slope at the edges. A free-edge plate obeys the biharmonic equation, has no closed-form modes (Ritz solved it numerically in 1909), and bends its nodal lines near the edges. Treat the patterns as a simplified model; the eigenfrequencies of a physical plate will differ.
Anatomy of the simulator
Every grain, every grid cell, and every readout traces back to the modal superposition and the stochastic transport model. Here is what each piece is doing and why it is built that way.
The canvas and its grains
01
The plate. A 640×640 HiDPI canvas with up to 2× device-pixel scaling. Each grain is a 2×2 px filled rectangle — deliberately not a particle system with sprites. At 5,000 grains the browser draws 10,000 rects per frame, which is trivial for the Canvas API and leaves the CPU for the physics step.
02
The driver marker. A ring-and-crosshair drawn at (x0,y0) in the theme's CTA color. Dragging anywhere on the plate moves it; the pointToPlate() function normalizes pointer coordinates to [0,1] plate units. Keyboard arrows nudge it at 0.02 or 0.05 (shift) per press — the same precision a finger gives.
03
The field overlay. Toggled via "Show field", it is a 145×145 imageData rendered on an offscreen canvas — one texel per grid cell, CTA-colored, alpha proportional to ∣u∣. It rebuilds only when the grid changes (not per frame) and shares the same fade-blend as the physics field, so it never disagrees with what the grains feel.
04
The render loop. Fixed 1201 s physics step via an accumulator pattern decoupled from frame rate (capped at 8 steps per frame). An IntersectionObserver pauses the sim when the canvas leaves the viewport. The loop never spins idle — it only ticks when visible and unpaused.
Controls and readouts
01
Frequency slider. Logarithmic log2(f) scale from 2−0.32≈0.8×f1 to 26.15≈71×f1, spanning the first 8×8 mode pairs. Presets snap to named resonances like star (4,2)/(2,4) and rosette (6,2)/(2,6). The slider is continuous — any fractional log2 value produces a valid superposition.
02
Resonance width γ. Controls the denominator in the resonance curve: small γ gives sharp, isolated modes; large γ blends neighbors. At the default 0.03, the star preset shows clean degenerate mixing; at 0.12 the same frequency produces a mushy blend with adjacent modes leaking in.
03
Drive point buttons. Center (0.5,0.5) excites only symmetric modes; off-axis (0.353,0.278) breaks symmetry and reveals asymmetric patterns; edge (0.5,0.02) simulates bowing the plate rim. The cross preset uses edge drive specifically to flip the sign of (2,0) coupling relative to (0,2) — the same physics, mathematically different superposition.
04
Grain count. 2.5k, 5k, or 9k particles. The transport model is O(N) — each grain independently samples the field and steps. At 9k on mobile the physics loop stays under budget because the grid evaluation is cheap (bilinear lookup into pre-computed arrays). Changing grain count re-initializes all positions randomly.
05
Readouts. Dominant modes lists the top 3 mode pairs by coefficient magnitude (degenerate partners folded together). Mode share shows the leading mode's percentage of total coefficient weight. Grains settled samples every N-th grain and counts those with ∣u∣<0.1umax — effectively, grains on or near a node. Driver shows the current (x0,y0) coordinates.
Prices shown were retrieved from the Amazon Product Advertising API on 8 October 2026 and are indicative only — the price and availability on Amazon at the time of purchase apply.
A free plate obeys the biharmonic equation, not the Helmholtz equation. Its eigenfunctions are not pure cos(mπx)cos(nπy) — they bend near the edges in ways cosine modes cannot capture. The sim pairs cosine shapes with plate-like frequencies (f ∝ m² + n²), so the nodal lines near boundaries and the eigenfrequencies themselves differ from any physical plate. If you build a real Chladni rig, expect the frequencies to be shifted and some patterns to look slightly warped.
Degenerate modes share the work
On a square plate, (m,n) and (n,m) are always at the same eigenfrequency. Both respond together and the resulting pattern is their superposition — not "one of them won." The metrics readout folds degenerate partners into one entry so you see the combined effect. If you see diagonal symmetry in a pattern, it is almost always coming from a degenerate pair, not from a single mode with unusual shape.
The solver, copyable
The two functions behind every grain on this page. The first computes the mode coefficients from a drive frequency and point — the heart of the modal superposition. The second advances the sand grains along the amplitude gradient with stochastic jitter.
computeCoefficients + stepPhysics
const modeFreq = (m, n) => (m * m + n * n) / 2;function computeCoefficients(f) { const all = []; for (let m = 0; m <= MAX_MODE; m++) { for (let n = 0; n <= MAX_MODE; n++) { if (m === 0 && n === 0) continue; const fmn = modeFreq(m, n); const coupling = Math.cos(m * Math.PI * driveX) * Math.cos(n * Math.PI * driveY); const denom = Math.hypot(fmn * fmn - f * f, gamma * f * fmn); const c = coupling / denom; if (Math.abs(c) > 1e-9) all.push({ m, n, c }); } } all.sort((a, b) => Math.abs(b.c) - Math.abs(a.c)); const kept = all.slice(0, COEFF_KEEP); const floor = kept.length ? Math.abs(kept[0].c) * 1e-3 : 0; return kept.filter(k => Math.abs(k.c) >= floor);}function stepPhysics() { const umax = blendedUMax(), inv = 1 / umax; for (let p = 0; p < grainCount; p++) { const s = sampleField(px[p], py[p]); const un = s[0] * inv; const drift = -MU * 2 * un * inv * PHYSICS_DT; let dx = drift * s[1] + JITTER * Math.abs(un) * (Math.random() - 0.5); let dy = drift * s[2] + JITTER * Math.abs(un) * (Math.random() - 0.5); dx = Math.min(STEP_CAP, Math.max(-STEP_CAP, dx)); dy = Math.min(STEP_CAP, Math.max(-STEP_CAP, dy)); let nx = px[p] + dx, ny = py[p] + dy; if (nx < 0) nx = -nx; else if (nx > 1) nx = 2 - nx; if (ny < 0) ny = -ny; else if (ny > 1) ny = 2 - ny; px[p] = nx; py[p] = ny; }}
Two worked examples
Both use the page's default drive point, the plate centre (0.5, 0.5), and γ=0.03. Every figure is solved when the page is built, by the same mode weights the simulator evaluates, and checked in the site's test suite against hand-derived values. Frequencies are in units of f1, the (1,1) mode. Inputs for the two cases: f=4&g=0.03&x=0.5&y=0.5 and f=10&g=0.03&x=0.5&y=0.5 (f drive frequency, g resonance width, x, y drive point).
A · One mode on its own: the (2,2) windowpane
Drive at f=4f1. Only (2,2) has m2+n2=8, so nothing shares its frequency.
c22=γf21=2.083
Drive frequency
4 × f₁
Leading mode
(2,2)
Kept modes
12
Weight of the leading mode
89.4 %
(0,2) and (2,0), each, relative to the leader
-4 %
Nodal lines of the leading mode along x
2
The shape cos(2πx)cos(2πy) is zero at x=1/4 and 3/4, and the same for y: the leading mode alone would put the sand on a 2 by 2 grid of lines. The other kept modes carry the rest of the weight and bend those lines slightly, so the simulated field is not exactly zero on them (at (1/4,1/4) it is 1.6% of the peak). The two small neighbours are (0,2) and (2,0), which have the opposite sign at the centre.
B · A degenerate pair: the (4,2) and (2,4) Star
Drive at f=10f1. Both (4,2) and (2,4) have m2+n2=20.
c42=c24=−γf21=−0.3333
Drive frequency
10 × f₁
Tied leading modes
(2,4) + (4,2)
Kept modes (cap reached)
16
Weight of the pair
85.2 %
(4,0) and (0,4), each, relative to the leader
-8.31 %
Sign changes along the diagonal x = y
6
On the diagonal the equal-weight pair is 2cos(4πx)cos(2πx), which is zero at x=1/8,1/4,3/8,5/8,3/4,7/8: six crossings. Swapping x and y leaves the field unchanged because the two weights are equal.
Frequently asked questions
How does this Chladni patterns simulator work?⌣
It sums standing-wave modes. For a drive frequency f and drive point (x₀, y₀), each mode (m, n) gets the weight cos(mπx₀)·cos(nπy₀) / √((fₘₙ² − f²)² + (γ·f·fₘₙ)²), with fₘₙ = (m² + n²)/2 in units of f₁. The 16 strongest modes are summed into a displacement field u(x, y), and the sand grains drift down the gradient of u² until they rest where u is zero. At the default settings, f = 10 × f₁ and γ = 0.03, the solver keeps 16 modes and the (4,2) and (2,4) modes share the top weight. It is a simplified model, not a finite-element plate solution.
What are Chladni patterns?⌣
Chladni patterns are the visible geometry of standing waves. When you vibrate a plate at a resonant frequency, regions of high vibration amplitude eject sand, while the nodal lines — the curves where amplitude is zero — collect it. The sand traces out the mode shapes of the plate. Different frequencies excite different mode shapes, each with a distinct pattern of intersecting nodal lines.
Why do some modal patterns look the same or share symmetry?⌣
On a square plate, the modes (m,n) and (n,m) have the same frequency. In this simulator that is because f ∝ m² + n². When the drive sits on that frequency, both modes respond and the pattern is their sum. At the default setting (drive at the centre, γ = 0.03, f = 10 × f₁) the (4,2) and (2,4) weights are equal, so the sum does not change when x and y are swapped. Along the diagonal x = y the field changes sign 6 times. This is the figure the Star preset draws. Exact frequency ties like this come from the square shape; a rectangular plate does not have them.
What does the resonance width γ control?⌣
γ sets how sharply the plate responds to being slightly off resonance. In the model, a mode's response falls to 1/√2 of its peak when f is off by γ·fₘₙ/2 on either side, so the full width is about γ times the mode frequency. A small γ (0.01) isolates a single mode: you must land within about 1% of its frequency or its weight drops. A large γ (0.12) blends neighboring modes together, creating broader, less distinct patterns. It plays the role of 1/Q, the inverse quality factor, for every mode.
Why does moving the drive point change the pattern?⌣
Each mode's amplitude depends on the product φₘₙ(x₀,y₀) × φₘₙ(x,y). The first factor is the mode shape evaluated at the drive point. If you place the driver on a nodal line of a particular mode — a line where that mode's amplitude is zero — that mode cannot be excited at all. Move the driver away and the mode comes back. This is why off-axis drive creates asymmetric patterns: it selectively suppresses modes symmetric about the new position.
What is the difference between a Chladni plate and a drum membrane?⌣
A Chladni plate carries bending waves, where ω ∝ k². A drum membrane stretches under tension and obeys a different wave equation where ω ∝ k. For a square, plate-like modes are spaced by f ∝ m² + n² and membrane modes by f ∝ √(m² + n²). In this simulator every mode frequency is a whole-number multiple of the (1,0) frequency, because it uses f ∝ m² + n² exactly. A real free-edge plate does not: its frequencies are not whole-number multiples of its lowest one, and they have no closed form. The slider is logarithmic for a different reason: a resonance is about γ wide in relative terms, so a log slider gives every resonance the same width on the slider.
Shareable still
The instrument, captured—not illustrated.
This 16:9 frame is rendered from the real browser instrument above. It is the page's canonical preview for image search, link unfurls, and posts that need to show what the tool actually does.
Answers are computed here, in your browser, by the same functions that render the published pages — not looked up, not generated. Every one links to its page and to the public endpoint that returns it as JSON.
No match for
Try a lab name, or an engineering question like lowpass 1 kHz.