Repository navigation
Equilibrium - BUGFIX - Detect field-line ODE failure instead of consuming a truncated surface - #442
Merged
Merged
Conversation
…ming a truncated surface direct_fieldline_int solved the flux-surface field-line ODE and never checked sol.retcode, then read sol.u[end] as though the surface had closed at eta = 2*pi. A failed solve does not throw -- it returns a solution truncated wherever the integrator gave up -- so the caller silently built a wrong flux surface and the damage surfaced downstream as unrelated nonsense, or not at all. Check both the retcode and the endpoint: a solve can stop early through a callback-driven terminate and still report Success, so neither check subsumes the other. Both errors name the psifac that failed and point at psihigh sitting too close to the separatrix, which is the usual cause. No healthy deck is affected: runtests_equil.jl passes 281/281 and the DIII-D-like ideal example runs end to end with neither guard firing. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PSrf6JCViFfVzqzkQ66o6b
logan-nc
force-pushed
the
bugfix/fieldline-ode-retcode
branch
from
September 11, 2026 22:06
0bb4993 to
d65375d
Compare
Both annotation blocks narrated the investigation behind the guard. Keep only the non-obvious reason two checks are needed: a callback can end the solve early and still report Success. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PSrf6JCViFfVzqzkQ66o6b
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.
Release note
A flux surface whose field-line integration failed used to be consumed as if it had closed, so GPEC
carried on and produced a silently wrong equilibrium. It now stops with an error naming the
psifacthat failed. This most often means
psihighis too close to the separatrix for the equilibrium gridto resolve.
Regression report
Run at
d65375dff, before the 2026-10-01 develop merge. Not re-run after it: the only later changes on this branch are that merge and comment-only edits, so the stamp is deliberately left where the harness actually ran.The bug
direct_fieldline_intsolves the flux-surface field-line ODE and never checkssol.retcode. Thevery next line consumes
sol.u[end]as though the field line had closed ateta = 2*pi. But afailed solve does not throw — it returns a solution truncated wherever the integrator gave up. So
the caller silently builds a flux surface from a partial trace, and the damage surfaces downstream as
unrelated nonsense, or not at all.
The fix
Two checks, because neither subsumes the other:
sol.retcode != ReturnCode.Success— the ordinary failure.sol.t[end]did not reach2*pi— a solve can stop early through a callback-driven terminate andstill report
Success.direct_fieldline_intinstalls aDiscreteCallback, so this is reachable.Both errors name the
psifacthat failed, and the first points atpsihighsitting too close to theseparatrix, which is the usual cause. The failure becomes attributable to a surface rather than a
stack trace somewhere further down the pipeline.
Verification
Pkg.test()sandbox,runtests_equil.jl— 286/286 pass (theEquilibrium Unit Testsset;281 of those predate this PR, the rest come from sibling work on this base).
firing.
develop @ f36ecef86. Expected — on a healthy equilibrium this adds two predicates and changesnothing.
A note on the test
The added testset asserts the guards against the source text rather than triggering them. A genuinely
non-closing field line is not cheap to synthesize here, and forcing
psifactoward the separatrixwould likely hit a different error first and be flaky across machines. The standing positive control
that neither guard false-fires is the EFIT testsets already in that file, which trace real surfaces
through this function. Happy to swap in a behavioral trigger if a reviewer sees a clean way to build one.
Scope
Equilibriumonly; no SLAYER/Tearing code touched. Split out of theFKR-widthwork as anindependent fix, same shape as #399.
🤖 Generated with Claude Code
https://claude.ai/code/session_01PSrf6JCViFfVzqzkQ66o6b