KineticForces - BUGFIX! - Give the energy integration its own tolerances - #392
KineticForces - BUGFIX! - Give the energy integration its own tolerances#392logan-nc wants to merge 3 commits into
Conversation
…erances The energy (x) integration was handed the same atol_xlmda/rtol_xlmda pair as the pitch (lambda) integration that encloses it. Since the pitch integrand IS the energy integral, the outer integrator was asked to resolve its integrand to the same tolerance to which that integrand was itself computed, so it chases the inner integrator's quadrature noise instead of converging. Adds atol_x/rtol_x, defaulting (NaN sentinel) to nested_tolerance_margin = 1e-2 times the pitch tolerances, which extends the nesting rule the struct already documents one level up for rtol_psi vs rtol_xlmda. Wired through both the psi-quadrature path (tpsi!) and the kinetic-matrix path. This deliberately changes default numerical behaviour: shipped decks now integrate the energy variable to atol 1e-10 / rtol 1e-7 rather than 1e-8 / 1e-5, and pay for it in runtime. A deck can set atol_x/rtol_x explicitly to override the derived values, or widen nested_tolerance_margin to recover the old cost. Julia analog of the second commit of Fortran GPEC PR #280. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
Ready for review; not yet ready to merge. The physics/code argument is complete and self-contained, so review can start now. The regression-harness table is still outstanding and is a merge gate per CLAUDE.md — I'll post it here before this is merged. Note the machine currently has other regression runs in flight, so the kinetic cases are queued behind the PR #339 re-baseline rather than run in parallel. |
Regression harness —
|
| Case | Values | Runtime |
|---|---|---|
diiid_n1 |
48 unchanged | 430.0s → 419.0s |
solovev_kinetic_ntv |
6 unchanged | 340.1s → 323.8s |
solovev_kinetic_nuzero |
5 changed, all ~1e-7 relative |
193.3s → 251.2s (+30%) |
solovev_kinetic_calculated |
6 changed, all ~1e-7 relative |
191.7s → 184.1s |
solovev_kinetic_nuzero develop branch Diff
total energy Re(et[1]) 2.245439e+00 2.245440e+00 3.347e-07 (0.00%)
total energy Im(et[1]) -2.034869e+00 -2.034869e+00 7.464e-08 (0.00%)
plasma energy Re(ep[1]) -8.485145e+00 -8.485145e+00 6.104e-07 (0.00%)
How to read "unchanged" here — the guards are coarser than the effect
Two of the four cases report no change, but that is not evidence the tolerance tightening did nothing. The relevant noise_thresholds are absolute and coarse relative to the quantities they guard:
| Quantity | value | noise_threshold |
effective relative sensitivity |
|---|---|---|---|
solovev_kinetic_ntv NTV torque fgar |
~1.3e-4 N·m | 1e-8 |
~1e-4 |
diiid_n1 NTV torque FGAR |
5.59e-1 N·m | 1e-2 |
~1.8% |
diiid_n1 NTV kinetic energy dW FGAR |
6.9e-2 J | 1e-3 |
~1.4% |
kinetic eigenvalues (nuzero/calculated) |
O(1) | 1e-10 |
~1e-10 |
So the movements we can actually resolve — the O(1) eigenvalues, guarded at 1e-10 — are ~1e-7 relative. A change of that size in the NTV torque would sit three to five orders of magnitude below its guard and be reported as "unchanged." The eigenvalue rows are the only ones in this suite sensitive enough to see this effect at all.
What the table does establish:
- The change is real and reaches the integrator. The
+30%runtime onsolovev_kinetic_nuzerois the energy integrator doing genuinely more work atrtol 1e-7instead of1e-5. The plumbing was verified separately:atol_x/rtol_x/nested_tolerance_marginflow fromKineticForcesControlthroughCompute.jlintotpsi!and throughcompute_kinetic_matrices_at_psi!. - The effect is small where it is resolvable,
~1e-7relative on the eigenvalues — i.e. the previous aliased tolerances were already close to converged on these well-behaved cases, which is reassuring for existing published results. - The runtime cost is real but not uniform —
+30%on one case, within noise on the other three. Thenested_tolerance_marginknob exists precisely so a deck can trade this back.
The honest summary: this is a consistency fix to the tolerance nesting, and on the cases we track it moves results at the 1e-7 level for up to +30% runtime. It is not expected to change any physics conclusion; it removes the situation where the outer pitch integrator was chasing its own integrand's quadrature error.
|
This pull request is missing a reviewer. If you are not ready to name them, mark this pull request as a draft. |
…ergy-pitch-tolerances
# Conflicts: # src/KineticForces/CalculatedKineticMatrices.jl # src/KineticForces/Compute.jl
Regression re-run after re-syncing with developPR #339 merged, so this branch was updated to Every changed row on the two Solovev kinetic cases is at 0.00% relative (absolute diffs ~1e-6 to 1e-8 on O(1) eigenvalues, plus one-step ODE count moves) — they cross the harness's tight Runtime cost of the tighter energy tolerance is larger than first measured: |
The metadata job read only requested_reviewers, which holds pending review requests. GitHub removes a reviewer from that list as soon as they submit a review, so the check went quiet while nobody had reviewed and fired once somebody did -- nagging precisely the pull requests furthest along. Treat a submitted review from anyone other than the author as evidence that a reviewer was named. Assignment alone still suffices; the reviewer never has to act. Verified against all open pull requests: silences #390, #391, #392, #407, leaves every pending-request PR untouched, and still nags the nine with nobody named. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Dh1NCejnd3fYMmcRKoQRcG
Release note
nested_tolerance_margin(oratol_x/rtol_x) if you need the previous runtime back.The energy integration is nested inside the pitch integration, but both were handed the same tolerance pair, so the outer integrator chased its own integrand's quadrature noise instead of converging. The energy level now gets its own tolerances, derived by default as
nested_tolerance_margintimes the pitch tolerances and overridable per deck.What
Give the energy (x) integration its own tolerances instead of aliasing them to the pitch (λ) integration's.
Julia analog of the second commit of Fortran GPEC PR #280.
Why
The integrations nest: ψ quadrature ⊃ λ (pitch) ⊃ x (energy). The pitch integrand is the energy integral, so handing both levels the same
atol_xlmda/rtol_xlmdaasks the outer integrator to resolve its integrand to exactly the tolerance to which that integrand was itself computed — it then chases the inner integrator's quadrature noise instead of converging.The control struct already documents this same nesting rule one level further out (
keep rtol_psi ≳ 10 × rtol_xlmda); this extends it to the level that was missing it.API
atol_x/rtol_xdefault to aNaNsentinel meaning "derive asnested_tolerance_margin× the pitch tolerance". Explicit values override. Wired through both the ψ-quadrature path (tpsi!) and the kinetic-matrix path.This changes default numerical behaviour, deliberately
atolrtol1e-81e-51e-2margin)1e-101e-7Every deck that does not set the new controls integrates the energy variable more tightly than before and pays for it in runtime. That is the intent — the previous nesting was inconsistent — but it is a behaviour change, not a no-op. Reviewers should decide whether
1e-2is the margin they want; wideningnested_tolerance_marginrecovers the old cost.Note the derived values do not restore the
EnergyIntegrationmodule's own much tighter internal defaults; a deck can ask for those explicitly viaatol_x/rtol_x.Validation
runtests_kinetic.jl: 277/277.1e-10/1e-7, explicitatol_x/rtol_xoverride, and TOML-dict construction of the new keys works.🤖 Generated with Claude Code