Reaction Diffusion Simulator

Two chemicals, one feeding on the other, both spreading out — and spots, stripes and mazes appear that no line of the equations asks for. Click the F–k map to move between them, or set both diffusion rates equal and watch the pattern fail to form.

F–k map: click or drag to set F and k

  • Pattern in the article’s run (17 of 42)
  • Dish filled uniformly (16)
  • v died out (9)
  • Left of the dashed line: the v-rich uniform state is stable
  • Right of the solid line: u = 1, v = 0 is the only uniform state
  • Presets on this page
Steps since reseed0
Area with v > 0.25—
Separate regions—
Dominant wavelength (cells)—
Article’s class (judged at 9,000 steps)—
Running on—
0.0300
0.0550
0.160
0.080Du/Dv = 2.00
24
6

Drag on the picture to drop v (Shift-drag or right-drag erases). Clicking the map changes F and k without restarting, so the pattern you have turns into the new one; press Reseed for a clean start. The grid wraps around at its edges, so a saved PNG tiles seamlessly.

What this simulator computes

This is the Gray–Scott model, the reaction–diffusion system behind many of the Turing-pattern pictures you see online. Two chemicals share a dish. u is fed in from outside; v eats u to make more of itself and is slowly removed. Both spread out by diffusion, at different speeds:

∂u/∂t = Du ∇²u − u v² + F (1 − u)
∂v/∂t = Dv ∇²v + u v² − (F + k) v

F is the feed rate of u, k the kill rate of v, Du and Dv the two diffusion rates. Nothing in those two lines mentions spots or stripes, which is the whole point.

The page solves them the same way the experiment behind it did: a five-point Laplacian on a square grid with cell size 1, explicit Euler steps of dt = 1, both fields clipped to [0, 1] after every step, and edges that wrap around. Defaults are Du = 0.16 and Dv = 0.08, the values in that experiment's published code. The update runs on the GPU as a WebGL2 fragment shader that ping-pongs between two floating-point textures, several steps per frame. If the browser can't render to float textures, the same update runs on the CPU, by default at 128 × 128, and the Running on readout says which path you got. On start-up the page runs its shader and its CPU function side by side on a small random grid; if they disagree beyond rounding, it switches to the CPU.

How to use it

  1. Press a preset to load a known pattern, or click anywhere on the F–k map. Dragging across the map changes F and k continuously, and the pattern on screen morphs into the new one without restarting.
  2. Drag on the picture to drop v with the brush. Shift-drag, right-drag or the Erase setting removes it. Empty dish plus the brush is the way to draw your own starting shape.
  3. Move Du and Dv to change how fast each chemical spreads. The ratio is printed next to the sliders, and it matters more than either value.
  4. Save PNG exports the current state at the grid size or smoothly enlarged to 1024 or 2048 pixels. Because the grid wraps around, the image tiles seamlessly as a texture.
  5. Copy link to these settings stores F, k, Du, Dv, the colour map and the starting pattern in the URL.

The F–k map: where patterns live

The dots on the map are the experiment in the Japanese article this tool is built from: F at 7 values from 0.014 to 0.062, k at 6 values from 0.045 to 0.065, 42 runs of 9,000 steps each, all started from a small square of v in the middle. Only 17 of the 42 made something you would call a pattern. In 16 the v-rich state took over the whole dish uniformly, and in 9 v died out and left nothing. Patterns are the exception in this plane, not the rule.

The two lines come from the equations with diffusion switched off, so they can be derived rather than measured. Setting both time derivatives to zero, a uniform state other than the empty one (u = 1, v = 0) exists only when F ≥ 4(F + k)², that is when k ≤ √F / 2 − F. That is the solid line. It reaches its largest k, 1/16 = 0.0625, at F = 1/16. To its right the empty dish is the only uniform state, so anything you see there is a structure keeping itself alive. The v-rich state on its left has a Jacobian with trace k − v², so it is stable only while v² > k. The dashed line is where v² = k, a Hopf bifurcation. Left of it, a uniform fill is a stable answer, and that is where the article's grey dots sit.

The orange dots cluster around the two lines, on both sides of the solid one. Both lines ignore diffusion, so they stay put when you move Du and Dv. The dots were measured at Du/Dv = 2 and do not carry over to other ratios.

As a check on this page, its own update function was run on the same 42 conditions (140 × 140 grid, 9,000 steps, the article code's starting square, but a different random noise). It put all 42 in the same class as the article: 17 patterns, 16 filled, 9 empty. The Article’s class readout uses the same thresholds, more than 90% of cells with v > 0.25 for "filled" and under 2% for "empty", and is meant to be read at 9,000 steps, the point where the article judged.

Equal diffusion: the pattern never forms

Turing's 1952 argument was that reaction alone does not make a pattern: adding diffusion can make a uniform mixture unstable, and in the usual two-chemical picture that requires the two to spread at different speeds. The article tested this directly. It kept F = 0.030, k = 0.055, the starting state and the random numbers fixed, held Du at 0.16 and changed only the ratio Du/Dv. The article's code used a 160 × 160 grid and 9,000 steps; the right-hand column is this page's update function under the same setup, averaged over five random seeds.

Du/DvPattern area (article)This page, mean of 5 seeds
1.00.00%0.00% (all five)
1.10.20%0.20%
1.55.83%7.34% (1.39–13.60)
2.032.05%32.69%
3.042.53%42.41%
4.043.09%43.09%

With equal diffusion the drop in the middle simply fades. On this page's runs the spatial standard deviation of v fell from 0.040 at the start to 0.005 after 1,000 steps and to zero by 3,000. At Du/Dv = 2, from the same start, it rose to 0.069, 1.75 times the initial value. Press Equal diffusion (Du = Dv) to watch it happen, then drag Dv back down to 0.08 and reseed. Around a ratio of 1.5 the outcome depends heavily on the random noise (1.39% to 13.60% across five seeds), which is why one run there is not a reliable number.

The pattern also gets finer as the ratio rises. Over the runs that formed a pattern, the dominant wavelength fell from 23.0 cells at ratio 1.5 to 12.7 at 2.0 and 7.6 at 4.0. At ratio 1.0 there is nothing to measure: v has vanished, and the method returns 160/3 = 53.3 on a 160-cell grid, the longest wavelength it can report. The article first listed that 53.3 as a wavelength and was corrected on 10 October 2026.

One caution the article makes as well: many Gray–Scott patterns grow from a finite seed rather than from an infinitesimal instability, so this experiment shows that the ratio decides whether a pattern appears under this setup. It is not a proof of classical Turing instability, and not a rule for every reaction–diffusion system.

Same spacing, different shapes

The article's representative patterns look nothing alike, but their spacing is almost the same. It measured the dominant wavelength with a spatial Fourier transform: the radially averaged amplitude spectrum of v, its peak located with a parabolic fit. On a 256 × 256 grid after 14,000 steps it found:

FkWavelength (article)Blobs (article)Wavelength (this page)
0.0300.05512.61612.8
0.0220.05112.710412.7
0.0380.06111.75811.7
0.0260.05812.342712.2
0.0340.06514.48114.5

The blob count varies 26-fold, from 16 to 427, while the spacing stays between 11.7 and 14.4 cells. The last column comes from this page's functions run with the same grid, step count and start. The blob counts depend on the random noise and are not repeated here. The Dominant wavelength readout uses the same method with one change: it only looks at wavelengths up to 32 cells. Without that cap, a colony that has not yet filled the dish reports its own diameter as the "wavelength".

The presets, measured

The names describe what each setting actually did on this page's 256 × 256 grid, checked over three random seeds:

Limits

Stability. Explicit Euler with this Laplacian is stable for diffusion only while 4·D·dt / dx² < 1. The verification feeds a checkerboard into pure diffusion and gets an amplification of exactly 1 − 8D per step: −0.92 at D = 0.24, −1.08 (growing) at D = 0.26. The sliders stop at 0.24.

Clipping and precision. Clipping to [0, 1] is part of the model here, as in the article's code. Devices without 32-bit float render targets fall back to 16-bit ones, which round small changes away; the readout then says "half float", and the startup check compares it with the CPU before using it.

Other simulators. Some scale the diffusion constants differently or use a 9-point Laplacian, so Du and Dv values taken from elsewhere do not transfer directly. F, k and the ratio Du/Dv are what carry over. Patterns also depend on the grid size, the starting state and how long you wait, so a run here will not reproduce the article's numbers to the last digit.

What will you try next?

Share this tool

Part of Shake AI Lab — interactive experiments in mathematics and machine learning. · More tools · 日本語の解説記事