Calculations

Derived-parameter calculation schemas. Mirrors ionworkspipeline.calculations.

Schemas for calculations.

class ionworks_schema.calculations.AreaToSquareWidthHeight(source=None)

Bases: Calculation

Calculate electrode height and width from area assuming square geometry.

Reads "Electrode area [m2]" and produces "Electrode height [m]" and "Electrode width [m]" as sqrt(area). Useful when only total electrode area is known.

Examples

>>> calc = iws.calculations.AreaToSquareWidthHeight()
>>> config = iws.Pipeline({"geometry": calc}).to_config()

Extends: ionworks_schema.calculations.calculations.Calculation

model_config = {'arbitrary_types_allowed': True, 'extra': 'forbid', 'populate_by_name': True, 'validate_assignment': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

model_post_init(context: Any, /) None

This function is meant to behave like a BaseModel method to initialise private attributes.

It takes context as an argument since that’s what pydantic-core passes when calling it.

Args:

self: The BaseModel instance. context: The context.

class ionworks_schema.calculations.ArrheniusDiffusivityFromMSMRData(electrode, data, direction='', phase='', options=None)

Bases: Calculation

Calculate the diffusivity from OCP data as

\[D = - \frac{F}{RT_{ref}} D_{ref} x (1-x) \frac{dU}{dx} \exp(E / R (1 / T_{ref} - 1 / T))\]

where \(D_{ref}\) is the reference diffusivity, \(x\) is the stoichiometry, \(U\) is the open-circuit potential, \(R\) is the gas constant, \(F\) is Faraday’s constant, \(T\) is the temperature, \(T_{ref}\) is the reference temperature, and \(E\) is the activation energy. This formula is derived from the transport equation in the MSMR model.

This calculation leaves the following parameter to be defined (e.g. by fitting to data):

  • Negative/Positive particle reference diffusivity [m2.s-1] ($D_{ref}$)

Parameters

electrodestr

The electrode to calculate the diffusivity for (either “positive” or “negative”).

dataDataLoader, DataFrame, str, or dict
OCP data with the following columns:
  • “Stoichiometry” : array

  • “Voltage [V]” : array

directionstr, optional

Specifies lithiation or delithiation for hysteresis models. Default is an empty string.

phasestr, optional

Specifies the phase (“primary” or “secondary”) for composite electrode models. Default is an empty string.

optionsdict, optional

Options for the calculation. The available options are:

  • “interpolator”str

    The interpolator to use. Default is “linear”. For more options, see the documentation for pybamm.Interpolant

  • “x tolerance”float

    The tolerance for the stoichiometry values near 0 and 1. Default is 1e-6. Data points where x < tolerance or x > (1 - tolerance) are excluded from the calculation.

  • “minimum dUdx”float

    The minimum value for the gradient of the open-circuit potential with respect to the stoichiometry. Default is 1e-6. When the absolute value of dU/dx is below this minimum, the corresponding y_data = x(1-x)dU/dx values are clipped.

Extends: ionworks_schema.calculations.calculations.Calculation

electrode: Literal['positive', 'negative', 'lumped']
data: str | DataFrame | DataFrame | DataLoader | dict[str, Any]
direction: Literal['', 'delithiation', 'lithiation']
phase: Literal['', 'primary', 'secondary']
options: dict[str, Any] | None
model_config = {'arbitrary_types_allowed': True, 'extra': 'forbid', 'populate_by_name': True, 'validate_assignment': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

model_post_init(context: Any, /) None

This function is meant to behave like a BaseModel method to initialise private attributes.

It takes context as an argument since that’s what pydantic-core passes when calling it.

Args:

self: The BaseModel instance. context: The context.

class ionworks_schema.calculations.ArrheniusDiffusivityFromMSMRFunction(electrode, voltage_limits, direction='', phase='', options=None)

Bases: Calculation

Calculate the diffusivity from an OCP function as

\[D = - \frac{F}{RT_{ref}} D_{ref} x (1-x) \frac{dU}{dx} \exp(E / R (1 / T_{ref} - 1 / T))\]

where \(D_{ref}\) is the reference diffusivity, \(x\) is the stoichiometry, \(U\) is the open-circuit potential, \(R\) is the gas constant, \(F\) is Faraday’s constant, \(T\) is the temperature, \(T_{ref}\) is the reference temperature, and \(E\) is the activation energy. This formula is derived from the transport equation in the MSMR model.

This calculation leaves the following parameter to be defined (e.g. by fitting to data):

  • Negative/Positive particle reference diffusivity [m2.s-1] ($D_{ref}$)

Parameters

electrodestr

The electrode to calculate the diffusivity for (either “positive” or “negative”).

voltage_limitstuple[float, float]

The voltage limits to use for the OCP data.

directionstr, optional

Specifies lithiation or delithiation for hysteresis models. Default is an empty string.

phasestr, optional

Specifies the phase (“primary” or “secondary”) for composite electrode models. Default is an empty string.

optionsdict, optional

Options for the calculation. The available options are:

  • “interpolator”str

    The interpolator to use. Default is “linear”. For more options, see the documentation for pybamm.Interpolant

  • “x tolerance”float

    The tolerance for the stoichiometry values near 0 and 1. Default is 1e-6. Data points where x < tolerance or x > (1 - tolerance) are excluded from the calculation.

  • “minimum dUdx”float

    The minimum value for the gradient of the open-circuit potential with respect to the stoichiometry. Default is 1e-6. When the absolute value of dU/dx is below this minimum, the corresponding y_data = x(1-x)dU/dx values are clipped.

Extends: ionworks_schema.calculations.calculations.Calculation

electrode: Literal['positive', 'negative', 'lumped']
voltage_limits: tuple[int | float, int | float] | list[int | float]
direction: Literal['', 'delithiation', 'lithiation']
phase: Literal['', 'primary', 'secondary']
options: dict[str, Any] | None
model_config = {'arbitrary_types_allowed': True, 'extra': 'forbid', 'populate_by_name': True, 'validate_assignment': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

model_post_init(context: Any, /) None

This function is meant to behave like a BaseModel method to initialise private attributes.

It takes context as an argument since that’s what pydantic-core passes when calling it.

Args:

self: The BaseModel instance. context: The context.

class ionworks_schema.calculations.ArrheniusLogLinear(data, reference_temperature=None, include_func=False)

Bases: Calculation

Fit an Arrhenius (log-linear) temperature dependence to a quantity measured at several temperatures.

Parameters

dataDataLoader, DataFrame, str, or dict

Measured values at each temperature.

reference_temperaturefloat, optional

Reference temperature (in K) used to anchor the Arrhenius fit. If None, a default is chosen from the data.

include_funcbool, optional

If True, also output an interpolant function so the value can be evaluated at any temperature, not just the measured ones. Default False.

Examples

>>> calc = iws.calculations.ArrheniusLogLinear(data="path/to/temperature_sweep.csv")
>>> config = iws.Pipeline({"arrhenius": calc}).to_config()

Extends: ionworks_schema.calculations.calculations.Calculation

data: str | DataFrame | DataFrame | DataLoader | dict[str, Any]
reference_temperature: int | float | None
include_func: bool
model_config = {'arbitrary_types_allowed': True, 'extra': 'forbid', 'populate_by_name': True, 'validate_assignment': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

model_post_init(context: Any, /) None

This function is meant to behave like a BaseModel method to initialise private attributes.

It takes context as an argument since that’s what pydantic-core passes when calling it.

Args:

self: The BaseModel instance. context: The context.

class ionworks_schema.calculations.AverageMSMRParameters(electrode, options=None)

Bases: Calculation

Average the MSMR species parameters across the lithiation and delithiation directions for one electrode.

Useful when you’ve fit the MSMR parameters separately in each direction (to capture hysteresis) but now want a single, direction-independent parameter set for downstream simulations.

Parameters

electrodestr

Electrode whose MSMR parameters are being averaged.

optionsdict, optional

Settings:

  • species_format (str): "Xj" (default) or "Qj".

  • phase (str): "primary" or "secondary" for composite

    electrodes. Default None.

Examples

>>> calc = iws.calculations.AverageMSMRParameters(electrode="positive")
>>> config = iws.Pipeline({"average": calc}).to_config()

Extends: ionworks_schema.calculations.calculations.Calculation

electrode: Literal['positive', 'negative', 'lumped']
options: dict[str, Any] | None
model_config = {'arbitrary_types_allowed': True, 'extra': 'forbid', 'populate_by_name': True, 'validate_assignment': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

model_post_init(context: Any, /) None

This function is meant to behave like a BaseModel method to initialise private attributes.

It takes context as an argument since that’s what pydantic-core passes when calling it.

Args:

self: The BaseModel instance. context: The context.

class ionworks_schema.calculations.Calculation(source=None)

Bases: BaseSchema

A pipeline step that derives one or more parameters from others without fitting to data.

A calculation reads existing parameters, applies an algebraic or numerical recipe, and writes new parameters back into the parameter set. Typical uses are computing geometric properties (volume, surface area), capacity-related quantities, stoichiometry windows, or concentrations.

Parameters

sourcestr, optional

Free-text note describing where the calculation method comes from (paper citation, algorithm description). Optional and only used by some subclasses.

Extends: ionworks_schema.base.BaseSchema

source: str | None
model_config = {'arbitrary_types_allowed': True, 'extra': 'forbid', 'populate_by_name': True, 'validate_assignment': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

model_post_init(context: Any, /) None

This function is meant to behave like a BaseModel method to initialise private attributes.

It takes context as an argument since that’s what pydantic-core passes when calling it.

Args:

self: The BaseModel instance. context: The context.

class ionworks_schema.calculations.CellMass(model_options=None)

Bases: Calculation

Compute the total cell mass in kilograms by summing the masses of the electrodes, separator, and current collectors from their densities, porosities, and thicknesses.

Adds Cell mass [kg] to the parameter set so downstream calculations (e.g. specific heat capacity, gravimetric energy density) can use it.

Parameters

model_optionsdict, optional

The pybamm model options — needed only when the cell has composite electrodes so the right phase masses get summed.

Initial credit: PyBOP team

Examples

>>> calc = iws.calculations.CellMass()
>>> config = iws.Pipeline({"cell_mass": calc}).to_config()

Extends: ionworks_schema.calculations.calculations.Calculation

model_options: dict[str, Any] | None
model_config = {'arbitrary_types_allowed': True, 'extra': 'forbid', 'populate_by_name': True, 'validate_assignment': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

model_post_init(context: Any, /) None

This function is meant to behave like a BaseModel method to initialise private attributes.

It takes context as an argument since that’s what pydantic-core passes when calling it.

Args:

self: The BaseModel instance. context: The context.

class ionworks_schema.calculations.CyclableLithium(method='electrode capacities', options=None)

Bases: Calculation

Calculation of amount of cyclable lithium capacity, either based on previously calculated electrode capacities and initial stoichiometries (“electrode capacities” option), or based on the initial positive electrode capacity and some formation loss (“formation loss” option).

The latter option assumes that before formation the amount of cyclable lithium available is equal to the amount of lithium in the positive electrode (positive electrode starts out fully lithiated, negative electrode starts out fully delithiated), and that a fixed fraction, f, of that lithium is lost during the formation process. Then, the cyclable lithium capacity is given by

\[Q_Li = f * Q_p\]

where f is the parameter “Formation lithium loss” and Q_p is the parameter “Positive electrode capacity [A.h]”.

Parameters

methodstr, optional

The method to use to calculate the cyclable lithium capacity. Either “electrode capacities” or “formation loss”. Default is “electrode capacities”.

optionsdict, optional
Options for the calculation. The available options are:
  • particle phases: tuple of str

    Specifies the number of phases for each electrode as a tuple (negative, positive). Each element can be “1” (single phase) or “2” (composite with Primary and Secondary phases). Default is (“1”, “1”).

Examples

>>> calc = iws.calculations.CyclableLithium(method="electrode capacities")
>>> config = iws.Pipeline({"cyclable_li": calc}).to_config()

Extends: ionworks_schema.calculations.calculations.Calculation

method: str
options: dict[str, Any] | None
model_config = {'arbitrary_types_allowed': True, 'extra': 'forbid', 'populate_by_name': True, 'validate_assignment': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

model_post_init(context: Any, /) None

This function is meant to behave like a BaseModel method to initialise private attributes.

It takes context as an argument since that’s what pydantic-core passes when calling it.

Args:

self: The BaseModel instance. context: The context.

class ionworks_schema.calculations.DensityFromVolumeAndMass(source=None)

Bases: Calculation

Calculate the density from the mass and volume.

Examples

>>> calc = iws.calculations.DensityFromVolumeAndMass()
>>> config = iws.Pipeline({"density": calc}).to_config()

Extends: ionworks_schema.calculations.calculations.Calculation

model_config = {'arbitrary_types_allowed': True, 'extra': 'forbid', 'populate_by_name': True, 'validate_assignment': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

model_post_init(context: Any, /) None

This function is meant to behave like a BaseModel method to initialise private attributes.

It takes context as an argument since that’s what pydantic-core passes when calling it.

Args:

self: The BaseModel instance. context: The context.

class ionworks_schema.calculations.DiameterToSquareWidthHeight(source=None)

Bases: Calculation

Sets the electrode height and width to be the square root of the electrode cross-sectional area, calculated from the diameter (for a coin cell).

Examples

>>> calc = iws.calculations.DiameterToSquareWidthHeight()
>>> config = iws.Pipeline({"geometry": calc}).to_config()

Extends: ionworks_schema.calculations.calculations.Calculation

model_config = {'arbitrary_types_allowed': True, 'extra': 'forbid', 'populate_by_name': True, 'validate_assignment': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

model_post_init(context: Any, /) None

This function is meant to behave like a BaseModel method to initialise private attributes.

It takes context as an argument since that’s what pydantic-core passes when calling it.

Args:

self: The BaseModel instance. context: The context.

class ionworks_schema.calculations.DiffusivityDataInterpolant(electrode, data, direction='', phase='', options=None)

Bases: Calculation

A pipeline element that creates an interpolant for the diffusivity from an array of diffusivity data. This interpolant can be used to calculate the diffusivity at any point within the range of the data.

Parameters

electrodestr

The electrode to create the interpolant for (either “positive” or “negative”).

dataDataLoader, DataFrame, str, or dict

Diffusivity data with the following columns:

  • “Stoichiometry”array

    The stoichiometry values.

  • “Diffusivity [m2.s-1]”array

    The corresponding diffusivity values.

directionstr, optional

Specifies lithiation or delithiation for hysteresis models. Default is an empty string.

phasestr, optional

Specifies the phase (“primary” or “secondary”) for composite electrode models. Default is an empty string.

optionsdict, optional

Options for the calculation. The available options are:

  • “interpolator”str

    The interpolator to use. Default is “linear”. For more options, see the documentation for pybamm.Interpolant

  • “transformation”str

    The transformation to apply to the data before creating the interpolant. Options are “none” (default) or “log” (interpolant is created in log10 space).

  • “scale factor”bool

    Whether to multiply the diffusivity by a scale factor. Default is False. If True, this leaves the following parameter to be defined (e.g. by fitting to data):

    • Negative/Positive particle diffusivity scale factor

Extends: ionworks_schema.calculations.calculations.Calculation

electrode: Literal['positive', 'negative', 'lumped']
data: str | DataFrame | DataFrame | DataLoader | dict[str, Any]
direction: Literal['', 'delithiation', 'lithiation']
phase: Literal['', 'primary', 'secondary']
options: dict[str, Any] | None
model_config = {'arbitrary_types_allowed': True, 'extra': 'forbid', 'populate_by_name': True, 'validate_assignment': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

model_post_init(context: Any, /) None

This function is meant to behave like a BaseModel method to initialise private attributes.

It takes context as an argument since that’s what pydantic-core passes when calling it.

Args:

self: The BaseModel instance. context: The context.

class ionworks_schema.calculations.DiffusivityFromMSMRData(electrode, data, direction='', phase='', options=None)

Bases: Calculation

Calculate the diffusivity from OCP data as

\[D = - \frac{F}{RT} D_{ref} x (1-x) \frac{dU}{dx}\]

where \(D_{ref}\) is the reference diffusivity, \(x\) is the stoichiometry, \(U\) is the open-circuit potential, \(R\) is the gas constant, \(F\) is Faraday’s constant, and \(T\) is the temperature. This formula is derived from the transport equation in the MSMR model.

This calculation leaves the following parameter to be defined (e.g. by fitting to data):

  • Negative/Positive particle reference diffusivity [m2.s-1] ($D_{ref}$)

Parameters

electrodestr

The electrode to calculate the diffusivity for (either “positive” or “negative”).

dataDataLoader, DataFrame, str, or dict
OCP data with the following columns:
  • “Stoichiometry” : array

  • “Voltage [V]” : array

directionstr, optional

Specifies lithiation or delithiation for hysteresis models. Default is an empty string.

phasestr, optional

Specifies the phase (“primary” or “secondary”) for composite electrode models. Default is an empty string.

optionsdict, optional

Options for the calculation. The available options are:

  • “interpolator”str

    The interpolator to use. Default is “linear”. For more options, see the documentation for pybamm.Interpolant

  • “x tolerance”float

    The tolerance for the stoichiometry values near 0 and 1. Default is 1e-6. Data points where x < tolerance or x > (1 - tolerance) are excluded from the calculation.

  • “minimum dUdx”float

    The minimum value for the gradient of the open-circuit potential with respect to the stoichiometry. Default is 1e-6. When the absolute value of dU/dx is below this minimum, the corresponding y_data = x(1-x)dU/dx values are clipped.

Extends: ionworks_schema.calculations.calculations.Calculation

electrode: Literal['positive', 'negative', 'lumped']
data: str | DataFrame | DataFrame | DataLoader | dict[str, Any]
direction: Literal['', 'delithiation', 'lithiation']
phase: Literal['', 'primary', 'secondary']
options: dict[str, Any] | None
model_config = {'arbitrary_types_allowed': True, 'extra': 'forbid', 'populate_by_name': True, 'validate_assignment': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

model_post_init(context: Any, /) None

This function is meant to behave like a BaseModel method to initialise private attributes.

It takes context as an argument since that’s what pydantic-core passes when calling it.

Args:

self: The BaseModel instance. context: The context.

class ionworks_schema.calculations.DiffusivityFromMSMRFunction(electrode, voltage_limits, direction='', phase='', options=None)

Bases: Calculation

Calculate the diffusivity from an OCP function as

\[D = - \frac{F}{RT} D_{{ref}} x (1-x) \frac{dU}{dx}\]

where \(D_{ref}\) is the reference diffusivity, \(U\) is the open-circuit potential, \(R\) is the gas constant, \(F\) is Faraday’s constant, and \(T\) is the temperature. This formula is derived from the transport equation in the MSMR model.

This calculation leaves the following parameter to be defined (e.g. by fitting to data):

  • Negative/Positive particle reference diffusivity [m2.s-1] ($D_{ref}$)

Parameters

electrodestr

The electrode to calculate the diffusivity for (either “positive” or “negative”).

voltage_limitstuple[float, float]

The voltage limits to use for the OCP data.

directionstr, optional

Specifies lithiation or delithiation for hysteresis models. Default is an empty string.

phasestr, optional

Specifies the phase (“primary” or “secondary”) for composite electrode models. Default is an empty string.

optionsdict, optional

Options for the calculation. The available options are:

  • “interpolator”str

    The interpolator to use. Default is “linear”. For more options, see the documentation for pybamm.Interpolant

  • “x tolerance”float

    The tolerance for the stoichiometry values near 0 and 1. Default is 1e-6. Data points where x < tolerance or x > (1 - tolerance) are excluded from the calculation.

  • “minimum dUdx”float

    The minimum value for the gradient of the open-circuit potential with respect to the stoichiometry. Default is 1e-6. When the absolute value of dU/dx is below this minimum, the corresponding y_data = x(1-x)dU/dx values are clipped.

Extends: ionworks_schema.calculations.calculations.Calculation

electrode: Literal['positive', 'negative', 'lumped']
voltage_limits: tuple[int | float, int | float] | list[int | float]
direction: Literal['', 'delithiation', 'lithiation']
phase: Literal['', 'primary', 'secondary']
options: dict[str, Any] | None
model_config = {'arbitrary_types_allowed': True, 'extra': 'forbid', 'populate_by_name': True, 'validate_assignment': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

model_post_init(context: Any, /) None

This function is meant to behave like a BaseModel method to initialise private attributes.

It takes context as an argument since that’s what pydantic-core passes when calling it.

Args:

self: The BaseModel instance. context: The context.

class ionworks_schema.calculations.DiffusivityFromPulse(electrode, data, direction='', phase='', options=None)

Bases: Calculation

A pipeline element that calculates the diffusion coefficient from pulse data by directly using the voltage data from the pulse, without the need for fitting a model. This method uses eqn 26 from Wang et al. [Wang2022] to calculate the diffusion coefficient. Advantages of this method are that it is simple and fast. Disadvantages are that the calculation relies on assumptions that may not be valid in all cases, and the results may be sensitive to noise in the data since we only use 4 data points to calculate the diffusion coefficient.

Parameters

electrodestr

The electrode to calculate the diffusivity for (either “positive” or “negative”).

dataDataLoader, DataFrame, str, or dict

The pulse data. Must include columns "Current [A]", "Voltage [V]" and "Step number".

directionstr, optional

Specifies lithiation or delithiation for hysteresis models. Default is an empty string.

phasestr, optional

Specifies the phase (“primary” or “secondary”) for composite electrode models. Default is an empty string.

optionsdict, optional
Options for the calculation. The available options are:
  • “step number”int

    The step number to use for the calculation. If not provided, the first non-rest step is used.

  • “dt_IR”float

    The time to establish the IR drop, in seconds. If not provided, the IR drop is assumed to be established at the start of the pulse (first data point with that step number)

  • “dt_pulse”float

    The time at which to calculate the diffusion coefficient, in seconds. If not provided, the diffusion coefficient will be calculated at the end of the pulse.

Raises

ValueError

If no rest step is found after the pulse.

References

[Wang2022]

Wang, A. A., et al. “Review of parameterisation and a novel database (LiionDB) for continuum Li-ion battery models.” Progress in Energy 4.3 (2022): 032004.

Extends: ionworks_schema.calculations.calculations.Calculation

electrode: Literal['positive', 'negative', 'lumped']
data: str | DataFrame | DataFrame | DataLoader | dict[str, Any]
direction: Literal['', 'delithiation', 'lithiation']
phase: Literal['', 'primary', 'secondary']
options: dict[str, Any] | None
model_config = {'arbitrary_types_allowed': True, 'extra': 'forbid', 'populate_by_name': True, 'validate_assignment': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

model_post_init(context: Any, /) None

This function is meant to behave like a BaseModel method to initialise private attributes.

It takes context as an argument since that’s what pydantic-core passes when calling it.

Args:

self: The BaseModel instance. context: The context.

class ionworks_schema.calculations.ElectrodeCapacity(electrode, use_stoich_window=False, method='auto', phase=None)

Bases: Calculation

A pipeline element that calculates variables related to the capacity. Automatically determines the method and unknown.

Solves the algebraic equation: c_max * eps * L * A_cc * (stoich_max - stoich_min) * F / 3600 = capacity,

where capacity can be the electrode capacity, the electrode loading times the area, or the theoretical capacity from the crystal density, fraction of Li per mole of material, and molecular mass of active material. All but one of c_max, eps, L, A_cc, stoich_max, and stoich_min must be provided (stoich_min and stoich_max are only required if use_stoich_window is True). Either capacity, loading, or the crystal density, fraction of Li per mole of material, and molecular mass of active material must be provided.

Parameters

electrodestr

Electrode to calculate capacity for: “positive” or “negative”.

use_stoich_windowbool, default=False

Whether to use stoichiometry limits in the calculation. Set True if capacity is based on a voltage window (e.g., 0-100% SOC from RPT). Set False if capacity represents the full material limit (e.g., from OCP fitting).

methodstr, default=”auto”

Calculation method. Use “auto” to automatically determine based on inputs.

phasestr | None, default=None

Phase for multi-phase materials: “primary” or “secondary”.

Examples

>>> calc = iws.calculations.ElectrodeCapacity(electrode="positive")
>>> config = iws.Pipeline({"capacity": calc}).to_config()

Extends: ionworks_schema.calculations.calculations.Calculation

electrode: Literal['positive', 'negative', 'lumped']
use_stoich_window: bool
method: str
phase: Literal['', 'primary', 'secondary'] | None
model_config = {'arbitrary_types_allowed': True, 'extra': 'forbid', 'populate_by_name': True, 'validate_assignment': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

model_post_init(context: Any, /) None

This function is meant to behave like a BaseModel method to initialise private attributes.

It takes context as an argument since that’s what pydantic-core passes when calling it.

Args:

self: The BaseModel instance. context: The context.

class ionworks_schema.calculations.ElectrodeSOH(options=None)

Bases: Calculation

Calculate electrode stoichiometry windows from capacity using electrode SOH algorithm.

Reads "Nominal cell capacity [A.h]" (or "Cyclable lithium capacity [A.h]"), the electrode OCPs, and electrode dimensions/concentrations, and produces the stoichiometries at 0% and 100% SOC for both electrodes. Uses the algorithm from Mohtat et al. (2019) [Mohtat2019].

Parameters

optionsdict, optional

Calculation options:

  • known valuestr, default=”cyclable lithium capacity”

    What capacity measure is known: “cyclable lithium capacity” or “cell capacity”.

References

[Mohtat2019]

Mohtat, P., Lee, S., Siegel, J. B., & Stefanopoulou, A. G. (2019). Towards better estimability of electrode-specific state of health: Decoding the cell expansion. Journal of Power Sources, 427, 101-111.

Examples

>>> calc = iws.calculations.ElectrodeSOH()
>>> config = iws.Pipeline({"esoh": calc}).to_config()

Extends: ionworks_schema.calculations.calculations.Calculation

options: dict[str, Any] | None
model_config = {'arbitrary_types_allowed': True, 'extra': 'forbid', 'populate_by_name': True, 'validate_assignment': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

model_post_init(context: Any, /) None

This function is meant to behave like a BaseModel method to initialise private attributes.

It takes context as an argument since that’s what pydantic-core passes when calling it.

Args:

self: The BaseModel instance. context: The context.

class ionworks_schema.calculations.ElectrodeSOHHalfCell(electrode, options=None)

Bases: Calculation

Calculate minimum and maximum electrode stoichiometries for a half-cell using the electrode-specific SOH algorithm.

See ElectrodeSOH for more details.

Parameters

electrodestr

The electrode to calculate the initial concentration for, either “positive” or “negative”.

optionsdict, optional

A dictionary of options to be passed to the calculation. The following options are available:

  • simulation_kwargs: dict

    Keyword arguments to pass to the simulation (iwp.Simulation). Default is None.

Extends: ionworks_schema.calculations.calculations.Calculation

electrode: Literal['positive', 'negative', 'lumped']
options: dict[str, Any] | None
model_config = {'arbitrary_types_allowed': True, 'extra': 'forbid', 'populate_by_name': True, 'validate_assignment': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

model_post_init(context: Any, /) None

This function is meant to behave like a BaseModel method to initialise private attributes.

It takes context as an argument since that’s what pydantic-core passes when calling it.

Args:

self: The BaseModel instance. context: The context.

class ionworks_schema.calculations.ElectrodeVolumeFractionFromLoading(electrode, method)

Bases: Calculation

Calculate the volume fraction of active material in the electrodes from the loading and maximum concentration or from the coating mass and crystal density.

Parameters

electrode[“positive”, “negative”, “both”]

The electrode to calculate the volume fraction for.

method[“loading”, “coating mass”]

The method to use to calculate the volume fraction.

Extends: ionworks_schema.calculations.calculations.Calculation

electrode: Literal['positive', 'negative', 'lumped']
method: str
model_config = {'arbitrary_types_allowed': True, 'extra': 'forbid', 'populate_by_name': True, 'validate_assignment': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

model_post_init(context: Any, /) None

This function is meant to behave like a BaseModel method to initialise private attributes.

It takes context as an argument since that’s what pydantic-core passes when calling it.

Args:

self: The BaseModel instance. context: The context.

class ionworks_schema.calculations.ElectrodeVolumeFractionFromPorosity(electrode)

Bases: Calculation

Calculate the volume fraction of active material in the electrodes from the porosity and the active volume fraction of solid.

Parameters

electrodestr

The electrode to calculate the volume fraction for. Must be either “negative” or “positive”.

Extends: ionworks_schema.calculations.calculations.Calculation

electrode: Literal['positive', 'negative', 'lumped']
model_config = {'arbitrary_types_allowed': True, 'extra': 'forbid', 'populate_by_name': True, 'validate_assignment': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

model_post_init(context: Any, /) None

This function is meant to behave like a BaseModel method to initialise private attributes.

It takes context as an argument since that’s what pydantic-core passes when calling it.

Args:

self: The BaseModel instance. context: The context.

class ionworks_schema.calculations.EntropicChangeDataInterpolant(electrode, data, options=None)

Bases: Calculation

Create an interpolant for the open-circuit entropic change from data.

Parameters

electrodestr

The electrode to create the interpolant for, either “positive”, “negative”, or “lumped”. If “lumped”, assumes a single electrode and modifies parameter names accordingly.

dataDataLoader, DataFrame, str, or dict

The data to use for the interpolant. Must have columns "Stoichiometry" and "Entropic change [V.K-1]".

optionsdict, optional

A dictionary of options to pass to the calculation.

  • interpolator: str, optional

    The interpolator to use for the interpolant. Can be “linear” or “cubic”. Default is “linear”.

  • tolerance: float

    The tolerance to use when restricting the data to avoid interpolation issues. Default is 1e-6.

  • phase: str, optional

    The phase of the electrode, either “primary” or “secondary”. Default is None, which means no phase is assumed.

  • scale factor: float, optional

    The scale factor to apply to the entropic change. Default is 1.

Extends: ionworks_schema.calculations.calculations.Calculation

electrode: Literal['positive', 'negative', 'lumped']
data: str | DataFrame | DataFrame | DataLoader | dict[str, Any]
options: dict[str, Any] | None
model_config = {'arbitrary_types_allowed': True, 'extra': 'forbid', 'populate_by_name': True, 'validate_assignment': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

model_post_init(context: Any, /) None

This function is meant to behave like a BaseModel method to initialise private attributes.

It takes context as an argument since that’s what pydantic-core passes when calling it.

Args:

self: The BaseModel instance. context: The context.

class ionworks_schema.calculations.EntropicChangeFromMSMRFunction(electrode, voltage_limits, options=None)

Bases: Calculation

Create an interpolant for the open-circuit entropic change from MSMR parameters.

Parameters

electrodestr

The electrode to create the interpolant for, either “positive” or “negative”.

voltage_limitstuple of float

The voltage limits to use to generate data for the interpolant.

optionsdict, optional

A dictionary of options to pass to the calculation.

  • interpolator: str, optional

    The interpolator to use for the interpolant. Can be “linear” or “cubic”. Default is “linear”.

  • tolerance: float

    The tolerance to use when restricting the data to avoid interpolation issues. Default is 1e-6.

  • phase: str, optional

    The phase of the electrode, either “primary” or “secondary”. Default is None, which means no phase is assumed.

  • scale factor: float, optional

    The scale factor to apply to the entropic change. Default is 1.

Extends: ionworks_schema.calculations.calculations.Calculation

electrode: Literal['positive', 'negative', 'lumped']
voltage_limits: tuple[int | float, int | float] | list[int | float]
options: dict[str, Any] | None
model_config = {'arbitrary_types_allowed': True, 'extra': 'forbid', 'populate_by_name': True, 'validate_assignment': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

model_post_init(context: Any, /) None

This function is meant to behave like a BaseModel method to initialise private attributes.

It takes context as an argument since that’s what pydantic-core passes when calling it.

Args:

self: The BaseModel instance. context: The context.

class ionworks_schema.calculations.HalfCellNominalCapacity(electrode)

Bases: Calculation

Set nominal cell capacity and current function equal to electrode capacity.

For half-cell models, the cell capacity is determined by the working electrode capacity. Reads "Positive electrode capacity [A.h]" (or the negative-electrode equivalent) and writes the same value to "Nominal cell capacity [A.h]" and "Current function [A]", providing the cell-level parameters required by PyBaMM.

Parameters

electrodestr

Working electrode: “negative” or “positive”.

Extends: ionworks_schema.calculations.calculations.Calculation

electrode: Literal['positive', 'negative', 'lumped']
model_config = {'arbitrary_types_allowed': True, 'extra': 'forbid', 'populate_by_name': True, 'validate_assignment': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

model_post_init(context: Any, /) None

This function is meant to behave like a BaseModel method to initialise private attributes.

It takes context as an argument since that’s what pydantic-core passes when calling it.

Args:

self: The BaseModel instance. context: The context.

class ionworks_schema.calculations.InitialConcentrationFromInitialStoichiometryHalfCell(electrode, options=None)

Bases: Calculation

Calculate the initial concentration in the given electrode from the initial stoichiometry and maximum concentration.

Parameters

electrodestr

The electrode to calculate the initial concentration for, either “positive” or “negative”.

optionsdict, optional

A dictionary of options to be passed to the calculation. The following options are available:

  • phase: str

    The phase to solve for the initial concentration. Can be “primary” or “secondary”. Default is None.

Extends: ionworks_schema.calculations.calculations.Calculation

electrode: Literal['positive', 'negative', 'lumped']
options: dict[str, Any] | None
model_config = {'arbitrary_types_allowed': True, 'extra': 'forbid', 'populate_by_name': True, 'validate_assignment': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

model_post_init(context: Any, /) None

This function is meant to behave like a BaseModel method to initialise private attributes.

It takes context as an argument since that’s what pydantic-core passes when calling it.

Args:

self: The BaseModel instance. context: The context.

class ionworks_schema.calculations.InitialSOC(soc)

Bases: Calculation

Calculate initial electrode concentrations from target SOC.

Reads the stoichiometry windows ("Negative/Positive electrode stoichiometry at 0%/100% SOC") and maximum concentrations for both electrodes, and produces "Initial stoichiometry in negative/positive electrode" and the corresponding "Initial concentration in negative/positive electrode [mol.m-3]".

Parameters

socfloat

Target state of charge (0.0 to 1.0).

Examples

>>> calc = iws.calculations.InitialSOC(soc=0.5)
>>> config = iws.Pipeline({"initial_soc": calc}).to_config()

Extends: ionworks_schema.calculations.calculations.Calculation

soc: int | float | str
model_config = {'arbitrary_types_allowed': True, 'extra': 'forbid', 'populate_by_name': True, 'validate_assignment': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

model_post_init(context: Any, /) None

This function is meant to behave like a BaseModel method to initialise private attributes.

It takes context as an argument since that’s what pydantic-core passes when calling it.

Args:

self: The BaseModel instance. context: The context.

class ionworks_schema.calculations.InitialSOCHalfCell(electrode, soc, options=None)

Bases: Calculation

Calculate initial electrode concentration from target SOC for half-cell.

Reads the working electrode’s stoichiometry window and maximum concentration, and produces "Initial stoichiometry in positive/negative electrode" and "Initial concentration in positive/negative electrode [mol.m-3]".

Parameters

electrodestr

Working electrode: “negative” or “positive”.

socfloat | int | str

Target SOC. Can be numeric (0.0-1.0) or string (“0%”, “100%”, “minimum”, “maximum”).

optionsdict, optional

Calculation options:

  • phasestr | None, default=None

    Phase for multi-phase materials: “primary” or “secondary”.

Extends: ionworks_schema.calculations.calculations.Calculation

electrode: Literal['positive', 'negative', 'lumped']
soc: int | float | str
options: dict[str, Any] | None
model_config = {'arbitrary_types_allowed': True, 'extra': 'forbid', 'populate_by_name': True, 'validate_assignment': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

model_post_init(context: Any, /) None

This function is meant to behave like a BaseModel method to initialise private attributes.

It takes context as an argument since that’s what pydantic-core passes when calling it.

Args:

self: The BaseModel instance. context: The context.

class ionworks_schema.calculations.InitialSOCfromMaximumStoichiometry(options=None)

Bases: Calculation

Calculate the initial concentration in the negative and positive electrodes from the initial SOC and stoichiometry windows in each electrode.

Parameters

optionsdict, optional

A dictionary of options to be passed to the calculation. The following options are available:

  • particle phases: tuple of str

    Specifies the number of phases for each electrode as a tuple (negative, positive). Each element can be “1” (single phase) or “2” (composite with Primary and Secondary phases). Default is (“1”, “1”).

Extends: ionworks_schema.calculations.calculations.Calculation

options: dict[str, Any] | None
model_config = {'arbitrary_types_allowed': True, 'extra': 'forbid', 'populate_by_name': True, 'validate_assignment': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

model_post_init(context: Any, /) None

This function is meant to behave like a BaseModel method to initialise private attributes.

It takes context as an argument since that’s what pydantic-core passes when calling it.

Args:

self: The BaseModel instance. context: The context.

class ionworks_schema.calculations.InitialStoichiometryFromVoltageHalfCell(electrode, options=None)

Bases: Calculation

Calculate the initial stoichiometry in the given electrode from the initial voltage (i.e. find the stoichiometry that gives the correct voltage).

Parameters

electrodestr

The electrode to calculate the initial concentration for, either “positive” or “negative”.

optionsdict, optional

A dictionary of options to be passed to the calculation. The following options are available:

  • simulation_kwargs: dict

    Keyword arguments to pass to the simulation (iwp.Simulation). Default is {“solver”: pybamm.AlgebraicSolver()}.

  • direction: str

    The direction to solve for the initial stoichiometry. Can be “lithiation” or “delithiation”. Default is None, which means no directionality is assumed.

  • phase: str

    The phase to solve for the initial stoichiometry. Can be “primary” or “secondary”. Default is None.

Extends: ionworks_schema.calculations.calculations.Calculation

electrode: Literal['positive', 'negative', 'lumped']
options: dict[str, Any] | None
model_config = {'arbitrary_types_allowed': True, 'extra': 'forbid', 'populate_by_name': True, 'validate_assignment': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

model_post_init(context: Any, /) None

This function is meant to behave like a BaseModel method to initialise private attributes.

It takes context as an argument since that’s what pydantic-core passes when calling it.

Args:

self: The BaseModel instance. context: The context.

class ionworks_schema.calculations.InitialStoichiometryFromVoltageMSMRHalfCell(electrode)

Bases: Calculation

Calculate the initial stoichiometry in the given electrode from the initial voltage (i.e. find the stoichiometry that gives the correct voltage) using the MSMR framework.

Parameters

electrodestr

The electrode to calculate the initial concentration for, either “positive” or “negative”.

Extends: ionworks_schema.calculations.calculations.Calculation

electrode: Literal['positive', 'negative', 'lumped']
model_config = {'arbitrary_types_allowed': True, 'extra': 'forbid', 'populate_by_name': True, 'validate_assignment': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

model_post_init(context: Any, /) None

This function is meant to behave like a BaseModel method to initialise private attributes.

It takes context as an argument since that’s what pydantic-core passes when calling it.

Args:

self: The BaseModel instance. context: The context.

class ionworks_schema.calculations.InitialVoltageFromConcentration(electrode)

Bases: Calculation

Calculate initial voltage from target concentration using OCP inversion.

Reads "Positive/Negative electrode lithiation" (the OCP function), "Maximum concentration in positive/negative electrode [mol.m-3]", and "Initial concentration in positive/negative electrode [mol.m-3]", and produces "Initial voltage in positive/negative electrode [V]" by numerically inverting the lithiation function.

Parameters

electrodestr

Electrode: “negative” or “positive”.

Extends: ionworks_schema.calculations.calculations.Calculation

electrode: Literal['positive', 'negative', 'lumped']
model_config = {'arbitrary_types_allowed': True, 'extra': 'forbid', 'populate_by_name': True, 'validate_assignment': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

model_post_init(context: Any, /) None

This function is meant to behave like a BaseModel method to initialise private attributes.

It takes context as an argument since that’s what pydantic-core passes when calling it.

Args:

self: The BaseModel instance. context: The context.

class ionworks_schema.calculations.JellyRollThermalDimensions(source=None)

Bases: Calculation

Calculate thermal properties of cylindrical jelly roll cell.

Reads "Jelly roll height [m]" and "Jelly roll radius [m]" and produces "Cell volume [m3]" and "Cell cooling surface area [m2]" assuming cylindrical geometry for thermal modeling.

Examples

>>> calc = iws.calculations.JellyRollThermalDimensions()
>>> config = iws.Pipeline({"thermal": calc}).to_config()

Extends: ionworks_schema.calculations.calculations.Calculation

model_config = {'arbitrary_types_allowed': True, 'extra': 'forbid', 'populate_by_name': True, 'validate_assignment': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

model_post_init(context: Any, /) None

This function is meant to behave like a BaseModel method to initialise private attributes.

It takes context as an argument since that’s what pydantic-core passes when calling it.

Args:

self: The BaseModel instance. context: The context.

class ionworks_schema.calculations.LumpedHeatCapacityAndDensity(source=None)

Bases: Calculation

Sets the specific heat capacity and density for each cell component to the lumped (cell-level) values.

Extends: ionworks_schema.calculations.calculations.Calculation

model_config = {'arbitrary_types_allowed': True, 'extra': 'forbid', 'populate_by_name': True, 'validate_assignment': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

model_post_init(context: Any, /) None

This function is meant to behave like a BaseModel method to initialise private attributes.

It takes context as an argument since that’s what pydantic-core passes when calling it.

Args:

self: The BaseModel instance. context: The context.

class ionworks_schema.calculations.MSMRElectrodeSOHHalfCell(electrode)

Bases: Calculation

Calculate minimum and maximum electrode stoichiometries for a half-cell by evaluating the extent of lithiation at the minimum and maximum OCV.

See ElectrodeSOH for more details.

Parameters

electrodestr

The electrode to calculate the minimum and maximum stoichiometries for.

Extends: ionworks_schema.calculations.calculations.Calculation

electrode: Literal['positive', 'negative', 'lumped']
model_config = {'arbitrary_types_allowed': True, 'extra': 'forbid', 'populate_by_name': True, 'validate_assignment': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

model_post_init(context: Any, /) None

This function is meant to behave like a BaseModel method to initialise private attributes.

It takes context as an argument since that’s what pydantic-core passes when calling it.

Args:

self: The BaseModel instance. context: The context.

class ionworks_schema.calculations.MSMRFullCellCapacities(data, method='total capacity')

Bases: Calculation

A pipeline element that calculates variables related to the capacity from the MSMR full-cell balance.

Parameters

dataDataLoader, DataFrame, str, or dict

The data to use to calculate the useable capacity, see FittingObjective.

parameter_formatstr, optional

The format of the parameters to fit. One parameter is always the lower excess capacity, and this option determines the other parameter, which can be either the total capacity or the upper excess capacity. Default is “total capacity”. (Q_tot = Q_lowex + Q_use + Q_uppex)

Extends: ionworks_schema.calculations.calculations.Calculation

data: str | DataFrame | DataFrame | DataLoader | dict[str, Any]
method: str
model_config = {'arbitrary_types_allowed': True, 'extra': 'forbid', 'populate_by_name': True, 'validate_assignment': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

model_post_init(context: Any, /) None

This function is meant to behave like a BaseModel method to initialise private attributes.

It takes context as an argument since that’s what pydantic-core passes when calling it.

Args:

self: The BaseModel instance. context: The context.

class ionworks_schema.calculations.MSMRFunction(electrode, direction=None, phase=None)

Bases: Calculation

Specifies the MSMR function for the open-circuit potential for the given electrode.

Parameters

electrodestr

The name of the electrode.

directionstr, optional

The direction of the MSMR function.

phasestr, optional

The phase of the MSMR function.

Extends: ionworks_schema.calculations.calculations.Calculation

electrode: Literal['positive', 'negative', 'lumped']
direction: Literal['', 'delithiation', 'lithiation'] | None
phase: Literal['', 'primary', 'secondary'] | None
model_config = {'arbitrary_types_allowed': True, 'extra': 'forbid', 'populate_by_name': True, 'validate_assignment': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

model_post_init(context: Any, /) None

This function is meant to behave like a BaseModel method to initialise private attributes.

It takes context as an argument since that’s what pydantic-core passes when calling it.

Args:

self: The BaseModel instance. context: The context.

class ionworks_schema.calculations.OCPDataInterpolant(electrode, data, options=None)

Bases: Calculation

Create an interpolant for the open-circuit voltage (OCP) from data.

Parameters

electrodestr

The electrode to create the interpolant for, either “positive”, “negative”, or “lumped”. If “lumped”, assumes a single electrode and modifies parameter names accordingly.

dataDataLoader, DataFrame, str, or dict

The data to use for the interpolant. Must have columns “Stoichiometry” and “Voltage [V]”.

optionsdict, optional

A dictionary of options to pass to the calculation.

  • interpolator: str, optional

    The interpolator to use for the interpolant. Can be “linear” or “cubic”. Default is “linear”.

  • tolerance: float

    The tolerance to use when restricting the data to avoid interpolation issues. Default is 1e-6.

  • direction: str

    The direction of the OCP, either “lithiation” or “delithiation”. Default is None, which means no directionality is assumed.

  • phase: str, optional

    The phase of the electrode, either “primary” or “secondary”. Default is None, which means no phase is assumed.

Extends: ionworks_schema.calculations.calculations.Calculation

electrode: Literal['positive', 'negative', 'lumped']
data: str | DataFrame | DataFrame | DataLoader | dict[str, Any]
options: dict[str, Any] | None
model_config = {'arbitrary_types_allowed': True, 'extra': 'forbid', 'populate_by_name': True, 'validate_assignment': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

model_post_init(context: Any, /) None

This function is meant to behave like a BaseModel method to initialise private attributes.

It takes context as an argument since that’s what pydantic-core passes when calling it.

Args:

self: The BaseModel instance. context: The context.

class ionworks_schema.calculations.OCPDataInterpolantMSMRExtrapolation(electrode, data, voltage_limits, options=None)

Bases: Calculation

Create an interpolant for the open-circuit voltage (OCP) from data and use MSMR parameters to extrapolate outside the data range and to convert capacity to stoichiometry.

The blending uses smooth weight functions to transition between OCP data in the observed stoichiometry range and MSMR extrapolation outside it. Mathematical formulation:

V(x) = w(x)·V_ocp(x) + (1-w(x))·V_msmr_corrected(x)

where w(x) is a smooth bump function based on the error function, and V_msmr_corrected includes a linear offset to ensure C⁰ continuity at the OCP boundaries.

Parameters

electrodestr

The electrode to create the interpolant for, either “positive” or “negative”.

dataDataLoader, DataFrame, str, or dict

The data to use for the interpolant. Must have columns “Capacity [A.h]” and “Voltage [V]”.

voltage_limitstuple of float

The voltage limits to use to generate MSMR data for extrapolation.

optionsdict, optional

A dictionary of options to pass to the calculation.

  • interpolator: str, optional

    The interpolator to use for the interpolant. Can be “linear” or “cubic”. Default is “linear”.

  • tolerance: float

    The tolerance to use when restricting the data to avoid interpolation issues. Default is 1e-6.

  • direction: str

    The direction of the OCP, either “lithiation” or “delithiation”. Default is None, which means no directionality is assumed.

  • phase: str, optional

    The phase of the electrode, either “primary” or “secondary”. Default is None, which means no phase is assumed.

Extends: ionworks_schema.calculations.calculations.Calculation

electrode: Literal['positive', 'negative', 'lumped']
data: str | DataFrame | DataFrame | DataLoader | dict[str, Any]
voltage_limits: tuple[int | float, int | float] | list[int | float]
options: dict[str, Any] | None
model_config = {'arbitrary_types_allowed': True, 'extra': 'forbid', 'populate_by_name': True, 'validate_assignment': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

model_post_init(context: Any, /) None

This function is meant to behave like a BaseModel method to initialise private attributes.

It takes context as an argument since that’s what pydantic-core passes when calling it.

Args:

self: The BaseModel instance. context: The context.

class ionworks_schema.calculations.OCPMSMRInterpolant(electrode, voltage_limits, options=None)

Bases: Calculation

Create an interpolant for the open-circuit voltage (OCP) from MSMR parameters.

Parameters

electrodestr

The electrode to create the interpolant for, either “positive” or “negative”.

voltage_limitstuple of float

The voltage limits to use to generate data for the interpolant.

optionsdict, optional

A dictionary of options to pass to the calculation.

  • interpolator: str, optional

    The interpolator to use for the interpolant. Can be “linear” or “cubic”. Default is “linear”.

  • tolerance: float

    The tolerance to use when restricting the data to avoid interpolation issues. Default is 1e-6.

  • direction: str

    The direction of the OCP, either “lithiation” or “delithiation”. Default is None, which means no directionality is assumed.

  • phase: str, optional

    The phase of the electrode, either “primary” or “secondary”. Default is None, which means no phase is assumed.

  • create_lithiation_function: bool

    Whether to create a lithiation function from the interpolant. Default is True.

Extends: ionworks_schema.calculations.calculations.Calculation

electrode: Literal['positive', 'negative', 'lumped']
voltage_limits: tuple[int | float, int | float] | list[int | float]
options: dict[str, Any] | None
model_config = {'arbitrary_types_allowed': True, 'extra': 'forbid', 'populate_by_name': True, 'validate_assignment': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

model_post_init(context: Any, /) None

This function is meant to behave like a BaseModel method to initialise private attributes.

It takes context as an argument since that’s what pydantic-core passes when calling it.

Args:

self: The BaseModel instance. context: The context.

class ionworks_schema.calculations.OpenCircuitLimits(source=None)

Bases: Calculation

Set OCV limits equal to voltage cutoffs for SOC calculations.

Reads "Lower voltage cut-off [V]" and "Upper voltage cut-off [V]" and produces "Open-circuit voltage at 0% SOC [V]" and "Open-circuit voltage at 100% SOC [V]", establishing the relationship between SOC and voltage windows.

Extends: ionworks_schema.calculations.calculations.Calculation

model_config = {'arbitrary_types_allowed': True, 'extra': 'forbid', 'populate_by_name': True, 'validate_assignment': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

model_post_init(context: Any, /) None

This function is meant to behave like a BaseModel method to initialise private attributes.

It takes context as an argument since that’s what pydantic-core passes when calling it.

Args:

self: The BaseModel instance. context: The context.

class ionworks_schema.calculations.PorosityFromElectrodeVolumeFraction(electrode)

Bases: Calculation

Calculate the porosity from the active material volume fraction.

Parameters

electrodestr

The electrode to calculate the porosity for. Must be either “negative” or “positive”.

Extends: ionworks_schema.calculations.calculations.Calculation

electrode: Literal['positive', 'negative', 'lumped']
model_config = {'arbitrary_types_allowed': True, 'extra': 'forbid', 'populate_by_name': True, 'validate_assignment': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

model_post_init(context: Any, /) None

This function is meant to behave like a BaseModel method to initialise private attributes.

It takes context as an argument since that’s what pydantic-core passes when calling it.

Args:

self: The BaseModel instance. context: The context.

class ionworks_schema.calculations.PouchCellThermalDimensions(source=None)

Bases: Calculation

Calculate thermal properties of rectangular pouch cell.

Reads "Pouch height [m]", "Pouch width [m]", and "Pouch thickness [m]", and produces "Cell volume [m3]" and "Cell cooling surface area [m2]" assuming rectangular prism geometry for thermal modeling.

Examples

>>> calc = iws.calculations.PouchCellThermalDimensions()
>>> config = iws.Pipeline({"thermal": calc}).to_config()

Extends: ionworks_schema.calculations.calculations.Calculation

model_config = {'arbitrary_types_allowed': True, 'extra': 'forbid', 'populate_by_name': True, 'validate_assignment': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

model_post_init(context: Any, /) None

This function is meant to behave like a BaseModel method to initialise private attributes.

It takes context as an argument since that’s what pydantic-core passes when calling it.

Args:

self: The BaseModel instance. context: The context.

class ionworks_schema.calculations.SlopesToKnots(base_parameter_name, breakpoint_values, breakpoint_parameter_name)

Bases: Calculation

Converts slopes and initial value to knot values for piecewise linear interpolation.

This calculation takes as input: - An initial value at the first breakpoint - Slopes for each segment between consecutive breakpoints

And outputs: - The value at each breakpoint (knot values)

The conversion follows: y_{i+1} = y_i + slope_i * (x_{i+1} - x_i)

Reads the initial value at the first breakpoint and the slopes between consecutive breakpoints (e.g. "Particle diffusion time at SOC 0 [s]", "Particle diffusion time slope from SOC 0 to 0.5 [s]"), and produces the knot value at every breakpoint (e.g. "Particle diffusion time at SOC 0.5 [s]", "Particle diffusion time at SOC 1 [s]").

Parameters

base_parameter_namestr

The name of the parameter (e.g., “Particle diffusion time [s]”)

breakpoint_valueslist[float]

List of breakpoint values (e.g., [0.0, 0.5, 1.0])

breakpoint_parameter_namestr

Name of the breakpoint parameter (e.g., “SOC”, “Temperature [K]”)

Extends: ionworks_schema.calculations.calculations.Calculation

base_parameter_name: str
breakpoint_values: list[int | float]
breakpoint_parameter_name: str
model_config = {'arbitrary_types_allowed': True, 'extra': 'forbid', 'populate_by_name': True, 'validate_assignment': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

model_post_init(context: Any, /) None

This function is meant to behave like a BaseModel method to initialise private attributes.

It takes context as an argument since that’s what pydantic-core passes when calling it.

Args:

self: The BaseModel instance. context: The context.

class ionworks_schema.calculations.SlopesToKnots2D(base_parameter_name, breakpoint1_values, breakpoint1_parameter_name, breakpoint2_values, breakpoint2_parameter_name)

Bases: Calculation

Converts slopes and initial value to knot values for 2D piecewise linear interpolation.

This calculation takes as input: - An initial value at (bp1_0, bp2_0) - Slopes along dimension 1 for the first row (at bp2_0) - Slopes along dimension 2 for all subsequent rows

And outputs: - The value at each 2D grid point (knot values)

The conversion follows the same strategy as PiecewiseInterpolation2D slopes mode: 1. Start with initial value at (bp1_0, bp2_0) 2. Use bp1-slopes to fill first row 3. Use bp2-slopes to fill remaining rows

Reads the initial value at (bp1_0, bp2_0), the bp1-slopes along the first row (e.g. "Diffusivity SOC-slope from SOC 0 to 1 at Temperature [K] 273.15 [m2.s-1]"), and the bp2-slopes for each bp1 grid point (e.g. "Diffusivity Temperature [K]-slope from Temperature [K] 273.15 to 323.15 at SOC 0 [m2.s-1]"), and produces the knot value at every 2D grid point.

Parameters

base_parameter_namestr

The name of the parameter (e.g., “Diffusivity [m2.s-1]”)

breakpoint1_valueslist[float]

List of first dimension breakpoint values (e.g., [0.0, 0.5, 1.0])

breakpoint1_parameter_namestr

Name of the first breakpoint parameter (e.g., “SOC”)

breakpoint2_valueslist[float]

List of second dimension breakpoint values (e.g., [273.15, 298.15])

breakpoint2_parameter_namestr

Name of the second breakpoint parameter (e.g., “Temperature [K]”)

Extends: ionworks_schema.calculations.calculations.Calculation

base_parameter_name: str
breakpoint1_values: list[int | float]
breakpoint1_parameter_name: str
breakpoint2_values: list[int | float]
breakpoint2_parameter_name: str
model_config = {'arbitrary_types_allowed': True, 'extra': 'forbid', 'populate_by_name': True, 'validate_assignment': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

model_post_init(context: Any, /) None

This function is meant to behave like a BaseModel method to initialise private attributes.

It takes context as an argument since that’s what pydantic-core passes when calling it.

Args:

self: The BaseModel instance. context: The context.

class ionworks_schema.calculations.SpecificHeatCapacity(source=None)

Bases: Calculation

Calculate the specific heat capacity from the lumped heat capacity and cell mass.

Examples

>>> calc = iws.calculations.SpecificHeatCapacity()
>>> config = iws.Pipeline({"cp": calc}).to_config()

Extends: ionworks_schema.calculations.calculations.Calculation

model_config = {'arbitrary_types_allowed': True, 'extra': 'forbid', 'populate_by_name': True, 'validate_assignment': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

model_post_init(context: Any, /) None

This function is meant to behave like a BaseModel method to initialise private attributes.

It takes context as an argument since that’s what pydantic-core passes when calling it.

Args:

self: The BaseModel instance. context: The context.

class ionworks_schema.calculations.StoichiometryAtMinimumSOC(electrode)

Bases: Calculation

Calculate the stoichiometry at the minimum SOC based on the stoichiometry at the maximum SOC, the electrode capacities, and the useable capacity.

Parameters

electrodestr

The electrode to calculate the initial concentration for, either “positive” or “negative”.

Extends: ionworks_schema.calculations.calculations.Calculation

electrode: Literal['positive', 'negative', 'lumped']
model_config = {'arbitrary_types_allowed': True, 'extra': 'forbid', 'populate_by_name': True, 'validate_assignment': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

model_post_init(context: Any, /) None

This function is meant to behave like a BaseModel method to initialise private attributes.

It takes context as an argument since that’s what pydantic-core passes when calling it.

Args:

self: The BaseModel instance. context: The context.

class ionworks_schema.calculations.StoichiometryLimitsFromCapacity(options=None)

Bases: Calculation

Calculate the minimum and maximum stoichiometries for each electrode in a full-cell based on the electrode total capacity, lower and upper excess capacities.

Parameters

optionsdict, optional

A dictionary of options to be passed to the calculation. The following options are available:

  • direction: str

    The direction to use for the calculation. Can be “charge” or “discharge”. Default is None. If a direction is specified, the lower and upper excess capacities are calculated based on the direction.

  • particle phases: tuple of str

    Specifies the number of phases for each electrode as a tuple (negative, positive). Each element can be “1” (single phase) or “2” (composite with Primary and Secondary phases). Default is (“1”, “1”).

Extends: ionworks_schema.calculations.calculations.Calculation

options: dict[str, Any] | None
model_config = {'arbitrary_types_allowed': True, 'extra': 'forbid', 'populate_by_name': True, 'validate_assignment': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

model_post_init(context: Any, /) None

This function is meant to behave like a BaseModel method to initialise private attributes.

It takes context as an argument since that’s what pydantic-core passes when calling it.

Args:

self: The BaseModel instance. context: The context.

class ionworks_schema.calculations.SurfaceAreaToVolumeRatio(electrode)

Bases: Calculation

Calculate the surface area to volume ratio for the electrodes from the active material volume fraction and particle radius, assuming spherical particles.

Parameters

electrodestr

The electrode to calculate the surface area to volume ratio for, either “positive”, “negative” or “both”.

Extends: ionworks_schema.calculations.calculations.Calculation

electrode: Literal['positive', 'negative', 'lumped']
model_config = {'arbitrary_types_allowed': True, 'extra': 'forbid', 'populate_by_name': True, 'validate_assignment': True, 'validate_by_alias': True, 'validate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

model_post_init(context: Any, /) None

This function is meant to behave like a BaseModel method to initialise private attributes.

It takes context as an argument since that’s what pydantic-core passes when calling it.

Args:

self: The BaseModel instance. context: The context.