> ## 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.

# Introduction to Pipelines

> Chain DirectEntry, Calculation, DataFit, and Validation elements to transform battery parameters and fit models to experimental data.

Battery parameterization is built around a simple abstraction: **pipeline elements** that transform input parameters into output parameters, chained together into a **pipeline**. This design provides flexibility to handle any parameterization workflow—from simple calculations to complex data fitting.

## Pipeline Elements

The basic building block is a pipeline element. Any pipeline element accepts a set of parameter values (possibly empty) and returns another set of parameter values. The full pipeline is built by calling each element in series to yield the complete parameter set.

There are five types of pipeline element:

| Type             | Description                                                                                                                                       |
| ---------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- |
| **DirectEntry**  | The simplest type—ignores input parameters and returns pre-defined values (e.g., from literature or direct measurements)                          |
| **Calculation**  | Computes new parameters based on provided inputs (e.g., calculating maximum particle concentration from capacity, volume fraction, and thickness) |
| **DataFit**      | Estimates parameters by fitting a model to experimental data                                                                                      |
| **ArrayDataFit** | Fits the same model separately at each value of an independent variable (e.g., a separate fit per temperature or per pulse SOC)                   |
| **Validation**   | Checks fitted parameters against held-out data                                                                                                    |

<Note>
  The pipeline element types and built-in calculations listed here are not exhaustive. See the [API reference](https://pipeline.docs.ionworks.com/source/api/index.html) for full details.
</Note>

```python theme={null}
import ionworkspipeline as iwp

pipeline = iwp.Pipeline([
    iwp.calculations.Capacity("Positive"),
    iwp.calculations.Capacity("Negative"),
    iwp.calculations.CyclableLithium(),
    iwp.calculations.ElectrodeSOH(),
])

result = pipeline.run(parameter_values)
```

Each element:

1. Takes input parameters from the parameter dictionary
2. Performs computation
3. Returns output parameters that become available to subsequent elements

<Note>
  To assemble and submit a pipeline programmatically, see [Pipelines → Overview](/pipelines/overview) in the Documentation tab.
</Note>

## Naming conventions

<CardGroup cols={2}>
  <Card title="Clear Naming" icon="tag">
    Use descriptive parameter names with units: `"Electrode capacity [A.h]"` not `"cap"`
  </Card>

  <Card title="Unit Consistency" icon="scale-balanced">
    Be explicit about unit conversions; use SI units internally
  </Card>
</CardGroup>

## Built-in Calculations

<CardGroup cols={2}>
  <Card title="Geometry & Capacity" icon="shapes" href="/guide/calculations/geometry-capacity">
    Electrode geometry, mass, capacity, cyclable lithium, and microstructure
  </Card>

  <Card title="Thermal Properties" icon="fire" href="/guide/calculations/thermal">
    Heat capacity, Arrhenius temperature dependence, and thermal modeling
  </Card>

  <Card title="Piecewise Interpolants" icon="stairs" href="/guide/calculations/piecewise">
    Smooth piecewise functions for SOC and temperature-dependent parameters
  </Card>
</CardGroup>

## Handling pipeline failures

Pipeline elements run sequentially. When an element fails, the pipeline reports an error and any downstream elements stop. The cause is recorded on the element as an `error_code`:

| `error_code`        | Meaning                                                                                                         |
| ------------------- | --------------------------------------------------------------------------------------------------------------- |
| `SUBMISSION_FAILED` | The element could not be submitted to a worker (for example, transient infrastructure issue). Safe to resubmit. |
| `EXECUTION_TIMEOUT` | The element exceeded its execution time limit. Adjust the configuration before retrying.                        |
| `INTERNAL_ERROR`    | An unexpected server-side error occurred while running the element.                                             |

### Resubmitting a failed pipeline

If the first failed element has `error_code = SUBMISSION_FAILED`, you can resubmit the pipeline. Resubmission resets that element and continues execution from where the pipeline stopped — completed elements are not re-run.

<Tabs>
  <Tab title="Studio">
    Open the pipeline detail page. When the lead failure is a submission error, a **Resubmit** button appears on the failed-element alert at the top of the page. Click it to retry the pipeline in place.
  </Tab>

  <Tab title="REST API">
    Resubmission goes through the generic jobs endpoint, and a pipeline is identified by its job ID (the same ID you pass to `client.pipeline.get(...)`):

    ```bash theme={null}
    curl -X POST \
      -H "Authorization: Bearer $IONWORKS_API_KEY" \
      https://api.ionworks.com/jobs/{pipeline_id}/resubmit
    ```

    The response is the updated pipeline with its elements. The endpoint returns `400` if the first failed element is not in a `SUBMISSION_FAILED` state, and `404` if the pipeline does not exist. See the API Reference for the full schema.
  </Tab>
</Tabs>

For failures with other error codes (timeouts, internal errors, or configuration issues), create a new pipeline with the corrected configuration instead of resubmitting.

## Data Fitting

The pipeline abstraction also powers **data fitting**—estimating unknown parameters by comparing model predictions to experimental data. A `DataFit` element wraps a pipeline with an optimization loop:

* The optimizer proposes parameter values
* The pipeline runs the model with those values
* The objective computes how well predictions match data
* This repeats until the best-fit parameters are found

<CardGroup cols={2}>
  <Card title="Data Fitting (theory)" icon="chart-line" href="/guide/data-fitting/overview">
    Cost functions, identifiability, regularization, and other theory.
  </Card>

  <Card title="Data Fitting (how-to)" icon="code" href="/pipelines/data-fitting/overview">
    Configure and submit data fits with `ionworks-schema` + `ionworks-api`.
  </Card>
</CardGroup>

## Pipeline errors

When a pipeline element fails, Studio shows the element in a **Failed** state with an error message and a machine-readable **error code**. Hover the status chip in any pipeline list to see the code, and expand the failed element to read the full message.

The same fields are returned by the API on failed jobs and pipeline elements:

```json theme={null}
{
  "status": "FAILED",
  "error": "'Negative electrode loading [A.h.cm-2]' not found. Best matches are [...]",
  "error_code": "CONFIGURATION_ERROR",
  "error_detail": {
    "exception_type": "ParameterNotFoundError"
  }
}
```

### Error codes

Use the `error_code` field to branch on failure type without parsing error strings:

| Code                  | When it's raised                                                                                                                                                                                                                                                                                                                                                                                                                                                                     | What to do                                                                                         |
| --------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | -------------------------------------------------------------------------------------------------- |
| `CONFIGURATION_ERROR` | A pipeline or element is misconfigured — for example, a required parameter is missing, a value is out of range, or a field has the wrong type. Includes `ParameterNotFoundError` from a `ParameterValues` lookup, `UserConfigurationError` raised by pipeline/data-fit parsing, and `ProtocolConfigurationError` raised by the UCP protocol engine (malformed step, unknown end-condition type, missing drive cycle, unresolved `goto` target, initial SOC out of `[0, 100]`, etc.). | Fix the pipeline configuration or input parameters. The `error` message names the offending field. |
| `SOLVER_ERROR`        | The numerical solver failed to converge (e.g., voltage cut-off violated, integration failure during a simulation).                                                                                                                                                                                                                                                                                                                                                                   | Check the operating protocol, initial conditions, and parameter values for physical consistency.   |
| `EXECUTION_TIMEOUT`   | The job exceeded its allowed wall-clock time.                                                                                                                                                                                                                                                                                                                                                                                                                                        | Reduce problem size, simplify the model, or split the run.                                         |
| `SUBMISSION_FAILED`   | The job could not be submitted to the compute backend.                                                                                                                                                                                                                                                                                                                                                                                                                               | Retry the job. Contact support if it persists.                                                     |
| `INTERNAL_ERROR`      | An unexpected error inside the platform. The raw exception message is intentionally sanitised.                                                                                                                                                                                                                                                                                                                                                                                       | Retry the job. Contact support if it persists.                                                     |

### Catching configuration errors in Python

The `ionworkspipeline` package exposes `ParameterNotFoundError` so you can catch missing-parameter failures without inspecting tracebacks or message strings. It subclasses `KeyError`, so existing `except KeyError` handlers continue to work.

```python theme={null}
import ionworkspipeline as iwp

try:
    pipeline.run(parameter_values)
except iwp.ParameterNotFoundError as err:
    print(f"Missing parameter: {err}")
```

`ParameterNotFoundError` subclasses `KeyError` and carries no custom attributes. The message — available via `str(err)` or `err.args[0]` — is the full text produced by pybamm's parameter lookup, e.g. `"'Negative electrode loading [A.h.cm-2]' not found. Best matches are [...]"`. It names the missing key and suggests close matches, which is useful when building diagnostic UIs or auto-correcting parameter sets.

The other configuration error raised by pipeline/data-fit parsing, `UserConfigurationError`, is **not** re-exported at the package root — only `ParameterNotFoundError` is. Import it from the submodule when you need to catch it directly: `from ionworkspipeline.exceptions import UserConfigurationError`. It subclasses `ValueError`, so an `except ValueError` handler also catches it.

When a UCP protocol can't be simulated as written — for example, a drive cycle referenced by name that wasn't supplied, a `goto` target that doesn't resolve, an end-condition string that doesn't parse, an initial SOC outside `[0, 100]`, or an expression that references an uninitialised variable — the failed pipeline element is tagged with the `CONFIGURATION_ERROR` code and its message is surfaced verbatim through the API. This distinguishes a user-correctable protocol issue (fix the protocol, drive cycles, or inputs and retry) from an unexpected internal failure, which is reported as `INTERNAL_ERROR`.
