> ## Documentation Index
> Fetch the complete documentation index at: https://docs.ionworks.com/llms.txt
> Use this file to discover all available pages before exploring further.

# 2026 06 22

<Update label="June 22, 2026" description="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 only `ionworks-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's `client.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 in `ionworkspipeline` 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.

  <AccordionGroup>
    <Accordion title="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-cost
        `objective_names` list. This lets a weighted `Wasserstein`
        (position-shifting dQ/dV) and a per-variable `SSE` share one
        `MultiCost` over an objective, with each cost explicitly scoped to
        the variables it should consume. `ElectrodeBalancing` gained a
        `dQdU model axis` option 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_options`
        keys (and method/options mismatches) are rejected at submission
        time, and `AskTellOptimizer` rejects 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_PENALTY` constant, so the fitting and
        design-optimization paths can no longer drift apart and the
        penalty value is better-conditioned for surrogate-GP fits.

      **Fixes**

      * 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 `geometry` passed through `simulation_kwargs` with symbolic
        bounds (e.g. a `pybamm.Scalar` min and a `pybamm.Parameter` max)
        is now deserialised back into pybamm objects before the simulation
        is built, instead of arriving as raw JSON and choking the solver.
      * `parse_model` now honours serialised `geometry`, `var_pts`,
        `spatial_methods`, and `submesh_types` for custom models, attaching
        them as per-instance defaults instead of letting pybamm rebuild
        geometry from `model.options`.
    </Accordion>

    <Accordion title="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.
    </Accordion>
  </AccordionGroup>
</Update>
