What Is Stiffness?
Stiffness is perhaps the single most important concept in computational ODE solving. A stiff problem is one where standard explicit methods (like DoPri5 or Tsit5) are forced to take absurdly small time steps — not for accuracy, but for numerical stability. Understanding stiffness lets you pick the right solver and avoid wasting hours of compute time on what should be a trivial integration.
A First Example
Section titled “A First Example”Consider two simple decay equations:
Non-stiff:
Stiff:
Both have the same form and the exact solution . The second decays much faster, but its solution is equally smooth. So why is it harder to solve numerically?
The answer lies in the stability region of the solver. An explicit method like forward Euler requires the step size to satisfy . For , this means . Even if you only care about the solution at (where to machine precision), an explicit method must still take thousands of tiny steps, each obeying the stability constraint rather than the accuracy requirement.
The Eigenvalue Interpretation
Section titled “The Eigenvalue Interpretation”For a linear system , the eigenvalues of determine the behavior of each solution mode. Stiffness arises when these eigenvalues span a wide range:
When this ratio is large (say, ), the system is stiff. The fast modes (large ) decay quickly and become negligible, but they continue to constrain the step size of explicit methods long after they contribute nothing to the solution.
For nonlinear systems , the Jacobian plays the role of . Its eigenvalues change with time and state, so stiffness can be localized — a problem might be stiff in one region and non-stiff in another.
Timescale Separation
Section titled “Timescale Separation”Physically, stiffness corresponds to the presence of multiple timescales:
| Timescale | Eigenvalue | Role |
|---|---|---|
| Fast () | Large | Transients that decay rapidly |
| Slow () | Small | The dynamics you actually care about |
The ratio is the stiffness ratio. When it exceeds , explicit methods become impractical.
Example: Chemical kinetics. A combustion reaction might involve radical species with lifetimes of seconds and bulk temperature changes over seconds — a stiffness ratio of .
A Precise Definition
Section titled “A Precise Definition”There is no single universally accepted definition of stiffness, but the most practical one comes from Lambert (1991):
A system is stiff if the step size required for stability is much smaller than the step size required for accuracy.
Equivalently, a problem is stiff over the interval if:
- All eigenvalues of the Jacobian have negative real parts (the system is stable), and
- The stiffness ratio .
Note that condition (1) is important: if an eigenvalue has a positive real part, the solution is genuinely growing fast and small steps are needed for accuracy, not just stability. That is not stiffness — that is a genuinely fast phenomenon.
Visual Intuition: The Phase Portrait
Section titled “Visual Intuition: The Phase Portrait”Consider the 2D system:
The Jacobian is:
with eigenvalues and . In the phase portrait:
- Fast direction (): trajectories snap almost instantaneously onto the slow manifold defined by .
- Slow direction (): trajectories then drift slowly along the manifold toward the origin.
An explicit solver must resolve the fast snap even during the slow drift, wasting enormous computational effort.
Classic Stiff Problems
Section titled “Classic Stiff Problems”Van der Pol Oscillator
Section titled “Van der Pol Oscillator”For small , this is non-stiff. For , sharp transitions alternate with slow relaxation phases, making it severely stiff.
use numra::ode::{Radau5, Solver, OdeProblem, SolverOptions};
let mu = 1000.0;let problem = OdeProblem::new( move |_t, y: &[f64], dydt: &mut [f64]| { dydt[0] = y[1]; dydt[1] = mu * (1.0 - y[0] * y[0]) * y[1] - y[0]; }, 0.0, 2000.0, vec![2.0, 0.0],);
let options = SolverOptions::default().rtol(1e-6).atol(1e-8);let result = Radau5::solve(&problem, 0.0, 2000.0, &[2.0, 0.0], &options) .expect("Radau5 should handle stiff Van der Pol");Robertson Chemical Kinetics
Section titled “Robertson Chemical Kinetics”This has rate constants spanning 11 orders of magnitude ( to ), making it one of the classic test problems for stiff solvers.
use numra::ode::{Radau5, Solver, OdeProblem, SolverOptions};
let problem = OdeProblem::new( |_t, y: &[f64], dydt: &mut [f64]| { dydt[0] = -0.04 * y[0] + 1e4 * y[1] * y[2]; dydt[1] = 0.04 * y[0] - 1e4 * y[1] * y[2] - 3e7 * y[1] * y[1]; dydt[2] = 3e7 * y[1] * y[1]; }, 0.0, 1e11, vec![1.0, 0.0, 0.0],);
let options = SolverOptions::default().rtol(1e-4).atol(1e-8);let result = Radau5::solve(&problem, 0.0, 1e11, &[1.0, 0.0, 0.0], &options) .expect("Robertson system is severely stiff");Stiff Linear System
Section titled “Stiff Linear System”Stiffness ratio of 1000. The solution quickly approaches the slow manifold and then decays exponentially with rate 1.
use numra::ode::{Esdirk54, Solver, OdeProblem, SolverOptions};
let problem = OdeProblem::new( |_t, y: &[f64], dydt: &mut [f64]| { dydt[0] = -1000.0 * y[0] + y[1]; dydt[1] = -y[1]; }, 0.0, 10.0, vec![1.0, 1.0],);
let options = SolverOptions::default().rtol(1e-6).atol(1e-9);let result = Esdirk54::solve(&problem, 0.0, 10.0, &[1.0, 1.0], &options) .expect("ESDIRK handles moderate stiffness well");Why Explicit Methods Fail
Section titled “Why Explicit Methods Fail”An explicit Runge-Kutta method (like DoPri5 or Tsit5) has a bounded stability region in the complex -plane. For a generic 4th-order method, the stability region extends roughly to along the negative real axis.
This means the step size must satisfy:
where depends on the method. When , this forces regardless of accuracy needs.
Implicit methods (Radau5, BDF, ESDIRK) solve a nonlinear system at each step, which makes each step more expensive but gives them unbounded stability regions (A-stability or L-stability). They can take large steps even when fast modes are present, because the implicit formulation automatically damps them.
| Aspect | Explicit (DoPri5, Tsit5) | Implicit (Radau5, BDF) |
|---|---|---|
| Stability region | Bounded | Unbounded (A-stable) |
| Step size limit | Limited only by accuracy | |
| Cost per step | (LU solve) | |
| Stiff problems | Catastrophically slow | Efficient |
| Non-stiff problems | Efficient | Overkill (wasted LU cost) |
The Bottom Line
Section titled “The Bottom Line”- If your solver takes millions of tiny steps but the solution looks smooth, your problem is probably stiff.
- Stiffness is about eigenvalue spread, not problem complexity.
- Use implicit solvers (Radau5, BDF, ESDIRK) for stiff problems.
- Use explicit solvers (DoPri5, Tsit5, Vern) for non-stiff problems.
- Numra’s
Autosolver detects stiffness automatically and picks the right method.
The next section shows how to detect stiffness before (or during) integration.