Models (moirae.models)#

Models for the physics, state of health, and transient states of energy storage systems

Cell Models#

Each cell model is in its own submodule to limit dependency conflicts.

Base Classes (moirae.models.base)#

Base classes which define the state of a storage system, the control signals applied to it, the outputs observable from it, and the mathematical models which links state, control, and outputs together.

class moirae.models.base.CellModel#

Bases: object

Base model for an energy storage system.

Cell models describe how to update the transient state of a system and compute expected outputs given the inputs and current A-SOH.

abstract calculate_terminal_voltage(new_inputs: InputQuantities, transient_state: GeneralContainer, asoh: HealthVariable) OutputQuantities#

Compute expected output (terminal voltage, etc.) of the cell.

Parameters:
  • new_inputs – Inputs at the current time step

  • transient_state – Current transient state

  • asoh – Health parameters of the cell

Returns:

Estimates for all measurable outputs of a cell

abstract update_transient_state(previous_inputs: InputQuantities, new_inputs: InputQuantities, transient_state: GeneralContainer, asoh: HealthVariable) GeneralContainer#

Update the transient state of a chemical cell

Parameters:
  • previous_inputs – Inputs at the last time step

  • new_inputs – Inputs at the current time step

  • transient_state – Current transient state

  • asoh – Health parameters of the cell

Returns:

A new transient state

class moirae.models.base.DegradationModel#

Bases: object

Base class for A-SOH aging models.

Degradation models update the A-SOH incrementally given the current transient state, similar to how the CellModel updates the transient state given current A-SOH.

abstract update_asoh(previous_asoh: HealthVariable, new_inputs: InputQuantities, new_transients: GeneralContainer | None, new_measurements: OutputQuantities | None) HealthVariable#

Degrade previous A-SOH based on inputs.

Parameters:
  • previous_asoh – previous A-SOH to be updated

  • new_inputs – new inputs since the previous A-SOH

  • new_transients – new transient states since the previous A-SOH

  • new_measurements – new outputs since the previous A-SOH

Returns:

A new A-SOH object representing the degraded state

pydantic model moirae.models.base.GeneralContainer#

Bases: BaseModel

General container class to store numeric variables.

Like the HealthVariable all values are stored as 2d numpy arrays where the first dimension is a batch dimension. Accordingly, denote the types of attributes using the ScalarParameter or ListParameter for scalar and 1-dimensional data, respectively.

Create a new model by parsing and validating input data from keyword arguments.

Raises [ValidationError][pydantic_core.ValidationError] if the input data cannot be validated to form a valid model.

self is explicitly positional-only to allow self as a field name.

Config:
  • arbitrary_types_allowed: bool = True

expand_names(names: Iterable[str]) tuple[str, ...]#

Expand a single name per field to a distinct name for each value within the field

from_numpy(values: ndarray) None#

Updates field values from a numpy array

length_field(field_name: str) int#

Returns length of provided field name. If the field is a float, returns 1, otherwise, returns length of array. If field is None, returns 0.

make_copy(values: ndarray) Self#

Helper method that returns a copy of the current object with values specified by numpy.ndarray

Parameters:

values – numpy array containing values to be used in copy

to_numpy() ndarray#

Outputs everything that is stored as a two-dimensional np.ndarray

property all_fields: tuple[str, ...]#

Names of all fields of the model in the order they appear in to_numpy()

Returns a single name per field, regardless of whether the field is a scalar or vector. See all_names() to get a single name per value.

property all_names: tuple[str, ...]#

Names of each value within the vector

property batch_size: int#

Batch size determined from the batch dimension of all attributes

pydantic model moirae.models.base.HealthVariable#

Bases: BaseModel

Base class for a container which holds the physical parameters of system and which ones are being treated as updatable.

Create a new model by parsing and validating input data from keyword arguments.

Raises [ValidationError][pydantic_core.ValidationError] if the input data cannot be validated to form a valid model.

self is explicitly positional-only to allow self as a field name.

Config:
  • arbitrary_types_allowed: bool = True

Fields:
Validators:
field updatable: set[str] [Optional]#

Which fields are to be treated as updatable by a parameter estimator

Validated by:
validator check_batch_size  »  all fields#
expand_names(names: Iterable[str]) Tuple[str, ...]#

Expand names which define a collection of values to one for each number.

Each member of a list of values become are annotated with [i] notation.

class ListHealth(HealthVariable):
    x: ListParameter = 1.

a = ListHealth()
a.expand_names(['x'])  # == ['x[0]']

Names of values that are themselves HealthVariable are expanded to include all values

class Health(HealthVariable):
    a: ListHealth

h = Health(a=a)
h.expand_names(["a"])  # == ['a.x[0]']
h.expand_names(["a.x"])  # == ['a.x[0]']
Parameters:

names – List of names to be expanded

Returns:

Expanded names

get_parameters(names: Sequence[str] | None = None) ndarray#

Get updatable parameters as a numpy vector

Parameters:

names – Names of the parameters to gather. If None, then will return all updatable parameters

Returns:

A numpy array of the values

iter_parameters(updatable_only: bool = True, recurse: bool = True) Iterator[tuple[str, ndarray]]#

Iterate over all parameters which are treated as updatable

Parameters:
  • updatable_only – Only iterate over variables which are updatable

  • recurse – Whether to gather parameters from attributes which are also HealthVariable classes.

Yields:

Tuple of names and parameter values as numpy arrays. The name of parameters from attributes which are HealthVariable will start will be “<name of attribute in this class>.<name of attribute in submodel>”

make_copy(values: ndarray, names: Sequence[str] | None = None) Self#

Create a copy of the current object with values specified by numpy.ndarray

Parameters:
  • values – numpy array containing values to be used in copy

  • names – sequence of the names of attributes to be returned with the values passed. If None, changes all updatable parameters

mark_all_fixed(recurse: bool = True)#

Mark all fields in the model as not updatable

Parameters:

recurse – Whether to mark all variables of submodels as not updatable

mark_all_updatable(recurse: bool = True)#

Make all fields in the model updatable

Parameters:

recurse – Make all parameters of each submodel updatable too

mark_updatable(name: str)#

Mark a specific variable as updatable

Will mark any submodel along the path to the requested name as updatable.

Parameters:

name – Name of the variable to be set as updatable

set_value(name: str, value: float | ndarray)#

Set the value of a certain variable by name

Parameters:
  • name – Name of the parameter to set.

  • value – Updated value

update_parameters(values: ndarray | list[float], names: Sequence[str] | None = None)#

Set the value for updatable parameters given their names

Parameters:
  • values – Values of the parameters to set

  • names – Names of the parameters to set. If None, then will set all updatable parameters

property all_fields: tuple[str, ...]#

Names of all fields which correspond to physical parameters and their types

property all_fields_with_types: tuple[tuple[str, Literal['parameter', 'variable', 'sequence', 'dict']], ...]#

Names of all fields which correspond to physical parameters and their types

Types of fields include:
  • parameter: a NumPy array of health parameter values

  • variable: another HealthVariable class

  • sequence: a list of HealthVariables

  • dict: a map of HealthVariables

property all_names: Tuple[str, ...]#

Names of all updatable parameters

property batch_size: int#

Batch size of this parameter

property num_updatable#

Number of updatable parameters in this HealthVariable

property updatable_names: Tuple[str, ...]#

Names of all updatable parameters

pydantic model moirae.models.base.InputQuantities#

Bases: GeneralContainer

The control of a battery system, such as the terminal current

Create a new model by parsing and validating input data from keyword arguments.

Raises [ValidationError][pydantic_core.ValidationError] if the input data cannot be validated to form a valid model.

self is explicitly positional-only to allow self as a field name.

Config:
  • arbitrary_types_allowed: bool = True

Fields:
field current: _encode_ndarray, return_type=PydanticUndefined, when_used=json-unless-none)] = 0.0#

Current applied to the storage system. Units: A

Constraints:
  • func = <function _encode_ndarray at 0x7f7b73e99900>

  • json_schema_input_type = PydanticUndefined

  • return_type = PydanticUndefined

  • when_used = json-unless-none

field temperature: _encode_ndarray, return_type=PydanticUndefined, when_used=json-unless-none)] | None = None#

Temperature reading(s). Units: °C

field time: _encode_ndarray, return_type=PydanticUndefined, when_used=json-unless-none)] = 0.0#

Timestamp(s) of inputs. Units: s

Constraints:
  • func = <function _encode_ndarray at 0x7f7b73e99900>

  • json_schema_input_type = PydanticUndefined

  • return_type = PydanticUndefined

  • when_used = json-unless-none

moirae.models.base.ListParameter#

Type annotation for parameters which can be any number of values

alias of Annotated[ndarray, FieldInfo(annotation=NoneType, required=True, json_schema_extra={‘type’: ‘moirae_parameter’}), BeforeValidator(func=~moirae.models.base., json_schema_input_type=PydanticUndefined), FieldInfo(annotation=NoneType, required=True, validate_default=True), WrapSerializer(func=_encode_ndarray, return_type=PydanticUndefined, when_used=json-unless-none)]

moirae.models.base.NumpyType#

Type annotation for a field which is a numpy array but does not requires the batch dimensions used by parameters

alias of Annotated[ndarray, BeforeValidator(func=array, json_schema_input_type=PydanticUndefined), FieldInfo(annotation=NoneType, required=True), WrapSerializer(func=_encode_ndarray, return_type=PydanticUndefined, when_used=json-unless-none)]

pydantic model moirae.models.base.OutputQuantities#

Bases: GeneralContainer

Output for observables from a battery system

Create a new model by parsing and validating input data from keyword arguments.

Raises [ValidationError][pydantic_core.ValidationError] if the input data cannot be validated to form a valid model.

self is explicitly positional-only to allow self as a field name.

Config:
  • arbitrary_types_allowed: bool = True

Fields:
field terminal_voltage: _encode_ndarray, return_type=PydanticUndefined, when_used=json-unless-none)] [Required]#

Voltage output of a battery cell/model. Units: V

Constraints:
  • func = <function _encode_ndarray at 0x7f7b73e99900>

  • json_schema_input_type = PydanticUndefined

  • return_type = PydanticUndefined

  • when_used = json-unless-none

moirae.models.base.ScalarParameter#

Type annotation for parameters which are exactly one value

alias of Annotated[ndarray, FieldInfo(annotation=NoneType, required=True, json_schema_extra={‘type’: ‘moirae_parameter’}), BeforeValidator(func=~moirae.models.base., json_schema_input_type=PydanticUndefined), FieldInfo(annotation=NoneType, required=True, validate_default=True), WrapSerializer(func=_encode_ndarray, return_type=PydanticUndefined, when_used=json-unless-none)]

moirae.models.base.enforce_dimensions(x: Any, dim=1) ndarray#

Make sure an array is the desired shape for batching

Arrays must be 2D or greater and the first dimension is always the batch dimension. That means arrays which represent “scalar values” (dim == 0), have shape (batches, 1).

Parameters:
  • x – Value to be altered

  • dim – Dimensionality of numbers being represented

Returns:

Array ready for use in a HealthVariable, etc

Reusable Components (moirae.models.components)#

Definitions of components used by multiple types of models

SOC-Dependent ASOH (moirae.models.components.soc)#

Models for parameters which vary as a function of SOC

moirae.models.components.soc.FloatOrArray#

A number of list of numbers

alias of Number | List[float] | ndarray

pydantic model moirae.models.components.soc.SOCDependentHealth#

Bases: HealthVariable

Interface for variables whose values depend on the state of charge

Create a new model by parsing and validating input data from keyword arguments.

Raises [ValidationError][pydantic_core.ValidationError] if the input data cannot be validated to form a valid model.

self is explicitly positional-only to allow self as a field name.

Config:
  • arbitrary_types_allowed: bool = True

Fields:

Validators:

abstract get_value(soc: Number | List[float] | ndarray, batch_id: int | None = None) ndarray#

Computes value(s) at given SOC(s).

Parameters:
  • soc

    Values at which to compute the property. Dimensions must be either

    1. a 2D array of shape (batch_size, soc_dim). The batch_size must either be 1 or equal to the batch size fo the parameters.

    2. a 1D array of shape (soc_dim,), in which case we will consider the batch_size to be equal to 1

    3. a 0D array (a scalar), in which case both batch_size and soc_dim are equal to 1.

  • batch_id – Which batch member for the parameters and input SOC values to use. Default is to use whole batch

Returns:

Interpolated values as a 2D with dimensions (batch_size, soc_points). The batch_size is 0 when batch_id is not None.

pydantic model moirae.models.components.soc.SOCInterpolatedHealth#

Bases: SOCDependentHealth

Health variables where SOC dependence is described by a piecewise-polynomial

Create a new model by parsing and validating input data from keyword arguments.

Raises [ValidationError][pydantic_core.ValidationError] if the input data cannot be validated to form a valid model.

self is explicitly positional-only to allow self as a field name.

Config:
  • arbitrary_types_allowed: bool = True

Fields:
Validators:

field base_values: _encode_ndarray, return_type=PydanticUndefined, when_used=json-unless-none)] = 0#

Values at specified SOCs

Constraints:
  • func = <function _encode_ndarray at 0x7f7b73e99900>

  • json_schema_input_type = PydanticUndefined

  • return_type = PydanticUndefined

  • when_used = json-unless-none

Validated by:
field interpolation_style: Literal['linear', 'nearest', 'nearest-up', 'zero', 'slinear', 'quadratic', 'cubic', 'previous', 'next'] = 'linear'#

Type of interpolation to perform

Validated by:
field soc_pinpoints: _encode_ndarray, return_type=PydanticUndefined, when_used=json-unless-none)] | None = None#

SOC pinpoints for interpolation.

Validated by:
get_value(soc: Number | List[float] | ndarray, batch_id: int | None = None) ndarray#

Computes value(s) at given SOC(s).

Parameters:
  • soc

    Values at which to compute the property. Dimensions must be either

    1. a 2D array of shape (batch_size, soc_dim). The batch_size must either be 1 or equal to the batch size fo the parameters.

    2. a 1D array of shape (soc_dim,), in which case we will consider the batch_size to be equal to 1

    3. a 0D array (a scalar), in which case both batch_size and soc_dim are equal to 1.

  • batch_id – Which batch member for the parameters and input SOC values to use. Default is to use whole batch

Returns:

Interpolated values as a 2D with dimensions (batch_size, soc_points). The batch_size is 0 when batch_id is not None.

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.

Parameters:
  • self – The BaseModel instance.

  • context – The context.

pydantic model moirae.models.components.soc.SOCPolynomialHealth#

Bases: SOCDependentHealth

A health parameter whose value is described by a power-series polynomial

Create a new model by parsing and validating input data from keyword arguments.

Raises [ValidationError][pydantic_core.ValidationError] if the input data cannot be validated to form a valid model.

self is explicitly positional-only to allow self as a field name.

Config:
  • arbitrary_types_allowed: bool = True

Fields:
  • coeffs (Annotated[numpy.ndarray, FieldInfo(annotation=NoneType, required=True, json_schema_extra={'type': 'moirae_parameter'}), pydantic.functional_validators.BeforeValidator(func=moirae.models.base.

Validators:

field coeffs: _encode_ndarray, return_type=PydanticUndefined, when_used=json-unless-none)] = 1.0#

Coefficients for the polynomial

Constraints:
  • func = <function _encode_ndarray at 0x7f7b73e99900>

  • json_schema_input_type = PydanticUndefined

  • return_type = PydanticUndefined

  • when_used = json-unless-none

Validated by:
get_value(soc: Number | List[float] | ndarray, batch_id: int | None = None) Number | List[float] | ndarray#

Computes value(s) at given SOC(s).

Parameters:
  • soc

    Values at which to compute the property. Dimensions must be either

    1. a 2D array of shape (batch_size, soc_dim). The batch_size must either be 1 or equal to the batch size fo the parameters.

    2. a 1D array of shape (soc_dim,), in which case we will consider the batch_size to be equal to 1

    3. a 0D array (a scalar), in which case both batch_size and soc_dim are equal to 1.

  • batch_id – Which batch member for the parameters and input SOC values to use. Default is to use whole batch

Returns:

Interpolated values as a 2D with dimensions (batch_size, soc_points). The batch_size is 0 when batch_id is not None.

pydantic model moirae.models.components.soc.ScaledSOCInterpolatedHealth#

Bases: SOCInterpolatedHealth

SOC interpolated health with scaling factors to adjust the shape of the curve

Scaling factors adjust the shape produced from the interpolation by an additive or multiplicative factor which varies as a function of SOC. The scaling factor is described using Legendre polynomials defined over the region of [0, 1].

Create a new model by parsing and validating input data from keyword arguments.

Raises [ValidationError][pydantic_core.ValidationError] if the input data cannot be validated to form a valid model.

self is explicitly positional-only to allow self as a field name.

Config:
  • arbitrary_types_allowed: bool = True

Fields:
  • additive (bool)

  • scaling_coeffs (Annotated[numpy.ndarray, FieldInfo(annotation=NoneType, required=True, json_schema_extra={'type': 'moirae_parameter'}), pydantic.functional_validators.BeforeValidator(func=moirae.models.base.

Validators:

field additive: bool = True#

Whether to add or multiply interpolated value with the scaling factor

Validated by:
field scaling_coeffs: _encode_ndarray, return_type=PydanticUndefined, when_used=json-unless-none)] [Required]#

Coefficients of a Legendre polynomial used to adjust the interpolation

Constraints:
  • func = <function _encode_ndarray at 0x7f7b73e99900>

  • json_schema_input_type = PydanticUndefined

  • return_type = PydanticUndefined

  • when_used = json-unless-none

Validated by:
get_value(soc: Number | List[float] | ndarray, batch_id: int | None = None) ndarray#

Computes value(s) at given SOC(s).

Parameters:
  • soc

    Values at which to compute the property. Dimensions must be either

    1. a 2D array of shape (batch_size, soc_dim). The batch_size must either be 1 or equal to the batch size fo the parameters.

    2. a 1D array of shape (soc_dim,), in which case we will consider the batch_size to be equal to 1

    3. a 0D array (a scalar), in which case both batch_size and soc_dim are equal to 1.

  • batch_id – Which batch member for the parameters and input SOC values to use. Default is to use whole batch

Returns:

Interpolated values as a 2D with dimensions (batch_size, soc_points). The batch_size is 0 when batch_id is not None.

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.

Parameters:
  • self – The BaseModel instance.

  • context – The context.

moirae.models.components.soc.adjust_soc_shape(soc: Number | List | ndarray) ndarray#

Adjust the SOC from a user-provided shape to 2D array

Parameters:

soc – SOC, as provided by user

Returns:

2D array where first dimension is the batch and second is the SOC values.

(SOC,T)-Dependent ASOH (moirae.models.components.soc)#

Models for parameters which vary as a function of SOC

pydantic model moirae.models.components.soc_t.SOCTempDependentHealth#

Bases: HealthVariable

Interface for variables whose values depend on the state of charge

Create a new model by parsing and validating input data from keyword arguments.

Raises [ValidationError][pydantic_core.ValidationError] if the input data cannot be validated to form a valid model.

self is explicitly positional-only to allow self as a field name.

Config:
  • arbitrary_types_allowed: bool = True

Fields:

Validators:

abstract get_value(soc: Number | List[float] | ndarray, temp: Number | List[float] | ndarray, batch_id: int | None = None) ndarray#

Computes value(s) at given SOC(s).

Parameters:
  • soc

    Values at which to compute the property. Dimensions must be either

    1. a 2D array of shape (batch_size, soc_dim). The batch_size must either be 1 or equal to the batch size fo the parameters.

    2. a 1D array of shape (soc_dim,), in which case we will consider the batch_size to be equal to 1

    3. a 0D array (a scalar), in which case both batch_size and soc_dim are equal to 1.

  • temp – Temperatures at which to evaluate the property. (Units: °C) Dimensions follow the same format as soc.

  • batch_id – Which batch member for the parameters and input SOC values to use. Default is to use whole batch

Returns:

Interpolated values as a 2D with dimensions (batch_size, soc_points). The batch_size is 0 when batch_id is not None.

pydantic model moirae.models.components.soc_t.SOCTempPolynomialHealth#

Bases: SOCTempDependentHealth

A parameter where the dependence on SOC and temperature are described by polynomial

The temperature-dependence is described by a polynomial centered on a reference temperature, \(f_T(T) = c_0 + c_1 (T - T_{ref}) + ...\)

The SOC-dependence is described by a polynomial as well, \(f_{SOC}(soc) = c_0 + c_1 * soc + ...\)

The two are added to express dependence in both: \(f(T, SOC) = f_T(T) + f_{SOC}(SOC)\)

Create a new model by parsing and validating input data from keyword arguments.

Raises [ValidationError][pydantic_core.ValidationError] if the input data cannot be validated to form a valid model.

self is explicitly positional-only to allow self as a field name.

Config:
  • arbitrary_types_allowed: bool = True

Fields:
  • soc_coeffs (Annotated[numpy.ndarray, FieldInfo(annotation=NoneType, required=True, json_schema_extra={'type': 'moirae_parameter'}), pydantic.functional_validators.BeforeValidator(func=moirae.models.base.

  • t_coeffs (Annotated[numpy.ndarray, FieldInfo(annotation=NoneType, required=True, json_schema_extra={'type': 'moirae_parameter'}), pydantic.functional_validators.BeforeValidator(func=moirae.models.base.

  • t_ref (Annotated[numpy.ndarray, FieldInfo(annotation=NoneType, required=True, json_schema_extra={'type': 'moirae_parameter'}), pydantic.functional_validators.BeforeValidator(func=moirae.models.base.

Validators:

field soc_coeffs: _encode_ndarray, return_type=PydanticUndefined, when_used=json-unless-none)] = 1.0#

Reference parameters for the OCV dependence polynomial

Constraints:
  • func = <function _encode_ndarray at 0x7f7b73e99900>

  • json_schema_input_type = PydanticUndefined

  • return_type = PydanticUndefined

  • when_used = json-unless-none

Validated by:
field t_coeffs: _encode_ndarray, return_type=PydanticUndefined, when_used=json-unless-none)] = 0.0#

Reference parameters for the temperature dependence polynomial

Constraints:
  • func = <function _encode_ndarray at 0x7f7b73e99900>

  • json_schema_input_type = PydanticUndefined

  • return_type = PydanticUndefined

  • when_used = json-unless-none

Validated by:
field t_ref: _encode_ndarray, return_type=PydanticUndefined, when_used=json-unless-none)] = 25.0#

Reference temperature for the temperature dependence. Units: °C

Constraints:
  • func = <function _encode_ndarray at 0x7f7b73e99900>

  • json_schema_input_type = PydanticUndefined

  • return_type = PydanticUndefined

  • when_used = json-unless-none

Validated by:
get_value(soc: Number | List[float] | ndarray, temp: Number | List[float] | ndarray, batch_id: int | None = None) ndarray#

Computes value(s) at given SOC(s).

Parameters:
  • soc

    Values at which to compute the property. Dimensions must be either

    1. a 2D array of shape (batch_size, soc_dim). The batch_size must either be 1 or equal to the batch size fo the parameters.

    2. a 1D array of shape (soc_dim,), in which case we will consider the batch_size to be equal to 1

    3. a 0D array (a scalar), in which case both batch_size and soc_dim are equal to 1.

  • temp – Temperatures at which to evaluate the property. (Units: °C) Dimensions follow the same format as soc.

  • batch_id – Which batch member for the parameters and input SOC values to use. Default is to use whole batch

Returns:

Interpolated values as a 2D with dimensions (batch_size, soc_points). The batch_size is 0 when batch_id is not None.