Skip to content

Breathe Simulate

A class for interacting with the Breathe Simulate API.

download_designs

download_designs(base_battery, designs=[], formats=[], output_tag='', folder='.')

Send the design parameters for a given battery to the API, and get the resulting design, to be used with the Simulink blocks.

Parameters:

Name Type Description Default
base_battery str

The base battery to use to generate the design

required
designs list[str]

The designs for the simulation.

[]
formats list[str]

The formats for the simulation.

[]
output_tag str

A tag to be included in the metadata description.

''
folder str

The folder where design files will be saved. Defaults to current directory.

'.'

Returns: (list[str]): The list of the file paths for the downloaded designs. Raises: BreatheException: description

ensure_logged_in

ensure_logged_in()

Checks if a valid token is available and refreshes it if necessary.

generate_ecm

generate_ecm(base_battery, design=None, **ecm_kwargs)

Generates equivalent circuit model (ECM) parameters for a cell design.

The physics model runs a virtual pulse characterisation over a grid of SoC and temperature operating points and fits an n-RC network to it. The result is a set of look-up tables (R0 and one R/C pair per RC branch) over SoC x temperature x C-rate for both current directions, plus the OCV curves and thermal constants needed to run the ECM — everything derived from the same cell design the physics simulations use.

This is a LONG-RUNNING job at large or default grids. With the queued transport enabled (BD_USE_ASYNC_ENDPOINTS=1) it runs on the asynchronous workers and the call polls until the job completes: there is NO client-side time limit anywhere in the SDK (long-run governance belongs to the platform).

Parameters:

Name Type Description Default
base_battery str

The base battery model to fit the ECM to.

required
design dict

A single run_sim-style design dict (with designName) to fit instead of the unmodified cell. The ageing knobs (lli/lamne/lampe) apply to the fitted physics, so a hand-specified aged state can be characterised directly.

None
**ecm_kwargs

The parameters of :func:breathe_simulate.ecm.ecm_options (n_rc, soc_grid, temp_grid_degC, charge_c_rates, ...). Alternatively pass a prebuilt block as ecm=ecm_options(...) — mutually exclusive with the individual keywords.

{}

Returns:

Type Description
EcmResults

A results handler wrapping the fitted ECM, with

EcmResults

the parameter tables, to_dataframe(), save()/load()

EcmResults

and plot_parameters().

Raises:

Type Description
BreatheException

If the inputs are invalid or the response carries no ECM data.

get_active_materials

get_active_materials()

Gets a list of all acive materials.

Returns:

Type Description
Dataframe

containing the battery active materials.

get_aged_ocv

get_aged_ocv(base_battery, LAMPE=0.0, LAMNE=0.0, LLI=0.0)

Gets the OCV summary table for a base battery.

Parameters:

Name Type Description Default
base_battery str

The base battery model for the design parameters.

required
LAMPE float

The electrolyte loss at positive electrode (PE) side.

0.0
LAMNE float

The electrolyte loss at negative electrode (NE) side.

0.0
LLI float

The loss of lithium inventory.

0.0

Returns:

Type Description
DataFrame

containing the OCV summary table.

get_batteries

get_batteries()

Gets a list of all batteries in your library.

Returns:

Type Description
list[str]

list of the available battery models. Use these strings in subsequent functions for the "base_battery" argument.

get_battery_format

get_battery_format(base_battery)

Gets the battery format for a base battery. These are the form factor and cell casing parameters available for change in the api.

Parameters:

Name Type Description Default
base_battery str

The base battery model for the battery format.

required

Returns:

Type Description
dict

A dictionary containing the battery format. The keys in the dictionary depend on the format shape:

dict

Common keys (all formats):

dict
  • shape (str): The format shape, either "cylinder" or "cuboid"
dict
  • material (str): The material used for the housing
dict
  • housingThickness_mm (float): Housing thickness in millimeters
dict

Cylindrical format keys (when shape == "cylinder"):

dict
  • diameter_mm (float): Outer diameter of the cylinder in millimeters
dict
  • height_mm (float): Height of the cylinder in millimeters
dict
  • innerDiameter_mm (float): Inner diameter of the cylinder in millimeters
dict

Cuboid format keys (when shape == "cuboid"):

dict
  • length_mm (float): Length of the cuboid in millimeters
dict
  • width_mm (float): Width of the cuboid in millimeters
dict
  • thickness_mm (float): Thickness of the cuboid in millimeters
dict
  • assemblyType (str, optional): Type of assembly (e.g., "Stacked", "Wound", "ZFolded")
Example

format = api.get_battery_format("Molicel P45B") if format["shape"] == "cylinder": ... print(f"Diameter: {format['diameter_mm']} mm") ... print(f"Height: {format['height_mm']} mm") elif format["shape"] == "cuboid": ... print(f"Length: {format['length_mm']} mm") ... print(f"Width: {format['width_mm']} mm")

get_design_parameters

get_design_parameters(base_battery)

Gets the design parameters for a base battery.

Parameters:

Name Type Description Default
base_battery str

The base battery model for the design parameters.

required

Returns:

Type Description
dict

containing the design parameters.

get_eqm_kpis

get_eqm_kpis(base_battery, designs=[], formats=[])

Gets the equilibrium kpis for a given base battery, designs, and initial conditions.

Parameters:

Name Type Description Default
base_battery str

The base battery model for the simulation.

required
designs list[dict]

The designs for the simulation.

[]
formats list[dict]

The battery formats for the simulation.

[]

Returns:

Type Description
SingleSimulationResults

A results handler object containing the equilibrium KPIs. Use the plot_sensitivities() method to generate sensitivity plots.

get_ocv

get_ocv(base_battery)

Gets the OCV summary table for a base battery.

Parameters:

Name Type Description Default
base_battery str

The base battery model for the design parameters.

required

Returns:

Type Description
DataFrame

containing the OCV summary table.

get_operating_window

get_operating_window(base_battery)

Gets the operating window of a cell, for both simulation families.

Callable for ANY battery — with or without a degradation model:

  • performance (run_sim): the design's voltage cut-offs (the per-cell hard limits, enforced on every protocol step) and the nominal capacity (the C-rate reference). Currents and temperatures are user inputs to the physics model.
  • degradation (run_ageing_sim): whether ageing simulations are available for this cell at all and, when they are, the degradation calibration's validity window (temperature, voltage, SoC, charge/discharge C-rate limits) — the envelope the model was fitted in and the only range campaigns are accepted in. When the cell has no degradation model, the result says so explicitly (has_degradation_model is False and printing the result shows the reason) rather than the section silently missing.

Parameters:

Name Type Description Default
base_battery str

The battery whose operating window to report.

required

Returns:

Type Description
OperatingWindow

a results handler — print it for the

OperatingWindow

readable summary; .performance / .degradation hold the

OperatingWindow

raw sections, .has_degradation_model the availability flag,

OperatingWindow

and .to_frame() the enforced limits as a tidy table.

get_service_version

get_service_version()

Get the version number of the API

Returns:

Name Type Description
_type_ Version

description

get_updated_format

get_updated_format(base_battery, **kwargs)

Gets the battery format for a base battery and updates it with the additional keywords. These are the form factor and cell casing parameters available for change in the api.

Parameters:

Name Type Description Default
base_battery str

The base battery model for the battery format.

required
**kwargs

Format parameters to update. The available parameters depend on the format shape: - For cylindrical formats: diameter_mm, height_mm, innerDiameter_mm, material, housingThickness_mm - For cuboid formats: length_mm, width_mm, thickness_mm, material, housingThickness_mm - name: Optional name for the updated format - assemblyType: Cannot be changed (raises an error if attempted)

{}

Returns:

Type Description
dict

A dictionary containing the updated battery format. See get_battery_format() for details on the returned dictionary structure.

Raises:

Type Description
BreatheException

If attempting to change assemblyType or if a key is not found in the battery format.

Example

For a cylindrical battery

format = api.get_updated_format( ... "Molicel P45B", ... name="Smaller Cell", ... diameter_mm=20.0, ... height_mm=65.0 ... )

For a cuboid battery

format = api.get_updated_format( ... "SomeCuboidBattery", ... name="Thinner Cell", ... thickness_mm=8.0 ... )

get_valid_assembly_types

get_valid_assembly_types()

Gets a list of valid assembly types for battery formats.

Returns:

Type Description
list[str]

A sorted list of valid assembly type names that can be used when defining cuboid battery formats (e.g., "stacked", "wound", "zFolded").

get_valid_format_materials

get_valid_format_materials()

Gets a list of valid material types for battery formats.

Returns:

Type Description
list[str]

A sorted list of valid material names that can be used when defining battery formats (e.g., "steel", "aluminum", "pouch_foil").

get_virtual_battery

get_virtual_battery(virtual_battery_uuid)

Get the details of a Discover virtual battery by its UUID.

You must have access to a project that the virtual battery belongs to — a project in your own organisation, or a public project, whose design space contains the virtual battery. If no such project is visible to you the call fails (the server returns 404, raised here as a BreatheException), so a virtual battery you cannot reach is not confirmed to exist.

Parameters:

Name Type Description Default
virtual_battery_uuid str

The virtual battery's UUID.

required

Returns:

Type Description
dict

The virtual battery's details, including its

dict

battery_definition, organisation_uuids, is_public,

dict

is_baseline and id.

Example

vb = api.get_virtual_battery("2ef233f6-021d-45e8-8184-46d9b7ed4ce5") vb["battery_definition"]

run_ageing_sim

run_ageing_sim(
    base_battery,
    ageing_cycler,
    rpt_cycler=None,
    max_cycles=200,
    rpt_every_n_cycles=10,
    stop_on_soh_pct=None,
    stop_on_dcir_ohm=None,
    stop_on_energy_throughput_Wh=None,
    stop_on_time_days=None,
    soc_reference="latest_rpt",
    performance_cycler=None,
    performance_start_soc=1.0,
    resume_from=None,
    initialTemperature_degC=25.0,
    ambientTemperature_degC=25.0,
    heatTransferCoefficient=35.0,
    heatCapacity_kJkgK=None,
    isothermal=False,
    return_rpt_timeseries=False,
    return_timeseries=False,
    return_dva=None,
    charge_time_soc_window=None,
    return_charge_analysis=False,
    timeseries_max_points_per_segment=None,
    show_progress=True,
    poll_interval_s=2.0,
    ecm=None,
)

Runs a cycle-by-cycle ageing (degradation) campaign for a base battery.

The campaign is: baseline RPT -> rpt_every_n_cycles ageing cycles -> RPT -> ... until a stop criterion fires. State of health (SoH) and DCIR are always measured by the reference performance test (RPT), never from the ageing cycles themselves. The base battery must have a degradation model; design or format modifications are not supported for ageing simulations (degradation models are calibrated per cell).

There is NO client-side time limit on the simulation: the call polls until the job completes. Long-run governance is handled by the platform.

Parameters:

Name Type Description Default
base_battery str

The base battery model for the simulation. Must have a degradation model attached, otherwise the API returns an error.

required
ageing_cycler dict | list

The ageing protocol, built with :class:breathe_simulate.ageing.AgeingCycler (cyclic, calendar, custom, or from_csv). A LIST of {"cycler": <protocol>, "cycles": N} phases runs a mixed schedule back to back — e.g. 100 cyclic cycles, then calendar storage — with the campaign-level RPT cadence and stop criteria applying across the whole schedule. cycles is the number of ageing cycles the phase runs (for a calendar phase, the number of storage blocks). When the schedule is exhausted before max_cycles or any stop criterion, the campaign stops with stop_condition["triggered"] == "schedule_complete". result.cycles carries a phase column (the 0-based phase index) for slicing per phase.

required
rpt_cycler dict

The RPT protocol, built with :class:breathe_simulate.ageing.RptCycler. When omitted, the campaign runs ageing-only: no SoH/DCIR columns, and SoH/DCIR stop criteria are unavailable.

None
max_cycles int

Hard ceiling on the number of ageing cycles. Defaults to 200.

200
rpt_every_n_cycles int

Ageing cycles between RPTs (for calendar ageing, one storage block runs between RPTs instead). Defaults to 10.

10
stop_on_soh_pct float

Stop when RPT-based SoH (in %, relative to the baseline RPT) falls to or below this value. Requires rpt_cycler.

None
stop_on_dcir_ohm float

Stop when the RPT pulse resistance (Ohm) rises to or above this value. Requires rpt_cycler.

None
stop_on_energy_throughput_Wh float

Stop when the cumulative discharged energy reaches this value (Wh). The counter includes the RPTs' own throughput, matching lab bookkeeping and the MATLAB reference implementation.

None
stop_on_time_days float

Stop when the simulated time reaches this value (days) — the natural criterion for calendar ageing.

None
soc_reference Literal['latest_rpt', 'bol']

How SoC bounds in the ageing protocol are defined: against the latest RPT's SoC-reference capacity (updates as the cell ages, like most lab protocols) or against the beginning-of-life capacity. Defaults to "latest_rpt".

'latest_rpt'
performance_cycler dict

The END-OF-CAMPAIGN performance test: ANY run_sim cycler built with :class:breathe_simulate.Cycler (cc_chg, cc_dch, cccv, dcir, rate_cap, or custom — including drive cycles), executed on the LIVE aged cell with degradation still active. It runs ONCE, after a stop criterion has fired, characterising the final aged state. Before the test the cell is preconditioned to a defined state: CC-CV charge to the RPT's full, then a coulomb-counted discharge to performance_start_soc. Results are exposed as result.performance with the same dynamic-data structure as run_sim. Compare against the campaign's baseline RPT for the fresh-versus-aged story. Requires rpt_cycler.

None
performance_start_soc int | float

State of charge (0-1) the cell is brought to before the performance test, defined against the latest RPT's reference capacity. Defaults to 1.0 (test starts from full).

1.0
resume_from dict

Reserved for resuming/branching from a previous campaign's saved state. Not supported in this release — must be None.

None
initialTemperature_degC int | float

Initial cell temperature in degC. Also the RPT reference temperature when the RPT's reset_temperature is enabled. Defaults to 25.

25.0
ambientTemperature_degC int | float

Ambient temperature during ageing in degC. Defaults to 25.

25.0
heatTransferCoefficient int | float

Heat transfer coefficient in W/m2/K. Defaults to 35.

35.0
heatCapacity_kJkgK int | float

Cell heat capacity in kJ/kg/K. If None, the battery model's own value is used.

None
isothermal bool

Run the whole campaign isothermally — the cell temperature is held at initialTemperature_degC (no self-heating, no ambient exchange). Ambient temperatures (campaign-level and per-leg drive-cycle ambients) then have no thermal effect. Defaults to False (lumped thermal model).

False
return_rpt_timeseries bool

Also return downsampled voltage/current/temperature traces for each RPT. Defaults to False.

False
return_timeseries bool

Also return the labelled campaign timeseries — downsampled voltage/current/temperature/ SoC for EVERY segment (ageing cycles and RPT parts), stitched onto one campaign time axis and labelled with segment type, cycle number and RPT number. Exposed as result.timeseries and plotted with result.plot_timeseries(kpi=...). Adds response size on long campaigns. Defaults to False.

False
return_dva bool

Opt into the differential analysis (result.dva: DVA dV/dQ and ICA dQ/dV, both the charge and the discharge branch of every RPT) — an advanced diagnostic, OFF by default. return_dva=True differentiates RPT part 1's recharge and SoC-reference discharge at no extra simulation cost. Defining a DEDICATED slow DVA cycle on the RPT (the classic lab check-up, e.g. C/10 — RptCycler.build(..., I_dva_dch=...)) opts in by itself; combining that with an explicit return_dva=False is rejected as contradictory.

None
charge_time_soc_window tuple

The SoC window the per-cycle charge time is measured over, as (low, high) fractions. Defaults to (0.1, 0.8), the conventional fast-charge figure of merit. The measured time appears in result.cycles as charge_time_<low>_<high>_pct_s and is plotted by result.plot_charge_time().

None
return_charge_analysis bool

Include the per-cycle fast-charge analysis (result.charge_analysis): the SoC window and whether each cycle traversed it, achieved SoC at entry and exit, charge time, throughput, mean and peak current and C-rate, voltage at the boundaries, and the minimum anode potential and peak temperature INSIDE the window. result.charge_analysis_definition states where the SoC comes from and how each quantity is defined. An opt-in, defaulting to False, so campaigns that are not about fast charge are not littered with a table they will not read. The one-line charge time stays in result.cycles regardless.

False
timeseries_max_points_per_segment int

Downsampling budget per segment for the campaign timeseries (None -> the backend default, 1000 points per segment).

None
show_progress bool

Print campaign progress. On the synchronous transport (the current default) this is a start line and a completion summary — the platform cannot stream progress mid-request. On the queued transport it renders a live progress line; a cycle bar with ETA appears once the platform workers publish per-cycle progress in the poll status. Defaults to True.

True
poll_interval_s float

Seconds between job status polls. Defaults to 2.

2.0
ecm bool | dict

Also fit an equivalent circuit model at the END-OF-CAMPAIGN aged state. True uses the default :func:breathe_simulate.ecm.ecm_options block; pass ecm_options(...) to customise the fit. The fit applies the campaign's final LLI / LAM state to the physics (SEI film resistance growth is not part of the aged parameter bridge today, matching aged run_sim). An ECM fit adds tens of minutes at the default grids. Exposed as result.ecm, whose degradation_state records the fitted aged state. Defaults to None (no fit).

None

Returns:

Type Description
AgeingSimulationResults

A results handler with .rpt (per-RPT

AgeingSimulationResults

summary, including the LLI split into SEI vs plating), .dcir

AgeingSimulationResults

(per-pulse resistance table), .cycles (per-cycle trajectory,

AgeingSimulationResults

including the minimum anode potential — the plating-risk

AgeingSimulationResults

indicator), .dva (opt-in per-RPT differential voltage /

AgeingSimulationResults

incremental capacity curves, both branches — see

AgeingSimulationResults

return_dva), .timeseries (labelled campaign signal),

AgeingSimulationResults

.performance (in-campaign performance tests, run_sim-shaped),

AgeingSimulationResults

.ecm (the aged-state equivalent circuit model, when

AgeingSimulationResults

requested), .stop_condition, and plotting helpers. Printing

AgeingSimulationResults

the result shows the grouped overview.

run_sim

run_sim(
    base_battery,
    cycler,
    designs=[],
    formats=[],
    initialSoC=None,
    initialVoltage=None,
    initialTemperature_degC=25.0,
    ambientTemperature_degC=25.0,
    heatTransferCoefficient=35.0,
    heatCapacity_kJkgK=None,
    initialVoltageOcvType="mean",
    isothermal=False,
    cellTemperatureProfile=None,
)

Runs a simulation for a given base battery, cycler, designs, and initial conditions.

Only one of initialSoC or initialVoltage should be provided.

On the queued transport (BD_USE_ASYNC_ENDPOINTS=1) there is NO client-side time limit: the call polls until the job completes. Long-run governance is handled by the platform.

Parameters:

Name Type Description Default
base_battery str

The base battery model for the simulation.

required
cycler dict

The cycler parameters for the simulation. Supports standard cycle types (CC_CHG, CC_DCH, etc.) and CUSTOM format.

Built-in current-driven cycle types also support optional advanced controls: - CC_CHG: soc_target, anode_potential_threshold_mV, temperature_threshold_degC or temperature_threshold_K - CC_DCH: soc_target, temperature_threshold_degC or temperature_threshold_K - CCCV: charge_target_soc, discharge_target_soc, anode_potential_threshold_mV, temperature_threshold_degC or temperature_threshold_K - RateCap: target_soc, temperature_threshold_degC or temperature_threshold_K

For CUSTOM cycles, the structure is: { "cycle_type": "CUSTOM", "control_parameters": { "control_arrays": { # Optional: define reusable current/time or power/time profiles "array_name": { "time": [0, 10, 20, ...], "current": [0.0, 2.0, 0.0, ...] # For current control # OR "power": [0.0, 10.0, -5.0, ...] # For power control (W) } }, "experiment_text": str | list, # Can be a string or list of strings/array refs "period": str, # Time period (e.g., "1s") "anode_potential_threshold_mV": float, # Optional top-level Vne limit "temperature_threshold_degC": float, # Optional top-level thermal limit "temperature_threshold_K": float, # Optional top-level thermal limit } } When using control_arrays, experiment_text can be a list containing: - Strings: Direct experiment commands (e.g., "Rest for 60 s") - Dicts: References to control arrays: - {"type": "current", "array": "array_name"} for current control - {"type": "power", "array": "array_name"} for power control - Structured current-step dictionaries: - {"type": "soc_current", "mode": "charge"|"discharge", "current_a": value, "until_soc": value_between_0_and_1} - {"type": "soc_current_profile", "steps": [...]} - {"type": "voltage_current", "mode": "charge"|"discharge", "current_a": value, "until_voltage_v": value_in_volts} - {"type": "step_current", "mode": "charge"|"discharge", "current_a": value, and one or both of "until_soc" / "until_voltage_v"; if both are provided, the step ends when the first threshold is reached} - {"type": "step_current_profile", "steps": [...]} Note: For power control, use "power" key in control_arrays and "type": "power" in references. Positive power = discharge, negative power = charge.

required
designs list[dict]

The design parameters for the simulation. Alongside the physical design knobs and the ageing state (lampe/lamne/lli), each design accepts capacityVariationPercent (-5 to +5): a cell-to-cell capacity variation in percent that scales the cell capacity and both electrodes' maximum lithium concentrations by 1 + percent/100, leaving the OCV and electrode balancing untouched. Use it to simulate cells slightly above or below nominal capacity, for example designs=[{"designName": "cell +2%", "capacityVariationPercent": 2.0}].

[]
formats list[dict]

The battery formats for the simulation.

[]
initialSoC int | float | list[int | float]

The initial state of charge for the simulation. If a single value is provided, it will be used for all simulations. If a list of values is provided, multiple simulations will be run with each value.

None
initialVoltage int | float | list[int | float]

The initial voltage for the simulation. If a single value is provided, it will be used for all simulations. If a list of values is provided, multiple simulations will be run with each value.

None
initialVoltageOcvType Literal['mean', 'charge', 'discharge']

When an initial voltage is selected, this controls how the starting SOC is determined. "charge" - the charging OCV curve is used to find the corresponding starting SOC for the supplied initialVoltage "discharge" - the discharging OCV curve is used "mean" - the mean of the charge and discharge OCV curves is used

'mean'
initialTemperature_degC int | float | list[int | float]

The initial temperature for the simulation in degC. If a single value is provided, it will be used for all simulations. If a list of values is provided, multiple simulations will be run with each value.

25.0
ambientTemperature_degC int | float | list[int | float]

The ambient temperature for the simulation in degC. If a single value is provided, it will be used for all simulations. If a list of values is provided, multiple simulations will be run with each value.

25.0
heatTransferCoefficient int | float | list[int | float]

The heat transfer coefficient for the simulation in W/m2/K. Must be >= 0; there is no upper limit. Ignored when isothermal=True. If a single value is provided, it will be used for all simulations. If a list of values is provided, multiple simulations will be run with each value.

35.0
heatCapacity_kJkgK int | float | list[int | float]

The heat capacity for the simulation in kJ/kg/K. If a single value is provided, it will be used for all simulations. If a list of values is provided, multiple simulations will be run with each value. If None, the default value from the battery model will be used.

None
isothermal bool

If True, run the simulation isothermally — the cell temperature is held constant at initialTemperature_degC for the whole run (no self-heating, no exchange with ambient). heatTransferCoefficient and ambientTemperature_degC have no thermal effect in this mode. Defaults to False (lumped thermal model). Applies to every run in a batch sweep.

False
cellTemperatureProfile TemperatureProfile | dict

A prescribed cell-temperature trajectory for open-loop coupling to an external thermal model. Either a TemperatureProfile object or a plain dict {"time": [seconds...], "value": [degC...]}. When provided, the cell temperature follows this trajectory (interpolated to the solver time points; the boundary value is held outside the supplied range) instead of the model's own thermal calculation, and ambientTemperature_degC/heatTransferCoefficient/isothermal are unused. Works with any cycler. The heat generation is returned in the dynamic data ("Heat generation total [W]") for feeding back into the external model. time must be strictly increasing with at least two points; value must be the same length. Mutually exclusive with isothermal=True and with batch sweeps (list-valued initial conditions). Defaults to None.

None

Returns:

Type Description
SimulationResults

A results handler object containing the simulation results. This automatically handles both single and batch simulations.

Version fe1f5cb5