Repository navigation
Conversation
|
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. |
…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>
… methods and repair the integrator docstrings - ode_solver must be one of the benchmarked methods (Vern6, Vern7, Vern8, Vern9, DP8), looked up in EL_ODE_SOLVERS; both control construction sites check it before any integration, so a bad name fails immediately instead of at the first solve. - el_ode_algorithm moves out of the middle of the using block. - ode_abstol's docstring says the Δ′ shooting solves use their own per-column absolute tolerance. - The equation blocks the formatter flattened into running text are fenced, and the Riccati driver's docs no longer describe Vern9 as the integrator. - Tests: an unknown ode_solver is refused by solve; every benchmarked name resolves. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
219d3e9 to
9fc00dd
Compare
|
Closing in favour of #480, which fixes the same unset absolute tolerance with a per-column value refreshed every step and keeps Vern9. Two things found while diagnosing this PR's tolerance study are tracked separately: the wrong-solution removal at ideal crossings (#489) and the reduction trigger missing near-parallel solutions (#490). The selectable |
Release note
eulerlagrange_tolerance. Against a reltol 1e-12 / abstol 1e-14 reference, NTV torques on the Solovev kinetic decks were 1.5–1.7 % off on develop and are 0.30–0.36 % off here. Δ′ on the DIII-D-like Riccati case moves 0.01 %, and δW moves at the 1e-6 to 1e-9 level. The one metric that gets worse is Re(et[1]) onsolovev_n1, from 5.6e-7 to 4.1e-6. (harness @ 9fc00dd)ode_solver = "Vern7"andode_abstol = 1e-8automatically.ode_solveracceptsVern6,Vern7,Vern8,Vern9orDP8; an unknown name is rejected before the equilibrium solve. To approximate old results, setode_solver = "Vern9"andode_abstol = 1e-6.Every Euler-Lagrange solve (forward sweep, Riccati outer plasma, propagator chunks, Δ′ shooting) now runs with an explicit absolute tolerance and a configurable explicit Runge-Kutta method, defaulting to Vern7. Previously it used Vern9 at the OrdinaryDiffEq default absolute tolerance of 1e-6. BLAS is pinned to one thread inside the integration.
Why this is a bug fix, not a speed-up. With
abstol = 1e-6, the solve error stopped responding toeulerlagrange_tolerancebelow about 1e-8. Two symptoms:abstol.Step counts rise, 20–97 % in the harness, because the tolerance is now actually enforced. Runtime stays roughly the same.
Regression report
regress --refs 20c466994,9fc00ddd5 --forceover every case, on feynman (SLURM, 8 threads; develop tip vs this branch rebased onto it, both fresh, manifest pinned). Changed rows only;gal_resistive_peis N/A on both refs (a pre-existing extraction gap on develop).The
diiid_slayer_n1γ line (0.01 %) is the unseeded-triangulation tie-break noise that #463 seeds away.Is it closer to converged?
The decks at
eulerlagrange_tolerance = 1e-7were scored against two references at reltol 1e-12 / abstol 1e-14 from different solver families: Vern9 and DP8. The numbers below are the error against the DP8 reference. The two references agree to 2e-5 or better on every quantity scored here.solovev_n1energies (all elements)solovev_n1Re(et[1])solovev_n1or multi-n. Onsolovev_n1the two references disagree by 3.7e-3, so that value is not converged at this resolution.eulerlagrange_tolerancewould be a separate, deck-level decision.Evidence from the integrator study
Reproducing the checks with what is in the repository.
[overrides]with"ForceFreeStates.ode_solver" = "DP8","ForceFreeStates.eulerlagrange_tolerance" = 1e-12and"ForceFreeStates.ode_abstol" = 1e-14, and run both cases at one commit, e.g.regress --cases solovev_kinetic_ntv,solovev_kinetic_ntv_ref --refs <sha>. Run the same pair at a develop commit for the "develop" column.examples/DIIID-like_ideal_example, comparesolve(equil, Riccati(; nchunks=0))withnchunks = 90:delta_prime.matrix[1,1]differs by 1.6e-5 relative on develop, the same ateulerlagrange_tolerance = 1e-12, and by 2e-8 here.The integrator study behind the method choice ran 20 solvers over 3 reltols × 4 abstols. Its drivers are not part of this PR, and the tables below are its output. On the shipped DIII-D-like case, with errors relative to a Vern9 reltol 1e-13 / abstol 1e-15 reference:
At equal tolerances Vern7 is about 1.8× faster than Vern9, because Vern9 rejects most of its steps near the rational surfaces. So the fix costs little time. The 8.6 s vs 9.9 s stage time comes largely from the BLAS pin, not from the method.
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:
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.
Notes for reviewers
ode_solveris limited to the benchmarked methods. Tsit5 lost Δ′ accuracy 10–100× on three corpus cases, and VCABM was not robust on the 10-surface case. The Δ′ shooting solves keep their per-column absolute tolerance (scale × reltol) rather thanode_abstol, as the field docstring now says.ode_solveris validated early, with tests.abstoldefect is independent of the equilibrium resampling Equilibrium - BUGFIX! - Sample all flux surfaces on common straight-fieldline abscissae and cap the coefficient-spline core knots #398 fixes, and Equilibrium - BUGFIX! - Sample all flux surfaces on common straight-fieldline abscissae and cap the coefficient-spline core knots #398 re-baselines these numbers either way.NO MERGE WITHOUT HUMAN REVIEW. This PR is a draft and needs a named human reviewer and an assignee before it can be considered for merge. Non-negotiable.
🤖 Generated with Claude Code