Search documentationSearch

Simulate a reaction network

Integrate a kinetic ODE model inside a job and save the concentration trace and mass-balance check.

Before you start

The shared Python runtime (`compute/runtime`). Uses NumPy and SciPy.

A time-series CSV (`concentrations.csv`) and solver metadata (`model.json`).

Run a mass-action kinetic model inside a job and save concentration and flux traces, the exact model inputs, and conservation checks. Inspect the results in a reusable Svelte/D3 browser plot.

Note: The platform runs your kinetic solver and stores its traces as artifacts, but does not automatically convert raw reaction barriers into rate constants. Always declare your rate constants, temperature, and initial concentrations explicitly.

1. Inspect the kinetic solver script

Look at compute/jobs/examples/simulate_network.py, which uses the shared kinetics library for a synthetic irreversible first-order reaction (, ). A and B have identical elemental composition. SciPy's stiff BDF solver integrates the model:

python
"""Run the shared kinetics job with a synthetic first-order A-to-B model."""
from __future__ import annotations
from pathlib import Path
from chemistry_kinetics.jobs import Run, simulatefrom chemistry_kinetics.model import Network, Reaction, Simulation, Species

def main() -> None:    model = Simulation(        network=Network(            temperature_k=298.15,            standard_concentration_mol_l=1.0,            species=[Species(id=s, label=s, atoms={"C": 1}, charge=0) for s in ("A", "B")],            reactions=[                Reaction(                    id="A-to-B",                    reactants={"A": 1},                    products={"B": 1},                    forward_rate=0.2,                    reverse_rate=0.0,                    provenance={"source": "synthetic example"},                )            ],            provenance={"description": "synthetic isomerization; each species has one C atom"},        ),        initial_mol_l={"A": 1.0},        end_s=30.0,    )    Path("kinetics-input.json").write_text(model.model_dump_json())    simulate(Run(file="kinetics-input.json"))

if __name__ == "__main__":    main()

What the script writes to results/:

  • concentrations.parquet, fluxes.parquet — Lossless float64 traces with internal Zstd compression. Each row is a sample, with time_s and value columns named species_id:<id> or reaction_id:<id>. Field metadata records identities and units; file metadata links to the exact model by SHA-256.
  • model.json — Exact rates, temperature, stoichiometry, initial concentrations, tolerances and provenance.
  • report.json — Element and charge conservation errors, minimum concentration, final composition and depletion times. Integration failure, non-finite concentrations, or conservation/negativity errors beyond tolerance fail the job.

2. Run the simulation locally

Execute the script with the shared scientific runtime (compute/runtime):

bash
ct-cli run compute/jobs/examples/simulate_network.py \  --profile-python "$PWD/compute/runtime/.venv/bin/python"

Inspect report.json and concentrations.parquet using the printed artifact paths (under the local attempt's work/projects/main/results/ directory). Read the table with chemistry_compute.parquet.read_table or Pandas. Time is in seconds, concentrations in mol/L, and net reaction fluxes in mol/L/s. At 1 second, A is about 0.818731 M and B is about 0.181269 M.

With the frontend workspace dependencies installed, export the plot from the attempt's results:

bash
node compute/kinetics/viewer/render.mjs /absolute/path/to/attempt/results \  --output /absolute/path/out/concentrations.svg

Open the SVG in a browser or place it in a slide. It embeds the shared font and saved numerical data; exporting does not submit another calculation.

3. Checklist for real reaction networks

For a completed registered job, Jobs → Outputs shows the graph automatically above the output files. The job explicitly declares a kinetics result, and the concentration Parquet contains the plot metadata. Tables and downloads remain available. A local run only writes files on disk; it does not upload a job to the web workspace.

When adapting this template to a multi-step reaction network from Build a reaction network:

  • Verify elemental and charge conservation across every time step, not just total mole count.
  • Retain relay molecules: A regenerated catalyst still contributes to the forward and reverse rate laws even though its net stoichiometric coefficient is zero.
  • Record units and reference states: Keep units in Parquet field metadata and record temperature and standard-state assumptions in model.json.

4. Sweep initial conditions in parallel

To sweep temperatures, initial concentrations, or rate-constant uncertainties across a cluster:

  1. Publish chemistry_kinetics.jobs:simulate as a reusable Program, staging a model file for each condition. Temperature changes require rate constants calculated at that temperature.
  2. Fan out across condition grids using a Flow in Build a scientific pipeline or compare kinetic models with Create an algorithm benchmark.