Use implicit midpoint for SPECTRE field lines#483
Merged
Conversation
5e96c1e to
3a2aeed
Compare
3a2aeed to
bf29923
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Risk tier
Correctness contract
Intended behavior change
Advance the SPECTRE canonical field-line pair with the second-order implicit midpoint rule. Use libneo's first-derivative-only vector-potential evaluation in the midpoint residual and endpoint-radius solve. The Poincare app builds a cubic hot-loop spline for one volume at a time and can read the same explicit seed file as the native SPECTRE tracer.
Behavior that must not change
Field lines remain confined to their SPECTRE volume. Section orientation, rotational-transform sign, vector-potential representation, and the
psi = A_thetacanonical momentum definition remain unchanged.Coordinate / unit conventions
The map still uses local SPECTRE
sin[-1,1], poloidal angletheta, and toroidal anglezeta; angles are dimensionless radians. The spline is periodic over2 piinthetaand2 pi/Nfpinzeta. The implicit solve advances(theta, psi)withzetaas time and recovers endpointsfromA_theta(s, theta, zeta) = psi.Numerical invariants
Implicit midpoint preserves the canonical symplectic form and is self-adjoint. A forward step followed by the same negative step returns
(s, theta, zeta, psi)within2e-11. The midpoint residual retains the1e-13tolerance. Long traces solve for a local angle increment to avoid subtracting large unwrapped angles.The hot-loop spline represents
A_thetaandA_zeta; all derivatives in the midpoint residual come from those same interpolants. The map is therefore symplectic for one internally consistent approximate Hamiltonian. The spline is constructed before a volume trace, read only while tracing, and destroyed before the next volume.Tests added
fopipelineGolden-record impact
Failure modes considered
The midpoint solve rejects a singular numerical Jacobian or failure to meet its residual tolerance. The endpoint-radius Newton solve remains separately checked. The angle-increment formulation avoids loss of residual precision after hundreds of unwrapped turns. Spline grid dimensions must exceed the cubic order.
Manual validation
A Profile build on
tok_islandattributed 98.3% of the post-midpoint run to direct vector-potential evaluation, which motivated the per-volume spline. The profile used 45 seeds, 50 toroidal transits, and 32 steps per field period.On the same 45 seeds and 500 transits, the final 32-step midpoint+spline run completed with zero terminations in 11.19 s and 57 MiB peak RSS. SPECTRE's native CyRK tracer took 11.35 s on the same host. Relative to the native section, the outer-volume errors were median
5.90e-4m, 95th percentile6.80e-3m, and maximum1.70e-1m. The stored 512-step first-order run took 324 s and has median3.94e-4m, 95th percentile3.15e-2m, and maximum4.39e-1m.Before the spline, the 32-step midpoint run took 50.0 s. Its outer-volume errors were median
4.83e-4m, 95th percentile3.36e-3m, and maximum2.92e-2m.Verification
Failing before, with the second-order convergence test run against main:
Passing after:
The dependency-pin failure was also reproduced before the final push:
After advancing
GOLDEN_LIBNEO_REFto merged libneo commit18b91aabffcc3c8833648f01a057e278809c15f2, the exact pinned deterministic configuration built all 1,153 targets successfully. The final barefogate then passed 175-module static analysis, build, tests, and lint.