A sunset sky where sliding air layers roll a cloud deck into breaking-wave billows.
Fast air slides over a slower, denser cloud layer. The shear between them is unstable: ripples tilt and grow until the interface rolls up into a row of breaking-wave billows, which pair up and collapse into turbulence, the rare wave clouds photographers chase. The air is a stratified Boussinesq flow in vorticity and stream function form with an exact FFT plus tridiagonal Poisson solve, and the cloud is a dye on a grid three times finer, lit by a low sun so curls catch gold rims. Past the right edge, an offscreen fringe relaxes the flow back to a fresh, gently flapping shear layer that re-enters on the left, so billows are born forever. Whether they grow is set by the Richardson number: by the Miles-Howard theorem, only below 1/4.
Try it. Drag left and right to change the shear, up and down to change the density layering (the Richardson number), or use the arrow keys. Push Ri above 1/4 and new billows stop forming. Tap the sky to drop a gust. T cycles sunset, dusk and daylight skies; R resets the layer.
Paste this into Claude Code, Codex or any coding agent to get a simple version running, then take it wherever you like.
Build a Kelvin-Helmholtz instability simulation with JavaScript and the HTML canvas element, drawn as wave clouds rolling up in a sunset sky. Put everything in a single index.html file with no libraries or build step, so I can open it directly in a browser.
Start simple:
- Use a grid of about 128 x 64 cells, periodic left to right, with walls at the top and bottom.
- Set up a shear layer: fast air above, slow air below, with velocity u(y) = U tanh((y - y0) / d). Store it as vorticity w = -du/dy, plus a small wavy perturbation.
- Each step: get velocity from a stream function psi (u = dpsi/dy, v = -dpsi/dx), advect w with semi-Lagrangian advection (trace back along the velocity and bilinearly sample), apply a little viscosity, and solve lap(psi) = -w with Jacobi or Gauss-Seidel iterations warm-started from the last frame.
- Carry a cloud dye that fills a band just below the interface, and draw it into ImageData on a small offscreen canvas scaled up with drawImage. Within seconds the interface should roll up into billows.
Once that works, make it beautiful:
- Paint a sunset gradient sky, a low sun and a dark ridgeline in silhouette, and blend the cloud over it with opacity from its density.
- Light the cloud from the sun using the dye gradient, so curls catch gold rims and their insides go dusky purple.
- Add stable density layering (a second advected field that pushes back with gravity) and show the Richardson number; billows only grow when it is below 1/4.
- Let dragging change the shear and the layering.
Explain the key ideas in short code comments. When you're done, tell me how to open it and suggest three directions I could take it next, such as an offscreen fringe region that keeps feeding fresh shear so billows never stop, a finer grid for the dye with MacCormack advection, or an FFT Poisson solver.