PyBaMM Version
26.3
Python Version
3.13
Describe the bug
Since commit 4d0c6cd (PR #5380, perf: precalculate state mapper for mapping between experimental steps, merged Feb 2026), the state vector passed as the rootfinder's initial guess at an experiment step transition is no longer algebraically consistent when the previous and next steps use different built-model instances (as is the case for CC→CV in any pybamm.Experiment).
Specifically, when the target model has an algebraic state variable (e.g. Current [A] in a CV hold) that was an input rather than a state in the previous step, build_initial_state_mapper cannot find a y-slice match, falls back to the target model's original initial condition (typically 0), and hands that to calculate_consistent_state. The Newton rootfinder then has to reduce a residual of ~1.5 from a seed that assumes zero current when the CC step actually ended at full charge current.
pybamm.SolverError: Could not find consistent states: Could not find acceptable solution:
solver terminated unsuccessfully and maximum solution error (0.24956) above tolerance (1e-06)
Steps to Reproduce
import sys
import numpy as np
import casadi
import pybamm
_residual_log = []
def _install_probe():
orig = pybamm.solvers.base_solver.BaseSolver.calculate_consistent_state
def patched(self, model, time=0, inputs=None):
try:
y0 = model.y0_list[0] if hasattr(model, "y0_list") else model.y0
inp_dict = inputs[0] if isinstance(inputs, list) else (inputs or {})
inp_vec = casadi.vertcat(*[v for v in inp_dict.values()])
fun = model.casadi_algebraic(time, y0, inp_vec)
r = float(np.max(np.abs(np.asarray(fun).ravel())))
_residual_log.append(r)
print(f" [consistent-init] t={time:9.3f} ||F(y0)||_inf={r:.6e}")
except Exception as e:
print(f" [consistent-init] probe failed: {e}")
return orig(self, model, time=time, inputs=inputs)
pybamm.solvers.base_solver.BaseSolver.calculate_consistent_state = patched
def main():
_install_probe()
experiment = pybamm.Experiment(
[
(
"Charge at 3 C until 4.2 V",
"Hold at 4.2 V for 1800 seconds or until C/20",
"Discharge at 1 C until 2.5 V",
),
],
period="1s",
)
params = pybamm.ParameterValues("Chen2020")
model = pybamm.lithium_ion.DFN()
solver = pybamm.CasadiSolver()
sim = pybamm.Simulation(
model, parameter_values=params, experiment=experiment, solver=solver
)
print(f"pybamm {pybamm.__version__}")
sim.solve(initial_soc=0.05)
cv_entry_residual = _residual_log[1]
print(f"\nCV-entry initial-guess residual: {cv_entry_residual:.3e}")
if cv_entry_residual > 1e-3:
print("REGRESSION: CV-entry initial guess is not algebraically consistent.")
sys.exit(1)
print("OK: CV-entry initial guess is consistent.")
if __name__ == "__main__":
main()
PyBaMM Version
26.3
Python Version
3.13
Describe the bug
Since commit 4d0c6cd (PR #5380, perf: precalculate state mapper for mapping between experimental steps, merged Feb 2026), the state vector passed as the rootfinder's initial guess at an experiment step transition is no longer algebraically consistent when the previous and next steps use different built-model instances (as is the case for CC→CV in any pybamm.Experiment).
Specifically, when the target model has an algebraic state variable (e.g. Current [A] in a CV hold) that was an input rather than a state in the previous step, build_initial_state_mapper cannot find a y-slice match, falls back to the target model's original initial condition (typically 0), and hands that to calculate_consistent_state. The Newton rootfinder then has to reduce a residual of ~1.5 from a seed that assumes zero current when the CC step actually ended at full charge current.
pybamm.SolverError: Could not find consistent states: Could not find acceptable solution:
solver terminated unsuccessfully and maximum solution error (0.24956) above tolerance (1e-06)
Steps to Reproduce