Skip to content

Commit d324d49

Browse files
committed
draft landscape
1 parent ce34658 commit d324d49

4 files changed

Lines changed: 221 additions & 0 deletions

File tree

132 KB
Loading
6.6 KB
Loading
6.67 KB
Loading
Lines changed: 221 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,221 @@
1+
---
2+
layout: post.njk
3+
title: Landscape of ODE Solvers in R
4+
subtitle: A Practical Overview
5+
date: 2026-04-26
6+
lastModified: 2026-04-26
7+
description: 'An overview of ODE solvers in R, highlighting their capabilities, performance, and practical considerations.'
8+
author: Evgeny Metelkin
9+
authorURL: https://metelkin.me
10+
canonical: https://metelkin.me/landscape-of-ode-solvers-in-r/
11+
openGraph:
12+
title: 'Landscape of ODE Solvers in R'
13+
description: 'An overview of ODE solvers in R, highlighting their capabilities, performance, and practical considerations.'
14+
url: https://metelkin.me/landscape-of-ode-solvers-in-r/
15+
image: https://metelkin.me/landscape-of-ode-solvers-in-r/img/fig0-cover-520x270.png
16+
site_name: Evgeny Metelkin
17+
type: article
18+
tags:
19+
- post
20+
# - featured
21+
- SoftwareEngineering
22+
- modeling
23+
- software
24+
- r
25+
---
26+
![Cover](./img/fig0-cover.png)
27+
28+
Solving **ordinary differential equations (ODEs)** is a common task in many fields, including systems biology, pharmacometrics, and engineering. The R ecosystem offers a collection of tools for this purpose: from lightweight numerical solvers to full modeling frameworks.
29+
30+
This article provides **a practical overview of ODE solvers in R**, with a focus on helping users navigate the ecosystem and choose appropriate tools.
31+
32+
All packages here was tested with simple examples and the code was published in the [GitHub repository](https://github.com/metelkin/ode-solvers-in-r).
33+
34+
## What is included
35+
36+
We include tools that:
37+
38+
- Provide an API for R
39+
- Support solving general ODE systems
40+
- Are mentioned in literature, documentation, or community discussions
41+
42+
We intentionally exclude:
43+
44+
- Deprecated or archived packages (e.g., RxODE)
45+
- Thin wrappers around other frameworks without original solvers or formats (e.g., nlmixr2)
46+
- Small helper packages
47+
- Highly specialized tools limited to narrow domains
48+
49+
Some tools included in this review go beyond ODE solving and provide additional capabilities such as parameter estimation or simulation workflows. We include them for completeness, without going into those advanced features.
50+
51+
## Overview table
52+
53+
| Package | Type | Engine | Algorithms | Model format | Stiff | DAE | DDE | Time events | Conditional events | CRAN downloads (2025) |
54+
|---------|------|---------|------------|--------------|-----------------|-----|-----|-------------|--------------------|------------------------|
55+
| [deSolve](https://cran.r-project.org/package=deSolve) | Compiled | [ODEPACK](http://www.netlib.org/odepack/); [DASPK](http://www.netlib.org/ode/) (in FORTRAN) | lsoda, lsode, radau, euler, rk4, ode23, ode45, etc. | R func (Interpreted); C / C++ / Fortran (Compiled) | Yes (via lsoda) | Yes (via daspk) | Yes (via dede) | Yes | Yes | 635628 |
56+
57+
#### Type
58+
59+
- **Pure R solvers**: Numerical algorithms implemented directly in R. These are easy to inspect and flexible, but typically slower due to interpreter overhead.
60+
- **Compiled solvers**: Implemented in C/C++/Fortran or wrapping established libraries (e.g., ODEPACK). These provide significantly better performance and are the default choice for most applications.
61+
- **External runtime interfaces**: Packages that delegate computation to external ecosystems such as Julia or Python. These act as bridges rather than standalone solvers.
62+
63+
#### Engine / Algorithms
64+
65+
- **Engine** refers to the underlying numerical implementation used by the package. This can be:
66+
- a well-known external library (e.g., ODEPACK),
67+
- a custom compiled implementation,
68+
- or an external runtime (e.g., Julia),
69+
- another R package.
70+
71+
- **Algorithms** lists the available numerical methods (e.g., LSODA, Runge–Kutta, Radau).
72+
Some packages expose multiple algorithms, while others are limited to a specific class.
73+
74+
#### Model format
75+
76+
ODE models can be defined in different ways: as R functions, domain-specific languages (DSL), structured APIs, or even external code.
77+
78+
The key distinction affecting performance is how the model is executed:
79+
80+
- **Interpreted execution**: The model is defined as an R function and evaluated during each solver step.
81+
- **Compiled execution**: The model is translated into compiled code before simulation, avoiding interpreter overhead and improving performance.
82+
83+
#### Stiff
84+
85+
Indicates whether the solver can handle **stiff systems**.
86+
87+
Stiffness arises when a system contains processes evolving on very different time scales. Solvers that support stiffness typically use implicit methods or adaptive switching (e.g., LSODA).
88+
89+
#### DAE / DDE
90+
91+
Support for these features is solver-dependent and often requires specific algorithms.
92+
93+
- **DAE (Differential-Algebraic Equations)**: Systems that include algebraic constraints in addition to differential equations.
94+
- **DDE (Delay Differential Equations)**: Systems where derivatives depend on past states.
95+
96+
#### Time events / Conditional events
97+
98+
These features are important for modeling real-world systems with discontinuities.
99+
100+
- **Time events**: Discrete changes applied at predefined time points (e.g., dosing events).
101+
- **Conditional events**: Events triggered when a condition is met during simulation (e.g., threshold crossing).
102+
103+
#### CRAN downloads
104+
105+
Total number of downloads in 2025, reflecting usage statistics.
106+
107+
## Repository and test cases
108+
109+
To ensure practical consistency, packages were tested on two simple ODE models. The full code for all packages is available in the companion [GitHub repository](https://github.com/metelkin/ode-solvers-in-r).
110+
111+
We are providing here the code in `mrgsolve` format for two examples: a pharmacokinetic model with non-linear elimination, and the Robertson problem, which is a classic stiff ODE system.
112+
113+
### Example 1: Pharmacokinetic model with non-linear elimination
114+
115+
```r
116+
library(mrgsolve)
117+
library(magrittr)
118+
119+
# load model as DLS (C++ like)
120+
mod <- mcode("pk_model", '
121+
$PARAM
122+
kabs_Alc = 10.0
123+
Vmax_ADH = 3
124+
Km_ADH = 0.1
125+
V_blood = 5.5
126+
127+
$CMT
128+
Alc_g Alc_b_amt
129+
130+
$ODE
131+
double Alc_b = Alc_b_amt / V_blood;
132+
double vabs_Alc = kabs_Alc * Alc_g;
133+
double v_ADH = Vmax_ADH * Alc_b / (Km_ADH + Alc_b) * V_blood;
134+
135+
dxdt_Alc_g = -vabs_Alc;
136+
dxdt_Alc_b_amt = vabs_Alc - v_ADH;
137+
138+
$TABLE
139+
capture Alc_b;
140+
')
141+
142+
# time event
143+
ev1 <- ev(time = 2, amt = 50, cmt = "Alc_g")
144+
145+
# solve
146+
out <- mod %>%
147+
init(Alc_g = 50, Alc_b_amt = 0) %>%
148+
ev(ev1) %>%
149+
mrgsim(start = 0, end = 12, delta = 0.001)
150+
151+
plot(out)
152+
```
153+
154+
![example-1-sim](./img/fig1-example-1-sim.png)
155+
156+
### Example 2: Robertson problem stiff ODE
157+
158+
```r
159+
library(mrgsolve)
160+
library(magrittr)
161+
162+
# load model as DLS (C++ like)
163+
mod <- mcode("rob_model", '
164+
$CMT
165+
A B C
166+
167+
$ODE
168+
dxdt_A = -0.04 * A + 1e4 * B * C;
169+
dxdt_B = 0.04 * A - 1e4 * B * C - 3e7 * pow(B, 2);
170+
dxdt_C = 3e7 * pow(B, 2);
171+
')
172+
173+
# solve
174+
out <- mod %>%
175+
init(A = 1, B = 0, C = 0) %>%
176+
mrgsim(start = 0, end = 1, delta = 1e-2)
177+
178+
plot(out)
179+
```
180+
181+
![example-2-sim](./img/fig2-example-2-sim.png)
182+
183+
## Author's notes
184+
185+
The goal of this review was to provide **a maximally complete and objective overview** of tools for solving ODEs in R. The packages included in this survey differ significantly in their purpose and functionality: from simple numerical solvers to full-featured frameworks and specialized domain-specific tools. They are presented here on equal footing, without going into detailed feature comparisons.
186+
187+
Many aspects - such as computational performance, numerical accuracy, and advanced functionality - are intentionally not covered in this article.
188+
189+
The table includes popularity metrics in the form of download counts. However, these numbers do not reflect the actual capabilities of the packages. Downloads may include one-time installations for educational purposes, CI/CD workflows, or other non-analytical uses. Therefore, they should not be considered a deciding factor when choosing a tool, but rather as a rough indicator of visibility within the community.
190+
191+
Below is a subjective selection of packages that I would recommend paying attention to.
192+
193+
#### General-purpose solution: deSolve
194+
195+
[deSolve](https://cran.r-project.org/package=deSolve) is a robust and well-established package with broad functionality and support for multiple numerical methods. It provides advanced capabilities such as handling stiffness, DAEs, DDEs, and events, while maintaining good computational performance through compiled solvers and model interfaces. It also offers flexible ways to define models.
196+
197+
With a large user base and extensive documentation, it is a reliable default choice.
198+
199+
I would recommend it as a general-purpose tool for most ODE tasks in R. If you are new to ODE modeling in R, starting with deSolve is a safe and practical choice before exploring more specialized tools.
200+
201+
#### Domain-specific tool: rxode2
202+
203+
[rxode2](https://cran.r-project.org/package=rxode2) is a powerful tool designed for pharmacokinetics and pharmacodynamics (PK/PD).
204+
205+
Together with the [nlmixr2](https://nlmixr2.org/) toolkit, it extends beyond ODE solving to include parameter estimation from data and efficient Monte Carlo simulations in parallel and distributed environments.
206+
207+
If your work is related to PK/PD modeling, this can be an excellent choice.
208+
209+
#### Underappreciated tool: dMod
210+
211+
[dMod](https://cran.r-project.org/package=dMod) provides a powerful framework for dynamic modeling, parameter estimation, and identifiability analysis.
212+
213+
It combines symbolic model definition with efficient numerical solvers and supports gradient-based optimization workflows. While it has a steeper learning curve compared to simpler solvers, it offers a high level of flexibility and is particularly useful for more advanced modeling tasks.
214+
215+
Despite its capabilities, it appears to be less widely used, making it an interesting but often overlooked option.
216+
217+
#### Bridge to high-performance: diffeqr
218+
219+
[diffeqr](https://cran.r-project.org/package=diffeqr) provides an interface to the Julia-based DifferentialEquations.jl ecosystem, exposing a large collection of state-of-the-art solvers directly in R.
220+
221+
Rather than implementing its own numerical methods, it delegates computation to Julia, allowing access to advanced algorithms, GPU acceleration, and high-performance execution that are often beyond native R tools.

0 commit comments

Comments
 (0)