Breathe Simulate
A class for interacting with the Breathe Simulate API.
download_designs
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
Checks if a valid token is available and refreshes it if necessary.
generate_ecm
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. 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 |
None
|
**ecm_kwargs
|
The parameters of
:func: |
{}
|
Returns:
| Type | Description |
|---|---|
EcmResults
|
A results handler wrapping the fitted ECM, with |
EcmResults
|
the parameter tables, |
EcmResults
|
and |
Raises:
| Type | Description |
|---|---|
BreatheException
|
If the inputs are invalid or the response carries no ECM data. |
generate_pulse_heating_lut
Builds the maximum safe pulse-heating current table for a cell design.
Pulse heating warms a cold cell from the inside with a high-frequency current train. How much amplitude it can safely carry is set by the electrode potentials -- plating at the anode, oxidation at the cathode -- so the safe amplitude has to be worked out per temperature and state of charge. This returns that table.
It is FAST. The backend evaluates the cell's own expressions at rest
rather than simulating, so there is no cycler, no solve, and it returns
in seconds -- unlike
:meth:run_sim with a PULSE_HEATING cycler, which flies the table in
a closed loop and takes tens of minutes.
A run never returns this table alongside its trace, so ask for it here.
Building both from one set of variables -- the arguments below are the
same ones :meth:breathe_simulate.cycler.Cycler.pulse_heating takes --
is what keeps the table you plot the table the simulation flew.
The cell must carry a fitted double layer and be an SPMe design; the backend refuses anything else, naming the reason.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
base_battery
|
str
|
The base battery model to build the table for. |
required |
design
|
dict
|
A single run_sim-style design dict (with
|
None
|
**lut_kwargs
|
The parameters of
:func: |
{}
|
Returns:
| Type | Description |
|---|---|
PulseHeatingLutResults
|
A results handler wrapping the table, with |
PulseHeatingLutResults
|
|
PulseHeatingLutResults
|
limits it was built with. |
Raises:
| Type | Description |
|---|---|
BreatheException
|
If the inputs are invalid or the response carries no pulse-heating data. |
generate_resistance_vs_frequency
Computes total cell resistance against pulse frequency for a design.
A cell opposes a fast alternating current less than it opposes a steady one: the double layer progressively shorts out the charge-transfer and electrolyte paths as the half-period falls below its time constant. This returns that curve, from the DC resistance at low frequency down towards an instantaneous floor at high frequency. The gap between those two limits is what a pulse-heating scheme has to gain by running fast.
It is FAST. The backend evaluates the cell's own expressions at a rest state rather than simulating, so there is no cycler, no solve, and it returns in seconds.
The resistance is current-dependent, so c_rate genuinely changes the
answer rather than merely selecting a row of a table.
The cell must carry a fitted double layer and be an SPMe design -- the time constant shaping the curve is the double layer's -- so the backend refuses anything else, naming the reason. Results describe settled operation at beginning of life: a train started from rest shows a higher resistance for its first few cycles.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
base_battery
|
str
|
The base battery model to evaluate. |
required |
design
|
dict
|
A single run_sim-style design dict (with
|
None
|
**curve_kwargs
|
The parameters of
:func: |
{}
|
Returns:
| Type | Description |
|---|---|
ResistanceCurveResults
|
A results handler wrapping the curve, with |
ResistanceCurveResults
|
|
Raises:
| Type | Description |
|---|---|
BreatheException
|
If the inputs are invalid or the response carries no resistance data. |
get_active_materials
Gets a list of all acive materials.
Returns:
| Type | Description |
|---|---|
Dataframe
|
containing the battery active materials. |
get_aged_ocv
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
|
Note
These arguments are uppercase here, but the same ageing state inside
a run_sim design dict is written lowercase
({"lampe": …, "lamne": …, "lli": …}). The uppercase spelling is
accepted in a design too and normalized with a warning.
Returns:
| Type | Description |
|---|---|
DataFrame
|
containing the OCV summary table. |
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
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
|
|
dict
|
|
dict
|
|
dict
|
Cylindrical format keys (when |
dict
|
|
dict
|
|
dict
|
|
dict
|
Cuboid format keys (when |
dict
|
|
dict
|
|
dict
|
|
dict
|
|
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
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
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
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
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_modelis 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; |
OperatingWindow
|
raw sections, |
OperatingWindow
|
and |
get_service_version
Get the version number of the API
Returns:
| Name | Type | Description |
|---|---|---|
_type_ |
Version
|
description |
get_updated_format
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: |
{}
|
Returns:
| Type | Description |
|---|---|
dict
|
A dictionary containing the updated battery format. See |
Raises:
| Type | Description |
|---|---|
BreatheException
|
If attempting to change |
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
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
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 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
|
|
dict
|
|
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: |
required |
rpt_cycler
|
dict
|
The RPT protocol, built with
:class: |
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 |
None
|
stop_on_dcir_ohm
|
float
|
Stop when the RPT pulse
resistance (Ohm) rises to or above this value. Requires
|
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: |
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 |
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 |
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 |
False
|
return_dva
|
bool
|
Opt into the differential analysis
( |
None
|
charge_time_soc_window
|
tuple
|
The SoC window the
per-cycle charge time is measured over, as |
None
|
return_charge_analysis
|
bool
|
Include the per-cycle
fast-charge analysis ( |
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. |
None
|
Returns:
| Type | Description |
|---|---|
AgeingSimulationResults
|
A results handler with |
AgeingSimulationResults
|
summary, including the LLI split into SEI vs plating), |
AgeingSimulationResults
|
(per-pulse resistance table), |
AgeingSimulationResults
|
including the minimum anode potential — the plating-risk |
AgeingSimulationResults
|
indicator), |
AgeingSimulationResults
|
incremental capacity curves, both branches — see |
AgeingSimulationResults
|
|
AgeingSimulationResults
|
|
AgeingSimulationResults
|
|
AgeingSimulationResults
|
requested), |
AgeingSimulationResults
|
the result shows the grouped overview. |
run_sim
run_sim(
base_battery=None,
cycler=None,
designs=[],
formats=[],
initialSoC=None,
initialVoltage=None,
initialHysteresis=None,
initialTemperature_degC=25.0,
ambientTemperature_degC=25.0,
heatTransferCoefficient=35.0,
heatCapacity_kJkgK=None,
initialVoltageOcvType=None,
isothermal=False,
cellTemperatureProfile=None,
virtual_battery_uuid=None,
)
Runs a simulation for a given base battery, cycler, designs, and initial conditions.
Only one of initialSoC or initialVoltage should be provided.
Pass either base_battery or virtual_battery_uuid, not both.
The simulation runs on the queued workers and 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. |
None
|
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:
- 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. |
None
|
designs
|
list[dict]
|
The design parameters for the simulation.
Design keys are validated before the request is sent: an
unsupported key raises, listing the supported knobs, rather than
failing server-side. The ageing state is spelled
|
[]
|
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
|
initialHysteresis
|
int | float | list[int | float]
|
The cell's
initial OCV hysteresis state, in [-1, 1]. |
None
|
initialVoltageOcvType
|
Literal['mean', 'charge', 'discharge']
|
DEPRECATED,
use |
None
|
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 |
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 |
False
|
cellTemperatureProfile
|
TemperatureProfile | dict
|
A prescribed
cell-temperature trajectory for open-loop coupling to an external thermal model.
Either a |
None
|
virtual_battery_uuid
|
str
|
Run a Discover virtual battery instead
of |
None
|
Returns:
| Type | Description |
|---|---|
SimulationResults
|
A results handler object containing the simulation results. This automatically handles both single and batch simulations. |