Models

Schemas for battery models supported by the pipeline.

Schemas for models.

class ionworks.pipeline.models.ECM(options=None, simulation_settings=None)[source]

Bases: BaseSchema

A class for the Equivalent Circuit Model.

Parameters:
  • options (ECMOptions or dict, optional) – See ECMOptions for the available keys.

  • simulation_settings (SimulationSettings or dict, optional) – Persistent simulation settings (mesh + solver) re-applied at simulation time. When None the model defaults are used.

options: ECMOptions | None
simulation_settings: Annotated[SimulationSettings | dict[str, Any], FieldInfo(annotation=NoneType, required=True, metadata=[_PydanticGeneralMetadata(union_mode='left_to_right')])] | None
model_config = {'arbitrary_types_allowed': True, 'extra': 'forbid', 'populate_by_name': True, 'validate_assignment': 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 initialize 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.pipeline.models.ECMOptions(*, thermal: Literal['isothermal', 'lumped', 'two-state'] = 'isothermal', rc_pairs: Annotated[str, _PydanticGeneralMetadata(pattern='^\\d+$')] = '0', capacity: Literal['constant', 'function'] = 'constant', resistance_scale: Literal['constant', 'function'] = 'constant', butler_volmer: Literal['false', 'true'] = 'false', parameter_dependencies: dict[str, Any] | None = None)[source]

Bases: _ModelOptions

Options for an ECM model. See ECM for the physical meaning of each key.

thermal: Literal['isothermal', 'lumped', 'two-state']
rc_pairs: str
capacity: Literal['constant', 'function']
resistance_scale: Literal['constant', 'function']
butler_volmer: Literal['false', 'true']
parameter_dependencies: dict[str, Any] | None
model_config = {'arbitrary_types_allowed': True, 'extra': 'forbid', 'populate_by_name': True, 'validate_assignment': 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 initialize 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.pipeline.models.GITTModel(options=None, simulation_settings=None)[source]

Bases: BaseSchema

Diffusion-only model for fitting solid diffusivities to GITT or pulse data.

The model solves x-averaged spherical particle diffusion in each modelled electrode, with the surface flux set by the applied current, and computes the cell voltage from the electrode open-circuit potentials evaluated at the particle surface stoichiometries, minus an ohmic drop through a single lumped "Ohmic resistance [Ohm]" parameter. There are no reaction kinetics (Butler-Volmer), no electrolyte dynamics, and no thermal effects; all parameters are constant except the open-circuit potentials.

The "working electrode" option selects the cell configuration:

  • "both" (default): full cell. Both electrodes are modelled and the voltage is the difference of their open-circuit potentials minus the ohmic drop. A positive (discharge) current delithiates the negative electrode and lithiates the positive electrode.

  • "positive": half-cell against a lithium-metal counter electrode, following the pybamm half-cell convention. Only the working electrode is modelled (the counter electrode contributes no overpotential) and the voltage is its open-circuit potential minus the ohmic drop. A positive (discharge) current lithiates the working electrode. As in pybamm, anode-material half cells are also expressed with "positive" — rename the anode’s parameters to the positive convention first.

This is a fitting model intended for extracting solid-phase diffusivities (and the lumped ohmic resistance) from GITT or pulse-relaxation measurements — it is not a general-purpose simulation model. Each modelled electrode is parameterised with the standard full-cell parameter names (thickness, active material volume fraction, particle radius, diffusivity, OCP, maximum and initial concentrations) plus the current function, electrode cross-sectional area, initial temperature, and "Ohmic resistance [Ohm]".

Parameters:
  • options (GITTModelOptions or dict, optional) – See GITTModelOptions for the available keys.

  • simulation_settings (SimulationSettings or dict, optional) – Persistent simulation settings (mesh + solver) re-applied at simulation time. When None the model defaults are used.

options: GITTModelOptions | None
simulation_settings: Annotated[SimulationSettings | dict[str, Any], FieldInfo(annotation=NoneType, required=True, metadata=[_PydanticGeneralMetadata(union_mode='left_to_right')])] | None
model_config = {'arbitrary_types_allowed': True, 'extra': 'forbid', 'populate_by_name': True, 'validate_assignment': 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 initialize 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.pipeline.models.GITTModelOptions(*, working_electrode: Literal['both', 'positive'] = 'both', **extra_data: Any)[source]

Bases: _ModelOptions

Options for a GITTModel.

A hybrid bag: working electrode is typed, and any other key is forwarded to the underlying pybamm BatteryModelOptions unchanged (extra=allow).

model_config = {'arbitrary_types_allowed': True, 'extra': 'allow', 'populate_by_name': True, 'validate_assignment': True}

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

working_electrode: Literal['both', 'positive']
model_post_init(context: Any, /) → None

This function is meant to behave like a BaseModel method to initialize 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.pipeline.models.LumpedSPMeR(options=None, simulation_settings=None)[source]

Bases: BaseSchema

A class for the Lumped Single Particle Model with electrolyte and Resistance.

options: LumpedSPMROptions | None
simulation_settings: Annotated[SimulationSettings | dict[str, Any], FieldInfo(annotation=NoneType, required=True, metadata=[_PydanticGeneralMetadata(union_mode='left_to_right')])] | None
model_config = {'arbitrary_types_allowed': True, 'extra': 'forbid', 'populate_by_name': True, 'validate_assignment': 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 initialize 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.pipeline.models.LumpedSPMR(options=None, simulation_settings=None)[source]

Bases: BaseSchema

A class for the Lumped Single Particle Model with Resistance.

options: LumpedSPMROptions | None
simulation_settings: Annotated[SimulationSettings | dict[str, Any], FieldInfo(annotation=NoneType, required=True, metadata=[_PydanticGeneralMetadata(union_mode='left_to_right')])] | None
model_config = {'arbitrary_types_allowed': True, 'extra': 'forbid', 'populate_by_name': True, 'validate_assignment': 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 initialize 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.pipeline.models.LumpedSPMROptions(*, thermal: Literal['isothermal', 'lumped'] = 'isothermal', surface_temperature: Literal['ambient', 'lumped'] = 'ambient', working_electrode: Literal['both'] = 'both')[source]

Bases: _ModelOptions

Options for a LumpedSPMR (and LumpedSPMeR) model.

thermal: Literal['isothermal', 'lumped']
surface_temperature: Literal['ambient', 'lumped']
working_electrode: Literal['both']
model_config = {'arbitrary_types_allowed': True, 'extra': 'forbid', 'populate_by_name': True, 'validate_assignment': 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 initialize 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.pipeline.models.MSMRFullCellModel(negative_electrode_model, positive_electrode_model, options=None, simulation_settings=None)[source]

Bases: BaseSchema

Full-cell MSMR model of the open-circuit potential — pairs a negative and positive half-cell MSMR model into one full-cell OCV.

Use this with MSMRFullCell to fit an MSMR description of a full cell from full-cell OCV data.

Parameters:
  • negative_electrode_model (MSMRHalfCellModel) – MSMR model for the negative electrode.

  • positive_electrode_model (MSMRHalfCellModel) – MSMR model for the positive electrode.

  • options (dict, optional) – Extra options forwarded to the underlying model.

  • simulation_settings (SimulationSettings or dict, optional) – Persistent simulation settings (mesh + solver) re-applied at simulation time. When None the model defaults are used.

negative_electrode_model: Annotated[dict[str, Any] | BaseSchema, FieldInfo(annotation=NoneType, required=True, metadata=[_PydanticGeneralMetadata(union_mode='left_to_right')])]
positive_electrode_model: Annotated[dict[str, Any] | BaseSchema, FieldInfo(annotation=NoneType, required=True, metadata=[_PydanticGeneralMetadata(union_mode='left_to_right')])]
options: dict[str, Any] | None
simulation_settings: Annotated[SimulationSettings | dict[str, Any], FieldInfo(annotation=NoneType, required=True, metadata=[_PydanticGeneralMetadata(union_mode='left_to_right')])] | None
model_config = {'arbitrary_types_allowed': True, 'extra': 'forbid', 'populate_by_name': True, 'validate_assignment': 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 initialize 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.pipeline.models.MSMRHalfCellModel(electrode, options=None, simulation_settings=None)[source]

Bases: BaseSchema

Half-cell MSMR (Multi-Species Multi-Reaction) model for one electrode’s open-circuit potential.

For a composite electrode (particle phases = "2") the lower excess may be given either as a per-phase split (Primary/Secondary: {Electrode} electrode lower excess capacity [A.h], summed) when it is known from another source, or as a single electrode-level {Electrode} electrode lower excess capacity [A.h] when it is not.

Parameters:
  • electrode (str) – Electrode the model describes — "positive" or "negative".

  • options (MSMRHalfCellModelOptions or dict, optional) – See MSMRHalfCellModelOptions for the available keys.

  • simulation_settings (SimulationSettings or dict, optional) – Persistent simulation settings (mesh + solver) re-applied at simulation time. When None the model defaults are used.

electrode: Literal['positive', 'negative']
options: MSMRHalfCellModelOptions | None
simulation_settings: Annotated[SimulationSettings | dict[str, Any], FieldInfo(annotation=NoneType, required=True, metadata=[_PydanticGeneralMetadata(union_mode='left_to_right')])] | None
model_config = {'arbitrary_types_allowed': True, 'extra': 'forbid', 'populate_by_name': True, 'validate_assignment': 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 initialize 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.pipeline.models.MSMRHalfCellModelOptions(*, capacity_function: Callable | None = None, differential_capacity_function: Callable | None = None, species_format: Literal['Qj', 'Xj'] = 'Qj', direction: Literal['lithiation', 'delithiation'] | None = None, particle_phases: Literal['1', '2'] = '1')[source]

Bases: _ModelOptions

Options for a MSMRHalfCellModel.

capacity_function: Callable | None
differential_capacity_function: Callable | None
species_format: Literal['Qj', 'Xj']
direction: Literal['lithiation', 'delithiation'] | None
particle_phases: Literal['1', '2']
model_config = {'arbitrary_types_allowed': True, 'extra': 'forbid', 'populate_by_name': True, 'validate_assignment': 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 initialize 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.pipeline.models.SimulationSettings(var_pts=None, submesh_types=None, spatial_methods=None, geometry=None, solver=None, discretisation_kwargs=None)[source]

Bases: BaseSchema

pybamm Simulation keyword arguments for a model, parameterized model or run.

A finely resolved fit (e.g. a steep near-surface concentration gradient) can need a refined particle mesh or a specific solver that the model defaults lack. Every field is optional; a higher-precedence source overrides a lower one key by key.

Parameters:
  • var_pts (dict of str to int, optional) – Mesh points per spatial variable, e.g. {"r_n": 16, "r_p": 16}.

  • submesh_types (dict, optional) – Domain name (e.g. "negative particle") to a serialized submesh (pybamm.MeshGenerator.to_config()); a live MeshGenerator is serialized to it.

  • spatial_methods (dict, optional) – Domain name to a serialized pybamm.SpatialMethod.

  • geometry (dict, optional) – Serialized geometry override; when absent it is derived from the model.

  • solver (dict, optional) – Serialized solver (pybamm.BaseSolver.to_config(): the class name under "type" plus its options); a live BaseSolver is serialized to it.

  • discretisation_kwargs (dict of str to bool, optional) – pybamm.Discretisation options (check_model, remove_independent_variables_from_rhs, resolve_coupled_variables).

var_pts: dict[str, int] | None
submesh_types: dict[str, Any] | None
spatial_methods: dict[str, Any] | None
geometry: dict[str, Any] | None
solver: Any | None
discretisation_kwargs: dict[str, bool] | None
model_config = {'arbitrary_types_allowed': True, 'extra': 'forbid', 'populate_by_name': True, 'validate_assignment': 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 initialize 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.pipeline.models.SingleElectrodeLumpedSPMR(options=None, simulation_settings=None)[source]

Bases: BaseSchema

A class for the single-electrode Lumped SPM with Resistance.

options: SingleElectrodeLumpedSPMROptions | None
simulation_settings: Annotated[SimulationSettings | dict[str, Any], FieldInfo(annotation=NoneType, required=True, metadata=[_PydanticGeneralMetadata(union_mode='left_to_right')])] | None
model_config = {'arbitrary_types_allowed': True, 'extra': 'forbid', 'populate_by_name': True, 'validate_assignment': 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 initialize 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.pipeline.models.SingleElectrodeLumpedSPMROptions(*, thermal: Literal['isothermal', 'lumped'] = 'isothermal', surface_temperature: Literal['ambient', 'lumped'] = 'ambient', rc_pairs: Annotated[str, _PydanticGeneralMetadata(pattern='^\\d+$')] = '0', parameter_dependencies: dict[str, Any] | None = None)[source]

Bases: _ModelOptions

Options for a SingleElectrodeLumpedSPMR model.

thermal: Literal['isothermal', 'lumped']
surface_temperature: Literal['ambient', 'lumped']
rc_pairs: str
parameter_dependencies: dict[str, Any] | None
model_config = {'arbitrary_types_allowed': True, 'extra': 'forbid', 'populate_by_name': True, 'validate_assignment': 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 initialize 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.