# Catalyst.jl: symbolic modelling of reaction networks in Julia

> Catalyst.jl is a Julia package for chemical reaction networks and the dynamical systems built on top of them. You write the network as chemistry, in a domain specific language or programmatically, and it becomes a symbolic model you can solve as an ODE, a stochastic differential equation, a jump process or a hybrid of all three. The symbolic layer is what makes it more than a notation: it gives you sparsity, Jacobians and a dependency graph for free.

**SciML/Catalyst.jl** — Chemical reaction network and systems biology interface for scientific machine learning (SciML). High performance, GPU-parallelized, and O(1) solvers in open source software.

- Repository: https://github.com/SciML/Catalyst.jl
- Website: https://docs.sciml.ai/Catalyst/stable/
- Stars: 531 · Forks: 83
- Language: Julia
- License: NOASSERTION
- Published: 2026-10-22 · Updated: 2026-10-22 · Language: en
- Canonical page: https://hysenlabs.com/projects/sciml-catalyst-jl

## Write the network as chemistry, then solve it five ways

Catalyst.jl is a symbolic modeling package for analysis and high-performance simulation of chemical reaction networks and related dynamical systems.

The models can be specified using an intuitive domain-specific language, or constructed programmatically. The DSL documentation and the programmatic construction documentation are linked separately in the README, which tells you that both routes are first class rather than one being a convenience over the other.

The part that decides the value is the range of solvers it feeds. Catalyst supports ODE, steady-state ODE, SDE, stochastic chemical kinetics through jump processes, and hybrid simulations, including models that couple reactions with differential equations, events and external noise via Brownian Motions and or Poisson Processes.

That list covers the modelling questions that come up in a reaction network. A deterministic concentration model is an ODE. A system where molecules are counted rather than concentrations are a jump process. A gene circuit with a random input is a hybrid. And the same network description produces all of them, which is the point of having a symbolic layer rather than hand-written right hand sides.

The package is built on ModelingToolkitBase.jl and Symbolics.jl, and it uses the symbolic computation for sparsity exploitation, Jacobian construction, dependency graph analysis and parallelism. That last group is what a numerical solver wants and what a hand-written system does not provide: if Catalyst knows that two species never interact, the Jacobian is sparse and the solver can exploit that.

The generated models integrate with the wider Julia and SciML ecosystems for sensitivity analysis, parameter estimation, bifurcation analysis and more. The licence is a custom one that GitHub cannot classify, the documentation is at docs.sciml.ai/Catalyst/stable/, and the last push to the repository was on 2026-10-19.

## Installation, and the two documentation branches

Catalyst is installed through the Julia package manager, and the README's instructions include a step that is easy to overlook and worth keeping.

```julia
using Pkg

# (optional but recommended) create new environment in which to install Catalyst
Pkg.activate("catalyst_environment")

# install latest Catalyst release
Pkg.add("Catalyst")
```

The activate step is marked optional but recommended, and the reason is standard Julia practice: putting a package into its own project environment means that the dependency versions of Catalyst do not collide with the ones your own code needs. In a package that depends on ModelingToolkit and Symbolics, which move fast, that isolation is worth the two lines.

The documentation comes in two versions, and the badges at the top of the README make the distinction. There is a badge for the latest release for users, pointing at the stable documentation, and a badge for the master branch for developers, pointing at the development documentation, which describes unreleased features in the current master branch.

That split is the standard arrangement for a package that publishes regularly, and it has a practical consequence. If you are reading the dev documentation, you are reading about behaviour that is not in a released version, and the difference matters when a function signature changes between releases.

The README also points to the research paper, Catalyst: Fast and flexible modeling of reaction networks, published in PLOS Computational Biology, with the citation badge linking to it. The paper includes an overview of the package, its features and comparative benchmarking as of version 13, and the CITATION.bib file at the repository root is there for the same purpose.

## Version 16 is a breaking release, and the move off ModelingToolkit

The section on what is new in v16 is the most important part of the README for anybody already using the package, because it starts with a warning.

Version 16 is a breaking release. Most breaking changes primarily affect libraries built on top of Catalyst, and the README points at HISTORY.md for the full list of breaking changes and the migration guide.

That distinction between users and downstream libraries is the key. If you call Catalyst directly, a breaking release means your code may need adjusting. If you maintain a package that wraps Catalyst, the breakage lands in your users' projects instead, which is a much larger blast radius.

The first highlight is the ModelingToolkitBase foundation. Without any reduction in core functionality, Catalyst now depends on ModelingToolkitBase instead of ModelingToolkit, to avoid adding new, non-MIT licensed dependencies.

That is a licence-driven dependency change, which is an unusual and interesting reason to restructure a dependency graph. ModelingToolkit carries features that are not MIT licensed, and Catalyst did not want to pull them in. Splitting out the base means Catalyst can depend on the part that is MIT and leave the stronger structural simplification libraries to the user who wants them.

And Catalyst is still compatible with ModelingToolkit for users who want to use those more capable, non-MIT licensed structural simplification libraries, for example for Catalyst-generated DAE models.

So the arrangement is a licence split with both doors open. The cost is that the two packages have to be kept in step, and that a user who wants DAE simplification has to understand which package provides it.

## Hybrid models, a simpler jump API and new DSL syntax

The rest of the v16 highlights are the functional ones, and they are about two things: modelling systems that mix continuous and discrete behaviour, and reducing the ceremony around jump problems.

The hybrid models are the substantial new capability. The new HybridProblem and hybrid_model allow mixing ODE, SDE and jump reactions in a single system via per-reaction PhysicalScale metadata. So a model can now say, in one description, that some reactions are continuous rate laws and others are discrete events, and the physical scale of each tells the solver how the two combine.

The jump API is simpler. You create jump problems directly:

```julia
JumpProblem(rs, u0, tspan, ps)
```

with no DiscreteProblem or JumpInputs intermediate. That is a genuine simplification for anyone who has built a jump model before, since the intermediate objects existed to carry information that the new call can take directly.

The DSL gained several options. The @brownians and @poissonians macros couple environmental noise into the model. The @discretes macro handles event-modified parameters. The @tstops macro gives solver time stops. And the => syntax expresses event affects.

The conversion API was modernised at the same time. ode_model, sde_model, jump_model and ss_ode_model replace the old convert(ODESystem, rs) pattern, and all of them generate ModelingToolkitBase Systems.

And there is unit validation. The @unit_checks DSL option and the validate_units and assert_valid_units functions check that the quantities in your model are dimensionally consistent, with full support for non-SI units through the DynamicQuantities.jl symbolic units package. For a rate law, a dimension error is one of the easiest mistakes to make and one of the hardest to notice, because the model runs and produces nonsense.

## Network analysis, composition, space and steady states

Beyond the simulation types, the feature list covers the analyses that a reaction network makes possible, and each of them is a documentation page of its own.

Network analysis computes linkage classes, deficiencies, reversibility and other network properties. These are the structural properties that tell you whether a model is well posed before you simulate it, and they are the kind of thing that is tedious to compute by hand and easy to compute symbolically.

Compositional modeling builds models hierarchically with the @network_component macro, compose and extend, so that a large network can be assembled from pieces that are written and tested separately. The alternative is one enormous model definition, which nobody can review.

Spatial modeling simulates reaction networks on discrete spatial domains, which is how a diffusion or a spatial gradient enters a model that is otherwise well mixed.

Steady state analysis finds and analyses steady states, stability and bifurcation diagrams, with the documentation pointing at homotopy continuation for the search. That is the tool for the question of whether a system has more than one equilibrium and what happens as a parameter moves.

Coupled models is the fourth group: combining reactions with differential equations, with events, with Brownian noise and with Poisson jumps.

The through-line is that all of this is available from a single ReactionSystem. A model is described once, and the question you want to ask of it, an integration, a bifurcation diagram, a sensitivity analysis or a parameter estimate, selects the method rather than forcing a rewrite.

## Where Catalyst is the wrong tool

There are cases where a reaction network package is the wrong answer, and they are mostly about the modelling work involved.

If you do not have a network, Catalyst is overhead. A single ordinary differential equation with two coupled variables is described in two lines of DifferentialEquations.jl and solved in one. Catalyst's value is that it knows about species, stoichiometry and reactions, and if there are none of those, that knowledge buys nothing and the symbolic machinery costs you compile time and a dependency tree.

The second limit is that it models systems, not processes. It does not read a protocol, it does not run an experiment and it does not integrate with a laboratory instrument. It is a modelling and simulation package, and the data side of computational biology is elsewhere.

The third is the version 16 break. For a team with a large body of Catalyst-based code, upgrading means reading HISTORY.md and following a migration guide, and the downstream library case is worse, because your users see the break rather than you.

The alternative approach is to build the model with Symbolics.jl and solve it with the SciML differential equation stack directly. The difference in approach is that you get the numerical machinery without the network semantics, which means you derive the stoichiometry matrix, the rate law expressions and the conservation laws yourself, and you lose the automatic sparsity, the automatic Jacobian and the automatic dependency analysis that Catalyst derives from the network structure. For a genuine reaction network, that derivation is the tedious part and the part most likely to be wrong, so paying for Catalyst is usually worth it. For a non-network model, it is not.

## Conclusion

Catalyst suits somebody modelling a biochemical network, a signalling cascade or a population dynamics system who wants the stoichiometry and the rate laws to be written once and then solved with whichever method suits the question. It does not suit a plain differential equation with no network structure, where the SciML stack directly is less ceremony, and it does not suit a team pinned to the pre-16 API without reading the migration guide. Check three things before you adopt it: that you are prepared for the version 16 breaking changes if you depend on libraries built on Catalyst, that the licence suits your use, since GitHub records it as a custom licence that the LICENSE file defines, and which simulation types you actually need, because the jump and hybrid paths are where the modelling effort is. The last push to the repository was on 2026-10-19 and the newest release is v16.5.0.

## FAQ

### What is Catalyst.jl?

It is a symbolic modeling package for analysis and high-performance simulation of chemical reaction networks and related dynamical systems, part of the SciML ecosystem. Models can be specified with a domain specific language or constructed programmatically, and Catalyst supports ODE, steady-state ODE, SDE, jump and hybrid simulations.

### How do I install Catalyst.jl?

Through the Julia package manager: activate a dedicated environment with Pkg.activate and then Pkg.add("Catalyst"). The README marks the separate environment as optional but recommended, so that Catalyst's dependency versions do not collide with those of your own project.

### What changed in Catalyst version 16?

It is a breaking release, mostly for libraries built on Catalyst, with the full list in HISTORY.md. Catalyst now depends on ModelingToolkitBase rather than ModelingToolkit to avoid non-MIT licensed dependencies, while staying compatible with ModelingToolkit, and it adds hybrid models, a simplified jump API, new DSL options and unit validation.

### What do the new DSL options in Catalyst 16 do?

The @brownians and @poissonians macros couple environmental noise into a model, @discretes handles event-modified parameters, @tstops gives solver time stops, and the => syntax expresses event affects. Hybrid models additionally use per-reaction PhysicalScale metadata to mix ODE, SDE and jump reactions in one system.

### Can Catalyst.jl check the units in a model?

Yes. The @unit_checks DSL option and the validate_units and assert_valid_units functions validate quantities with full support for non-SI units through the DynamicQuantities.jl symbolic units package, which catches dimensionally wrong rate laws before they produce meaningless output.

## Sources

- [Issues](https://github.com/SciML/Catalyst.jl/issues)
- [Project website](https://docs.sciml.ai/Catalyst/stable/)
- [README](https://github.com/SciML/Catalyst.jl/blob/master/README.md)
- [Releases](https://github.com/SciML/Catalyst.jl/releases)
- [SciML/Catalyst.jl on GitHub](https://github.com/SciML/Catalyst.jl)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/sciml-catalyst-jl
