Repository navigation
Conversation
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. |
…eliable psi-spline Hessian
Two failure modes of `direct_position!` on otherwise healthy geqdsks, both caused by
the 2-D psi spline's second derivatives near the axis (dB_z/dR wanders between ~5
and ~0 within a few cells, so the Hessian goes near-singular or indefinite):
1. "Jacobian matrix is singular" -- one bad iterate sent the undamped Newton step
across the whole box, into a region where det J underflowed.
2. "Failed to find magnetic axis after 200 iterations" -- Newton cycled between
two points either side of the axis on an indefinite Hessian.
Fix, in two stages that leave the converging path untouched:
* Cap each Newton step at one midplane-march step. Inactive for well-behaved
iterations (their steps are < dr/2); it only keeps a bad iterate inside the
axis neighbourhood until the Hessian recovers. A singular Hessian now returns
"not converged" instead of erroring.
* If Newton does not converge, locate the axis with first derivatives only:
B_z changes sign across the axis along the midplane and B_r along a column,
so four alternating 1-D bisections (80 iterations each, widening bracket in Z)
converge to grad(psi) = 0 without touching the spline's second derivatives.
Newton is retried from that point; if it still fails, the bisection point is
used as the axis (it is a converged zero of the first derivatives) with an
@info message instead of an error.
Healthy equilibria never enter the fallback, so their results are bit-identical
(regression harness: diiid_n1 47/47, diiid_slayer_n1 15/15,
efit_fixedbdy_separatrix 5/5 unchanged vs 349a0c2).
Two 257x257 TJ circular geqdsks reproducing each failure mode are added as
fixtures with a test that both now locate the axis where the midplane B_z
crossing says it is, and that a healthy geqdsk takes the plain Newton path.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…ic-axis search falls back The TJ fixtures fail Newton because their ψ has a curvature spike at the axis, not because the spline's Hessian is unreliable. So the search no longer accepts an unconverged point: - Plain, uncapped Newton runs first, exactly as before, so smooth files are bit-identical by construction rather than because a step cap happened to stay inactive. - On failure, capped Newton restarts from a point found by alternating 1-D bisections on B_z and B_r. The bisection now checks that each bracket straddles a sign change, stays inside the grid, and errors when it cannot find one. - The restart must pass the same step-size test; otherwise "Failed to find magnetic axis" is an error again. A successful fallback warns that ψ is likely not smooth near the axis. - The test asserts the warned fallback on both fixtures and no warning on a healthy file; the fixtures' provenance and defect are recorded in the test-data README. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
d-burg
force-pushed
the
bugfix/equilibrium-axis-search-robustness
branch
from
September 23, 2026 22:11
7513e20 to
a0b33f6
Compare
…t needs no Logging dependency Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ck and report why Newton stopped - After the bisection-seeded Newton restart, evaluate det ∂(B_R,B_Z)/∂(R,Z) at the returned point and error unless it is positive (O-point; an X-point has det < 0). - The Newton helper returns :converged, :singular_jacobian or :iteration_cap, and the warning and error messages state which condition stopped it, plus |B_p| and det at the result, instead of asserting an indefinite Hessian that is never tested. - Replace the hand-written bisection with Roots.find_zero(..., Roots.Bisection()), whose float-bisection stop also terminates for brackets around Z = 0. - Name the singular-Jacobian threshold and the bisection pass count (values unchanged). - Drop the Fortran citation from the docstring and state the returned axis's contract. The plain Newton path is arithmetically unchanged. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… their closure find_separatrix_crossing assigned r and dr, which rebound (and boxed) the enclosing function's variables that the axis search also uses. Declaring them local keeps the closure self-contained; the arithmetic is unchanged. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…est cusped Solovev equilibrium Build the fallback fixture in the test: an up-down symmetric Solovev psi with a conical cusp at the axis, so the axis cells carry a curvature spike and Newton from the midplane march point does not converge. The tests now assert that the returned axis is an O-point of the psi spline, that |grad psi| is below the Newton step tolerance times psio/(rmax-rmin), that Z vanishes to rounding on the symmetric fixture, and that it lies within one grid cell of the cusp apex. A smooth variant and the COCOS_02 geqdsk must take the plain path with no warning. Drops the two 1.1 MB TJ geqdsks. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…e the march bracket, or not O-points On both the plain and the fallback path, the magnetic axis must now lie inside the psi grid and, when the midplane march took a step, inside its R-bracket of the B_z sign change; it must also be an O-point (det d(B_R,B_Z)/d(R,Z) > 0). After the fallback, |B_p| must be at most 1e-10 B_scale with B_scale = |psio| / (R_axis (R_max - R_min)). Each violation is an error that reports where Newton landed and the bounds it broke. Plain Newton on a cusped psi could previously converge silently to a false O-point off the grid, found by spline extrapolation. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…eted axis in the axis-search test The cusped-Solovev fixture takes explicit inboard and outboard grid extents. An inboard-heavy grid makes the midplane march bracket the axis, and cusp strengths 2.25 and 2.5 cells, where plain Newton converges off the grid, must now raise the off-grid error. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Collaborator
|
@d-burg should this be assigned a reviewer? |
…tarted axis search The axis of an up-down asymmetric equilibrium need not share its R with the midplane B_z sign change, so the bracket rejected a correct axis found by the direct Newton iteration. It now applies only to the restart. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…arted axis search On an up-down shifted grid with a cusp at the axis the restart found the correct axis and the bracket rejected it. The restart is still certified by the in-grid, O-point and residual checks. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…path a chaotic Newton takes Newton on the cusp fixture converges, cycles or leaves the grid depending on the machine's rounding, so tests that named the path failed on some hosts. The cusp sweep now asserts a verified axis or a loud failure, and the off-grid error uses a smooth grid that excludes the axis. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Collaborator
|
Merged develop and retained the axis-search changes in |
This branch has not been deployed
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
Two TJ-written 257×257 geqdsks (two points of an 81-point circular β scan) used to abort reading with
Jacobian matrix is singular near (…)orFailed to find magnetic axis after 200 iterations. The cause is the files, not the spline: their ψ has a curvature spike in the grid cells at the axis (∂²ψ/∂R² ≈ 13–19 against ≈ 3–10 on the neighbouring cells, in the raw data), so Newton from the midplane guess meets a singular or indefinite Hessian. The axis search now recovers such files without relaxing what "found" means, and says loudly that the file looks wrong.Regression report
Compared
develop@6d655c74cagainst this branch @bf4e298e1:diiid_n153 unchanged,diiid_n1_riccati17 unchanged,efit_fixedbdy_separatrix5 unchanged,diiid_slayer_n117 unchanged, andsolovev_n122 unchanged. All numeric differences are zero; checksums are identical, including the SLAYER results in this run. Focused equilibrium, axis-Newton, and grid-refinement tests passed.Run on ITER SDCC through Slurm, Julia 1.12.6, CI-pinned manifest, 2 Julia threads / 1 BLAS thread per case (16 threads for
diiid_error_field).Full regression report
What changed
|δR|, |δZ| ≤ 1e-12·R). Nothing on that path changed, so healthy files are bit-identical by construction.Failed to find magnetic axisis a hard error again. No unconverged point is ever accepted. A successful fallback issues a@warnthat ψ is likely not smooth near the axis.Notes for reviewers
@info, which quietly changed the convergence criterion. An adversarial review found both problems, and both are fixed here. The spline is faithfully interpolating defective data, so the files themselves should be regenerated. That is for the TJ geqdsk writer to fix, not something this PR can do.test/test_data/README_test_data.md. They are the only files known to reproduce each failure mode.bugfix/build-reproducible-arithmeticbranch: that branch edits the same Newton loop (an extra polish step after the stop test), so the two will conflict textually. The polish belongs inside_axis_newtonso both attempts get it.Audit round (2026-09-25)
Failed to find magnetic axiserror, with the fallback firing at least once. The off-grid error is tested on a smooth grid that excludes the axis.Roots.find_zero(…, Bisection()), the numerical controls are named, the warnings state which condition stopped Newton, and the docstring's Fortran citation is gone.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