Skip to main content
June 1, 2026
Ionworks solver replaces IDAKLU as the default, structured error details on failed pipelines and optimizations, Wasserstein weighted mode and MSMRFullCell dQ/dU output

Ionworks solver

A new IonworksSolver is now the default solver inside ionworkspipeline.Simulation. It is a drop-in replacement for pybamm.IDAKLUSolver that detects DAE structural properties (quadrature, linear-constant / linear-varying, block-constant / block-varying) and substitutes exact analytical solutions where the structure allows, falling back to IDAKLU for non-analytical models. Runtime C codegen via CasADi’s CodeGenerator plus Numba-JIT integration kernels reduce per-step cost on the analytical paths. Piecewise interpolation now also accepts smoothing=0 so a hard step function can be modelled directly.

Structured error details on failed pipelines and optimizations

Pipeline element and optimization failures now carry a structured error_detail with the exception type and a Sentry deep-link. Two new job error codes — CONFIGURATION_ERROR and SOLVER_ERROR — separate user-fixable config mistakes from solver-side failures. Inside the pipeline package, FuzzyDict / ParameterStore raise the new ParameterNotFoundError (instead of bare KeyError) and ConfigurationError distinguishes invalid configs from runtime errors, so the classifier attaches the right code. In Studio, failed optimizations now show a View in Sentry button (superadmin only) that opens the captured event directly; the exception message itself is stripped before serialization so user-visible diagnostics stay safe to share.

Wasserstein weighted-point-cloud mode and MSMRFullCell dQ/dU output

iws.costs.Wasserstein / iwp.costs.Wasserstein gain optional position_variable and weight_variable fields. When both are set, the cost computes one Wasserstein-1 distance per objective comparing two weighted point clouds — useful for full-cell MSMR fits where peak-location error in Voltage [V] should be measured by the |dQ/dV| weights instead of sample-by-sample. MSMRFullCell also now emits Differential capacity [Ah/V] when listed in objective variables, derived from Full voltage [V] / Full capacity [A.h] and interpolated to the data voltage grid.

Pipelines documentation moved to schema-first Docs section

The runnable “how do I actually run this” pipelines content has moved out of the Guide into a new schema-first Pipelines section under the Documentation tab, with every code sample rewritten to use ionworks-schema + ionworks-api. The Guide retains the theory — equations, parameter tables, intuition — and its existing “Pipelines” group is renamed to Parameterization. The Japanese tab mirrors the new section.
Fixes
  • Project-scoped ECM fitting from existing measurements no longer returns 422: the frontend now sends the nested {measurements: [{id, initial_soc?}], ecm_options: {...}} payload the backend has expected since the per-measurement SOC change, and shows a per-measurement initial-SOC input next to each selected measurement.
Improvements
  • client.simulation.protocol(...) accepts design_parameters again as a flat dict — the single-simulation convenience that was accidentally removed when the protocol-template flow landed. Supplying both design_parameters and design_parameters_doe, or a DOE that expands to more than one simulation, now raises explicitly instead of silently billing for the extra runs.
  • BioLogic .mps protocols with large embedded drive-cycle tables (e.g. ~96k-row Urban Profile traces inlined as YAML block scalars) no longer time out at the edge proxy on /protocols/parse-to-template — the modified YAML is no longer re-parsed with the slow PyYAML path.
  • iws.direct_entries.DirectEntry accepts a pybamm.ParameterValues directly. Callable values (concentration- / temperature-dependent interpolants) are serialized to symbol-JSON via ParameterValues.to_json() automatically, and the in-pipeline DirectEntry.from_schema path deserializes them back into pybamm symbols so local and API consumption paths behave the same.
Fixes
  • Child-module loggers under ionworkspipeline.* (e.g. ionworkspipeline.data_fits.*) are now governed by set_logging_level — the package logger was previously a sibling rather than the parent, so submodule records propagated past it.
Improvements
  • client.simple_pipeline.create(...) accepts a PipelineOptions (e.g. live_progress_updates=False) — the worker already honoured pipeline_options in job params, this wires the request model, service layer, and SDK client through.
Fixes
  • Outbound JSON payloads no longer raise TypeError when a request body contains a pandas DataFrame with datetime columns. pd.Timestamp is serialized via isoformat() and pd.NaT becomes null.
Fixes
  • BioLogic .mps parser no longer hangs on protocols like lfp_gr_cccv.mps where lim*_seq stores an internal sub-cycle pointer ≤ Ns+1. Only forward jumps (seq > Ns+1) emit gotos; backward or equal values are treated as plain step-ends.
Improvements
  • Ionworks skills can now be installed as a Gemini CLI extension via gemini extensions install ~/ionworks-skills; a GEMINI.md context file loads all eight skills as passive context on every session. The Coding agents docs page is updated to cover Gemini CLI, Cursor, and GitHub Copilot install paths alongside Codex and Claude Code.
  • New half-cell MSMR template (assets/half_cell_msmr_template.py) plus discover_half_cell.py, inspect_half_cell_data.py, and validate_half_cell_fit.py helpers in the parameterize skill. The reference page mandates the template and lays out a discover → inspect → scaffold → dry-run → submit → validate workflow so every half-cell OCP fit uses the same canonical priors, multistarts, and Xj method.
Fixes
  • The process-data skill now documents the platform’s actual current sign convention (positive = discharge), matches the validator and set_positive_current_for_discharge transform, and calls out the double-flip trap.