Overview of PyBaMM solvers, when to use each one, and how to configure tolerances, modes, and other solver options.
PyBaMM provides several solvers suited to different use cases. All solvers accept a common set of tolerance parameters and are interchangeable — you pass a solver instance to pybamm.Simulation.
The recommended general-purpose solver. Uses CasADi for JIT-compiled, efficient integration. Supports DAEs, events, and multiple operating modes.
IDAKLUSolver
High-performance solver using SUNDIALS IDA with the KLU sparse direct solver. The fastest option for most PyBaMM models, especially in experiment mode or when solving many steps.
ScipySolver
Wraps scipy.integrate.solve_ivp. Easy to use and well-understood, but does not support DAEs or sensitivity analysis. Good for ODE-only models and debugging.
JaxSolver
JAX-compiled solver, enabling JIT compilation and automatic differentiation. Requires Python ≥ 3.11 and is not available on Intel macOS.
The mode parameter controls the integration strategy:
Mode
Description
When to use
"safe" (default)
Step-and-check in global steps of size dt_max, looking for events
Full charge/discharge simulations
"fast"
Direct integration without event detection
Drive cycles or simulations where no events should be triggered
"fast with events"
Direct integration, then retrospectively check for events
Experimental
"safe without grid"
Step-by-step without pre-computing the time grid
Experimental; can be faster in some cases
# Fast mode for drive cyclessolver = pybamm.CasadiSolver(mode="fast")# Safe mode with custom step sizesolver = pybamm.CasadiSolver(mode="safe", dt_max=60) # 60 s max step
IDAKLUSolver can solve multiple input sets in parallel using OpenMP threads:
solver = pybamm.IDAKLUSolver( options={"num_threads": 4, "num_solvers": 4})# Solve with a list of input dicts in parallelinput_list = [ {"Current function [A]": 1.0}, {"Current function [A]": 2.0}, {"Current function [A]": 5.0},]sol = sim.solve([0, 3600], inputs=input_list)
model = pybamm.lithium_ion.DFN()# Use CasadiSolver in fast modesolver = pybamm.CasadiSolver(mode="fast", rtol=1e-6, atol=1e-6)sim = pybamm.Simulation(model, solver=solver)sol = sim.solve([0, 3600])
You can also override the solver at solve time:
sol = sim.solve([0, 3600], solver=pybamm.IDAKLUSolver())
All solvers accept rtol (relative) and atol (absolute) tolerance parameters. Tighter tolerances improve accuracy at the cost of speed:
# Default tolerances (1e-6 / 1e-6) for most solverssolver = pybamm.CasadiSolver(rtol=1e-6, atol=1e-6)# Tighter tolerances for more accurate resultssolver = pybamm.CasadiSolver(rtol=1e-8, atol=1e-8)# IDAKLU defaults to rtol=1e-4 (looser but faster)solver = pybamm.IDAKLUSolver(rtol=1e-4, atol=1e-6)
For degradation studies requiring many cycles, start with IDAKLUSolver and loosen tolerances (rtol=1e-4) for speed. For a single precise discharge, use CasadiSolver with default tolerances.