Does a structureless chemical soup pick a length scale on its own — and is that scale the fastest-growing Turing mode of the linearized dynamics, recoverable from nothing but the raw PDE?
Units: dimensionless Gray–Scott length units (k_max = 0.5258853 rad/unit; F=0.0866, k=0.0605, Du=0.16, Dv=0.08)
▶ Run this simulationRead how it works
Reaction–diffusion / Turing scale selection — the emergent length from the raw Gray–Scott PDE: with NOTHING coded but a 5-point Laplacian + the kinetics f = −uv² + F(1−u), g = uv² − (F+k)v (no dispersion relation, no Jacobian, no closed form), a homogeneous state that is ODE-stable (tr J = −0.030) yet destabilized by UNEQUAL diffusion selects the fastest-growing wavelength λ̂ = 11.94815 ± 2.7e-5 vs Turing's λ_c = 2π/k_max = 11.94782 (2.8e-5 rel, 8 seeds) — the whole measured growth curve σ̂(κ) lands on the eigenvalue curve to 1.7e-5, the unstable band is confined to κ ∈ [0.27, 0.81], scaling both diffusivities by s slides λ ∝ √s (log–log slope 0.49981), and the historical rival — EQUAL diffusivities — kills every mode (max σ̂ = −0.019, band power ×3.3e-8): differential diffusion isn't a detail, it IS the mechanism, exactly as Turing 1952 requires
Raw Gray–Scott only. The generator codes ONE thing the module also codes: the 5-point toroidal Laplacian plus the Gray–Scott kinetics, stepped by explicit Euler (f64, h=0.5, dt=0.2, 192² torus). No dispersion relation, no Jacobian, no closed form is in the recovery path: the homogeneous 'blue' steady state is found by finite-difference Newton on (f,g)=0; it is seeded with 1e-8 broadband noise; each Fourier mode (nx,ny) is projected out of the raw v-field at 8 snapshots and its growth rate σ̂ is the LS slope of ln|a| vs t, inverted through the exact Euler map σ = (e^{m·dt}−1)/dt. The selected scale is the vertex of a cubic fit through clean modes (r² ≥ 0.9999) within ±0.07 in κ of the observed argmax — plotted against each mode's exact discrete-Laplacian eigenvalue κ, the von-Neumann-style scorer correction that removes all lattice bias. The scorer alone holds Turing's known λ_c, the eigenvalue curve σ(q), and the band edges. Rival: the SAME machinery with EQUAL diffusivities. 12 gates in scripts/reactdiff-derisk.mjs (~16 s): 7 physics gates plus an honest-module certificate (H–L) that EXECUTES the shipped ReactionDiffusionModule.ts — sha-pinned, type-stripped, lockstepped 1800 calls bit-exact against a statics-built replica; tamper ⇒ exit 1. ?world=reactdiff.
2.6500e-5
3.5400e-5
8
Turing's diffusion-driven instability (Phil. Trans. R. Soc. B 237, 37, 1952): a homogeneous steady state stable to well-mixed perturbations (tr J < 0, det J > 0) is destabilized by unequal diffusion, and the emerging pattern's scale is the fastest-growing wavenumber k_max = argmax σ(k²) of the linearized dynamics σ(k²) = larger eigenvalue of J − k²·diag(Du,Dv). For Gray–Scott kinetics this gives λ_c = 2π/k_max = 11.9478 length units. Non-circular because the generator is one level MORE primitive than the law: it steps only the raw PDE (Laplacian + kinetics) and finds the steady state by numerical Newton; the Jacobian, the eigenvalue curve σ(q), k_max, the band edges and λ_c live ONLY in the scorer — every one is read off measured per-mode growth rates, never fed into the simulation. The decisive control is the historical one: with EQUAL diffusivities (Turing's counterfactual) the identical machinery kills all modes and forms no pattern — a max-growth sign flip of ~2e-2 that no tuning can undo — because differential diffusion is the mechanism. Opens the reaction–diffusion / morphogenesis family (distinct from the SOC worlds sandpile/baksneppen and the growth worlds kpz/dla: here a length scale, not a scaling exponent, is selected). Honest scope: the on-screen module runs the far-from-equilibrium Pearson regime whose coarsening length has no closed form; this finding validates the linear-Turing scale-selection claim the module's framing points at but does not itself measure — the module_estimator block discloses the gap.
CERTIFIED (gates H–L, 2026-07-27): the module is untouched, and the shipped file itself is now EXECUTED by the oracle rather than described — sha-pinned, mechanically type-stripped, and lockstepped 1800 calls bit-exact against a replica built from its own statics. Three things that were prose before are executed facts now. (1) The on-screen λ is the disclosed measurement: the executed module's λ at substep 5400 is Object.is-equal to gate 7's independently written instrument, 13.027941109516162 — a cross-code-path identity, not a resemblance. (2) The display has a measured latency, not zero: the %5 HUD cadence lags the state by one measure, ≤42 ms, so the number a viewer reads is the tick-420 value (13.1 cells / 2.61 u) while the state holds tick 450 — pinned as such. (3) The instrument's honest gap is pinned too: at tick 90 the autocorrelation genuinely has no interior peak (the blob fronts are still colliding) and the HUD shows '—' rather than a stale λ; that null is one of 15 Object.is-pinned trajectory values. Randomness is fully accounted: 26,043 mulberry32 draws all inside _seedField, the stream frozen at that exact position before AND after the lockstep, and both Math.random sites (no-seed fallback, 'r' re-seed key) executed under counting stubs rather than merely grepped. The remaining gap is scientific, not instrumental: the module runs a DIFFERENT experiment than the oracle validates. On screen it steps the far-from-equilibrium Pearson regime (F=0.0545, k=0.062) and measures a NONLINEAR coarsening wavelength from the activator autocorrelation — which the module already frames honestly as an emergent length with no closed-form value. The oracle instead validates the cited claim the module's framing gestures at: linear Turing scale selection at a genuinely Turing-unstable point (F=0.0866, k=0.0605), recovered from per-mode growth rates. Gate 7 reproduces the module's exact f32 estimator and confirms it is seed-independent (CV 1.9%) and quasi-stationary (drift 2.1%/3k steps) — an honest characterization of the on-screen number (13.07 cells), disclosed as coarsening, not scored against λ_c. The gap is the module's regime, not a bug: closing it fully would mean adding a linear-regime on-screen mode, deferred as a module change out of this run's scope.
1 retry — first full run was 6/7 with the diffusive-scaling gate at 6.3e-3 (> 2e-3): the cubic fit window was held FIXED in κ while scaling both D maps the dispersion curve to q/s, so a fixed κ-window covers a different fraction of the (rescaled) peak per s and the cubic-truncation bias varied across the sweep. Fixed by scaling the fit half-width as HALF/s (identical window in the rescaled variable q·s) — worst ratio dev dropped to 4.5e-4, slope 0.49981; no tolerance touched, the physics was exact all along (κ-space σ_s(q) = σ_1(sq)). Prototype-first (2 scratchpad scripts) set three design choices before the oracle: (a) noise 1e-8 not 1e-6 — at 1e-6 the difference-wavevector quadratic products of the kinetics measurably contaminate slow-mode growth and bias the curve gate; (b) cubic vertex not quadratic — the σ(κ) peak is skewed, biasing a quadratic vertex −6.6e-3 vs cubic 3e-5 (the blackbody lesson); (c) score in κ-space against the exact discrete-Laplacian eigenvalue, the reaction–diffusion analogue of the waves oracle's von Neumann correction, so the argmax needs no lattice fudge. Tamper self-test: known_value → 12.5 ⇒ lambda gate FAILs (rel 4.4e-2), exit 1, recovered λ̂ unchanged at 11.94815; restored by hand. Scope: only reactdiff-owned files touched (oracle pair + finding + fragment + loop line); no src/ change, gate = build + derisk. — 2026-07-27 REFINER (validated → validated + honest-module): appended gates H–L, append-only (the 7 physics gates are byte-untouched), no module edit, no tolerance change. Prototype-first in the scratchpad discovered every pin by execution and the first full derisk run was 11/12 — the single miss was my own prediction, not the science: I had assumed the HUD quotes the current λ, but the %5 render cadence writes at calls 1, 6, …, 1796 while the last measure lands at call 1800, so the display lags one measure. Fixed by pinning what a viewer actually sees (the tick-420 value) and disclosing the ≤42 ms latency — the module was right, my model of it was wrong. Tampers this run: sha ⇒ H only; science tamper (0.999× the autocatalytic gain in the v update) ⇒ J diverges at call 4 (the first PDE tick) + K + L, with H and I green — the predicted blast radius, because this world's HUD quotes only tamper-invariant constants (F, k, seed) and λ stays null until tick 30, so unlike cooperation's init-frozen display there is nothing for a science tamper to poison at call 1; known_value ⇒ lambda gate only, recovery byte-unchanged.
npm run derisk -- reactdiff (scripts/reactdiff-derisk.mjs)scripts/oracles/reactdiff.reference.jsonA. M. Turing, 'The Chemical Basis of Morphogenesis', Phil. Trans. R. Soc. B 237, 37–72 (1952); P. Gray & S. K. Scott, Chem. Eng. Sci. 39, 1087 (1984); J. E. Pearson, 'Complex Patterns in a Simple System', Science 261, 189–192 (1993); J. D. Murray, Mathematical Biology II, ch. 2–3 (3rd ed., 2003) — dispersion relation σ(k²), Turing conditions, k_max (scorer side only).