sim.solve() and invoked automatically as the solver progresses through cycles and steps.
The Callback API is experimental — the interface may change in future releases.
Built-in callbacks
LoggingCallback
Added automatically if noLoggingCallback is present in the list passed to sim.solve(). It logs progress to pybamm.logger or an optional log file:
LoggingCallback emits:
NOTICEon experiment start, each cycle start, each step start, and experiment endWARNINGwhen an experiment step is infeasibleERRORon solver errors
CallbackList
CallbackList wraps multiple callbacks so they can be dispatched as one:
CallbackList manually — setup_callbacks() does this for you and ensures a LoggingCallback is always present.
Callback interface
Every callback method receives a singlelogs dict. The table below lists each hook and the keys available in logs at that point:
| Method | When called | Key logs entries |
|---|---|---|
on_experiment_start(logs) | Before the first cycle | — |
on_cycle_start(logs) | Before each cycle | "cycle number" (current, total) tuple; "elapsed time" |
on_step_start(logs) | Before each step | "cycle number", "step number" (current, total) tuple, "step operating conditions" |
on_step_end(logs) | After each step completes | "stopping conditions" → {"time": ...}, "experiment time" |
on_cycle_end(logs) | After each cycle completes | "stopping conditions" → {"capacity": ..., "voltage": ...}, "summary variables", "start capacity", "Minimum voltage [V]" |
on_experiment_end(logs) | After the last cycle | "elapsed time" |
on_experiment_error(logs) | When a SolverError occurs | "error" |
on_experiment_infeasible_time(logs) | Step hits default duration | "step duration", "cycle number", "step number", "step operating conditions" |
on_experiment_infeasible_event(logs) | Step terminated by an event | "termination", "cycle number", "step number", "step operating conditions" |
Creating a custom callback
Subclasspybamm.callbacks.Callback and override whichever hooks you need. Methods that are not overridden default to pass.
save_callback.py
Using callbacks with Simulation
Pass a list of callback instances to thecallbacks keyword of sim.solve():
use_callbacks.py
Example: early-stopping callback
The following callback raises an exception to stop the simulation if the voltage drops below a threshold mid-experiment:early_stop_callback.py
Callback dispatch internals
Callback dispatch internals
CallbackList delegates every on_* call to each registered callback using a callback_loop_decorator. The decorator is applied automatically at class definition time by inspecting all methods that start with on_ via inspect.getmembers. This means adding a new on_custom_event method to Callback automatically becomes dispatchable through CallbackList without any changes to CallbackList itself.