← the simple version · evals · A campfire, from the equations up. live · Navier–Stokes + heat · 320×180 cells

Fourier's Fire

A 1990s trick, the one line it was missing, and a language model reading the fire's name.

u/∂t + (u·∇)u = −∇p + βT ŷ
T/∂t + (u·∇)T = −kT ∇·u = 0. The β term is "hot air is light". The rest is bookkeeping.
embers
inferno

loading a 23 MB sentence model into your browser…

What the trick was

Every pixel copies the pixel below it, blurs it sideways, and cools a bit.

That is the whole 1990s effect, the one that fit in under 256 bytes of assembler. Random embers on the bottom row, and each frame every cell looks one row down and a random step sideways, averages with its neighbours, and loses a little heat. Colour is a lookup from black through red and yellow to white.

Written as a limit, "look one row down" is an advection term v ∂T/∂y, "a random step, then average" is Fourier's diffusion D ∂²T/∂x², and "lose a little" is decay −kT. The demo coders were solving the heat equation from 1822 by finite differences at sixty frames a second on a 486, and calling it a trick.

What it does not have is a reason to go up. The updraft v is a constant the coder typed in. In a real fire the air rises because it is hot, and that one fact, hot air is light, is where all the flicker comes from. So the fire at the top of this page adds it: a velocity field pushed upward by temperature, kept incompressible, carrying the heat with it. Navier–Stokes with the Boussinesq approximation, solved the way Jos Stam did it in 1999.

the trick, 11 linesFourier + updraft

The heat equation with a constant updraft. No buoyancy, so no puffing. Its spectrum is in the charts below, in ochre.

The fit

A real fire next to the equations.

Left, a campfire filmed on 7 September 2026. Right, the equations, with four constants. Drop your own clip on the left pane. The brightness profile is what you fit by hand. The flicker spectrum is what buoyancy gives you for free.

videosample · 8 s loop

Brightness per row is measured from each frame, and the mean of the whole frame goes into the spectrum. Nothing leaves your browser.

equations320×180 cells

β in cells per frame² per unit heat, k per frame. ε is vorticity confinement, the swirl a coarse grid would otherwise smear away. p is the boundary condition, not part of the equations. The sentence at the top moves β, k and p too, and replaces p with its words.

Brightness by height

videoequationsthe trick

Each row's mean brightness, normalised to the brightest row. Both models can fit this: cooling sets the height, embers the base.

Flicker spectrum

videoequationsthe trick

Power of whole-frame brightness over the last ~10 s. A real fire puffs at about 1.5/√d Hz for a fire d metres across. The equations puff too, because hot air is light. The trick is flat noise whatever you set.

The model, and what it is actually doing

One direction in the model, read instead of written.

The sentence at the top goes through a small sentence encoder, all-MiniLM-L6-v2, 22 million parameters, running in this tab. It turns the sentence into a point in a 384-dimensional space. Nothing is generated. The model never answers.

At load, thirty-two sentences are embedded: sixteen about a roaring fire, sixteen about dying embers. The difference between the two mean points is a direction. That is the same object people add to a model's activations to steer it, a steering vector by difference of means. Here it is not added. It is read: your sentence is projected onto it, and the projection is the position of the dot between "embers" and "inferno". That number sets buoyancy, cooling and ember density.

Then each word is removed in turn and the sentence embedded again. How far the projection falls when a word is missing is that word's share of the fire, and that share is its heat on the bottom row. The flames rise from the words that carry them. This is occlusion, the oldest attribution method there is, and it is shown here instead of an attention map because the exported model does not expose its attention, and because a heat that you can remove and watch go out is easier to believe than a heat you are told about.

Each word's share of the fire

waiting for the model

Bars are the drop in projection when the word is removed, in units where the two training means sit at ±1. Blue bars pull toward embers. On 40 held-out sentences the sign is right 30 times; chance is 20. The eval runs here.

The trick, in full

This is the entire 1990s fire, including drawing it.

The originals were under 256 bytes of x86 assembler, and the trick was often code that wrote the inner loop for itself. This is the same loop in JavaScript. The version with physics is fluid.js, about ninety lines, and it is not a trick.


    
Where the numbers come from

Two hundred years, six papers, one demo.