Repository navigation
DCON, RDCON, STRIDE - BUGFIX - Trace-aware Frobenius exponents at resonant surfaces - #305
Merged
Merged
Conversation
…onant surfaces The Frobenius powers at a resonant surface are the eigenvalues tr/2 -+ SQRT(tr**2/4-det) of the 2x2 resonant block of M0. The codes used -+ SQRT(-det), which is only right for a traceless block. On up-down asymmetric equilibria the block has a small imaginary trace, and the wrong powers and zeroth-order eigenvectors give a spurious imaginary Delta'. sing_vmat/sing1_vmat now store the eigenvalues in singp%power and build the eigenvectors from them. sing_get_ua, sing_get_dua, sing_get_ua_cut and the sing1 versions scale each column by its own power. The RDCON sing_order ceiling uses the exponent separation 2*Re SQRT(tr**2/4-det). singp%alpha keeps the Mercier value SQRT(-di). RDCON appends the two resonant powers to the end of each surface's header record in vmat.bin, and RMATCH uses them, so it stays consistent with the RDCON series. Older readers skip the appended values; for files without them RMATCH uses -alpha, +alpha, exactly as before. Port of OpenFUSIONToolkit/GPEC#517. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ecision singp%alpha = SQRT(-CMPLX(singp%di)): CMPLX without KIND returns default (single precision) complex, so alpha carried ~1e-7 relative rounding. Use KIND=r8. alpha no longer sets the powers or the order ceiling, so on the DIII-D and Solov'ev examples only the alpha stored in vmat.bin changes. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
StuartBenjamin
marked this pull request as draft
October 13, 2026 07:24
StuartBenjamin
requested review from
matt-pharr
and removed request for
d-burg
October 13, 2026 08:19
… BACKSPACE; clearer comments Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
StuartBenjamin
marked this pull request as ready for review
October 13, 2026 09:29
matt-pharr
approved these changes
Oct 15, 2026
Collaborator
|
This checks out and I verified that it is the same as Julia #517 OpenFUSIONToolkit/GPEC#517. |
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.
Fortran port of Julia GPEC #517.
Near a rational surface the solutions go as |ψ − ψ_s|^p, where p are the eigenvalues of the 2×2 resonant block of M0: p = tr/2 ∓ √(tr²/4 − det). DCON, RDCON and STRIDE use ∓√(−det), which assumes tr = 0. It isn't: on the DIII-D example tr is imaginary, 1e-7 to 8e-4 (largest at q = 5 and 6). Δ′ is read off a coefficient |dψ|^(2α) below the big solution, so this small error becomes a large spurious imaginary part on the Δ′ diagonal: STRIDE gives Δ′(q=5) = −2412 − 47180i.
Changes
sing_vmat/sing1_vmatstore the powers tr/2 ∓ √(tr²/4 − det) insingp%power. The zeroth-order eigenvectors,sing_get_ua,sing_get_dua,sing_get_ua_cutand thesing1_*versions use them.sing_order_ceilinguses 2 Re √(tr²/4 − det), as ForceFreeStates - BUGFIX! - Use trace-aware Frobenius exponents at resonant surfaces OpenFUSIONToolkit/GPEC#517 does.siggives M0_L = −D M0_R D with D = diag(1, −1), so the left powers are −p.vmat.bin, and RMATCH reads them. Old RMATCH reads new files. New RMATCH on an old file rereads the header without the powers (by rewind and skip, since the file position after a failed read is processor dependent) and uses ±α, giving bitwise the oldua.singp%alpha = SQRT(-CMPLX(di))was single precision (noKIND); nowKIND=r8in DCON, RDCON and STRIDE. α no longer sets the powers, so this only changes the α written tovmat.bin.Results
DIII-D examples (STRIDE: DIIID_ideal; RDCON: DIIID_resistive, Cholesky), Δ′ diagonal at q = 2…6:
Not changed: the
sing1degenerate branch (sing1_flag) still assumes ±1/2, and RMATCHmatch.fkeeps −0.5 ± √(−di). As with OpenFUSIONToolkit/GPEC#517, a physics check against Glasser 2016 would be welcome. The RDCON numbers above still include the issues fixed in #303 and #304.Scripts: frobenius_trace_scripts.zip:
scripts/run.sh RUNSET <case> <code>(edit its paths), thenscripts/collect.sh TESTROOT > tests.txtandscripts/plot_imdp.py.vmat.bincompatibility:scripts/rmatch_read/run_read_tests.sh NEW_WT DEVELOP_WT TESTROOT.🤖 Generated with Claude Code