Skip to content

Multilayer zoo entry: build each zone from PyBaMM's own model - #5840

Open
mleot wants to merge 3 commits into
pybamm-team:multilayer-pouch-thermal-zoofrom
mleot:multilayer-pouch-thermal-zoo
Open

mleot wants to merge 3 commits into
pybamm-team:multilayer-pouch-thermal-zoofrom
mleot:multilayer-pouch-thermal-zoo

Conversation

@mleot

@mleot mleot commented Oct 3, 2026

Copy link
Copy Markdown
Contributor

Description

Targets the branch of #5815, so it lands there when merged.

Each zone of multilayer_3d_thermal becomes PyBaMM's own SPM, SPMe or DFN, built with the stack's options and renamed into the stack with pybamm.replace, instead of hand-written equations. Model options (particle phases, hysteresis, intercalation kinetics) now take effect in every zone, and a zone_model hook builds zones with a replaced submodel. This replaces the zone equations, and with them the SPMe and DFN fixes in #5815, which the new zones no longer need.

Also fixed, found against PyBaMM's lumped model:

  • Zones spanned L_x while heat capacity included the current collectors: an insulated stack heated 21% too fast. Zones now span the full unit cell.
  • Through-stack conduction used the in-plane lambda_eff. Interfaces now carry the layers' series conduction, the outer faces half a zone of it, and core-to-skin no longer depends on the number of zones.
  • The parallel current split solved fractions of the stack current, singular at zero current. Zone currents are now the unknowns, so a stack can start from rest, and zones that differ exchange current at rest.
  • Each unit cell carried a whole foil of each current collector, which counts every foil twice in a stack of double-sided electrodes. A coating argument, "double-sided" by default, gives each unit cell half of each foil; "single-sided" keeps whole foils.

New outputs: left and right face, surface, and core temperatures, each zone's current density and heat capacity, and the stack's heat terms in watts.

Held isothermal, the stacks match SPM, SPMe and DFN to 0.013, 0.008 and 0.005 mV, and with a two-phase hysteretic negative electrode they match SPMe and DFN to 0.09 and 0.014 mV. The README's Validation section lists every check, and the entry's tests cover each fix. The commit messages have the details.

Type of change

A model zoo entry; its bullet in packages/pybamm-model-zoo/CHANGELOG.md is updated, and nothing under packages/pybamm/ changes.

Important checks

  • No style issues: pre-commit passes on the changed files
  • All tests pass: the model zoo suite, 201 tests, including the contract suite and examples
  • Code is commented for hard-to-understand areas
  • Tests added that prove each fix is effective

mleot added 2 commits October 2, 2026 20:33
…olume

Each zone is now pybamm.lithium_ion.SPM, SPMe or DFN, built with the
stack's options and renamed into the stack with pybamm.replace, in
place of hand-written equations. Particle phases, open-circuit
potential models including hysteresis, intercalation kinetics and every
other electrochemical option now behave as they do in PyBaMM. A
zone_model hook builds zones with a replaced submodel, for example a
composite heat of mixing until PyBaMM's own builds on two phases.

Held isothermal, the stacks match SPM, SPMe and DFN to 0.013, 0.008 and
0.005 mV (previously 0.03, 0.34 and 0.15 mV), and with a two-phase
hysteretic negative electrode they match SPMe and DFN to 0.09 and 0.014 mV.

Fixes found against PyBaMM's lumped model:

- Zones spanned L_x, the electrodes and separator, while heat capacity
  and conductivity included the current collectors. An insulated stack
  heated 21% faster than the lumped cell. Zones now span the full unit
  cell and use the zone's own heat capacity, and the rise matches to 1e-5.
- Conduction through the stack used lambda_eff, the in-plane mean. The
  interfaces now carry the unit cell's layers in series, and the outer
  zones carry half a zone of it in series with the face cooling.
  Core-to-skin no longer depends on the number of zones (it was 2% of
  the slab value at two zones) and is within 2% of a uniformly heated slab.
  The contact resistance is now in addition to this, default 0.
- The parallel split solved current fractions, which are singular at
  zero current: a window starting from rest failed at t = 0. Each zone's
  current is now the unknown, so the stack starts from rest, and zones
  that differ exchange current at rest.

New outputs: Left and Right face temperatures, Surface temperature (the
outer faces' mean), Core temperature and Core-to-skin difference, each
zone's Total current density and heat capacity, and the stack's heat
terms in watts and Discharge capacity. The options "thermal",
"dimensionality" and "cell geometry" are checked, since the stack's
fields are its thermal model.
The current collector thicknesses are whole foils, as in PyBaMM's
parameter sets, but each unit cell carried a whole foil of each, which
counts every foil twice in a stack of double-sided electrodes. A new
coating argument, "double-sided" by default, gives each unit cell half
of each foil in the stack's thickness, its heat capacity and in-plane
conductivity, and the series conduction through it, inside the zones
and in the stack alike. "single-sided" keeps whole foils per unit cell,
as PyBaMM's single-cell models assume.

An insulated double-sided stack heats as PyBaMM's lumped cell given half
of each foil, and a single-sided one as a lumped cell with whole foils.
Each zone is a full PyBaMM model and brought its own voltage cut-off
events. Renamed into the stack, an experiment no longer replaced them
with its own limits, so "Discharge at 3C until 2.8 V" stopped at the
parameter set's lower cut-off, 3.105 V on Marquis2019. The stack sets
the limits once, as before; the zones' copies are dropped.

Tests now pin the options the zones are built with against PyBaMM's own
models: two particle phases with one-state hysteresis under
Butler-Volmer and Marcus-Hush-Chidsey kinetics on SPM, SPMe and DFN,
the heat of mixing, a lumped thermal capacity, a lumped surface
temperature option, and a zone_model that swaps a submodel.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant