The first page covered the spine of the engine: shape, modes, sound. This one covers the parts that sit around it — how the sound field in the air is drawn, what the air trapped inside an instrument does, and what changes when you leave flat 2D behind. Same rule as before: every demo computes for real.
← Start with "How it actually works"The mesh tells you how the object moves. The next question is what that motion does to the air around it — and unlike the object, the air is not meshed at all.
Christiaan Huygens had the idea in 1678: treat every point of a disturbance as the source of its own expanding ripple, then add all the ripples up. Whatever pattern emerges is the wave. It sounds too simple to work, and it works remarkably well.
So the viewer takes the boundary of the shape, notes how fast each boundary point is moving outward, and treats each one as a tiny source. For any pixel of empty space it adds up the contribution of every source — delayed by how long the sound took to travel there.
Interference does the rest. Two sources whose ripples arrive in step reinforce; arrive half a cycle apart and they cancel. That is the entire origin of the lobes, beams and quiet zones you see in the medium view.
A row of sources along the bottom, each emitting the same tone. The field is computed by summing every source at every pixel — exactly the calculation the viewer does on the GPU. Widen the array or raise the frequency and watch a smooth bubble collapse into sharp beams.
Set curvature away from zero and the sources delay each other into a lens: the beam focuses to a point. That is a phased array, and it is the same maths.
Here is the neat part. If everything is ringing at one frequency, then every point in the air is doing the same thing: going round and round a circle at that frequency. The only thing that differs from point to point is how big its circle is and where on the circle it currently is.
Two numbers per point. Size and angle. And once you store those two numbers, you no longer need to store time at all — you can rebuild the pressure at any instant, past or future, instantly. That pair is called a phasor.
Left: a point in the air, drawn as an arrow going round a circle. Right: the pressure that arrow traces out over time. The arrow is the stored data; the wave is what you hear. Nothing is being simulated forward — the wave is read straight off the rotation.
Drag "angle" and the whole wave slides in time without changing shape. That is all a phase is: a head start.
Once the field is stored as phasors, you can ask it questions that a plain animation cannot answer. The viewer's Field Lab offers nine; here is what each one means.
The animated blue-and-red view is the obvious one, but it is also the least informative: everything is moving, so nothing stands still long enough to be read. The other views trade the animation for insight.
| View | What it draws | What it is good for |
|---|---|---|
| Live | the pressure right now | the intuitive picture — waves moving outward |
| Envelope | how big each point's circle is | the standing pattern: bright = always loud, dark = permanently quiet |
| Phase | where each point is on its circle, as a colour wheel | seeing wavefronts as bands, and spotting singularities |
| Complex | phase as hue, size as brightness | both at once — the mathematician's view of a complex field |
| Intensity | which way energy is actually flowing | tracing where the sound goes, not just where it is |
| Vorticity | where that flow swirls | finding the whirlpools of acoustic energy |
| Divergence | where flow appears from nothing | locating the effective sources |
| Laplacian | how sharply the envelope curves | picking out nodal lines and fringe edges |
| Spacetime | a slab of time as a solid block | seeing the whole history at once (section 5) |
If the size of a point's circle shrinks to exactly zero, then its angle is meaningless — there is no direction to point. These are phase singularities, and they are not rare accidents. In any field made of a few interfering waves they appear naturally, as isolated points where all the colours of the phase wheel meet.
Circle one and the phase runs through a full turn. Energy does not just sit there either: it orbits the singularity. That is what the Vorticity view finds — genuine whirlpools in the flow of sound energy. They are a real, studied phenomenon (acoustic vortices), not a rendering artifact.
Three sources interfering. Every panel below is computed from one stored phasor field — the derived views are just arithmetic on the two stored numbers. Look for the little swirls in Vorticity: each one sits exactly on a point where the Phase panel has all its colours meeting.
Envelope and Phase are the two halves of the stored data. Everything else is derived from them by taking differences between neighbouring pixels.
A guitar is not a vibrating plate. It is a vibrating plate wrapped around a box of air — and that air is an instrument in its own right.
Blow across a bottle and you get a note. Nothing solid is vibrating: the plug of air in the neck is sloshing in and out, and the air in the body is being squashed and released. The plug is the mass, the trapped body of air is the spring. It is the simplest oscillator there is, made purely of air.
Once the box is large compared to the wavelength, it stops being one simple oscillator and
starts having standing waves — the same story as the string, but in
pressure instead of displacement. A closed box of length L has a lowest air mode at roughly
speed of sound / 2L, then multiples of it.
The engine handles this with the same machinery as the structure. It meshes the air, builds a stiffness and a mass matrix for pressure instead of displacement, and solves the very same eigenproblem. Air modes come out looking exactly like string modes — because mathematically they are.
Left: the pressure pattern of the air modes in a closed duct — red is compressed, blue is rarefied, and the pale bands are where the pressure never changes at all. Right: how the resonance frequency moves as you change the box.
Note the air modes are a plain harmonic series, like a string. It is the geometry of the container, not the material, that sets them.
Now the interesting bit. The wooden top pushes the air; the pressurised air pushes back on the wooden top. Neither is independent any more — they are coupled, and you have to solve them together.
And when you do, something familiar happens. If you tune the air resonance close to a plate resonance, the two do not simply coincide. They repel: one moves down, one moves up, and both become a blend of wood-motion and air-motion. It is the avoided crossing from the first page, turning up again in a completely different guise.
The horizontal axis tunes the air cavity through the plate's frequency. Dashed lines are what you would naively expect (they cross). Solid lines are what a coupled solve actually gives — computed live by solving the 2×2 coupled system at each step.
Turn the coupling to zero and the solid lines drop onto the dashed ones. Any coupling at all, and they split apart at the meeting point.
Everything so far assumed a flat sheet moving in its own plane. Real objects are curved, thick, and three-dimensional — and each step up costs something.
The size of the problem is set by how many numbers you need per node to describe the motion. That number is the difference between a membrane and a bell.
| Model | Numbers per node | What it can do | Cost |
|---|---|---|---|
| Membrane | 2 — slide in x, y | a drum skin; stretches but cannot bend | cheapest |
| Plate | 3 — lift, plus two tilts | proper bending stiffness; a cymbal, a bar | modest |
| Shell | 5 — slide, lift, and tilt | curvature, which couples stretching to bending | higher |
| Solid | 3 — but every node is in 3D | real volume; thick, chunky objects | far more nodes |
The jump to a solid is brutal not because 3 is a big number but because filling a volume with elements needs vastly more of them than covering a surface. Double the detail on a 2D mesh and you get four times the nodes; do it in 3D and you get eight. The eigensolve grows faster still. That is why the 3D solids in the app are coarse and marked experimental.
Take a flat sheet of paper and it flops. Curve it slightly — a taco, a bent business card — and suddenly it holds itself up. Nothing about the material changed.
The reason: on a curved surface you cannot bend without also stretching. Bending is easy, stretching is enormously harder, and curvature welds the two together so the easy motion has to drag the hard one along. That coupling is exactly what a shell model adds over a plate, and it is why a curved cymbal rings so differently from a flat disc of the same metal.
The same strip, curved by different amounts, with the same push applied. Flat, it folds easily. Curved, the deflection collapses and the frequency climbs — and the pitch rises even though nothing about the material changed.
This is why a curved shell needs five numbers per node: the in-plane sliding and the out-of-plane lifting can no longer be treated as separate problems.
A solid is chopped into tetrahedra — the 3D cousin of the triangle. Drag to rotate. The counter shows why this gets expensive so quickly.
Each step of the detail slider multiplies the node count by about eight, and the solve time by far more than that.
The last idea is the one that sounds most abstract and turns out to be the most visual: stop animating time, and draw it as an axis instead.
An animation shows you one instant, then throws it away. If instead you stack every instant into a solid block — two dimensions of space, one of time — you can see the whole history at once. A photograph of a wave becomes a sculpture of a wave.
What was moving becomes something you can read off a shape:
becomes a set of straight vertical columns — the still points never move, so they carve stationary lines through the whole block.
becomes a slanted sheet. The slope of the slant is the wave speed: shallow means fast.
becomes a block that fades along its length, so you can see the decay envelope directly rather than waiting for it.
produce a beating pattern that shows up as regular bulges up the time axis — obvious in the block, easy to miss live.
And because the field is stored as phasors, this costs nothing. The viewer does not record frames; it simply evaluates the same two stored numbers at whatever time each layer needs. Time becomes a coordinate you can look along rather than a thing you wait for.
The same 1D wave shown two ways: animated on the left, and stacked into a space-time block on the right (space across, time downward). Switch between a standing and a travelling wave and watch the block change character completely.
Standing: vertical stripes, fixed nodes. Travelling: diagonal stripes whose slope is the speed. Same maths, completely different picture.
Everything you have played with so far quietly cheated. Not in the physics — the equations are right — but in the shapes. And that one cheat is the entire reason finite elements exist.
Every demo here used a string, a rectangle, or a disc. Those three are not a random selection: they are essentially the complete list of shapes whose modes can be written down as a formula. A string gives sines. A rectangle gives products of sines. A disc gives Bessel functions. Pick literally anything else — a guitar body, a bell, a bar with a notch filed in it, a rectangle with a hole — and no formula exists. Not "is hard to find". Does not exist.
That is the wall. And the way through it is to stop looking for a formula and start approximating: chop the shape into thousands of pieces so simple that each one does have a formula, then let the computer stitch them back together. That is the finite element method, and it is why this project has one.
Drag the slider to deform a perfect circle. At zero, the modes are known exactly — textbook Bessel functions. Move it even slightly and every closed form evaporates, while the meshing approach carries on without noticing.
The mesh does not care what shape you give it. That indifference is the whole point of the method.
The shape cheat is the big one, but it is not the only one. Here is an honest accounting of this page against the actual engine.
| These demos | Modal2D | |
|---|---|---|
| Shapes | string, rectangle, disc — because formulas exist | any outline, plus holes, curvature, thickness, multiple joined bodies |
| Where modes come from | closed forms, or a 36×36 matrix | stiffness and mass assembled from thousands of triangles |
| Solver | dense Jacobi rotations — lovely, and hopeless past a few hundred | sparse shift-invert Lanczos, or a GPU dense solver; only the lowest 24–120 modes |
| Elements | none — nothing is discretised in space | membrane, thin plate, thick plate, shallow shell, tetrahedron, beam |
| Material | one stiffness number | stiffness, Poisson ratio, density, thickness, grain direction, tension, per-mode damping |
| Audio | a two-second buffer built in JavaScript | a GPU kernel at 44.1 kHz, repeated-strike ring buffers, reverb and nonlinear stages |
| Air | one frequency, no obstacles, purely decorative | meshed cavity modes genuinely coupled to the structure |
| Interaction | sliders | strike, bow, pluck, sustain, live re-solve while you edit, and a search that tunes a shape to a target pitch |
The eigensolver on the first page is real, and it is genuinely the algorithm Jacobi published in 1846. It is also the wrong tool at scale. It works on a dense matrix and costs roughly the cube of the size: 36 unknowns is instant, 600 is a pause, and a few thousand is hopeless — and it computes every mode when we only ever wanted the lowest few dozen.
The engine therefore does three things differently. It keeps the matrices sparse, since a node only touches its neighbours and storing the zeros would be absurd. It asks only for the lowest modes, using a shift that turns the smallest, most awkward frequencies into the largest and easiest ones. And it pushes the dense work onto the GPU when the problem is small enough to fit.