Skip to content

feat: add store_first_last solver kwarg for memory-light long experiments#5499

Merged
rtimms merged 6 commits into
pybamm-team:mainfrom
rtimms:feat/store-first-last-solver-kwarg
May 11, 2026
Merged

feat: add store_first_last solver kwarg for memory-light long experiments#5499
rtimms merged 6 commits into
pybamm-team:mainfrom
rtimms:feat/store-first-last-solver-kwarg

Conversation

@rtimms
Copy link
Copy Markdown
Contributor

@rtimms rtimms commented May 7, 2026

Summary

  • Adds a store_first_last: bool = False kwarg to BaseSolver (forwarded through IDAKLUSolver, CasadiSolver, ScipySolver, JaxSolver).
  • When True, only the first and last sample of each integration window are stored: one experiment step in Simulation.solve, or the full [t_eval[0], t_eval[-1]] window in plain BaseSolver.solve.
  • Composes with output_variables for memory-light long ageing experiments whose post-processing only reads per-step first/last values (e.g. metrics built on per-cycle/per-step First / Last aggregators).
  • Has effect on solvers that support intra-solve interpolation (IDAKLUSolver); other solvers warn once per instance and no-op.

The flag is intended for the case where post-processing only needs first/last state. With this flag set, intra-step interpolation falls back to linear across the whole step (IDAKLU's Hermite checkpoints are auto-disabled by the existing t_interp non-empty path), so it is not appropriate when post-processing queries an intra-step time (e.g. a RelativeTime-style sample).

Implementation notes

  • Centralised in BaseSolver._store_first_last_endpoints, called from both solve() (collapses t_eval so IDAKLU stops only at endpoints) and process_t_interp() (sets t_interp to the same endpoints).
  • BaseStep._setup_timestepping short-circuits to t_interp = [0, tf] when the flag is set, overriding any per-step period and any caller-provided t_interp.
  • Round-trips through Serialise.serialise_solver automatically (reflected from the __init__ signature).

Test plan

  • Plain solver.solve(model, t_eval=...) returns 2 stored samples on IDAKLU.
  • Each experiment step's sub-solution has exactly 2 stored samples; end-of-step values match a reference solve.
  • Per-step period and caller t_interp are overridden when the flag is on.
  • output_variables composes (variables-only × endpoints-only).
  • Non-IDAKLU solvers (Casadi) warn once per instance and integrate normally.
  • to_config() / from_config() round-trips for IDAKLU and Casadi.

🤖 Generated with Claude Code

rtimms and others added 3 commits May 7, 2026 10:30
…ents

When set, the solver only stores the first and last sample of each
integration window — one experiment step in `Simulation.solve`, or the
full `[t_eval[0], t_eval[-1]]` window in a plain `solve` call. Composes
with `output_variables` for ageing simulations whose post-processing
only reads per-step first/last values. Has effect on solvers that
support intra-solve interpolation (`IDAKLUSolver`); other solvers warn
and no-op. With this flag set, intra-step interpolation falls back to
linear across the whole step, so it is not appropriate when
post-processing queries an intra-step time.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- Extract `_store_first_last_endpoints` and use it from both `solve()`
  and `process_t_interp()` so the endpoint array is constructed in one
  place.
- Gate the no-op warning on a per-instance flag so it fires once per
  non-IDAKLU solver instance instead of once per `step()` call.
- Drop a couple of narrating comments restating the next line.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@rtimms rtimms requested a review from a team as a code owner May 7, 2026 09:44
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@codecov
Copy link
Copy Markdown

codecov Bot commented May 7, 2026

Codecov Report

❌ Patch coverage is 96.15385% with 1 line in your changes missing coverage. Please review.
✅ Project coverage is 98.16%. Comparing base (82ee554) to head (d3caecb).

Files with missing lines Patch % Lines
src/pybamm/solvers/base_solver.py 95.83% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #5499      +/-   ##
==========================================
- Coverage   98.17%   98.16%   -0.01%     
==========================================
  Files         338      338              
  Lines       31222    31245      +23     
==========================================
+ Hits        30651    30673      +22     
- Misses        571      572       +1     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Copy link
Copy Markdown
Member

@BradyPlanden BradyPlanden left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is looking good, just a few comments on docs / alignment.

Comment thread src/pybamm/experiment/step/base_step.py Outdated
Comment thread src/pybamm/solvers/idaklu_solver.py Outdated
Comment thread tests/unit/test_solvers/test_store_first_last.py Outdated
Comment thread src/pybamm/solvers/base_solver.py
Comment thread src/pybamm/solvers/base_solver.py Outdated
Comment thread tests/unit/test_solvers/test_store_first_last.py Outdated
- Drop defensive getattr in BaseStep._setup_timestepping; expose
  store_first_last on test duck-typed solvers (DummySolver,
  SolverWithoutInterp) so the attribute is guaranteed on all solver-likes,
  matching t_eval / t_interp.
- Reword store_first_last docstrings in BaseSolver and IDAKLUSolver to
  drop the ambiguous "Composes with output_variables" phrasing.
- Append a section to the 06-output-variables notebook demonstrating
  store_first_last + output_variables together.
- Drop the explanatory comment block above _store_first_last_endpoints
  in BaseSolver.solve.
- Trim docstring on _build_simple_dae_model.
- Tighten end-of-step reference-solve tolerance to solver precision
  (both runs stop at the same t_eval points).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@review-notebook-app
Copy link
Copy Markdown

Check out this pull request on  ReviewNB

See visual diffs & provide feedback on Jupyter Notebooks.


Powered by ReviewNB

Copy link
Copy Markdown
Member

@BradyPlanden BradyPlanden left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice one! The notebook results are great 🚀

@rtimms rtimms merged commit 42ef377 into pybamm-team:main May 11, 2026
26 of 27 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants