June 22, 2026
GITTModel for diffusion-only fits, ionworks-model download for pybamm-only users, full app-URL helpers, and the start of a strict schema-config contract
GITTModel — a first-class diffusion-only model
GITTModel and HalfCellGITTModel are now first-class models in
ionworkspipeline (with matching ionworks_schema siblings). GITT
fits overwhelmingly use the same lightweight model rather than SPMe:
x-averaged particle diffusion per electrode, a single lumped ohmic
resistance, fixed OCPs, and no Butler-Volmer kinetics, electrolyte
dynamics, or thermal effects. Until now that model lived as
near-identical local copies in per-engagement repos, which meant the
API route could not run it. Shipping it as a built-in model unblocks
server-side GITT fits and backs the new half-cell GITT fit template.Download ionworks-defined models for plain pybamm
Users who have onlyionworks-schema / ionworks-api — and not the
licensed ionworkspipeline package — can now obtain ionworks-defined
models (ECM, LumpedSPMR, the MSMR models, GITTModel) in a form
they can load and run with plain pybamm. A new
POST /discovery/ionworks_models/serialize endpoint builds the model
server-side (where the license lives) and returns a loadable
serialisation, exposed through the Python SDK.App-URL helpers for every routed resource
The SDK’sclient.urls grew from a single .measurement() method to
a full set of web-app link builders — project, model,
parameterized_model, optimization, pipeline, study,
simulation, cell_specification, cell_instance, and more — so
callers never hand-construct app.ionworks.com URLs from IDs. The
helpers are environment-aware, deriving the right host for whichever
API environment the client is configured against.Stricter, clearer pipeline configuration
Most user-driven errors inionworkspipeline now raise
UserConfigurationError (a ValueError subclass) instead of bare
ValueError / KeyError, so configuration mistakes — wrong field
types, out-of-range values, missing keys — are routed to a clear
Configuration error for the user instead of paging on-call as an
internal error. Alongside this, an in-progress schema-contract
hardening effort began validating optimizer configs at the boundary:
passing SciPy-only keys to a native optimizer (e.g.
DifferentialEvolution(popsize=5, maxiter=10)) now hard-errors at
submission time instead of being silently swallowed.Pipeline
Pipeline
Improvements
- A single calculation structure —
dict[str, list[str] | None]mapping each objective to the variables to compute — is now the source of truth for objective- and variable-level cost scoping, replacing the per-costobjective_nameslist. This lets a weightedWasserstein(position-shifting dQ/dV) and a per-variableSSEshare oneMultiCostover an objective, with each cost explicitly scoped to the variables it should consume.ElectrodeBalancinggained adQdU model axisoption that emits dQ/dV on the model’s own full-window voltage axis so a weighted Wasserstein can align peaks in voltage rather than on the data grid. - Strict optimizer-option validation: unknown
algorithm_optionskeys (and method/options mismatches) are rejected at submission time, andAskTellOptimizerrejects unknown constructor kwargs at runtime with an actionable message — the previous behaviour silently ignored them. The typed option wrappers (CMAESOptions,PSOOptions,DEOptions,XNESOptions,BayesianOptimizationOptions,SOBEROptions,TuRBOOptions) remain the recommended way to pass options. - Failure sentinels across the cost and design spaces are unified
into a single
FAILURE_PENALTYconstant, so the fitting and design-optimization paths can no longer drift apart and the penalty value is better-conditioned for surrogate-GP fits.
- ECM coulomb-count capacity reference is now computed per segment. Multi-measurement fits previously accumulated the cumulative integral across concatenated segment boundaries, inflating the capacity estimate to roughly the sum of per-segment throughputs and triggering spurious capacity-sanity-check warnings.
- A
geometrypassed throughsimulation_kwargswith symbolic bounds (e.g. apybamm.Scalarmin and apybamm.Parametermax) is now deserialised back into pybamm objects before the simulation is built, instead of arriving as raw JSON and choking the solver. parse_modelnow honours serialisedgeometry,var_pts,spatial_methods, andsubmesh_typesfor custom models, attaching them as per-instance defaults instead of letting pybamm rebuild geometry frommodel.options.
Python API
Python API
Improvements
client.model.download/serialize(introduced above) return ionworks-defined models in a plain-pybamm-loadable form.client.urls(introduced above) now builds links for every routed resource, environment-aware.