Skip to content

Show a summary at the start of every run; mode_average=True in the tutorials - #31

Merged
jtravs merged 6 commits into
mainfrom
feature/run-start-diagnostics
Oct 26, 2026
Merged

jtravs merged 6 commits into
mainfrom
feature/run-start-diagnostics

Conversation

@jtravs

@jtravs jtravs commented Oct 26, 2026

Copy link
Copy Markdown
Contributor

Every run now opens with one block saying what it is about to compute, so a default nobody chose (no shot noise, say) is visible before the run spends time on it. It also converts the last hand-built mode-averaged tutorials to mode_average=True. No default changes: noise, integrator and tolerances are as they were.

What the printout looks like

These are real runs on a terminal (progress="auto" draws a bar). First a mode-averaged argon capillary with a gradient fill, plasma and input noise:

Starting propagation from z = 0 m to 10 mm
  backend:        numba_cpu
  threads:        1 kernel, 1 FFTW; budget 18 (affinity)
  precision:      double
  grid:           field, 4096 points, window 683.1 fs, band 150 nm to 4 um
  representation: mode-averaged, one mode, scalar
  medium:         Ar, 293.15 K, core radius 125 um
  pressure:       PressureGradient(1 bar to 0.7002 bar over 10 mm, 2 points)
  responses:      Kerr, third harmonic
                  plasma (Ar), rate optmat recommended
                  Raman off
  shot noise:     input model, seed 7
  integrator:     Multistep, variable order up to 5, exponential formulation
  propagator:     recompute
  tolerances:     rtol 1e-06, atol 1e-10, dz_max 5 mm
  absorber:       temporal, nonlinear scheme
  save planes:    2 after the entrance, 5 mm to 10 mm
  output:         HDF5Output run.h5
  start:          new run
finished at z = 1.000000e-02 m: 229 steps (2 rejected) in 1.16 s, achieved/requested tolerance ratio 8.414e-01

Then a GNLSE fibre run with the defaults (prop_gnlse):

Starting propagation from z = 0 m to 50 mm
  backend:        numba_cpu
  threads:        1 kernel, 1 FFTW; budget 18 (affinity)
  precision:      double
  grid:           envelope, 1024 points, window 1.704 ps, band 500 nm to 2 um
  representation: GNLSE, one mode, scalar
  medium:         fibre, gamma 0.11 /W/m
  responses:      Kerr
                  Raman off
  shot noise:     off
  integrator:     Multistep, variable order up to 5, exponential formulation
  propagator:     recompute
  tolerances:     rtol 1e-08, atol 1e-14, dz_max 25 mm
  absorber:       none
  save planes:    2 after the entrance, 25 mm to 50 mm
  output:         MemoryOutput
  start:          new run
finished at z = 5.000000e-02 m: 15 steps (0 rejected) in 0.11 s, achieved/requested tolerance ratio 4.290e-02

With raman=True the Raman line reads Raman, fraction 0.2188 held back from Kerr. On a resume, start reads resuming at z = …, k of n planes to go.

How it works

  • One source. run_problem builds the summary (solprop.driver.summary.run_summary) from the kernel problem, the run's RunMetadata and the backend's own metadata(). Every route goes through run_problem: all six prop_* functions, Simulation.run and SimulationRunner. The metadata's configuration supplies what the problem holds only as compiled tables: the response objects, the mixture and the pressure profile. When a problem is run directly with a record that has no configuration, the responses are named from the compiled terms instead.
  • It follows progress=. The block goes to the reporter through a new optional call, SummarisingReporter.summary(text). It works like the existing InterruptibleReporter: NullReporter has a no-op, and a reporter written to the four basic calls is simply not shown the summary.
    • Bar ("auto" on a terminal or in a notebook, or "bar"): the summary and the closing line are written to the bar's stream. They used to be log records only, which nobody saw because the package installs just a NullHandler. If a console handler is configured that would print them anyway, they are only logged, so they appear once.
    • "log": both are INFO records on solprop.log, as before.
    • "none": nothing.
  • Recorded as an annotation, with no schema change. A plane store keeps the summary under the run_summary annotation: a list of {"title", "rows"}, and a resume appends its own. Annotations sit outside the record and its hash, so the output schema stays at 25. Putting the summary in RunMetadata itself would have needed a new field and a bump to schema 26. I didn't do that, because every row is derived from fields the record already holds.
  • Scans. Scan points still run with progress="none", so they show no summary. The outer scan bar is created with echo=False, so it does not print a meaningless "finished at z = N m: 0 steps" line.
  • Fixed in passing: the noise row of a printed Simulation named the realisation's class; it now gives input model, seed 5.
  • Docs: the summary is described in docs/guide/performance/progress.md (sample, routing table, annotation) and noted in results/provenance.md and architecture §14. The API index and the CHANGELOG (Added and Fixed) are updated.

The mode-averaged examples

I checked every replace( and default_spec("mode_averaged") hit under docs/examples, docs/tutorials, docs/introduction and docs/guide. The ones that remain are unrelated:

  • settings replacements;
  • a synthetic analytic run in tutorials/basics/plot_03_analysing_a_run.py.

No worked example still used the old route (the MI-ensemble and Raman-comb examples had already been converted), so no gallery output needed regenerating.

Two focused tutorials built a one-mode Simulation(grid, mode, …) by hand. They now use Simulation.from_capillary(..., mode_average=True):

  • tutorials/capillaries/plot_04_air_mixture.py: the ionisation inventories are identical. The final energy is 0.05 % lower, because the constructor applies its default temporal absorber. The tutorial's slow regression test (test_air_tutorial, pinned to an independent oracle) passes in 20 s.
  • tutorials/capillaries/plot_05_envelope_plasma.py: the carrier-resolved and envelope runs still agree to 0.004 %. The fractions differ from the hand-built ones by about 1e-6 relative.

Focused tutorials regenerate on every docs build, so there is no committed output to update.

Verification

  • Tests:
    • New: tests/driver/test_summary.py, covering the summary per route (GNLSE, mode-averaged and resolved capillary, mixture, radial, Cartesian, line, planar, vector) and its routing (event order, bar stream, "log", "none", a reporter without the call, a direct run_problem, resume appending).
    • Added to tests/test_log.py: the bar's echo rule.
    • Run with --dist loadgroup on numpy_ref and numba_cpu (native not installed locally), all passing:
      • tests/driver, tests/output, tests/processing, tests/plotting;
      • test_log, test_package, test_guide_snippets, test_display, tests/backends/test_driver.py;
      • doctests of the changed modules.
  • Coverage: summary.py is at 100 % branch coverage from its own tests.
  • Static checks: ruff, basedpyright, numpydoc and codespell are clean.
  • Not run locally: the full gate and the docs build; CI covers both.

🤖 Generated with Claude Code

jtravs and others added 5 commits October 26, 2026 22:30
run_problem builds one block from the kernel problem, the run's metadata
and the backend's execution record (solprop.driver.summary): backend,
threads, precision, grid, representation, medium and fill, responses
(Raman named on or off), shot noise with model and seed or off,
integrator, tolerances, absorber, save planes, output and resume state.
It reaches the reporter through the optional SummarisingReporter.summary
call, so it follows progress=: a bar writes it and the closing line on
its stream unless a console handler would print them, 'log' logs them at
INFO, 'none' shows nothing. Plane stores keep it as the run_summary
annotation, outside the record and its hash, so no schema change.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The air-mixture and envelope-plasma tutorials built a one-mode Simulation
by hand; Simulation.from_capillary(..., mode_average=True) is the route.
Ionisation inventories agree with the hand-built runs (the air run's
final energy is 0.05 % lower: the constructor's default temporal
absorber), and the envelope comparison still agrees to 0.004 %.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A run with no optmat rate still writes no peak-field annotation; it now
carries the run summary, so the test asks for the one it means.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Copilot AI balanced review requested due to automatic review settings October 26, 2026 22:36

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Copilot was unable to review this pull request because the user who requested the review has insufficient remaining quota.

…sume equality

The layers figure lists every module, so it draws driver/summary.py; the
reporter docstrings name SummarisingReporter.summary by its full path for
Sphinx; and the moving-guide resume comparison leaves out the run_summary
annotation, which records a resumed file's two starts by design.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@read-the-docs-community

Copy link
Copy Markdown

@codecov

codecov Bot commented Oct 26, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

@jtravs
jtravs merged commit c50e002 into main Oct 26, 2026
31 checks passed
jtravs added a commit that referenced this pull request Oct 27, 2026
SEP 35's carrier-frame Adams kernels ported from general.cpp into the
policy-templated general_impl.hpp. Kernel schema 38 and output schema 27 for
SEP 36 (main took 37 for SEP 35 and 26 for SEP 37); SEP 36's ADR renumbered
ADR-057 after ADR-055 (SEP 37) and ADR-056 (PR #33).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
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