pybamm-team / PyBaMM

Fast and flexible physics-based battery models in Python
https://www.pybamm.org/
BSD 3-Clause "New" or "Revised" License
1.06k stars 526 forks source link

Time stepping in IDA - minimise solver restarts #4312

Closed martinjrobins closed 2 weeks ago

martinjrobins commented 1 month ago

proposal by @MarcBerliner (https://github.com/pybamm-team/PyBaMM/issues/3910#issuecomment-2260736100)

Time stepping

In PyBaMM, the solver currently stops at all values in the t_eval vector. It seems that we use t_eval and set some dt for a few distinct purposes:

  1. To enforce time-dependent discontinuities within a single step, like with a drive cycle
  2. To set the data collection frequency (as in the period experiment kwarg)
  3. Setting a small dt to force better solver convergence (take smaller time steps)

These three reasons for setting a dt are all valid, but stopping the simulation at all time steps can have a drastic impact on the adaptive time stepping and performance. For example, consider a full C/10 discharge with

If we compare the solver stats,

Even though we solve the same system, the dense t_eval b. is nearly 4x slower! To address these issues, I propose the following changes that align the time-stepping options with Julia's differential equation solvers (see Output Control):

martinjrobins commented 1 month ago

By default, save every t and y determined by IDA's adaptive time stepping algorithm. This eliminates issues like the one above with the C/10 discharge.

So this y would be the state matrix stored in the pybamm.Solution class?

We can accurately post-interpolate the solution onto specific times with IDA's Hermite interpolator

are you thinking this would this happen in the pybamm.ProcessedVariable class? You'd need to expose the sundials interpolator via pybind11 then.

MarcBerliner commented 1 month ago

So this y would be the state matrix stored in the pybamm.Solution class?

Yes.

are you thinking this would this happen in the pybamm.ProcessedVariable class? You'd need to expose the sundials interpolator via pybind11 then.

In short, yes. I'm still looking into the details, but this is a bit complicated because we may need access to ida_mem in python if we cannot extract IDA's interpolant. Currently, we free ida_mem at the end of each solve, so we cannot do any post-interpolation with IDAGetDky(ida_mem, ...). My thinking is to add a kwarg that lets us retain ida_mem without freeing it and also (for general convenience) add python bindings to all the IDAGetx(), IDASetx(), etc. functions.