ODE solver library in Rust
132
stars
553
commits
Rust
primary language
Sep 10, 2026
updated
diffsol is a library for solving ordinary differential equations (ODEs) or semi-explicit differential algebraic equations (DAEs) in Rust. It can solve equations in the following form:
M \frac{dy}{dt} = f(t, y, p)
where $M$ is a (possibly singular and optional) mass matrix, $y$ is the state vector, $t$ is the time and $p$ is a vector of parameters.
The equations can be given by either rust code or the DiffSL Domain Specific Language (DSL). The DSL uses automatic differentiation using Enzyme to calculate the necessary jacobians, and JIT compilation (using either LLVM or Cranelift) to generate efficient native code at runtime. The DSL is ideal for using diffsol from a higher-level language like Python or R while still maintaining similar performance to pure rust.
You can add diffsol using cargo add diffsol or directly in your Cargo.toml:
[dependencies]
diffsol = "0.16"
diffsol has the following features that can be enabled or disabled:
nalgebra: Use nalgebra for linear algebra containers and solvers (enabled by default).faer: Use faer for linear algebra containers and solvers (enabled by default).cuda: Use in-built CUDA linear algebra containers and solvers (disabled by default).diffsl-llvm15, diffsl-llvm16, diffsl-llvm17, diffsl-llvm18, diffsl-llvm19, diffsl-llvm20, diffsl-cranelift: Enable DiffSL with the specified JIT backend (disabled by default). You will need to set the LLVM_SYS_XXX_PREFIX (see llvm-sys) and LLVM_DIR environment variables to point to your LLVM installation, where XXX is the version number (150, 160, 170, 181, 191, 201, 211).diffsl-external-dynamic: Use an precompiled external dynamic library for the DiffSL model equations, this is loaded and linked at runtime using the provided library path (disabled by default).diffsl-external-f64 or diffsl-external-f32: Use a precompiled static library for the DiffSL model equations, with f64 or f32 precision respectively. The static library must be linked in at build time (disabled by default).suitesparse: Enable SuiteSparse KLU sparse linear solver (disabled by default, requires faer).autodiff: Uses std:autodiff, enables *_autodiff methods on OdeBuilder to calculate gradients automatically.You can add any of the above features by specifying them in your Cargo.toml. For example, to enable the diffsl-cranelift JIT backend, you would add:
[dependencies]
diffsol = { version = "0.16", features = "diffsl-cranelift" }
See the Cargo.toml documentation for more information on specifying features.
The diffsol book describes how to use diffsol using examples taken from several application areas (e.g. population dynamics, electrical circuits and pharmacological modelling), as well as more detailed information on the various APIs used to specify the ODE equations. For a more complete description of the API, please see the docs.rs API documentation.
For a quick start, see the following example of solving the Lorenz system of equations using the BDF solver and the DiffSL DSL with the LLVM JIT backend:
use diffsol::{LlvmModule, NalgebraLU, NalgebraMat, OdeBuilder, OdeSolverMethod};
pub fn lorenz() -> Result<(), Box<dyn std::error::Error>> {
let problem = OdeBuilder::<NalgebraMat<f64>>::new().build_from_diffsl::<LlvmModule>(
"
a { 14.0 } b { 10.0 } c { 8.0 / 3.0 }
u_i {
x = 1.0,
y = 0.0,
z = 0.0,
}
F_i {
b * (y - x);
x * (a - z) - y;
x * y - c * z;
}
",
)?;
let mut solver = problem.bdf::<NalgebraLU<f64>>()?;
let (_ys, _ts, _stop_reason) = solver.solve(0.0)?;
Ok(())
}
The following ODE solvers are available in diffsol
All solvers feature:
If you use diffsol in your research, please cite it:
Contributions are very welcome, as are bug reports! Please see the contributing guidelines for more information, but in summary:
diffsol is designed to be easy to use from higher-level languages like Python or R. I'd prefer not to split my focus away from the core library, so I'm looking for developers who would like to lead the development of these wrappers. If you're interested, please get in touch.
diffsol makes heavy use of generic programming, which can make it difficult to use from other languages. To help with this, the diffsol-c crate provides a wrapper around the core library using runtime polymorphism, and a C API that can be called via FFI. Combined with the DiffSL DSL, this allows for efficient use of diffsol from other languages without needing to write rust code. The following wrappers are currently planned:
Rust
78.1%
HTML
14.7%
C
5.6%
ODE solver library in Rust
132
stars
553
commits
Rust
primary language
Sep 10, 2026
updated
diffsol is a library for solving ordinary differential equations (ODEs) or semi-explicit differential algebraic equations (DAEs) in Rust. It can solve equations in the following form:
M \frac{dy}{dt} = f(t, y, p)
where $M$ is a (possibly singular and optional) mass matrix, $y$ is the state vector, $t$ is the time and $p$ is a vector of parameters.
The equations can be given by either rust code or the DiffSL Domain Specific Language (DSL). The DSL uses automatic differentiation using Enzyme to calculate the necessary jacobians, and JIT compilation (using either LLVM or Cranelift) to generate efficient native code at runtime. The DSL is ideal for using diffsol from a higher-level language like Python or R while still maintaining similar performance to pure rust.
You can add diffsol using cargo add diffsol or directly in your Cargo.toml:
[dependencies]
diffsol = "0.16"
diffsol has the following features that can be enabled or disabled:
nalgebra: Use nalgebra for linear algebra containers and solvers (enabled by default).faer: Use faer for linear algebra containers and solvers (enabled by default).cuda: Use in-built CUDA linear algebra containers and solvers (disabled by default).diffsl-llvm15, diffsl-llvm16, diffsl-llvm17, diffsl-llvm18, diffsl-llvm19, diffsl-llvm20, diffsl-cranelift: Enable DiffSL with the specified JIT backend (disabled by default). You will need to set the LLVM_SYS_XXX_PREFIX (see llvm-sys) and LLVM_DIR environment variables to point to your LLVM installation, where XXX is the version number (150, 160, 170, 181, 191, 201, 211).diffsl-external-dynamic: Use an precompiled external dynamic library for the DiffSL model equations, this is loaded and linked at runtime using the provided library path (disabled by default).diffsl-external-f64 or diffsl-external-f32: Use a precompiled static library for the DiffSL model equations, with f64 or f32 precision respectively. The static library must be linked in at build time (disabled by default).suitesparse: Enable SuiteSparse KLU sparse linear solver (disabled by default, requires faer).autodiff: Uses std:autodiff, enables *_autodiff methods on OdeBuilder to calculate gradients automatically.You can add any of the above features by specifying them in your Cargo.toml. For example, to enable the diffsl-cranelift JIT backend, you would add:
[dependencies]
diffsol = { version = "0.16", features = "diffsl-cranelift" }
See the Cargo.toml documentation for more information on specifying features.
The diffsol book describes how to use diffsol using examples taken from several application areas (e.g. population dynamics, electrical circuits and pharmacological modelling), as well as more detailed information on the various APIs used to specify the ODE equations. For a more complete description of the API, please see the docs.rs API documentation.
For a quick start, see the following example of solving the Lorenz system of equations using the BDF solver and the DiffSL DSL with the LLVM JIT backend:
use diffsol::{LlvmModule, NalgebraLU, NalgebraMat, OdeBuilder, OdeSolverMethod};
pub fn lorenz() -> Result<(), Box<dyn std::error::Error>> {
let problem = OdeBuilder::<NalgebraMat<f64>>::new().build_from_diffsl::<LlvmModule>(
"
a { 14.0 } b { 10.0 } c { 8.0 / 3.0 }
u_i {
x = 1.0,
y = 0.0,
z = 0.0,
}
F_i {
b * (y - x);
x * (a - z) - y;
x * y - c * z;
}
",
)?;
let mut solver = problem.bdf::<NalgebraLU<f64>>()?;
let (_ys, _ts, _stop_reason) = solver.solve(0.0)?;
Ok(())
}
The following ODE solvers are available in diffsol
All solvers feature:
If you use diffsol in your research, please cite it:
Contributions are very welcome, as are bug reports! Please see the contributing guidelines for more information, but in summary:
diffsol is designed to be easy to use from higher-level languages like Python or R. I'd prefer not to split my focus away from the core library, so I'm looking for developers who would like to lead the development of these wrappers. If you're interested, please get in touch.
diffsol makes heavy use of generic programming, which can make it difficult to use from other languages. To help with this, the diffsol-c crate provides a wrapper around the core library using runtime polymorphism, and a C API that can be called via FFI. Combined with the DiffSL DSL, this allows for efficient use of diffsol from other languages without needing to write rust code. The following wrappers are currently planned:
Rust
78.1%
HTML
14.7%
C
5.6%