BaseModel defines the core equation containers, BaseBatteryModel extends it with battery-specific geometry and mesh defaults, and concrete models like SPM or DFN live at the top. You can plug in at any layer.
Model hierarchy
BaseModel.__init__ initialises all equation containers to empty dicts and sets sensible defaults (use_jacobian=True, convert_to_format="casadi").
Core equation containers
Every model instance exposes four primary dictionaries you must populate:
All four dicts validate their contents on assignment.
Building a custom ODE model from scratch
The example below builds a single-state ODE for a lumped thermal model: the cell temperatureT evolves according to
1
Define the state variable and parameters
custom_ode.py
2
Set the right-hand side
custom_ode.py
3
Set initial conditions
custom_ode.py
4
Expose variables
custom_ode.py
5
Provide parameter values and solve
custom_ode.py
Adding algebraic equations
For DAE systems, usemodel.algebraic. The key must be the variable being solved for, and the value is the residual (set to zero):
algebraic_constraint.py
Boundary conditions
Boundary conditions are set per-variable with side ("left" / "right") and a type string:
boundary_conditions.py
"Dirichlet" (prescribed value) and "Neumann" (prescribed flux).
Submodel architecture
Large battery models are assembled from submodels — isolated components that each contribute equations and variables. Each submodel subclassespybamm.BaseSubModel.
The submodel interface
BaseSubModel exposes six methods you override selectively:
All methods default to
pass, so you only override the ones relevant to your submodel.Writing a submodel
my_submodel.py
Registering submodels in a model
model_with_submodels.py
Building a model
Callingmodel.build_model() runs three internal passes in order:
build_fundamental()— callsget_fundamental_variables()on every submodelbuild_coupled_variables()— callsget_coupled_variables(variables)on every submodelbuild_model_equations()— callsset_rhs,set_algebraic,set_boundary_conditions,set_initial_conditions, andadd_events_fromon every submodel
BaseModel instances), setting the equation dicts directly means there is nothing to build — Simulation will build for you implicitly.
Model serialization
PyBaMM can save a discretised model to a JSON file and reload it without re-discretising.model.save_model() parameters:
convert_to_format options
convert_to_format options
The
model.convert_to_format attribute controls how the expression tree is compiled before handing to the solver:"casadi"(default) — converts to a CasADi expression graph; required forCasadiSolver"python"— converts to Python callable; used withScipySolver"jax"— converts to JAX pytree; used withJaxSolverNone— retains the PyBaMM expression tree; useful for debugging