pybop-team / PyBOP

A parameterisation and optimisation package for battery models.
https://pybop-docs.readthedocs.io
BSD 3-Clause "New" or "Revised" License
63 stars 20 forks source link

Add Ability to Simulate an Experiment w/ Events instead of Current Function #345

Open mleot opened 3 months ago

mleot commented 3 months ago

Feature description

I think this feature is a fairly simple one. The implementation is not exactly clear to me as the whole package is really centered around the use of current functions.

In short:

Motivation

The primary motivation for adding this feature is that it is currently not possible (as far as I am aware of) to have a composite interpolant function containing both current and voltage values. This makes it very difficult to optimize for CV steps. I believe that using an experiment to drive the simulation instead of a single current interpolant could be a more comprehensive way to provide inputs when optimizing for some output.

Possible implementation

One possible implementation: I think there would need to be the ability to pass the experiment object into the model upon initialization. The model object should then handle case differently when it has an experiment property which is not none.

Additional context

No response

NicolaCourtier commented 3 months ago

Hi @mleot - thanks for the clear description of your issue!

You are correct that currently FittingProblem-type optimisation problems require a Dataset that includes current and time. If, for example, the target dataset is a CCCV charge or discharge then it is possible to use the (measured) current as the input for parameterisation purposes. An example of this is shown in spm_adam.py. Synthetic data is generated using an experiment, by constructing an Experiment and passing this to model.predict (rather than model.simulate) which was created for this purpose. The resulting current from the PyBaMM solution (including both CC and CV steps) can then be used in the target dataset for parameterisation.

For design optimisation, using a DesignProblem, it is possible to use an experiment within the optimisation. Examples of this are shown in spme_max_energy.py and spm_electrode_design.ipynb.

This difference between the fitting and design optimisation problems was motivated by two reasons, if I remember correctly. Firstly, we would like to extract sensitivities from the PyBaMM solution whenever possible, so this information can be used by the gradient-based optimisers. Evaluating sensitivities is not currently possible when the simulation is split into different input-driven regimes. Secondly, using current as a function of time as the input enables fair comparison of error measures (e.g. RMSE) by ensuring that successful simulations have the same length as the target dataset. For design optimisation, however, there is no target dataset and we allow any kind of experiment to be optimised.

Please consider your particular use case and let us know if it may be solved by one of these existing approaches.

mleot commented 3 months ago

@NicolaCourtier Thanks for your response on this! I did see the examples that you listed above for a FittingProblem. Is there any motivation from your end to support experiments for fitting problems or do you think the use of current interpolants is going to be the only implementation?

You also mentioned extracting sensitivities from PyBaMM. Do you have a sense of what the performance impact on optimization is when extracting sensitivities?

NicolaCourtier commented 3 months ago

Hi @mleot, the codebase is evolving quite quickly at the moment so I'm not sure. If you can provide a motivating example for using an experiment over a current interpolant then that might push it up the priority list!

Re. extracting sensitivities, I haven't carried out a direct comparison to-date (but as far as I'm aware, it does not take much extra computation time compared to a standard PyBaMM simulation).

BradyPlanden commented 3 months ago

To note, I've added the model.simulateS1() method to the benchmarks last week: https://pybop-team.github.io/pybop-bench/

Comparing this to model.simulate() will give you an idea of the performance hit when computing the forward adjoint sensitivities in PyBaMM.