Skip to content

ForceFreeStates - PERF! - Default to Vern7 with an explicit absolute tolerance and pin BLAS in the sweep - #445

Draft
d-burg wants to merge 4 commits into
developfrom
performance/integrator-comparison
Draft

ForceFreeStates - PERF! - Default to Vern7 with an explicit absolute tolerance and pin BLAS in the sweep#445
d-burg wants to merge 4 commits into
developfrom
performance/integrator-comparison

Conversation

@d-burg

@d-burg d-burg commented Sep 9, 2026

Copy link
Copy Markdown
Collaborator

Release note

  • Audience: users
  • Numerical impact: Force-Free States δW and Δ′ move toward the converged solution at the 1e-5 to 1e-8 level (new ode_solver/ode_abstol defaults); no interface removed (harness @ a09f6bf)
  • Migration: none; ode_solver = "Vern9", ode_abstol = 1e-6 in [ForceFreeStates] restores the previous integration exactly

The Euler-Lagrange sweep now integrates with Vern7 at an explicit absolute tolerance of 1e-8 (previously Vern9 at the OrdinaryDiffEq default 1e-6), and BLAS is pinned to one thread inside the sweep and the Δ′ BVP. Same δW and Δ′ to better than the old run's own error, in about half the RHS evaluations.

Regression report

regress --cases diiid_n1,diiid_n1_riccati,diiid_slayer_n1,solovev_n1,solovev_multi_n,solovev_kinetic_ntv --refs develop,performance/integrator-comparison
(OK rows omitted; every equilibrium, q-profile, singular-surface and mode-space quantity is unchanged)

Case: diiid_n1 — DIII-D-like equilibrium, n=1, ideal + perturbed equilibrium
Ref 1: develop  @ 349a0c262 (2026-09-04)
Ref 2: performance/integrator-comparison  @ a09f6bf34 (2026-09-09)
plasma energy (all)                           [35 elem]        [35 elem]                          1.754e-09 (0.00%)   ** CHANGED **
vacuum energy (all)                           [35 elem]        [35 elem]                          1.009e-09 (0.00%)   ** CHANGED **
total energy (all)                            [35 elem]        [35 elem]                          1.832e-09 (0.00%)   ** CHANGED **
ODE steps (saved)                             2647             3299                               6.520e+02 (24.63%)  ** CHANGED **
ODE steps (total)                             4715             5478                               7.630e+02 (16.18%)  ** CHANGED **
island half-widths                            [5 elem]         [5 elem]                           6.525e-07 (0.00%)   ** CHANGED **
Chirikov parameter                            [5 elem]         [5 elem]                           5.215e-05 (0.01%)   ** CHANGED **
PE toroidal torque                            5.086535e-02     5.086535e-02                       3.889e-12 (0.00%)   ** CHANGED **
Runtime (s)                                   157.2s           167.0s                                                 --
resonant area-weighted field b^r              [5 elem]         [5 elem]                           1.013e-08 (0.00%)   ** CHANGED **
Summary: 9 changed, 38 unchanged

Case: diiid_n1_riccati — DIII-D-like equilibrium, n=1, Riccati integrator Δ' matrix
Ref 1: develop  @ 349a0c262 (2026-09-04)
Ref 2: performance/integrator-comparison  @ a09f6bf34 (2026-09-09)
delta prime (BVP diagonal)     [5 elem]       [5 elem]                           3.312e-01 (0.01%)   ** CHANGED **
delta prime (raw side-major)   [10 elem]      [10 elem]                          1.680e-01 (0.00%)   ** CHANGED **
edge coil response delta_coil  [10 elem]      [10 elem]                          5.357e-06 (0.00%)   ** CHANGED **
total energy Re(et[1])         8.038607e-01   8.038606e-01                       1.350e-07 (0.00%)   ** CHANGED **
plasma energy Re(ep[1])        -1.344628e+00  -1.344628e+00                      2.192e-07 (0.00%)   ** CHANGED **
vacuum energy Re(ev[1])        2.148488e+00   2.148488e+00                       8.415e-08 (0.00%)   ** CHANGED **
total energy (all)             [35 elem]      [35 elem]                          1.292e-03 (0.00%)   ** CHANGED **
ODE steps (total)              1667           3280                               1.613e+03 (96.76%)  ** CHANGED **
Runtime (s)                    119.0s         122.4s                                                 --
Summary: 8 changed, 9 unchanged

Case: diiid_slayer_n1 — DIII-D-like H-mode equilibrium, n=1, SLAYER tearing-mode analysis (uncoupled per-surface, AM
Ref 1: develop  @ 349a0c262 (2026-09-04)
Ref 2: performance/integrator-comparison  @ a09f6bf34 (2026-09-09)
SLAYER γ_Hz [2/1,3/1,4/1]           [3 elem]  [3 elem]                           1.296e-01 (0.02%)  ** CHANGED **
Runtime (s)                         149.4s    140.3s                                                --
Summary: 1 changed, 16 unchanged

Case: solovev_n1 — Solovev analytical equilibrium, n=1, ideal stability
Ref 1: develop  @ 349a0c262 (2026-09-04)
Ref 2: performance/integrator-comparison  @ a09f6bf34 (2026-09-09)
total energy Re(et[1])        5.748525e-01     5.748772e-01                       2.475e-05 (0.00%)   ** CHANGED **
total energy Im(et[1])        -1.054421e-03    -1.071186e-03                      1.676e-05 (1.59%)   ** CHANGED **
plasma energy Re(ep[1])       -9.821799e+00    -9.821762e+00                      3.715e-05 (0.00%)   ** CHANGED **
vacuum energy Re(ev[1])       1.039665e+01     1.039664e+01                       1.240e-05 (0.00%)   ** CHANGED **
plasma energy (all)           [32 elem]        [32 elem]                          6.914e-04 (0.00%)   ** CHANGED **
vacuum energy (all)           [32 elem]        [32 elem]                          4.446e-04 (0.00%)   ** CHANGED **
total energy (all)            [32 elem]        [32 elem]                          5.144e-04 (0.00%)   ** CHANGED **
ODE steps (saved)             394              639                                2.450e+02 (62.18%)  ** CHANGED **
ODE steps (total)             626              974                                3.480e+02 (55.59%)  ** CHANGED **
ca_left (checksum)            2e29a01cdae9...  c18b8f9b2301...                    0.000e+00 (0.00%)   ** CHANGED **
Runtime (s)                   111.6s           103.6s                                                 --
Summary: 10 changed, 12 unchanged

Case: solovev_multi_n — Solovev analytical equilibrium, multi-n, ideal stability
Ref 1: develop  @ 349a0c262 (2026-09-04)
Ref 2: performance/integrator-comparison  @ a09f6bf34 (2026-09-09)
total energy Re(et[1])        -1.906006e+00    -1.906003e+00                      2.316e-06 (0.00%)   ** CHANGED **
total energy Im(et[1])        -3.696662e-05    -3.674848e-05                      2.181e-07 (0.59%)   ** CHANGED **
plasma energy (all)           [70 elem]        [70 elem]                          1.152e-02 (0.00%)   ** CHANGED **
vacuum energy (all)           [70 elem]        [70 elem]                          9.410e-03 (0.00%)   ** CHANGED **
total energy (all)            [70 elem]        [70 elem]                          3.492e-03 (0.00%)   ** CHANGED **
ODE steps (saved)             34               50                                 1.600e+01 (47.06%)  ** CHANGED **
ODE steps (total)             1115             2086                               9.710e+02 (87.09%)  ** CHANGED **
Runtime (s)                   138.6s           110.0s                                                 --
Summary: 7 changed, 8 unchanged

Case: solovev_kinetic_ntv — Solovev analytical equilibrium, n=1, ideal + PE + NTV torque quadrature
Ref 1: develop  @ 349a0c262 (2026-09-04)
Ref 2: performance/integrator-comparison  @ a09f6bf34 (2026-09-09)
NTV torque fgar [Re, Im]                   [1 elem]      [1 elem]                           1.336e-06 (0.63%)   ** CHANGED **
NTV ψ quadrature evaluations               630           750                                1.200e+02 (19.05%)  ** CHANGED **
root-area-weighted total energy Re(et[1])  5.748525e-01  5.748772e-01                       2.475e-05 (0.00%)   ** CHANGED **
Runtime (s)                                139.6s        140.1s                                                 --
Summary: 3 changed, 3 unchanged

Evidence

Shipped DIII-D-like case (N=35, 5 rational surfaces), 4 Julia threads, Apple M1 Max. Errors are relative distances from a Vern9 reltol 1e-13 / abstol 1e-15 reference.

setting integration FFS stage lowest-5 δW error Δ′ error
develop: Vern9, 1e-10 / 1e-6 1.50 s 9.9 s 5e-8 1e-4
this PR: Vern7, 1e-10 / 1e-8 1.84 s 8.6 s 2e-9 1.5e-5
Vern9, 1e-10 / 1e-8 2.48 s 10.9 s 2e-9 1e-4

Why the old setting was fast: with abstol 1e-6 the error stopped responding to reltol below ~1e-8 (Vern9 at reltol 1e-13 took exactly the same 1667 steps as at 1e-10). With a real abstol, Vern9 rejects 68 % of its steps near the rational surfaces:

chunk-level work-precision

Whole-stage Δ′ and δW error vs wall time, 20 solvers × 3 reltol × 4 abstol (star = develop):

pipeline Δ′

Ten IDA_run geqdsks (EFIT, CAKE, TokaMaker; 65×65 to 257×257; H- and L-mode), reltol 1e-10 / abstol 1e-10 for every solver, 4 threads:

shot / time N msing STRIDE wall Vern9 integ. Vern7 integ. Vern7 Δ′ err / Vern9 Δ′ err
148798 / 3306 33 2 3.8 s 4.78 s 2.56 s 1.9e-6 / 3.5e-6
153833 / 3450 34 4 3.5 s 5.51 s 3.00 s 4.8e-6 / 7.0e-6
169510 / 3000 CAKE 34 4 3.8 s 6.06 s 3.34 s 4.1e-6 / 7.9e-6
178305 / 1800 (65×65) 36 5 4.5 s 8.83 s 4.85 s 1.7e-6 / 3.0e-6
179633 / 3200 L-mode 34 4 3.6 s 2.57 s 1.50 s 2.3e-6 / 6.9e-6
189392 / 4080 L-mode 34 4 3.6 s 2.42 s 1.39 s 1.2e-6 / 1.9e-6
201586 / 4200 (65×65) 40 10 13.5 s 13.73 s 8.81 s 3.2e-7 / 3.6e-7
204441 / 4409 37 7 7.8 s 5.80 s 3.92 s 3.3e-6 / 6.7e-6
TkMkr D3D H-mode 35 5 5.5 s 4.33 s 2.86 s 1.5e-5 / 9.7e-5

Vern7 vs Vern9 integration speedup: min 1.48×, median 1.81×, max 4.7×; δW within 2e-10 of the reference on all; Δ′ closer on 10/10.

Full IDA_run corpus (226 unique geqdsks) sweep, this PR vs develop vs STRIDE: running, figure and table to be added.

Notes for reviewers

  • Where the rest of the stage time goes on the shipped case (warm): Δ′ BVP 8.3 s (Double64 LU 3.8 s + serial shooting), ballooning scan 5.9 s, equilibrium 3.3 s; a fresh process adds ~52 s of JIT (follow-up PR adds a PrecompileTools workload). The integration itself is 1.5 s, already under STRIDE's 5.5 s whole run.
  • Three reverse-shear geqdsks in the corpus (q crossed twice) are handled in a separate bugfix PR; they are excluded from the speed statistics here.
  • Forward (DCON-like) mode: Vern7 is 1.5–1.6× faster than Vern9 across reltol 1e-10…1e-13 at identical δW; Vern9 at reltol ≤ 1e-13 collapses to 40–60k steps and drifts its δW by 1e-2, Vern7 does not.
  • Benchmark scripts added under benchmarks/ (chunk-level work-precision, whole-stage driver, stage profiler, corpus runner); their outputs are not committed.

🤖 Generated with Claude Code

d-burg and others added 2 commits September 9, 2026 14:04
…tolerance and pin BLAS in the sweep

A brute-force comparison of 20 OrdinaryDiffEq solvers on the Euler-Lagrange
propagator chunks (shipped DIII-D-like case plus ten IDA_run geqdsks) showed
that error control was dominated by the OrdinaryDiffEq default abstol of 1e-6,
and that once a real absolute tolerance is set Vern9 rejects two of every three
steps near the rational surfaces while fifth-to-seventh-order methods reach the
same accuracy for about half the RHS evaluations.

- Add `ode_solver` (default "Vern7") and `ode_abstol` (default 1e-8) to
  ForceFreeStatesControl and use them at every Euler-Lagrange solve site.
  On the corpus Vern7 is 1.5-4.7x faster than Vern9 at equal tolerances, with
  Δ′ closer to the converged solution in every case; the shipped case's
  Force-Free States stage is ~13 % faster than before while its eigenvalue and
  Δ′ errors against a 1e-13/1e-15 reference drop from 5e-8/1e-4 to 2e-9/1.5e-5.
- Pin BLAS to one thread inside the sweep and the Δ′ BVP: the mpert×mpert
  blocks lose more to BLAS synchronization than they gain (RHS cost 263 → 73 µs
  at mpert=35).
- Add the benchmark scripts used for the comparison: a chunk-level
  work-precision harness, a whole-stage driver that scores δW and Δ′ against
  a converged reference, and a cold/warm stage profiler.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…nd the geqdsk corpus runner

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@github-actions github-actions Bot added changed-results Results move or an interface breaks - read before upgrading perf Same answers, less time or memory labels Sep 9, 2026
@github-actions

github-actions Bot commented Sep 9, 2026

Copy link
Copy Markdown
Contributor

This pull request is missing an assignee and a reviewer.

If you are not ready to name them, mark this pull request as a draft.
docs/development/contributors.md suggests lead developers to ask.
Merging is not blocked here, but no pull request may be merged without human review.

d-burg and others added 2 commits September 9, 2026 14:45
…lizable

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…ck workers

Read nw/nh as the last two header integers, so TokaMaker-written geqdsks parse,
and SIGKILL a worker that outlives its wall-clock cap instead of letting the
failed shutdown end the sweep.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

changed-results Results move or an interface breaks - read before upgrading perf Same answers, less time or memory

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant