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

# Optimization Templates

> Pre-configured Design and Charge templates with parameters, objectives, and constraints for cell design and fast-charging optimization

# Optimization Templates

Optimization templates provide pre-configured starting points for common optimization scenarios. Each template defines default parameters, objectives, experiments, and constraints that you can customize for your specific needs.

## Template types

Ionworks Studio has two types of optimization templates:

* **System templates** — Built-in templates (Design, Charge) provided by Ionworks. These are read-only and available in every project.
* **Project templates** — Templates you create within a specific project. These are only visible to members of that project and can be fully edited or deleted.

When you open the optimization templates page for a project, you see both system templates and any project-specific templates. The **Type** column indicates whether a template is "System" or "Project".

## Available system templates

### Design Template

The **Design** template is optimized for cell design optimization, where you want to find optimal geometric and material parameters for your battery cell.

**Default Configuration:**

* **Objectives:** Maximize capacity or energy density
* **Parameters:** Electrode thicknesses, porosities, particle sizes
* **Constraints:** Manufacturing limits, safety requirements

**Typical Use Cases:**

* Optimizing electrode thickness ratios for a target application
* Balancing energy density vs. power capability
* Finding optimal particle sizes for rate capability

### Charge Template

The **Charge** template is designed for charging protocol optimization, where you want to find optimal current profiles to minimize charge time while respecting safety constraints.

**Default Configuration:**

* **Objectives:** Minimize total charge time (uses the `Last` metric on `Time [s]` to capture the final simulation time)
* **Parameters:** Two charging currents (`I_charge_0`, `I_charge_1`) bounded between 0.1–10 A
* **Experiment:** Two CC steps followed by a CV hold to 4.20 V (`C-rate < 0.05`), starting from 0% SOC
* **Constraints:** Minimum negative-electrode surface potential difference at the separator interface > 0 V (to avoid lithium plating)

**Typical Use Cases:**

* Multi-step constant current (MSCC) charging optimization
* Fast charging protocol design
* Balancing charge speed vs. battery health

<Note>
  The Charge template was simplified from six CC steps to two CC + CV. If you
  need finer-grained control (more CC stages, different cut-off voltages), copy
  the template into your project and add steps to the experiment as
  [described below](#customizing-templates).
</Note>

## Template Structure

Each optimization template consists of:

### Parameters Section

Defines which model parameters will be optimized:

```json theme={null}
{
  "parameters": {
    "I_charge_1": {
      "bounds": [-5.0, -0.5],
      "initial_value": -2.0
    },
    "I_charge_2": {
      "bounds": [-5.0, -0.5],
      "initial_value": -1.5
    }
  }
}
```

* **bounds**: \[min, max] range for the parameter
* **initial\_value**: Starting point for optimization

<Note>
  For charging currents, PyBaMM uses **negative values for charging** (positive
  \= discharging). So a charge current of -2.0 A means charging at 2.0 A.
</Note>

### Objectives Section

Defines the experiments to run and what to optimize:

```json theme={null}
{
  "objectives": {
    "charge_objective": {
      "experiment": "...",
      "metrics": {
        "charge_time": {
          "action": "Minimize",
          "weight": 1.0,
          "metric": {
            "type": "Time",
            "variable": "Time [s]",
            "value": -1
          }
        }
      },
      "constraints": {
        "anode_potential": {
          "action": "GreaterThan",
          "penalty": 1000000,
          "metric": {
            "type": "Minimum",
            "variable": "Anode potential [V]"
          },
          "value": 0
        }
      }
    }
  }
}
```

### Experiment Definition

Experiments are defined using [UCP format](/simulate/universal-cycler-protocol). Templates use `Input["parameter_name"]` syntax to reference optimizable parameters:

```yaml theme={null}
- CC Charge Step 1:
    - Charge:
        mode: Current
        value: Input["I_charge_1"]
        ends:
          - "Voltage > 4.0"
- CC Charge Step 2:
    - Charge:
        mode: Current
        value: Input["I_charge_2"]
        ends:
          - "Voltage > 4.2"
- CV Hold:
    - Charge:
        mode: Voltage
        value: 4.2
        ends:
          - "C-rate < 0.05"
```

## Custom Variables

Templates can define **custom variables** - derived quantities computed from simulation outputs using PyBaMM expressions. These are useful when you want to optimize based on quantities that aren't directly available as model outputs.

### Creating Custom Variables

Custom variables are defined per-objective with:

* **Name**: A descriptive name for the variable
* **Expression**: A PyBaMM expression string

**Example expressions:**

```python theme={null}
# Specific energy (Wh/kg)
pybamm.Variable("Energy [Wh]") / pybamm.Parameter("Cell mass [kg]")

# Anode surface potential difference
pybamm.CoupledVariable("Negative electrode surface potential difference [V]")
```

<Tip>
  Custom variables become available in the variable dropdown for goals and
  constraints, alongside model variables like "Voltage \[V]" and "Current \[A]".
</Tip>

## Metric Types

Templates use various metric types to extract values from simulation results:

### Aggregation Metrics

These compute a single value from a time series:

| Type           | Description                                                                        |
| -------------- | ---------------------------------------------------------------------------------- |
| **Maximum**    | Highest value during simulation                                                    |
| **Minimum**    | Lowest value during simulation                                                     |
| **Mean**       | Time-averaged value                                                                |
| **Sum**        | Accumulated total                                                                  |
| **Last**       | Final value of the variable (e.g., final `Time [s]` for total experiment duration) |
| **PointBased** | For values that don't change (e.g., cell properties)                               |

### Crossing Metrics

These evaluate the variable at a specific point:

| Type        | Value Field              | Description                                                                                        |
| ----------- | ------------------------ | -------------------------------------------------------------------------------------------------- |
| **Time**    | Seconds (scalar or list) | Value at specified time (-1 for end). Accepts a list of times to read multiple points in one call. |
| **SOC**     | 0-1                      | Value when reaching specified SOC                                                                  |
| **Voltage** | Volts                    | Value when reaching specified voltage                                                              |

**Example: Time to 80% SOC**

```json theme={null}
{
  "type": "SOC",
  "variable": "Time [s]",
  "value": 0.8
}
```

**Example: Voltage sampled at multiple times**

Pass a list of times to the `Time` metric to read the variable at each time in a single evaluation. The metric returns one value per time, in order.

```json theme={null}
{
  "type": "Time",
  "variable": "Voltage [V]",
  "value": [60, 300, 600, -1]
}
```

<Note>
  The vector form of the `Time` metric is intended for continuous, experiment-free
  solves where there are no per-cycle or per-step sub-solutions to slice. It is
  not supported inside a `DesignObjective` — use a scalar `value` there, or wrap
  the metric in a `StepwiseMetric` / `CyclewiseMetric` to target specific
  segments.
</Note>

### Iterative metrics (per-cycle and per-step)

Use **iterative metrics** when you need to evaluate a goal or constraint on a specific subset of cycles or steps inside a multi-cycle experiment, rather than over the whole simulation. They wrap any aggregation or crossing metric and tell the optimizer to apply it to the chosen indices only.

There are two wrapper types:

| Wrapper                           | Apply the inner metric to…                                                  | Configuration                                                            |
| --------------------------------- | --------------------------------------------------------------------------- | ------------------------------------------------------------------------ |
| **Per Cycle** (`CyclewiseMetric`) | Selected cycle indices, optionally restricted to one step within each cycle | `cycles` (list of cycle indices) and optional `step` (single step index) |
| **Per Step** (`StepwiseMetric`)   | Selected absolute step indices in the flattened experiment                  | `steps` (list of step indices)                                           |

In the optimization form, toggle **Evaluate per step/cycle** under any goal or constraint, then choose **Per Cycle** or **Per Step**:

* **Per Cycle** exposes a **Step** field (step index within each cycle) and a **Cycles** field that takes a comma-separated list of cycle indices, e.g. `0, 2, 4`.
* **Per Step** exposes a **Steps** field that takes a comma-separated list of absolute step indices, e.g. `0, 1, 2`.

All indices are 0-based. Studio displays the experiment's available bounds (total cycles, steps per cycle, total steps) inline and flags out-of-range indices before you submit.

**Example: minimum anode potential during the high-rate charge step of cycles 0, 5, and 10**

```json theme={null}
{
  "type": "CyclewiseMetric",
  "cycles": [0, 5, 10],
  "step": 1,
  "metric": {
    "type": "Minimum",
    "variable": "Negative electrode surface potential difference at separator interface [V]"
  }
}
```

**Example: time to reach 4.2 V on the second step**

```json theme={null}
{
  "type": "StepwiseMetric",
  "steps": [1],
  "metric": {
    "type": "Voltage",
    "variable": "Time [s]",
    "value": 4.2
  }
}
```

<Tip>
  Crossing metrics (`Time`, `SOC`, `Voltage`) almost always need to be wrapped
  in a `StepwiseMetric` or `CyclewiseMetric` so the crossing search runs on the
  intended segment of the simulation. Studio enables the wrapper toggle
  automatically for crossing metrics.
</Tip>

<Warning>
  The optimizer validates wrapper indices against the experiment before
  submitting. Cycle or step indices outside the experiment's range produce a
  validation error such as *"Metric 'no\_plating': cycle index 49 is out of
  range. Experiment has 30 cycle(s) (0–29)."* Update the experiment or the
  indices to fit within bounds.
</Warning>

## Customizing templates

When you select a template, all values are pre-filled but fully editable:

1. **Modify Parameters** - Add/remove parameters, adjust bounds
2. **Edit Objectives** - Change the experiment protocol, add/remove goals
3. **Adjust Constraints** - Modify constraint thresholds and penalties
4. **Add Custom Variables** - Create derived quantities for your specific needs
5. **Configure Algorithm** - Set multistarts and max iterations

<Info>
  Templates provide a starting point — you're encouraged to customize them for
  your specific cell chemistry, form factor, and optimization goals.
</Info>

## Saving an optimization as a template

Once you've tuned an optimization's parameters, objectives, and constraints to a configuration you want to reuse, you can save it as a new project template directly from the optimizations list — no need to rebuild the form by hand.

To save an optimization as a template:

1. Open the **Optimizations** list in your project.
2. Click the three-dot menu on the row of the optimization you want to reuse.
3. Select **Save as template**.
4. In the dialog, enter a **Template Name** (required) and an optional description.
5. Click **Save Template**.

Studio creates a new project-level template, copies the optimization's saved configuration into it verbatim, and navigates you to the template's detail page so you can rename it, edit it, or kick off a new optimization from it.

<Note>
  The optimization's saved configuration and a template's `initial_form_data`
  share the same schema, so settings like `validate_against_experiment_steps`,
  iterative metric wrappers, and custom variables are preserved exactly. The
  template stays in sync with what the optimization actually ran — not a
  re-derived form view of it.
</Note>

<Warning>
  Template names must be unique within a project. If a template with the same
  name already exists, the save fails — pick a different name and retry.
</Warning>

You can only save as a template when the source optimization has a valid saved configuration. Optimizations that were created without a complete config (e.g. partially imported drafts) cannot be turned into templates; rerun the optimization with a valid configuration first.

## Copying templates between projects

You can copy any template — including system templates — into another project in your organization. This is useful when you want to reuse a template configuration across multiple projects or create a project-specific version of a system template that you can then customize.

To copy a template:

1. Open the optimization templates list in your project
2. Click the three-dot menu on the template you want to copy
3. Select **Copy to project**
4. Choose the target project from the dialog
5. Click **Copy**

The copied template appears in the target project as a new project template that you can edit independently.

<Note>
  Template names must be unique within a project. If the target project already
  has a template with the same name, the copy will fail. Rename the conflicting
  template in the target project first to free up the name, then retry the copy.
</Note>

## Template permissions

Template permissions are managed at the project level:

| Action           | Required project role         |
| ---------------- | ----------------------------- |
| View templates   | Viewer, Contributor, or Admin |
| Create templates | Contributor or Admin          |
| Edit templates   | Contributor or Admin          |
| Delete templates | Admin                         |

<Info>
  System templates are read-only for all users. To modify a system template,
  copy it to your project first — the copy becomes a fully editable project
  template.
</Info>

## Next steps

* Follow the [Running an Optimization](/optimize/running-optimization) guide for step-by-step instructions
* Review [Simulation documentation](/simulate/simulations) to understand the underlying simulation process
