ReactionDiffusion.js

ReactionDiffusion — Interactive

ReactionDiffusion // chemical network editor

checking stability…
<div class="stage">
  <canvas id="plot" width="820" height="340"></canvas>
  <div class="legend" id="legend">
    <label><input type="checkbox" id="normalise"> normalise</label>
  </div>
  <div class="scrubber">
    <div class="transport">
      <button id="resetBtn" title="Reset to t=0">⏮</button>
      <button id="playBtn" title="Play / pause">⏸</button>
      <button id="skipBtn" title="Skip to steady state">⏭</button>
    </div>
    <input type="range" id="timeSlider" min="0" max="1" step="1" value="0">
    <span class="time-readout" id="timeReadout">t = 0.00</span>
  </div>
</div>

<div class="panel">
  <div class="field-group">
    <h2>Preset</h2>
    <select id="presetSelect"></select>
  </div>

  <div class="field-group">
    <h2>Reaction network</h2>
    <textarea id="networkText" spellcheck="false"></textarea>
    <div class="syntax-hint">
      <code>rate, A + B --> C</code> · <code>∅</code> for nothing · <code>(k+, k-), A &lt;--&gt; B</code> reversible ·
      functions: <code>hill hillr mm mmr exp log sqrt</code>
    </div>
    <div class="apply-row">
      <button id="applyBtn">Apply network</button>
    </div>
    <div class="parse-error" id="parseError"></div>
  </div>

  <div class="field-group">
    <h2>Parameters</h2>
    <div id="kineticsSliders"></div>
  </div>

  <div class="field-group">
    <h2>Diffusion &amp; domain</h2>
    <div id="diffusionSliders"></div>
  </div>

  <div class="field-group">
    <h2>Dispersion relation λ(k)</h2>
    <canvas id="scope" width="600" height="150"></canvas>
    <div class="turing-readout" id="turingReadout"></div>
  </div>
</div>
Reaction networks are parsed with a small Catalyst-style grammar: each line is rate, substrates --> products, with substrates/products built from species names joined by + (optionally prefixed by an integer coefficient), and /0 for "nothing". The rate expression is evaluated as written and multiplied by the mass-action product of the substrate concentrations (no combinatorial 1/n! factor, unlike Catalyst's stochastic convention) — so a fully custom nonlinear rate law (e.g. a Hill function of an unrelated species) should list as its substrate, exactly as in the Julia examples. Any identifier that never appears as a substrate/product becomes a slider parameter. Diffusion is stepped implicitly (tridiagonal solve, no-flux boundaries) and reaction explicitly, on a 100-point 1D grid — an IMEX scheme in place of the package's exact DCT/ETDRK4 pseudospectral integrator. The dispersion panel builds the characteristic polynomial of the (species × species) Jacobian at each domain eigenmode kn=nπ/L via Faddeev–LeVerrier and finds its roots via Durand–Kerner, generalizing turing_wavelength to any number of species.