Fitting PyBaMM Parameters: Why the Optimiser’s Numbers May Mean Nothing
Fitting PyBaMM Parameters: Why the Optimiser’s Numbers May Mean Nothing
Search
Ask the AI

Fitting PyBaMM Parameters: Why the Optimiser’s Numbers May Mean Nothing

You have a discharge curve from a real cell and a PyBaMM model that does not match it. The obvious move is to fit the parameters. Two things go wrong before you write a line of code, and a third goes wrong afterwards in a way that is much harder to notice.

This article is about all three: the tool the search results send you to is deprecated, the API you copy from tutorials has moved, and — the one that actually matters — most of the parameters you want to fit cannot be identified from the data you have, so the optimiser will happily return numbers that mean nothing.

1. The tool the search results give you is deprecated

Search for PyBaMM parameter fitting and the top result is pybamm-param. Its README opens with a deprecation notice:

All the functionality in pybamm-param is now available in PyBOP, which will be the focus of future development.

PyBOP is the maintained successor (pip install pybop). This is worth stating plainly because search rank and maintenance status are unrelated: pybamm-param still ranks first, still has working example code, and will still run. You will only discover it is a dead end when you need a feature or a fix.

2. Copied API snippets are likely to be stale

PyBOP’s own README notes that v25.10 was a major restructure. Tutorials, notebooks and forum answers written before it will not run unmodified, and the failure mode is an AttributeError or a changed constructor signature rather than anything that tells you the API moved.

So the practical rule for this particular library: take the API from the version of the examples that ships with the release you installed, not from a blog post — including this one. That is why there is no API snippet below. What follows is the part that does not change between releases and that the documentation does not cover: deciding what is worth fitting at all.

# Rather than copying a call that may be stale, read the examples that ship
# with the version you actually installed
python -c "import pybop, pathlib; print(pybop.__version__, pathlib.Path(pybop.__file__).parent)"
# then open examples/ at the matching tag in the repository - not an arbitrary
# tutorial from the search results

3. The real problem: you cannot fit what the data cannot see

A DFN model has on the order of fifty parameters. A discharge curve is one voltage trace. The optimiser does not know this is hopeless — hand it fifty free parameters and it will return fifty numbers with a small residual, and every one of them may be wrong.

The mechanism is the same one that makes a single impedance spectrum ambiguous: parameters appear in the equations in combinations, and only the combination is observable. Fit exchange current density and electrode specific surface area together against one curve and you can halve one, double the other, and the curve barely moves. The optimiser lands somewhere on that ridge, reports convergence, and the individual values are an artefact of where it started.

Two consequences follow, and they are the whole practical content of parameter fitting:

  • Fit few parameters, chosen deliberately. The evidence from practice is that open-circuit potential and particle diffusivity carry most of the discharge-curve shape; those are the ones worth freeing first.
  • Add experiments, not free parameters. A fit that will not resolve two parameters from one C-rate may resolve them from three, because the combination that dominates changes with rate. Adding data breaks the degeneracy; adding freedom hides it.

4. A protocol that separates fitted from fabricated

Whatever library you use, these steps decide whether the result is a measurement or a decoration.

Hold out a rate you did not fit

Fit on some C-rates, validate on one you excluded. A parameter set that reproduces the fitted rates and misses the held-out one has memorised the curves rather than identified the physics — the same failure as a model that scores well on its training set. This is the single cheapest check and it is skipped more often than any other.

Re-fit from several starting points

Run the same optimisation from a handful of different initial guesses. If the fitted values scatter widely while the residual stays about the same, the parameters are on a ridge and are not identifiable. If they converge to the same place from everywhere, that is evidence they are.

This is more informative than any single fit’s reported uncertainty, and it needs no extra theory.

Check the values against physical bounds

A diffusivity that comes back several orders of magnitude from anything in the literature, a porosity above one, a stoichiometry outside [0, 1] — these are not surprising discoveries, they are signs the optimiser reached them to compensate for something else being wrong. Bound the parameters where you know the physics, and treat a fit that pins against a bound as a failed fit rather than a successful one.

Look at the residual shape, not only its size

A small residual that is structured — consistently high at the start of discharge, or diverging at the end — means the model is missing a mechanism, and no amount of parameter tuning will remove it. A residual that looks like measurement noise is what a real fit produces. The number alone cannot tell these apart.

5. When the model is the problem, not the parameters

Fitting cannot fix a model that lacks the physics. Some symptoms point clearly away from the parameters:

Symptom Likely cause
Fit is good at low rate, diverges at high rate Electrolyte limitation the model averages away. SPM cannot represent it at all; try SPMe or DFN.
Fit is good on a fresh cell, drifts on an aged one No degradation submodel enabled, so the fit is compensating with unphysical transport parameters.
Fit needs a different parameter set per temperature Missing or wrong Arrhenius dependence; the temperature behaviour is being absorbed into constants.
Residual has a consistent offset Often not the cell at all – check the measurement, contact resistance and OCP reference.

The pattern in every row is the same: the optimiser is being asked to express, through parameters, a mechanism the equations do not contain. It will comply, and the parameters it returns will be meaningless outside the exact conditions of the fit.

6. What to record

A parameter set with no provenance is not reusable, and six months later you will not remember which of its numbers were fitted and which came from a published set.

Base set:        Chen2020
Fitted:          negative particle diffusivity, positive OCP shift
Held fixed:      everything else (source: Chen2020)
Data:            3 discharge curves, 0.5C / 1C / 2C, 25 C, cell ID ...
Held out:        1.5C, used only for validation
Optimiser:       <name and version>
Restarts:        8 starting points; fitted values spread < 5%
Held-out error:  RMSE ... mV
Residual shape:  noise-like, no structure at either end
Bounds hit:      none

The two lines that matter most are restarts and held-out error. A fit reported without them is a curve that was made to overlap, not a parameter set that was measured.

References

Related: PyBaMM architecture and solver choice (a fit against the wrong model has no physical meaning however tight it is), EIS labels and identifiability (the same degeneracy in the frequency domain), and solver convergence failures (what interrupts a fitting run most often). To see the same problem on real pulse data, the site’s HPPC pulse resistance analyser reports only a lower bound on tau when the rest period cannot support a point estimate, using exactly this criterion.

Leave a Reply

Scroll down