Skip to main content

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.

The ionworks-api Python package lets you run simulations and submit parameterization pipelines programmatically. For installation and authentication, see the Python API client page.

Running simulations

Use client.simulation to run simulations. A simulation requires a parameterized model and a protocol in UCP format.

Single simulation

response = client.simulation.protocol({
    "parameterized_model": "your-parameterized-model-id",
    "protocol_experiment": {
        "protocol": """
global:
  initial_soc: 1
  temperature: 25
steps:
  - direction: Discharge
    mode: C-rate
    value: 1
    ends:
      - variable: Voltage [V]
        value: 2.5
""",
        "name": "1C Discharge",
    },
})

print(f"Simulation ID: {response.simulation_id}")
print(f"Job ID: {response.job_id}")
You can also pass experiment parameters and design parameters:
response = client.simulation.protocol({
    "parameterized_model": "your-parameterized-model-id",
    "protocol_experiment": {
        "protocol": """
global:
  initial_soc: input["Initial SOC"]
steps:
  - direction: Discharge
    mode: C-rate
    value: input["C-rate"]
    ends:
      - variable: Voltage [V]
        value: 2.5
""",
        "name": "Parameterized Discharge",
    },
    "experiment_parameters": {
        "Initial SOC": 1.0,
        "C-rate": 0.5,
    },
    "design_parameters": {
        "Positive electrode thickness [m]": 75e-6,
    },
})

Waiting for results

Use wait_for_completion to poll until the simulation finishes. The method detects failed and canceled jobs immediately rather than waiting for the timeout.
result = client.simulation.wait_for_completion(
    response.simulation_id,
    timeout=120,        # seconds (default: 60)
    poll_interval=2,    # seconds between polls (default: 2)
    verbose=True,       # print status updates (default: True)
)
Set raise_on_failure=False to get the result dict instead of raising an exception when a simulation fails:
result = client.simulation.wait_for_completion(
    response.simulation_id,
    raise_on_failure=False,
)

Batch simulations with design of experiments

Run multiple simulations across a parameter sweep using protocol_batch:
responses = client.simulation.protocol_batch({
    "parameterized_model": "your-parameterized-model-id",
    "protocol_experiment": {
        "protocol": "...",
        "name": "C-rate Sweep",
    },
    "design_parameters_doe": {
        "sampling": "grid",
        "rows": [
            {
                "type": "discrete",
                "name": "Positive electrode thickness [m]",
                "values": [50e-6, 75e-6, 100e-6],
            },
        ],
    },
})

# Wait for all simulations
results = client.simulation.wait_for_completion(
    [r.simulation_id for r in responses],
    timeout=300,
)
Supported DOE row types:
TypeFieldsDescription
discretevaluesSpecific values to test
rangemin, max, countEvenly spaced values between min and max
normalmean, std, countValues sampled around the mean
Sampling strategies: grid (all combinations), random, latin_hypercube.

Retrieving simulation data

# List all simulations
simulations = client.simulation.list()

# Get a specific simulation
simulation = client.simulation.get(simulation_id)

# Get result data (time series, steps, metrics)
result = client.simulation.get_result(simulation_id)

Running pipelines

Pipelines combine data fitting, calculations, and validation steps for battery model parameterization. Use client.pipeline to submit and manage pipelines.
Pipelines require a project_id. You can pass it in the config or set the PROJECT_ID environment variable.

Submitting a pipeline

pipeline = client.pipeline.create({
    "project_id": "your-project-id",
    "name": "NMC622 Parameterization",
    "elements": {
        "entry": {
            "element_type": "entry",
            "values": {
                "model": {"type": "SPM"},
                "data": "db:your-measurement-id",
            },
        },
        "data_fit": {
            "element_type": "data_fit",
            "objectives": {"voltage": {"data": "entry.data"}},
            "parameters": {
                "Negative electrode diffusivity [m2.s-1]": {
                    "bounds": [1e-16, 1e-12],
                    "initial_value": 3.3e-14,
                }
            },
        },
    },
})

print(f"Pipeline ID: {pipeline.id}")
print(f"Status: {pipeline.status}")
Pipeline elements must be a dictionary (not a list). Each key is the element name and the value is its configuration.

Waiting for pipeline completion

result = client.pipeline.wait_for_completion(
    pipeline.id,
    timeout=600,        # seconds (default: 600)
    poll_interval=2,    # seconds between polls (default: 2)
    verbose=True,
)

print(f"Final status: {result.status}")

Getting pipeline results

pipeline_result = client.pipeline.result(pipeline.id)

# Access fitted parameter values
for name, element in pipeline_result.element_results.items():
    print(f"{name}: {element}")

Data references in pipelines

Use these prefixes to reference data sources in pipeline configs:
PrefixExampleDescription
db:"db:measurement-id"Reference an uploaded measurement by ID
file:"file:data.csv"Load a local CSV file
folder:"folder:data_dir/"Load from a local directory
For inline DataFrames in pipeline configs, there is a 1,000-row limit. Upload larger datasets as measurements first, then reference them with db:measurement-id.

PyBaMM model support

Pipeline configs accept PyBaMM model objects directly. The client auto-serializes them before sending:
import pybamm

pipeline = client.pipeline.create({
    "project_id": "your-project-id",
    "elements": {
        "entry": {
            "element_type": "entry",
            "values": {
                "model": pybamm.lithium_ion.SPM(),
            },
        },
    },
})

Managing studies

Use client.study to create, list, update, and delete studies. Studies are scoped to a project.

Listing studies

# List studies in a project
studies = client.study.list("your-project-id")
for study in studies:
    print(f"{study.name} (ID: {study.id})")

# Filter by name
studies = client.study.list("your-project-id", name="Discharge")

# Paginate results
studies = client.study.list("your-project-id", limit=10, offset=0)
Supported filters: name, name_exact, order_by, order.

Getting a study

study = client.study.get("your-project-id", "your-study-id")

Creating a study

study = client.study.create("your-project-id", {
    "name": "1C Discharge Sweep",
    "description": "Comparing discharge curves across temperatures",
})

Updating a study

study = client.study.update("your-project-id", "your-study-id", {
    "name": "1C Discharge Sweep v2",
})

Assigning simulations and measurements

# Assign a simulation to a study
client.study.assign_simulation("your-project-id", "your-study-id", "simulation-id")

# Remove a simulation from a study
client.study.remove_simulation("your-project-id", "your-study-id", "simulation-id")

# Assign a measurement to a study
client.study.assign_measurement("your-project-id", "your-study-id", "measurement-id")

# List measurements in a study
measurements = client.study.list_measurements("your-project-id", "your-study-id")

# Remove a measurement from a study
client.study.remove_measurement("your-project-id", "your-study-id", "measurement-id")

Deleting a study

client.study.delete("your-project-id", "your-study-id")

Managing protocols

Use client.protocol to validate UCP protocols.

Validating a protocol

result = client.protocol.validate("""
global:
  initial_soc: 1
  temperature: 25
steps:
  - direction: Discharge
    mode: C-rate
    value: 1
    ends:
      - variable: Voltage [V]
        value: 2.5
""")
print(result["valid"])  # True or False
if not result["valid"]:
    print(result["error"])

Finding input references

Find input[...] placeholders in a protocol string, useful for building experiment parameter forms.
refs = client.protocol.find_input_references("""
global:
  initial_soc: input["Initial SOC"]
steps:
  - direction: Discharge
    mode: C-rate
    value: input["C-rate"]
""")
print(refs)  # ["Initial SOC", "C-rate"]
You can find the ID for any resource from the Ionworks Studio web app. The ID is displayed in the URL when you navigate to a resource’s detail page.

Next steps

Simulations

Learn about running simulations in Ionworks Studio.

Protocol reference

Full reference for the Universal Cycler Protocol format.

Uploading data

Upload and manage cell data via the Python API.

Build API

List and retrieve models and parameterized models.