Skip to content

PerturbedEquilibrium - BUGFIX! - Converge the singular coupling with singfac_min = 1e-6 in the forward-integrator decks - #555

Merged
matt-pharr merged 4 commits into
developfrom
bugfix/singfac-min-converged
Oct 29, 2026
Merged

matt-pharr merged 4 commits into
developfrom
bugfix/singfac-min-converged

Conversation

@logan-nc

@logan-nc logan-nc commented Oct 22, 2026 •

Copy link
Copy Markdown
Collaborator

Closes #237.

Review package: https://claude.ai/artifact/VMcqrrHhyxbnJiMFzKQzLz (figures for every claim below; ask @logan-nc for access if the link doesn't open)

Release note

  • Audience: users
  • Numerical impact: PerturbedEquilibrium (PE) outputs of the forward-integrator example decks move: the DIII-D-like resonant field by up to 2%, island widths 1.8%, Chirikov 5.4%; the spurious ideal PE torque and Im(et) drop by 99%; the near-marginal Solovev n=1 energy by 32% and its NTV torque by 119%. Riccati Δ′, Galerkin stability, SLAYER and GGJ tracked quantities do not move; the Galerkin PE case has missing outputs on both refs. Calculated-kinetic Solovev displacement norms change by 8.35%, with NTV torque changing by approximately 0.0064%. (harness @ 4ecda73)
  • Migration: decks of your own that run "forward" into PerturbedEquilibrium should set singfac_min = 1e-6; the code default stays 1e-4.

The resonant coupling matrices (resonant field, current, island width², Δ′) were found not to depend on the working coordinates once the solve is converged. The 8–20% scatter reported in #237 came from the ideal-jump offset singfac_min = 1e-4, which left the outer rational surfaces unconverged. The forward-integrator example decks now use 1e-6. The code default stays 1e-4, because the Riccati Δ′ degrades at smaller offsets.

What was found

  • Coordinate independence: at singfac_min = 1e-6, Hamada, PEST and Boozer agree on |bʳ| to within 0.5% on four of the five DIII-D-like rational surfaces (1.4% for PEST at ψ = 0.993), and on the singular values of C̃ to within 0.7%. At 1e-4, the q = 4 surface was off by 12% (Hamada) to 20% (PEST, Boozer).
  • The definitions are sound: at the old offset, all four coupling outputs moved by the same ratio on each surface, so the error sat in the shared solution, not in any one matrix's normalization.
  • Ruled out: equilibrium mtheta, ODE tolerance, coil forcing (‖b̃ₓ‖ agrees to 0.03%) and the plasma response (leading permeability eigenvalue agrees to about 1%).
  • Equal-arc converges slowly in poloidal harmonics (q = 5 reaches 73% of Hamada at 83 harmonics). That is a resolution limit of that coordinate system.
  • C_penetrated_area_weighted_field cannot be checked yet: runs that match inner-layer solutions skip the singular coupling, so no deck writes it. Its rows are a field in T by construction, now documented.

Why only the forward decks

The same offset sets where the Riccati integrator matches to its asymptotic series across each rational surface. Its Δ′ diagonal should be real, but |Im Δ′|/|Re Δ′| on the q = 5 surface grows from 0.4% at 1e-4 to 18% at 1e-5 and 790% at 1e-6. A first version of this branch set 1e-6 globally, and the harness showed the Riccati Δ′ move by 851%. So:

  • "forward" decks feeding PE now use 1e-6: DIIID-like error_field, ideal, ideal_multi_n, truncation; Solovev ideal, kinetic_NTV, kinetic_calculated, kinetic_multiion; a10_kinetic.
  • The code default, and the Riccati, Galerkin, SLAYER, LAR and Solovev 3D / multi-n decks keep 1e-4.
  • The CoreTypes.jl docstring now states the trade-off. compute_singular_coupling_metrics! documents the row and column normalization.

Notes for reviewers

  • @d-burg: requested for the Δ′ side. The Riccati and Galerkin Δ′ quantities are unchanged in the harness (17/17 and 11/11). Separately, the Riccati Δ′ already has a 0.4% imaginary part at 1e-4 on q = 5, growing as the offset shrinks. That suggests the asymptotic matching at each crossing (sing_get_ua in Crossings.jl) loses accuracy. That is my inference and is out of scope here.
  • Large moves are expected. The Solovev n = 1 mode is near marginal: its plasma and vacuum energies each move ≤ 0.05% and nearly cancel, so et moves 32%. The response scales as 1/et, so the NTV torque scales as 1/et²: (1.091/0.736)² = 2.19, matching the +119%. A separate scan of that deck gives et = 0.01091, 0.00769, 0.00736, 0.00733 at 1e-4…1e-7 (0.45% from 1e-6 to 1e-7), and a breakdown at 1e-8 (sign flip, imaginary part). So 1e-6 is converged, and smaller is not safer.
  • The ideal PE toroidal torque (DIII-D-like n = 1: 1.1e-4 → 9.1e-7) and Im(et) (7.9e-5 → 1.1e-6) should be zero in ideal MHD; both move toward it.
  • ODE steps rise 35–50% in the forward decks; runtime changes under 4% in every case.
  • Test fixtures (test/test_data/regression_*) keep 1e-4, so no golden values move. The full test suite passed on the first (global 1e-6) version of the branch; CI covers this one.

Regression report

Updated after merging develop: 21 cases / 42 successful runs, zero failed runs, comparing develop f43b5bee8f1dc1bc772923b86f029c9465f0e3b0 with PR head 4ecda73be5dd823a65e45dcf505380dd17d2ca10. Harness exit status: 0. Julia 1.12.6, pinned manifest 4c9d54fa, 8 Julia threads / 4 BLAS threads on both refs.

The cutoff-induced numerical changes remain visible: ideal Solovev NTV torque is 39.47649088015491 → 86.57098121746682 N·m (+119.30%); multi-ion torque changes by +119.18%. The calculated-kinetic Solovev NTV quadrature torque changes by approximately +0.0064%, while displacement norms change by 8.35%. DIII-D-like n=1 resonant-field components change by up to 1.98%, island widths by 1.76%, and Chirikov by 5.32%; the spurious ideal PE torque drops by 99.19%.

Coverage caveat: all eight non-runtime quantities in gal_resistive_pe are missing/N/A on both refs. That case completed but provides no numerical validation of those outputs. Riccati, SLAYER, GGJ, the two Galerkin stability cases, and Solovev multi-n have unchanged tracked non-runtime quantities. Further cutoff-convergence investigation is deferred until after 2.0 in #610; this regression comparison is not a convergence proof.

Full 21-case regression report (spacing compacted; values unchanged)

================================================================
Case: diiid_error_field — DIII-D-like error-field assessment, n=1: ErrorFields stage with the NTV-limited correction couplings
================================================================

Regression Report: diiid_error_field
====================================================================================================
Ref 1: f43b5bee8  @ f43b5bee8 (2026-10-29)
  env: julia 1.12.6, x86_64-linux-gnu, manifest 4c9d54fa (pinned), 8 threads/4 BLAS, jit build
Ref 2: 4ecda73be  @ 4ecda73be (2026-10-29)
  env: julia 1.12.6, x86_64-linux-gnu, manifest 4c9d54fa (pinned), 8 threads/4 BLAS, jit build
----------------------------------------------------------------------------------------------------
Quantity  f43b5bee8  4ecda73be  Diff  Status
----------------------------------------------------------------------------------------------------
EFC overlap per kAt  [1 elem]  [1 elem]  1.011e-07 (0.57%)  ** CHANGED **
EFC whole-field NTV torque per kAt² [N·m]  [1 elem]  [1 elem]  3.667e-04 (1.07%)  ** CHANGED **
EFC residual-field NTV torque per kAt² [N·m]  [1 elem]  [1 elem]  9.264e-05 (4.11%)  ** CHANGED **
EFC reference rotation ω_ref [rad/s]  [1 elem]  [1 elem]  0.0e+00  OK
EFC rotation-scan shifts [rad/s]  [9 elem]  [9 elem]  0.0e+00  OK
EFC residual torque against rotation [N·m/kAt²]  [9 elem]  [9 elem]  3.104e-04 (4.85%)  ** CHANGED **
dominant-coupling singular values  [3 elem]  [3 elem]  7.665e-03 (0.34%)  ** CHANGED **
|delta_nominal| of coil set 1  1.406896e-06  1.414983e-06  8.087e-09 (0.57%)  ** CHANGED **
|Σ δ_as_designed| of the error-field coils  1.825432e-18  1.795975e-18  2.9e-20  OK
Monte Carlo mean |δ| of the error-field coils  4.701298e-05  4.701440e-05  1.424e-09 (0.00%)  ** CHANGED **
Runtime (s)  262.4s  259.6s  --
====================================================================================================
Summary: 7 changed, 3 unchanged


================================================================
Case: diiid_multi_n — DIII-D-like equilibrium, n = 1, 2, ideal + perturbed equilibrium
================================================================

Regression Report: diiid_multi_n
====================================================================================================
Ref 1: f43b5bee8  @ f43b5bee8 (2026-10-29)
  env: julia 1.12.6, x86_64-linux-gnu, manifest 4c9d54fa (pinned), 8 threads/4 BLAS, jit build
Ref 2: 4ecda73be  @ 4ecda73be (2026-10-29)
  env: julia 1.12.6, x86_64-linux-gnu, manifest 4c9d54fa (pinned), 8 threads/4 BLAS, jit build
----------------------------------------------------------------------------------------------------
Quantity  f43b5bee8  4ecda73be  Diff  Status
----------------------------------------------------------------------------------------------------
total energy Re(et[1])  -5.750527e-01  -5.750944e-01  4.176e-05 (0.01%)  ** CHANGED **
total energy (all)  [58 elem]  [58 elem]  8.913e-02 (0.00%)  ** CHANGED **
ODE steps (saved)  629  910  2.810e+02 (44.67%)  ** CHANGED **
mpert  29  29  0.0e+00  OK
npert  2  2  0.0e+00  OK
toroidal mode label of each mode index (checksum)  8d8d42b8832d...  8d8d42b8832d...  identical  OK
permeability diagonal P~_ii (all n blocks)  [58 elem]  [58 elem]  5.132e-03 (0.06%)  ** CHANGED **
forcing b~ (root-area-weighted), n = 1, 2  [58 elem]  [58 elem]  0.0e+00  OK
response b~ (root-area-weighted), n = 1, 2  [58 elem]  [58 elem]  1.499e-07 (0.05%)  ** CHANGED **
PE plasma energy (sum over n)  2.936559e+00  2.936508e+00  5.046e-05 (0.00%)  ** CHANGED **
PE vacuum energy (sum over n)  3.113946e+00  3.113946e+00  0.0e+00  OK
PE surface energy (sum over n)  3.523427e+00  3.523287e+00  1.395e-04 (0.00%)  ** CHANGED **
PE toroidal torque sum_n -2n Im(Phi_n' Lambda_nn^-1 Phi_n)/4  1.820338e-06  2.148527e-08  1.799e-06 (98.82%)  ** CHANGED **
resonant n per row (rows sorted by psi across n)  [7 elem]  [7 elem]  0.0e+00  OK
resonant m per row  [7 elem]  [7 elem]  0.0e+00  OK
resonant area-weighted field b^r per row  [7 elem]  [7 elem]  8.548e-07 (0.79%)  ** CHANGED **
island half-widths per row  [7 elem]  [7 elem]  2.854e-04 (1.52%)  ** CHANGED **
Chirikov parameter per row  [7 elem]  [7 elem]  3.851e-03 (0.81%)  ** CHANGED **
forcing-driven Delta' per row  [7 elem]  [7 elem]  4.204e-05 (1.23%)  ** CHANGED **
Runtime (s)  184.9s  180.0s  --
====================================================================================================
Summary: 12 changed, 7 unchanged


================================================================
Case: diiid_n1 — DIII-D-like equilibrium, n=1, ideal + perturbed equilibrium
================================================================

Regression Report: diiid_n1
====================================================================================================
Ref 1: f43b5bee8  @ f43b5bee8 (2026-10-29)
  env: julia 1.12.6, x86_64-linux-gnu, manifest 4c9d54fa (pinned), 8 threads/4 BLAS, jit build
Ref 2: 4ecda73be  @ 4ecda73be (2026-10-29)
  env: julia 1.12.6, x86_64-linux-gnu, manifest 4c9d54fa (pinned), 8 threads/4 BLAS, jit build
----------------------------------------------------------------------------------------------------
Quantity  f43b5bee8  4ecda73be  Diff  Status
----------------------------------------------------------------------------------------------------
total energy Re(et[1])  8.006122e-01  7.979262e-01  2.686e-03 (0.34%)  ** CHANGED **
total energy Im(et[1])  7.924882e-05  1.122427e-06  7.813e-05 (98.58%)  ** CHANGED **
plasma energy Re(ep[1])  -1.372261e+00  -1.377302e+00  5.040e-03 (0.37%)  ** CHANGED **
vacuum energy Re(ev[1])  2.172874e+00  2.175228e+00  2.354e-03 (0.11%)  ** CHANGED **
vacuum matrix min eigenvalue  1.873975e-01  1.873975e-01  0.0e+00  OK
plasma energy (all)  [35 elem]  [35 elem]  1.855e-01 (0.00%)  ** CHANGED **
vacuum energy (all)  [35 elem]  [35 elem]  9.474e-03 (0.00%)  ** CHANGED **
total energy (all)  [35 elem]  [35 elem]  1.844e-01 (0.00%)  ** CHANGED **
ODE steps (saved)  789  1166  3.770e+02 (47.78%)  ** CHANGED **
ODE steps (total)  784  1161  3.770e+02 (48.09%)  ** CHANGED **
q0  1.204212e+00  1.204212e+00  0.0e+00  OK
q95  4.781723e+00  4.781723e+00  0.0e+00  OK
beta_t  1.327024e-02  1.327024e-02  0.0e+00  OK
beta_n  1.372511e+00  1.372511e+00  0.0e+00  OK
internal inductance li1  8.842268e-01  8.842268e-01  0.0e+00  OK
internal inductance li2  7.080757e-01  7.080757e-01  0.0e+00  OK
internal inductance li3  7.304340e-01  7.304340e-01  0.0e+00  OK
poloidal beta betap1  6.680739e-01  6.680739e-01  0.0e+00  OK
poloidal beta betap2  5.349836e-01  5.349836e-01  0.0e+00  OK
poloidal beta betap3  5.518764e-01  5.518764e-01  0.0e+00  OK
# singular surfaces  5  5  0.0e+00  OK
singular psi locations  [5 elem]  [5 elem]  0.0e+00  OK
singular q values  [5 elem]  [5 elem]  0.0e+00  OK
current beta betaj  4.236480e-01  4.236480e-01  0.0e+00  OK
plasma volume  1.829472e+01  1.829472e+01  0.0e+00  OK
plasma current  1.152130e+00  1.152130e+00  0.0e+00  OK
mpert  35  35  0.0e+00  OK
npert  1  1  0.0e+00  OK
toroidal field bt0  2.006573e+00  2.006573e+00  0.0e+00  OK
wall field bwall  3.880145e-01  3.880145e-01  0.0e+00  OK
aspect ratio  2.845746e+00  2.845746e+00  0.0e+00  OK
elongation kappa  1.708322e+00  1.708322e+00  0.0e+00  OK
q profile (checksum)  6da947d0754e...  6da947d0754e...  identical  OK
pressure profile (checksum)  c9c6ca4072ca...  c9c6ca4072ca...  identical  OK
Mercier D_I profile (checksum)  26babbe22505...  26babbe22505...  identical  OK
resistive interchange D_R profile (checksum)  c46830151a0b...  c46830151a0b...  identical  OK
ballooning Delta' profile (checksum)  c27c6779804a...  c27c6779804a...  identical  OK
island half-widths  [5 elem]  [5 elem]  5.391e-04 (1.76%)  ** CHANGED **
Chirikov parameter  [5 elem]  [5 elem]  4.309e-02 (5.32%)  ** CHANGED **
||resonant area-weighted field||  5.288611e-04  5.286393e-04  2.218e-07 (0.04%)  ** CHANGED **
dominant-coupling singular values  [3 elem]  [3 elem]  7.665e-03 (0.34%)  ** CHANGED **
|forcing overlap with dominant mode|  1.411520e-04  1.419633e-04  8.113e-07 (0.57%)  ** CHANGED **
|delta_nominal| of coil set 1  7.034480e-05  7.074914e-05  4.043e-07 (0.57%)  ** CHANGED **
||ddelta/d(shift)|| over coil sets  1.245436e-04  1.246840e-04  1.404e-07 (0.11%)  ** CHANGED **
||ddelta/d(tilt)|| over coil sets  4.177322e-07  4.175435e-07  1.887e-10 (0.05%)  ** CHANGED **
PE plasma energy  3.320466e+00  3.321081e+00  6.151e-04 (0.02%)  ** CHANGED **
PE vacuum energy  3.174319e+00  3.174319e+00  0.0e+00  OK
PE surface energy  5.508585e+00  5.521987e+00  1.340e-02 (0.24%)  ** CHANGED **
PE toroidal torque  1.119354e-04  9.083725e-07  1.110e-04 (99.19%)  ** CHANGED **
NTV torque FGAR [N·m]  5.480624e-01  5.539336e-01  5.9e-03  OK
NTV kinetic energy dW FGAR [J]  8.163328e-02  8.225444e-02  6.2e-04  OK
Runtime (s)  212.0s  213.7s  --
||forcing b~|| (root-area-weighted)  4.683171e-04  4.683171e-04  0.0e+00  OK
resonant area-weighted field b^r  [5 elem]  [5 elem]  8.227e-06 (1.98%)  ** CHANGED **
====================================================================================================
Summary: 21 changed, 32 unchanged


================================================================
Case: diiid_n1_riccati — DIII-D-like equilibrium, n=1, Riccati integrator Δ' matrix
================================================================

Regression Report: diiid_n1_riccati
====================================================================================================
Ref 1: f43b5bee8  @ f43b5bee8 (2026-10-29)
  env: julia 1.12.6, x86_64-linux-gnu, manifest 4c9d54fa (pinned), 8 threads/4 BLAS, jit build
Ref 2: 4ecda73be  @ 4ecda73be (2026-10-29)
  env: julia 1.12.6, x86_64-linux-gnu, manifest 4c9d54fa (pinned), 8 threads/4 BLAS, jit build
----------------------------------------------------------------------------------------------------
Quantity  f43b5bee8  4ecda73be  Diff  Status
----------------------------------------------------------------------------------------------------
delta prime (BVP diagonal)  [5 elem]  [5 elem]  0.0e+00  OK
delta prime (raw side-major)  [10 elem]  [10 elem]  0.0e+00  OK
edge coil response delta_coil  [10 elem]  [10 elem]  0.0e+00  OK
total energy Re(et[1])  8.031971e-01  8.031971e-01  0.0e+00  OK
plasma energy Re(ep[1])  -1.368534e+00  -1.368534e+00  0.0e+00  OK
vacuum energy Re(ev[1])  2.171732e+00  2.171732e+00  0.0e+00  OK
total energy (all)  [35 elem]  [35 elem]  0.0e+00  OK
# singular surfaces  5  5  0.0e+00  OK
singular psi locations  [5 elem]  [5 elem]  0.0e+00  OK
singular q values  [5 elem]  [5 elem]  0.0e+00  OK
ODE steps (saved)  95  95  0.0e+00  OK
ODE steps (total)  2633  2633  0.0e+00  OK
mpert  35  35  0.0e+00  OK
npert  1  1  0.0e+00  OK
q0  1.204212e+00  1.204212e+00  0.0e+00  OK
q95  4.781723e+00  4.781723e+00  0.0e+00  OK
beta_n  1.372511e+00  1.372511e+00  0.0e+00  OK
Runtime (s)  183.6s  174.5s  --
====================================================================================================
Summary: 17 unchanged


================================================================
Case: diiid_n1_riccati_precompiled — DIII-D-like equilibrium, n=1, Riccati integrator Δ' matrix, precompiled build
================================================================

Regression Report: diiid_n1_riccati_precompiled
====================================================================================================
Ref 1: f43b5bee8  @ f43b5bee8 (2026-10-29)
  env: julia 1.12.6, x86_64-linux-gnu, manifest 4c9d54fa (pinned), 8 threads/4 BLAS, aot build
Ref 2: 4ecda73be  @ 4ecda73be (2026-10-29)
  env: julia 1.12.6, x86_64-linux-gnu, manifest 4c9d54fa (pinned), 8 threads/4 BLAS, aot build
----------------------------------------------------------------------------------------------------
Quantity  f43b5bee8  4ecda73be  Diff  Status
----------------------------------------------------------------------------------------------------
delta prime (BVP diagonal)  [5 elem]  [5 elem]  0.0e+00  OK
delta prime (raw side-major)  [10 elem]  [10 elem]  0.0e+00  OK
edge coil response delta_coil  [10 elem]  [10 elem]  0.0e+00  OK
total energy Re(et[1])  8.031971e-01  8.031971e-01  0.0e+00  OK
plasma energy Re(ep[1])  -1.368534e+00  -1.368534e+00  0.0e+00  OK
vacuum energy Re(ev[1])  2.171732e+00  2.171732e+00  0.0e+00  OK
total energy (all)  [35 elem]  [35 elem]  0.0e+00  OK
# singular surfaces  5  5  0.0e+00  OK
singular psi locations  [5 elem]  [5 elem]  0.0e+00  OK
singular q values  [5 elem]  [5 elem]  0.0e+00  OK
ODE steps (saved)  95  95  0.0e+00  OK
ODE steps (total)  2633  2633  0.0e+00  OK
mpert  35  35  0.0e+00  OK
npert  1  1  0.0e+00  OK
q0  1.204212e+00  1.204212e+00  0.0e+00  OK
q95  4.781723e+00  4.781723e+00  0.0e+00  OK
beta_n  1.372511e+00  1.372511e+00  0.0e+00  OK
Runtime (s)  21.9s  22.2s  --
====================================================================================================
Summary: 17 unchanged


================================================================
Case: diiid_slayer_n1 — DIII-D-like H-mode equilibrium, n=1, SLAYER tearing-mode analysis (uncoupled per-surface, AMR, validity-gated)
================================================================

Regression Report: diiid_slayer_n1
====================================================================================================
Ref 1: f43b5bee8  @ f43b5bee8 (2026-10-29)
  env: julia 1.12.6, x86_64-linux-gnu, manifest 4c9d54fa (pinned), 8 threads/4 BLAS, jit build
Ref 2: 4ecda73be  @ 4ecda73be (2026-10-29)
  env: julia 1.12.6, x86_64-linux-gnu, manifest 4c9d54fa (pinned), 8 threads/4 BLAS, jit build
----------------------------------------------------------------------------------------------------
Quantity  f43b5bee8  4ecda73be  Diff  Status
----------------------------------------------------------------------------------------------------
SLAYER surface indices  [6 elem]  [6 elem]  0.0e+00  OK
SLAYER poloidal m  [6 elem]  [6 elem]  0.0e+00  OK
SLAYER toroidal n  [6 elem]  [6 elem]  0.0e+00  OK
SLAYER minor radius rs  [6 elem]  [6 elem]  0.0e+00  OK
SLAYER r-based shear  [6 elem]  [6 elem]  0.0e+00  OK
SLAYER Lundquist S  [6 elem]  [6 elem]  0.0e+00  OK
SLAYER D_norm  [6 elem]  [6 elem]  0.0e+00  OK
SLAYER P_perp  [6 elem]  [6 elem]  0.0e+00  OK
SLAYER tauk  [6 elem]  [6 elem]  0.0e+00  OK
SLAYER iota_e  [6 elem]  [6 elem]  0.0e+00  OK
SLAYER Q_e  [6 elem]  [6 elem]  0.0e+00  OK
SLAYER Q_i  [6 elem]  [6 elem]  0.0e+00  OK
SLAYER Q_root [2/1,3/1,4/1]  [3 elem]  [3 elem]  0.0e+00  OK
SLAYER ω_Hz [2/1,3/1,4/1]  [3 elem]  [3 elem]  0.0e+00  OK
SLAYER γ_Hz [2/1,3/1,4/1]  [3 elem]  [3 elem]  0.0e+00  OK
SLAYER no_root flags [2/1,3/1,4/1]  [3 elem]  [3 elem]  0.0e+00  OK
CRF b_r/B_φ crit [2/1,3/1,4/1]  [3 elem]  [3 elem]  0.0e+00  OK
CRF Q_peak [2/1,3/1,4/1]  [3 elem]  [3 elem]  0.0e+00  OK
CRF Q0 [2/1,3/1,4/1]  [3 elem]  [3 elem]  0.0e+00  OK
CRF b_r crit in tesla [2/1,3/1,4/1]  [3 elem]  [3 elem]  0.0e+00  OK
SLAYER enabled flag  1  1  0.0e+00  OK
Runtime (s)  206.5s  206.0s  --
====================================================================================================
Summary: 21 unchanged


================================================================
Case: diiid_slayer_n1_chi_perp_e — DIII-D-like H-mode equilibrium, n=1, SLAYER tearing-mode analysis with P_perp_model = chi_perp_e
================================================================

Regression Report: diiid_slayer_n1_chi_perp_e
====================================================================================================
Ref 1: f43b5bee8  @ f43b5bee8 (2026-10-29)
  env: julia 1.12.6, x86_64-linux-gnu, manifest 4c9d54fa (pinned), 8 threads/4 BLAS, jit build
Ref 2: 4ecda73be  @ 4ecda73be (2026-10-29)
  env: julia 1.12.6, x86_64-linux-gnu, manifest 4c9d54fa (pinned), 8 threads/4 BLAS, jit build
----------------------------------------------------------------------------------------------------
Quantity  f43b5bee8  4ecda73be  Diff  Status
----------------------------------------------------------------------------------------------------
SLAYER surface indices  [6 elem]  [6 elem]  0.0e+00  OK
SLAYER poloidal m  [6 elem]  [6 elem]  0.0e+00  OK
SLAYER toroidal n  [6 elem]  [6 elem]  0.0e+00  OK
SLAYER minor radius rs  [6 elem]  [6 elem]  0.0e+00  OK
SLAYER r-based shear  [6 elem]  [6 elem]  0.0e+00  OK
SLAYER Lundquist S  [6 elem]  [6 elem]  0.0e+00  OK
SLAYER D_norm  [6 elem]  [6 elem]  0.0e+00  OK
SLAYER P_perp  [6 elem]  [6 elem]  0.0e+00  OK
SLAYER tauk  [6 elem]  [6 elem]  0.0e+00  OK
SLAYER iota_e  [6 elem]  [6 elem]  0.0e+00  OK
SLAYER Q_e  [6 elem]  [6 elem]  0.0e+00  OK
SLAYER Q_i  [6 elem]  [6 elem]  0.0e+00  OK
SLAYER Q_root [2/1,3/1,4/1]  [3 elem]  [3 elem]  0.0e+00  OK
SLAYER ω_Hz [2/1,3/1,4/1]  [3 elem]  [3 elem]  0.0e+00  OK
SLAYER γ_Hz [2/1,3/1,4/1]  [3 elem]  [3 elem]  0.0e+00  OK
SLAYER no_root flags [2/1,3/1,4/1]  [3 elem]  [3 elem]  0.0e+00  OK
CRF b_r/B_φ crit [2/1,3/1,4/1]  [3 elem]  [3 elem]  0.0e+00  OK
CRF Q_peak [2/1,3/1,4/1]  [3 elem]  [3 elem]  0.0e+00  OK
CRF Q0 [2/1,3/1,4/1]  [3 elem]  [3 elem]  0.0e+00  OK
CRF b_r crit in tesla [2/1,3/1,4/1]  [3 elem]  [3 elem]  0.0e+00  OK
SLAYER enabled flag  1  1  0.0e+00  OK
Runtime (s)  212.3s  212.5s  --
====================================================================================================
Summary: 21 unchanged


================================================================
Case: diiid_slayer_n1_coupled — DIII-D-like H-mode equilibrium, n=1, SLAYER coupled multi-surface determinant with kinetic-file E×B rotation (reuses the n=1 deck via overrides)
================================================================

Regression Report: diiid_slayer_n1_coupled
====================================================================================================
Ref 1: f43b5bee8  @ f43b5bee8 (2026-10-29)
  env: julia 1.12.6, x86_64-linux-gnu, manifest 4c9d54fa (pinned), 8 threads/4 BLAS, jit build
Ref 2: 4ecda73be  @ 4ecda73be (2026-10-29)
  env: julia 1.12.6, x86_64-linux-gnu, manifest 4c9d54fa (pinned), 8 threads/4 BLAS, jit build
----------------------------------------------------------------------------------------------------
Quantity  f43b5bee8  4ecda73be  Diff  Status
----------------------------------------------------------------------------------------------------
SLAYER tauk  [6 elem]  [6 elem]  0.0e+00  OK
SLAYER q_shift  [6 elem]  [6 elem]  0.0e+00  OK
SLAYER coupled Q_root  [1 elem]  [1 elem]  0.0e+00  OK
SLAYER coupled ω  [1 elem]  [1 elem]  0.0e+00  OK
SLAYER coupled γ  [1 elem]  [1 elem]  0.0e+00  OK
SLAYER coupled no_root flag  [1 elem]  [1 elem]  0.0e+00  OK
SLAYER enabled flag  1  1  0.0e+00  OK
Runtime (s)  206.9s  212.4s  --
====================================================================================================
Summary: 7 unchanged


================================================================
Case: diiid_truncation_n1 — DIII-D-like, n=1, psihigh=0.9999 with the resistive-layer overlap cap binding (truncation only)
================================================================

Regression Report: diiid_truncation_n1
====================================================================================================
Ref 1: f43b5bee8  @ f43b5bee8 (2026-10-29)
  env: julia 1.12.6, x86_64-linux-gnu, manifest 4c9d54fa (pinned), 8 threads/4 BLAS, jit build
Ref 2: 4ecda73be  @ 4ecda73be (2026-10-29)
  env: julia 1.12.6, x86_64-linux-gnu, manifest 4c9d54fa (pinned), 8 threads/4 BLAS, jit build
----------------------------------------------------------------------------------------------------
Quantity  f43b5bee8  4ecda73be  Diff  Status
----------------------------------------------------------------------------------------------------
layer-overlap cap applied  1  1  0.0e+00  OK
layer-overlap psilim  9.985081e-01  9.985081e-01  0.0e+00  OK
first overlapping surface index  7  7  0.0e+00  OK
diffusive-resistive layer widths (Δψ)  [7 elem]  [7 elem]  0.0e+00  OK
qlim  6.200000e+00  6.200000e+00  0.0e+00  OK
psilim  9.949767e-01  9.949767e-01  0.0e+00  OK
mpert  37  37  0.0e+00  OK
# singular surfaces  5  5  0.0e+00  OK
singular q values  [5 elem]  [5 elem]  0.0e+00  OK
singular psi locations  [5 elem]  [5 elem]  0.0e+00  OK
plasma energy Re(ep[1])  -1.372379e+00  -1.377419e+00  5.041e-03 (0.37%)  ** CHANGED **
total energy Re(et[1])  8.005436e-01  7.978575e-01  2.686e-03 (0.34%)  ** CHANGED **
Runtime (s)  172.1s  173.5s  --
====================================================================================================
Summary: 2 changed, 10 unchanged


================================================================
Case: efit_fixedbdy_separatrix — Fixed-boundary EFIT (box hugs LCFS), Newton separatrix-find regression
================================================================

Regression Report: efit_fixedbdy_separatrix
====================================================================================================
Ref 1: f43b5bee8  @ f43b5bee8 (2026-10-29)
  env: julia 1.12.6, x86_64-linux-gnu, manifest 4c9d54fa (pinned), 8 threads/4 BLAS, jit build
Ref 2: 4ecda73be  @ 4ecda73be (2026-10-29)
  env: julia 1.12.6, x86_64-linux-gnu, manifest 4c9d54fa (pinned), 8 threads/4 BLAS, jit build
----------------------------------------------------------------------------------------------------
Quantity  f43b5bee8  4ecda73be  Diff  Status
----------------------------------------------------------------------------------------------------
psio (total poloidal flux)  3.344390e-01  3.344390e-01  0.0e+00  OK
q0  1.155202e+00  1.155202e+00  0.0e+00  OK
q95  5.741022e+00  5.741022e+00  0.0e+00  OK
beta_t  3.945172e-05  3.945172e-05  0.0e+00  OK
beta_n  1.009505e-01  1.009505e-01  0.0e+00  OK
Runtime (s)  43.5s  42.5s  --
====================================================================================================
Summary: 5 unchanged


================================================================
Case: gal_resistive_diiid — DIII-D-like, n=1, RDCON outer-region Galerkin Δ′ with rpec coil columns (delta_coil)
================================================================

Regression Report: gal_resistive_diiid
====================================================================================================
Ref 1: f43b5bee8  @ f43b5bee8 (2026-10-29)
  env: julia 1.12.6, x86_64-linux-gnu, manifest 4c9d54fa (pinned), 8 threads/4 BLAS, jit build
Ref 2: 4ecda73be  @ 4ecda73be (2026-10-29)
  env: julia 1.12.6, x86_64-linux-gnu, manifest 4c9d54fa (pinned), 8 threads/4 BLAS, jit build
----------------------------------------------------------------------------------------------------
Quantity  f43b5bee8  4ecda73be  Diff  Status
----------------------------------------------------------------------------------------------------
gal # singular surfaces  4  4  0.0e+00  OK
gal singular q values  [4 elem]  [4 elem]  0.0e+00  OK
gal PEST3 Δ diagonal  [4 elem]  [4 elem]  0.0e+00  OK
||gal Δ′ matrix||  2.302048e+03  2.302048e+03  0.0e+00  OK
||gal Δ_coil block||  1.581714e+01  1.581714e+01  0.0e+00  OK
gal D_I per surface  [4 elem]  [4 elem]  0.0e+00  OK
gal α per surface  [4 elem]  [4 elem]  0.0e+00  OK
||gal inner-layer Δ||  1.474577e+06  1.474577e+06  0.0e+00  OK
||gal match cout||  3.048397e-02  3.048397e-02  0.0e+00  OK
||gal match bpen||  1.206218e+00  1.206218e+00  0.0e+00  OK
gal match residual  1.545495e-16  1.545495e-16  0.0e+00  OK
Runtime (s)  169.3s  170.1s  --
====================================================================================================
Summary: 11 unchanged


================================================================
Case: gal_resistive_diiid_galinner — DIII-D-like, n=1, Galerkin Δ′ matched with the Galerkin inner-layer backend
================================================================

Regression Report: gal_resistive_diiid_galinner
====================================================================================================
Ref 1: f43b5bee8  @ f43b5bee8 (2026-10-29)
  env: julia 1.12.6, x86_64-linux-gnu, manifest 4c9d54fa (pinned), 8 threads/4 BLAS, jit build
Ref 2: 4ecda73be  @ 4ecda73be (2026-10-29)
  env: julia 1.12.6, x86_64-linux-gnu, manifest 4c9d54fa (pinned), 8 threads/4 BLAS, jit build
----------------------------------------------------------------------------------------------------
Quantity  f43b5bee8  4ecda73be  Diff  Status
----------------------------------------------------------------------------------------------------
gal # singular surfaces  4  4  0.0e+00  OK
gal singular q values  [4 elem]  [4 elem]  0.0e+00  OK
gal PEST3 Δ diagonal  [4 elem]  [4 elem]  0.0e+00  OK
||gal Δ′ matrix||  2.302048e+03  2.302048e+03  0.0e+00  OK
||gal Δ_coil block||  1.581714e+01  1.581714e+01  0.0e+00  OK
gal D_I per surface  [4 elem]  [4 elem]  0.0e+00  OK
gal α per surface  [4 elem]  [4 elem]  0.0e+00  OK
||gal inner-layer Δ||  1.474566e+06  1.474566e+06  0.0e+00  OK
||gal match cout||  3.048397e-02  3.048397e-02  0.0e+00  OK
||gal match bpen||  1.206218e+00  1.206218e+00  0.0e+00  OK
gal match residual  2.007742e-16  2.007742e-16  0.0e+00  OK
Runtime (s)  165.9s  167.2s  --
====================================================================================================
Summary: 11 unchanged


================================================================
Case: gal_resistive_pe — DIII-D-like, n=1, DRIVEN/RPEC: gal-matched resistive ξ → PerturbedEquilibrium (coil-driven singular coupling)
================================================================

Regression Report: gal_resistive_pe
====================================================================================================
Ref 1: f43b5bee8  @ f43b5bee8 (2026-10-29)
  env: julia 1.12.6, x86_64-linux-gnu, manifest 4c9d54fa (pinned), 8 threads/4 BLAS, jit build
Ref 2: 4ecda73be  @ 4ecda73be (2026-10-29)
  env: julia 1.12.6, x86_64-linux-gnu, manifest 4c9d54fa (pinned), 8 threads/4 BLAS, jit build
----------------------------------------------------------------------------------------------------
Quantity  f43b5bee8  4ecda73be  Diff  Status
----------------------------------------------------------------------------------------------------
rational q values  N/A  N/A  N/A  N/A
island half-widths  N/A  N/A  N/A  N/A
Chirikov parameter  N/A  N/A  N/A  N/A
||resonant b field||  N/A  N/A  N/A  N/A
resonant b field (all)  N/A  N/A  N/A  N/A
penetrated b field  N/A  N/A  N/A  N/A
PE Δ' per surface  N/A  N/A  N/A  N/A
||C resonant b field||  N/A  N/A  N/A  N/A
Runtime (s)  165.7s  173.2s  --
====================================================================================================
Summary: 8 missing/N/A


================================================================
Case: ggj_ray_q500i — GGJ inner-layer :ray backend, q=4 surface, Q = 500i (beyond :galerkin)
================================================================

Regression Report: ggj_ray_q500i
====================================================================================================
Ref 1: f43b5bee8  @ f43b5bee8 (2026-10-29)
  env: julia 1.12.6, x86_64-linux-gnu, manifest 4c9d54fa (pinned), 8 threads/4 BLAS, jit build
Ref 2: 4ecda73be  @ 4ecda73be (2026-10-29)
  env: julia 1.12.6, x86_64-linux-gnu, manifest 4c9d54fa (pinned), 8 threads/4 BLAS, jit build
----------------------------------------------------------------------------------------------------
Quantity  f43b5bee8  4ecda73be  Diff  Status
----------------------------------------------------------------------------------------------------
Re(Δ₊ interchange)  2.472007e+00  2.472007e+00  0.0e+00  OK
Im(Δ₊ interchange)  1.335402e+01  1.335402e+01  0.0e+00  OK
Re(Δ₋ tearing)  1.374966e-01  1.374966e-01  0.0e+00  OK
Im(Δ₋ tearing)  7.427542e-01  7.427542e-01  0.0e+00  OK
Runtime (s)  19.7s  19.6s  --
====================================================================================================
Summary: 4 unchanged


================================================================
Case: ggj_reference — GGJ inner-layer Galerkin solver, Glasser & Wang 2020 Eq. 55 with physical τ_A, τ_R, 1 kHz rotation (Q ≈ 0.22i)
================================================================

Regression Report: ggj_reference
====================================================================================================
Ref 1: f43b5bee8  @ f43b5bee8 (2026-10-29)
  env: julia 1.12.6, x86_64-linux-gnu, manifest 4c9d54fa (pinned), 8 threads/4 BLAS, jit build
Ref 2: 4ecda73be  @ 4ecda73be (2026-10-29)
  env: julia 1.12.6, x86_64-linux-gnu, manifest 4c9d54fa (pinned), 8 threads/4 BLAS, jit build
----------------------------------------------------------------------------------------------------
Quantity  f43b5bee8  4ecda73be  Diff  Status
----------------------------------------------------------------------------------------------------
Re(Δ₊ interchange)  1.225728e+03  1.225728e+03  0.0e+00  OK
Im(Δ₊ interchange)  2.064823e+04  2.064823e+04  0.0e+00  OK
Re(Δ₋ tearing)  -5.345663e+00  -5.345663e+00  0.0e+00  OK
Im(Δ₋ tearing)  2.592091e+01  2.592091e+01  0.0e+00  OK
Runtime (s)  9.2s  9.2s  --
====================================================================================================
Summary: 4 unchanged


================================================================
Case: solovev_kinetic_calculated — Solovev, n=1, kinetic_source=calculated, kinetic_factor=1.0, 50/50 D-T multi-ion kinetic matrices, mode-converged band (delta_m=8, mpert=32); pressure-consistent kinetic.dat (n·T tied to the Solovev P₀≈4.27e4 Pa).
================================================================

Regression Report: solovev_kinetic_calculated
====================================================================================================
Ref 1: f43b5bee8  @ f43b5bee8 (2026-10-29)
  env: julia 1.12.6, x86_64-linux-gnu, manifest 4c9d54fa (pinned), 8 threads/4 BLAS, jit build
Ref 2: 4ecda73be  @ 4ecda73be (2026-10-29)
  env: julia 1.12.6, x86_64-linux-gnu, manifest 4c9d54fa (pinned), 8 threads/4 BLAS, jit build
----------------------------------------------------------------------------------------------------
Quantity  f43b5bee8  4ecda73be  Diff  Status
----------------------------------------------------------------------------------------------------
vacuum energy Re(ev[1])  1.054739e+01  1.054739e+01  4.198e-06 (0.00%)  ** CHANGED **
q0  1.900003e+00  1.900003e+00  0.0e+00  OK
NTV fgar quadrature torque [N·m]  2.267351e-03  2.267496e-03  1.448e-07 (0.01%)  ** CHANGED **
||xi_clebsch_alpha||  6.041963e-01  6.546389e-01  5.044e-02 (8.35%)  ** CHANGED **
total energy Re(et[1])  1.828278e+00  1.828280e+00  2.248e-06 (0.00%)  ** CHANGED **
total energy Im(et[1])  -1.326607e+00  -1.326608e+00  1.019e-06 (0.00%)  ** CHANGED **
plasma energy Re(ep[1])  -8.719112e+00  -8.719105e+00  6.446e-06 (0.00%)  ** CHANGED **
ODE steps (saved)  608  612  4.000e+00 (0.66%)  ** CHANGED **
# singular surfaces  2  2  0.0e+00  OK
boundary-response torque [N·m]  2.285518e-03  2.285502e-03  1.617e-08 (0.00%)  ** CHANGED **
singular psi locations  [2 elem]  [2 elem]  0.0e+00  OK
total energy (all)  [32 elem]  [32 elem]  3.399e-03 (0.00%)  ** CHANGED **
ODE steps (total)  607  611  4.000e+00 (0.66%)  ** CHANGED **
mpert  32  32  0.0e+00  OK
q95  3.147422e+00  3.147422e+00  0.0e+00  OK
||Jb_theta_reg||  3.945600e-03  4.007262e-03  6.166e-05 (1.56%)  ** CHANGED **
Runtime (s)  202.2s  205.9s  --
T_xe applied-forcing torque [N·m]  2.285518e-03  2.285502e-03  1.617e-08 (0.00%)  ** CHANGED **
||dxi_clebsch_psi/dpsi||  3.791914e+00  4.108708e+00  3.168e-01 (8.35%)  ** CHANGED **
singular q values  [2 elem]  [2 elem]  0.0e+00  OK
npert  1  1  0.0e+00  OK
====================================================================================================
Summary: 13 changed, 7 unchanged


================================================================
Case: solovev_kinetic_multiion — Solovev n=1, ideal + PE + multi-ion NTV (D + T + electron summed)
================================================================

Regression Report: solovev_kinetic_multiion
====================================================================================================
Ref 1: f43b5bee8  @ f43b5bee8 (2026-10-29)
  env: julia 1.12.6, x86_64-linux-gnu, manifest 4c9d54fa (pinned), 8 threads/4 BLAS, jit build
Ref 2: 4ecda73be  @ 4ecda73be (2026-10-29)
  env: julia 1.12.6, x86_64-linux-gnu, manifest 4c9d54fa (pinned), 8 threads/4 BLAS, jit build
----------------------------------------------------------------------------------------------------
Quantity  f43b5bee8  4ecda73be  Diff  Status
----------------------------------------------------------------------------------------------------
NTV total (D+T+imp+e) [N·m]  3.141935e+01  6.886429e+01  3.744e+01 (119.18%)  ** CHANGED **
NTV Deuterium [N·m]  1.973825e+01  4.328549e+01  2.355e+01 (119.30%)  ** CHANGED **
NTV Tritium [N·m]  2.046391e+01  4.487573e+01  2.441e+01 (119.29%)  ** CHANGED **
NTV electron [N·m]  -8.782805e+00  -1.929693e+01  1.051e+01 (119.71%)  ** CHANGED **
total energy Re(et[1])  1.090559e-02  7.362765e-03  3.543e-03 (32.49%)  ** CHANGED **
# singular surfaces  2  2  0.0e+00  OK
Runtime (s)  196.6s  198.7s  --
====================================================================================================
Summary: 5 changed, 1 unchanged


================================================================
Case: solovev_kinetic_ntv — Solovev analytical equilibrium, n=1, ideal + PE + NTV torque quadrature
================================================================

Regression Report: solovev_kinetic_ntv
====================================================================================================
Ref 1: f43b5bee8  @ f43b5bee8 (2026-10-29)
  env: julia 1.12.6, x86_64-linux-gnu, manifest 4c9d54fa (pinned), 8 threads/4 BLAS, jit build
Ref 2: 4ecda73be  @ 4ecda73be (2026-10-29)
  env: julia 1.12.6, x86_64-linux-gnu, manifest 4c9d54fa (pinned), 8 threads/4 BLAS, jit build
----------------------------------------------------------------------------------------------------
Quantity  f43b5bee8  4ecda73be  Diff  Status
----------------------------------------------------------------------------------------------------
NTV torque fgar [Re, Im]  [1 elem]  [1 elem]  4.709e+01 (119.30%)  ** CHANGED **
NTV ψ quadrature evaluations  45  45  0.0e+00  OK
fluid CGL energy fcgl [J]  1.552025e+01  3.408647e+01  1.857e+01 (119.63%)  ** CHANGED **
root-area-weighted total energy Re(et[1])  1.090559e-02  7.362765e-03  3.543e-03 (32.49%)  ** CHANGED **
# singular surfaces  2  2  0.0e+00  OK
singular psi locations  [2 elem]  [2 elem]  0.0e+00  OK
q0  1.900006e+00  1.900006e+00  0.0e+00  OK
Runtime (s)  197.1s  217.4s  --
====================================================================================================
Summary: 3 changed, 4 unchanged


================================================================
Case: solovev_kinetic_nuzero — Solovev, n=1, kinetic_source=calculated, nutype=zero (collisionless energy integral), 50/50 D-T multi-ion kinetic matrices, mode-converged band (delta_m=8, mpert=32). Reuses the calculated example deck via override; pressure-consistent kinetic.dat.
================================================================

Regression Report: solovev_kinetic_nuzero
====================================================================================================
Ref 1: f43b5bee8  @ f43b5bee8 (2026-10-29)
  env: julia 1.12.6, x86_64-linux-gnu, manifest 4c9d54fa (pinned), 8 threads/4 BLAS, jit build
Ref 2: 4ecda73be  @ 4ecda73be (2026-10-29)
  env: julia 1.12.6, x86_64-linux-gnu, manifest 4c9d54fa (pinned), 8 threads/4 BLAS, jit build
----------------------------------------------------------------------------------------------------
Quantity  f43b5bee8  4ecda73be  Diff  Status
----------------------------------------------------------------------------------------------------
vacuum energy Re(ev[1])  1.058613e+01  1.058612e+01  4.671e-06 (0.00%)  ** CHANGED **
q0  1.900003e+00  1.900003e+00  0.0e+00  OK
total energy Re(et[1])  2.290965e+00  2.290968e+00  3.093e-06 (0.00%)  ** CHANGED **
total energy Im(et[1])  -1.564546e+00  -1.564547e+00  1.211e-06 (0.00%)  ** CHANGED **
plasma energy Re(ep[1])  -8.295163e+00  -8.295156e+00  7.764e-06 (0.00%)  ** CHANGED **
ODE steps (saved)  608  614  6.000e+00 (0.99%)  ** CHANGED **
# singular surfaces  2  2  0.0e+00  OK
singular psi locations  [2 elem]  [2 elem]  0.0e+00  OK
total energy (all)  [32 elem]  [32 elem]  3.613e-03 (0.00%)  ** CHANGED **
ODE steps (total)  607  613  6.000e+00 (0.99%)  ** CHANGED **
mpert  32  32  0.0e+00  OK
q95  3.147422e+00  3.147422e+00  0.0e+00  OK
Runtime (s)  203.9s  203.6s  --
singular q values  [2 elem]  [2 elem]  0.0e+00  OK
npert  1  1  0.0e+00  OK
====================================================================================================
Summary: 7 changed, 7 unchanged


================================================================
Case: solovev_multi_n — Solovev analytical equilibrium, multi-n, ideal stability
================================================================

Regression Report: solovev_multi_n
====================================================================================================
Ref 1: f43b5bee8  @ f43b5bee8 (2026-10-29)
  env: julia 1.12.6, x86_64-linux-gnu, manifest 4c9d54fa (pinned), 8 threads/4 BLAS, jit build
Ref 2: 4ecda73be  @ 4ecda73be (2026-10-29)
  env: julia 1.12.6, x86_64-linux-gnu, manifest 4c9d54fa (pinned), 8 threads/4 BLAS, jit build
----------------------------------------------------------------------------------------------------
Quantity  f43b5bee8  4ecda73be  Diff  Status
----------------------------------------------------------------------------------------------------
total energy Re(et[1])  -2.134718e+00  -2.134718e+00  0.0e+00  OK
total energy Im(et[1])  2.580339e-10  2.580339e-10  0.0e+00  OK
vacuum matrix min eigenvalue  1.730832e+00  1.730832e+00  0.0e+00  OK
plasma energy (all)  [70 elem]  [70 elem]  0.0e+00  OK
vacuum energy (all)  [70 elem]  [70 elem]  0.0e+00  OK
total energy (all)  [70 elem]  [70 elem]  0.0e+00  OK
ODE steps (saved)  56  56  0.0e+00  OK
ODE steps (total)  1044  1044  0.0e+00  OK
q0  1.900006e+00  1.900006e+00  0.0e+00  OK
q95  3.147422e+00  3.147422e+00  0.0e+00  OK
# singular surfaces  3  3  0.0e+00  OK
singular psi locations  [3 elem]  [3 elem]  0.0e+00  OK
mpert  35  35  0.0e+00  OK
npert  2  2  0.0e+00  OK
q profile (checksum)  2340b888d410...  2340b888d410...  identical  OK
Runtime (s)  189.5s  183.1s  --
====================================================================================================
Summary: 15 unchanged


================================================================
Case: solovev_n1 — Solovev analytical equilibrium, n=1, ideal stability
================================================================

Regression Report: solovev_n1
====================================================================================================
Ref 1: f43b5bee8  @ f43b5bee8 (2026-10-29)
  env: julia 1.12.6, x86_64-linux-gnu, manifest 4c9d54fa (pinned), 8 threads/4 BLAS, jit build
Ref 2: 4ecda73be  @ 4ecda73be (2026-10-29)
  env: julia 1.12.6, x86_64-linux-gnu, manifest 4c9d54fa (pinned), 8 threads/4 BLAS, jit build
----------------------------------------------------------------------------------------------------
Quantity  f43b5bee8  4ecda73be  Diff  Status
----------------------------------------------------------------------------------------------------
total energy Re(et[1])  1.090559e-02  7.362765e-03  3.543e-03 (32.49%)  ** CHANGED **
total energy Im(et[1])  1.446761e-10  2.140458e-10  6.9e-11  OK
plasma energy Re(ep[1])  -1.041640e+01  -1.042157e+01  5.178e-03 (0.05%)  ** CHANGED **
vacuum energy Re(ev[1])  1.042730e+01  1.042894e+01  1.635e-03 (0.02%)  ** CHANGED **
vacuum matrix min eigenvalue  2.170703e+00  2.170703e+00  0.0e+00  OK
plasma energy (all)  [32 elem]  [32 elem]  5.178e-03 (0.00%)  ** CHANGED **
vacuum energy (all)  [32 elem]  [32 elem]  1.635e-03 (0.00%)  ** CHANGED **
total energy (all)  [32 elem]  [32 elem]  4.907e-03 (0.00%)  ** CHANGED **
ODE steps (saved)  287  383  9.600e+01 (33.45%)  ** CHANGED **
ODE steps (total)  285  381  9.600e+01 (33.68%)  ** CHANGED **
q0  1.900006e+00  1.900006e+00  0.0e+00  OK
q95  3.147422e+00  3.147422e+00  0.0e+00  OK
beta_t  4.621027e-02  4.621027e-02  0.0e+00  OK
beta_n  3.217775e+00  3.217775e+00  0.0e+00  OK
# singular surfaces  2  2  0.0e+00  OK
singular psi locations  [2 elem]  [2 elem]  0.0e+00  OK
singular q values  [2 elem]  [2 elem]  0.0e+00  OK
mpert  32  32  0.0e+00  OK
npert  1  1  0.0e+00  OK
q profile (checksum)  2340b888d410...  2340b888d410...  identical  OK
pressure profile (checksum)  108b947087e6...  108b947087e6...  identical  OK
ca_left (checksum)  fc761aba9205...  dec3aca30808...  0.000e+00 (0.00%)  ** CHANGED **
Runtime (s)  182.4s  177.1s  --
====================================================================================================
Summary: 9 changed, 13 unchanged


🤖 Generated with Claude Code

https://claude.ai/code/session_01VdRsGGg4YRG6E9fgLGbpdF

logan-nc and others added 3 commits October 22, 2026 00:19
…the singular coupling converges

At 1e-4 the coupling at the outermost rational surfaces is off by up to 20% and
differs between working coordinates; at 1e-6 Hamada, PEST and Boozer agree to
0.5% at no measurable runtime cost. Example decks follow the new default; the
test fixtures and Fortran benchmark namelists keep 1e-4. Documents the row and
column normalization of the singular coupling matrices.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VdRsGGg4YRG6E9fgLGbpdF
…singfac_min = 1e-6 in the forward-integrator decks

The Riccati Δ' gains a spurious imaginary part as singfac_min shrinks (on the
DIII-D-like deck, surface 4 goes from -2275-9i at 1e-4 to -2278-421i at 1e-5
and -2449-19369i at 1e-6), so the code default and the Riccati, Galerkin and
SLAYER decks stay at 1e-4. Only the forward-integrator decks, which feed
PerturbedEquilibrium, move to 1e-6, and the singfac_min docstring states the
trade-off.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VdRsGGg4YRG6E9fgLGbpdF
@logan-nc logan-nc self-assigned this Oct 22, 2026
@logan-nc
logan-nc requested a review from d-burg October 22, 2026 10:15
@github-actions github-actions Bot added bugfix Something was wrong and now is not changed-results Results move or an interface breaks - read before upgrading labels Oct 22, 2026

@d-burg d-burg left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for chasing #237 down to the offset. Showing that the coupling definitions are sound and the scatter lives in the shared solution is useful, and so is the write up of the Riccati trade off. This only moves the jump closer to the surface and loosens nothing, so I'm good with it. Before it goes in, some Claude findings for your consideration:

  1. Scope: any forward run is affected, not only PE. Your Solovev numbers show the FFS energy et moving 32 % (NTV 119 %) between 1e-4 and 1e-6. Could the docstring and Migration line say "forward runs", and could a forward run that keeps 1e-4 warn (or get an integrator-aware default)? Related: diiid_n1_riccati at 1e-4 gives et = 0.8032 against 0.7979 for converged forward on the same deck, so the Riccati energies look offset-limited too. That seems worth a follow-up issue next to the crossing-match question.
  2. Convergence evidence for the coupling. The Solovev et scan is convincing. For the DIII-D-like coupling we only see 1e-4 and 1e-6 plus the cross-coordinate check, and the outer surface is still 1.4 % apart. Could you add a 1e-7 point for resonant b^r, island widths and Chirikov on diiid_n1, and a tighter-rtol control for the Solovev scan (those decks run at rtol 1e-7, so the 1e-8 breakdown may be tolerance-driven)? A small harness case pinning the Hamada/PEST/Boozer agreement would lock in the #237 fix.
  3. Kinetic decks. With kinetic_factor > 0, singfac_min sets the trapezoidal step across the kinetic singular surfaces, which the evidence here doesn't cover. I'd revert those two decks (suggestions inline) or add a scan for that path.

Smaller items:

  • The coupling is read at a fixed 5e-4/(n·q′) offset that doesn't follow singfac_min; a sentence on why that spot is converged would help (comment fix inline).
  • The truncation and a10 decks stop before PE, so the PE rationale doesn't cover them; the forward-et rationale does.
  • On auto-grid decks singfac_min also sets the knot bracketing (covered in suggestion 1).
  • "Runtime under 4 %" is harness wall time, dominated by compilation; ODE steps go up 35–50 % (diiid_n1 781 → 1174).
  • The Numerical impact line is missing the kinetic ξ norms (7.8 %), the error-field residual torque (up to 4.8 %) and the truncation et (0.34 %).
  • The test fixtures still pin the 1e-4 values. Fine to defer, but worth a tracking issue.

The ! and the regression report look right to me.

- `numsteps_init::Int` - Initial array size for ODE data storage
- `numunorms_init::Int` - Initial array size for solution normalization data
- `singfac_min::Float64` - Fractional distance from rational q at which ideal jump condition is enforced
- `singfac_min::Float64` - Fractional distance from rational q at which ideal jump condition is enforced. The default 1e-4 suits the Riccati Δ′, whose asymptotic matching gains a spurious imaginary part as it shrinks; `"forward"` runs feeding PerturbedEquilibrium need about 1e-6 for the singular coupling to converge at the outer rational surfaces.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Scope the docstring to forward runs in general, mark the Riccati cause as observed, and name the two other places the value acts.

Suggested change
- `singfac_min::Float64` - Fractional distance from rational q at which ideal jump condition is enforced. The default 1e-4 suits the Riccati Δ′, whose asymptotic matching gains a spurious imaginary part as it shrinks; `"forward"` runs feeding PerturbedEquilibrium need about 1e-6 for the singular coupling to converge at the outer rational surfaces.
- `singfac_min::Float64` - Fractional distance from rational q at which ideal jump condition is enforced. With `kinetic_factor > 0` it instead sets the half-width of the trapezoidal step across each kinetic singular surface, and on the auto ψ grid it also sets the rational-surface knot bracket. `"forward"` runs need about 1e-6 for the free-boundary energies and the PerturbedEquilibrium singular coupling to converge. The default 1e-4 is kept for the Riccati Δ′, whose imaginary part grows as the offset shrinks (observed, cause not yet isolated), so Riccati energies at the default are not offset-converged.

Comment on lines +258 to +260
- Columns: every stored matrix is right-multiplied by the control-surface `flux_conform`, so it
acts on the root-area-weighted field b̃ in T and its singular values do not depend on `jac_type`.
The applied vectors are evaluated before that, on the run's own forcing flux.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Say which offset the coupling is actually read at, and limit the jac_type claim to the converged case.

Suggested change
- Columns: every stored matrix is right-multiplied by the control-surface `flux_conform`, so it
acts on the root-area-weighted field b̃ in T and its singular values do not depend on `jac_type`.
The applied vectors are evaluated before that, on the run's own forcing flux.
- Columns: every stored matrix is right-multiplied by the control-surface `flux_conform`, so it
acts on the root-area-weighted field b̃ in T and, once the solve is converged, its singular values do not depend on `jac_type`.
The applied vectors are evaluated before that, on the run's own forcing flux.
- Offset: the jump in ∂b^ψ/∂ψ is read at ψ_s ± 5e-4/(|n|·|q′|), independent of `singfac_min`.

integrator = "forward" # Integration formalism: "forward" (dense ξ, needed for [PerturbedEquilibrium]/kinetic), "riccati" (chunked propagator BVP, unlocks the singular-surface Δ′ matrix), or "galerkin" (RDCON outer-region singular Galerkin Δ′, with the optional RPEC inner-layer match)
eulerlagrange_tolerance = 1e-7 # Relative tolerance for ODE integration of Euler-Lagrange equations
singfac_min = 1e-4 # Fractional distance from rational q at which ideal jump enforced
singfac_min = 1e-6 # Fractional distance from rational q at which ideal jump enforced

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

With kinetic_factor > 0 this sets the kinetic crossing step, not the ideal jump, and the 7.8 % ξ-norm move is unexplained. Revert unless a kinetic-crossing scan is added.

Suggested change
singfac_min = 1e-6 # Fractional distance from rational q at which ideal jump enforced
singfac_min = 1e-4 # Fractional distance from rational q at which ideal jump enforced

integrator = "forward" # Integration formalism: "forward" (dense ξ, needed for [PerturbedEquilibrium]/kinetic), "riccati" (chunked propagator BVP, unlocks the singular-surface Δ′ matrix), or "galerkin" (RDCON outer-region singular Galerkin Δ′, with the optional RPEC inner-layer match)
eulerlagrange_tolerance = 1e-7 # Relative tolerance for ODE integration of Euler-Lagrange equations
singfac_min = 1e-4 # Fractional distance from rational q at which ideal jump enforced
singfac_min = 1e-6 # Fractional distance from rational q at which ideal jump enforced

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same mechanism, this deck also stops before PE and has no harness case.

Suggested change
singfac_min = 1e-6 # Fractional distance from rational q at which ideal jump enforced
singfac_min = 1e-4 # Fractional distance from rational q at which ideal jump enforced

shear = abs(nn) * sing_surf.q1 / sing_surf.q

# Evaluate bwp1_mn = ∂b^ψ/∂ψ at lpsi and rpsi using permeability-weighted eigenstates.
# Matches Fortran gpout_resp: evaluate bwp1_mn at lpsi/rpsi via gpeq_sol

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The "matches Fortran default singfac_min" comment no longer matches either value in use. Suggested one-liner:

            # Fixed evaluation offset 5e-4/(|n|·|q′|), independent of singfac_min

@matt-pharr

matt-pharr commented Oct 29, 2026 •

Copy link
Copy Markdown
Collaborator

Opened #610 to track further Solovev cutoff-convergence investigation after the 2.0 release, alongside the crossing/conditioning work in #481 and #520. We will not hold this PR up on that additional numerical investigation.

The follow-up distinguishes the FFS integration/crossing cutoff from PE's coupling-sampling offset and its field regularization. The ideal-plus-NTV examples use a prescribed regularization; their torque is a downstream diagnostic of the ideal response, not a self-consistent kinetic torque. The calculated-kinetic examples need separate validation.

The remaining task is to establish a supported cutoff range through tolerance/resolution checks and focused regression coverage, rather than assume smaller cutoffs are always safer. This does not call for reverting the example changes or adding a solver refactor to #555.

The existing human approval by @d-burg is noted. GitHub currently reports merge conflicts, so those still need resolution and the normal review/check requirements still apply before merging. I will do that and get this merged now.

@matt-pharr
matt-pharr merged commit e975f9d into develop Oct 29, 2026
9 of 10 checks passed
@matt-pharr
matt-pharr deleted the bugfix/singfac-min-converged branch October 29, 2026 12:01
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bugfix Something was wrong and now is not changed-results Results move or an interface breaks - read before upgrading

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Check coordinate independence of all resonant coupling matrices

3 participants