Design Principles

The goal of this package is to provide reuseable building blocks for building a battery model parameterization pipeline. Details of the fitting process, such as the order of fitting parameters, depend on the available experimental data and specifics of the system. For example, in some cases, we might want to calculate electrode capacity from theoretical knowledge of the material, and then use the capacity to calculate stoichiometry limits. In other cases, we might want to estimate the electrode capacity and stoichiometry limits simultaneously from dV/dQ data. This package is designed to be flexible enough to handle any case. However, this flexibility makes certain aspects of the design counterintuitive at first. This document provides an overview of the blocks and explains and justifies the various aspects of the design.

Design

The basic building block is the PipelineElement. Any PipelineElement takes as input a set of parameter values (possibly empty) and returns another set of parameter values. Then the full pipeline is built by calling each of the pipeline elements in series to yield the full set of parameters.

More specifically, there are three types of elements:

Type

Description

DirectEntry

The simplest type of element, ignores the inputted parameters and simply returns a pre-defined set of parameters (e.g. from literature, or direct measurements)

Calculation

Calculates new parameters based on the ones that have been passed in (e.g. calculating maximum particle concentration from areal capacity, active material volume fraction, and thickness)

DataFit

Calculates new parameters by fitting a model to some data

The first two are fairly straightforward and intuitive, but the DataFit is a bit more complicated

DataFit

The DataFit class is a standard wrapper class that requires the following customizable inputs:

  • An objective (see Objective below), which includes the model and data

  • The parameters to fit, their initial guesses, and their bounds

  • Other parameters required to run the model

We split the work done by the DataFit into a few different classes:

  • An Objective class, which takes in the data and metadata, along with any options and callbacks. This class implements a method build, which takes in some parameter values and defines a run function that can be called with a dictionary of inputs and a dictionary of results whose keys match the data being used in the fit.

  • A Cost class, which describes how to compare the model and data. This class implements a __call__ method which creates a cost (e.g. least squares) given a dictionary of data and model results.

  • An Optimizer class, which defines the optimization routine to be used.

The DataFit class takes in the Objective, a dictionary of parameters to be fit together with their form, initial guesses and bounds, a Cost, an Optimizer and some options. The “form” of the parameters can be:

  • An iwp.Parameter object, e.g. iwp.Parameter("x").

  • A PyBaMM expression, in which case the other parameters should also be explicitly provided as iwp.Parameter objects, e.g.

    {
        "param": 2 * pybamm.Parameter("half-param"),
        "half-param": iwp.Parameter("half-param")
    }
    

    works, but

    {"param": 2 * iwp.Parameter("half-param")}
    

    does not.

  • A function containing other parameters, in which case the other parameters should again also be explicitly provided as iwpParameter objects, e.g.

    {
        "main parameter": lambda x: pybamm.Parameter("other parameter") * x**2,
        "other parameter": iwp.Parameter("other parameter")
    }
    

The name of the input parameter does not need to match the name of the parameter. The DataFit class will automatically process the dictionary of input values into a vector of values to be passed to the optimizer.

Separating the Objective, Cost and Optimizer from the DataFit has several benefits:

  • the same Objective can be used with different costs (e.g. RMSE of the whole data vs extracting features)

  • objectives can be reused within a pipeline, for example first to get an approximate value for the parameters, and then again later to get a more accurate value

  • combined objectives can be created by combining different objectives to simultaneously optimize over different data sets (for example constant-current discharge at different C-rates or temperatures)

In summary, the Objective and Cost classes determine how the model and data are compared for generic parameter values and inputs, and the Optimizer class is used to perform the optimization. The DataFit class manages the process by specifying the parameters, Optimizer, Cost, and Objective.