IDA adaptive time stepping#4351
Conversation
Codecov ReportAll modified and coverable lines are covered by tests ✅
Additional details and impacted files@@ Coverage Diff @@
## develop #4351 +/- ##
===========================================
- Coverage 99.50% 99.46% -0.05%
===========================================
Files 289 289
Lines 22146 22200 +54
===========================================
+ Hits 22037 22081 +44
- Misses 109 119 +10 ☔ View full report in Codecov by Sentry. 🚨 Try these New Features:
|
valentinsulzer
left a comment
There was a problem hiding this comment.
Looks good to me other than some very minor comments. I have a feeling there are several bits of code we'll be able to refactor once this is in as the default everywhere but that can be a job for later. As usual will leave the C++ code to others to review
martinjrobins
left a comment
There was a problem hiding this comment.
Really great work @MarcBerliner, this looks excellent and some really great speed-ups! :) I've suggested a few changes below that need to be fixed but mostly minor. One general question I had: many of the idaklu tests use a dense t_eval and an identical t_interp, which is now the "slow" way of running the solver. When not specificly testing the interpolation code, I would use the most efficient / standard way of running solver.solve, which I believe would be t_eval = [start, stop] and t_interp = None or t_interp = np.linspace(start, stop, N)?
@martinjrobins good point. The most efficient way to run it is using the Once this PR merges, we can fully migrate all the tests to using |
martinjrobins
left a comment
There was a problem hiding this comment.
thanks @MarcBerliner, just a few more minor changes below
martinjrobins
left a comment
There was a problem hiding this comment.
Looks great, thanks @MarcBerliner
Description
This PR makes several changes to adaptive time-stepping in IDA. Previously, the
t_evaldecided both the points at which we store the solution and the points to explicitly stop the IDA solver. Now, the time-stepping has been broken down intot_eval(which retains the same behavior) andt_interp, which uses IDA's internal Hermite interpolator to efficiently store the solution. Additionally, we default to saving the adaptive time steps, which gives us full-order solution accuracy without negatively impacting the solve speed with periods or denset_evalvectors.This PR cleans up the main
solveloop of the IDA solver and clearly delineates saving the full solutionyvs. specific output variables.Example: adaptive time outputs (new) vs. fixed outputs
The above picture shows the difference in resolution between the new adaptive time-stepping scheme and the previous approach without affecting the performance. The markers show every data point available in
sol.tPeriod/drive cycles improvements
The above figure shows the
solvetime for a full C/10 discharge. The new IDA solver is strictly faster than the old IDA and the Casadi solver. For the SPM, the IDA vs. Casadi timings are closer because IDA is a DAE solver while Casadi is using an ODE solver. Adding CVODE to pybamm could be future work to further improve our ODE speed.For small periods, the new IDA solver is about an order of magnitude faster than the old IDA. For large periods, it's about half an order of magnitude faster than Casadi.
In a parameter estimation context, you can also post-interpolate the adaptive time-stepping solution without specifying a
t_interporperiodfor just the variable of interest (such as voltage) which will dramatically improve the performance.Adaptive time-stepping (no period)
When
t_evalor aperiodis not set for an experiment, the new IDA is strictly faster than the previous IDA. Additionally, adaptive time-stepping has much better performance for slower simulations that previously used a denset_evalvector by default.Fixes #4312
Type of change
Please add a line in the relevant section of CHANGELOG.md to document the change (include PR #) - note reverse order of PR #s. If necessary, also add to the list of breaking changes.
Key checklist:
$ pre-commit run(or$ nox -s pre-commit) (see CONTRIBUTING.md for how to set this up to run automatically when committing locally, in just two lines of code)$ python run-tests.py --all(or$ nox -s tests)$ python run-tests.py --doctest(or$ nox -s doctests)You can run integration tests, unit tests, and doctests together at once, using
$ python run-tests.py --quick(or$ nox -s quick).Further checks: