Water heated from below boils into mushroom plumes and rolling convection cells.
A layer of fluid is heated from below and cooled from above, and buoyancy turns the conduction state into rolling convection cells. The Boussinesq equations are solved in vorticity and stream function form on a coarse grid, with an exact FFT plus tridiagonal Poisson solve and implicit viscosity each step, and no-slip plates via Thom's wall vorticity formula. Temperature lives on a grid three times finer and is carried by MacCormack advection, so thin plumes and boundary layers stay sharp, and it is rendered as a diverging thermal image with tracer particles leaving long-exposure streaks. The live Nusselt number measures how many times better than conduction the flow is carrying heat.
Try it. Drag the Rayleigh number slider from below onset (about 1708, marked) through steady rolls to turbulence, or use the arrow keys. Drag in the fluid to paint heat; the chip, H, a right-click or Shift switches to cooling. R restarts from rest. Left alone, the Rayleigh number slowly sweeps through the regimes.
Paste this into Claude Code, Codex or any coding agent to get a simple version running, then take it wherever you like.
Build a Rayleigh-Benard convection simulation with JavaScript and the HTML canvas element: a layer of fluid heated from below and cooled from above that organizes itself into rolling convection cells. 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 over a box that is periodic left to right, with a hot plate at the bottom (temperature 1) and a cold plate at the top (temperature 0).
- Store vorticity w and temperature T per cell. Each step: compute velocity from a stream function psi (u = dpsi/dy, v = -dpsi/dx), move w and T backward along the velocity with semi-Lagrangian advection (trace each cell back and bilinearly sample), add buoyancy to the vorticity (w -= dt * dT/dx with y pointing down), diffuse both, then solve lap(psi) = -w with a few hundred Jacobi or Gauss-Seidel iterations (warm-started from the last frame).
- Start from the linear conduction profile plus a little random noise, and expose the Rayleigh number Ra: viscosity is sqrt(Pr / Ra) and thermal diffusivity 1 / sqrt(Ra * Pr), with Pr around 1 to 7.
- Draw T through a color map into ImageData on a small offscreen canvas and scale it up with drawImage.
Once that works, make it beautiful:
- Use a diverging palette (icy blue for cold, near black for the mixed interior, fire orange for hot) so plumes glow.
- Keep temperature on a grid two or three times finer than the flow and use MacCormack advection (forward, backward, correct, clamp), so thin plumes and mushroom caps stay crisp.
- Add a few hundred tracer particles that leave fading trails, and a slider for Ra so you can watch steady rolls break into plumes and turbulence.
- Let the mouse paint hot or cold spots.
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 FFT-based Poisson solver, no-slip walls with Thom's formula, or measuring the Nusselt number live.