Skip to content

PerturbedEquilibrium - API! - Build the plasma response once and force it per source - #574

Merged
matt-pharr merged 14 commits into
developfrom
refactor/plasma-response
Oct 27, 2026
Merged

matt-pharr merged 14 commits into
developfrom
refactor/plasma-response

Conversation

@matt-pharr

@matt-pharr matt-pharr commented Oct 23, 2026 •

Copy link
Copy Markdown
Collaborator

Release note

  • Audience: users
  • Numerical impact: regularization_width now defaults to 0, so ideal runs that leave it unset get unregularized profiles near the rationals; error-field NTV couplings now use the run's width. No tracked harness quantity moves (harness @ f684954)
  • Migration: perturbed_equilibrium(ffs, rmp; ...) is replaced by two calls, resp = plasma_response(ffs; compute_singular_coupling=true, compute_torque_response=false) then perturbed_equilibrium(resp, rmp; regularization_width, verbose, write_outputs_to_HDF5, output_filename). PerturbedEquilibriumControl and PerturbedEquilibriumInternal are gone. The response and coupling matrices, rational-surface labels and dominant modes moved from the result to its response field (pe.response.permeability, pe.response.C_delta_prime, ...). ResonantCoupling(pe, ffs) is now ResonantCoupling(pe.response). A deck that sets compute_response in [PerturbedEquilibrium] now stops; delete the line. compute_torque_response still lives in that section and now goes to plasma_response; compute_torque_response! and torque_response_matrices are replaced by torque_response_matrix, build_torque_response! and apply_torque_response!. regularization_width now defaults to 0 for every result (Fortran reg_flag = f); before, it defaulted to 0.05 on ideal results and was forced to 0 on kinetic ones. Only the regularized profiles move (dxi_clebsch_psidpsi, xi_clebsch_alpha, contravariant ξ^θ/ξ^ζ, the *_reg field and current datasets, and the KineticForces torque built from them); response and coupling matrices, resonant fields, Δ′, islands and energies do not. A deck that drives KineticForces with an ideal solve should set regularization_width = 0.05, as the example decks that do so already do. An explicit width is now respected on kinetic results too. efc_couplings now uses the run's width instead of always 0.05, so error-field NTV couplings move on decks whose width is not 0.05. Galerkin and :matched results now error at plasma_response whatever the flags, which supersedes PerturbedEquilibrium - BUGFIX! - Refuse Galerkin and matched results until they publish wp #556's advice to turn compute_response and compute_singular_coupling off; stop such a run after force-free states instead.

The perturbed-equilibrium stage used to rebuild the plasma response and singular-coupling operators for every forcing source. plasma_response(ffs) now builds them once into a PlasmaResponse, and perturbed_equilibrium(resp, rmp) applies them to one field, so scans over sources and the error-field correction couplings reuse one response. RMPField(modes) wraps a control-surface spectrum computed elsewhere as a forcing source.

Regression report

One SDCC fan-out over all 20 harness cases at 8 CPUs per task (Julia 1.12.6 with the CI manifest pin) tracked develop (db90e82), #569 (7fd923d) and #574 (125f4a0) in a single run. Checked against that run's results database rather than only the report's last-vs-previous summary, every stored value other than runtime is bit-identical from develop to #569 and from #569 to #574: 271 tracked values in 19 cases per step, integers, reals, full arrays and checksums alike. gal_resistive_pe reads its 8 expected N/A on all three refs, since develop refuses that Galerkin PE run too.

The stamp is f684954, which adds only the merge of #569's test commit (5786d2d: PlasmaEquilibrium in three tests, and a fixed @test_broken promoted) on top of 125f4a0.

The regularization default cannot show here: the two cases whose decks moved to 0 (solovev_n1, diiid_multi_n) track no regularized quantity, and every case that does keeps an explicit 0.05. TorqueResponse/total_torque in solovev_kinetic_calculated runs the torque response through its new home.

Full report (tracking all three refs)
================================================================
Case: diiid_error_field — DIII-D-like error-field assessment, n=1: ErrorFields stage with the NTV-limited correction couplings
================================================================

Regression Tracking: diiid_error_field
==========================================================================================================
Ref 1: db90e824d  @ db90e824d (2026-10-26)
       env: julia 1.12.6, x86_64-linux-gnu, manifest 4c9d54fa (pinned), 8 threads/4 BLAS, jit build
Ref 2: 7fd923d36  @ 7fd923d36 (2026-10-27)
       env: julia 1.12.6, x86_64-linux-gnu, manifest 4c9d54fa (pinned), 8 threads/4 BLAS, jit build
Ref 3: 125f4a069  @ 125f4a069 (2026-10-27)
       env: julia 1.12.6, x86_64-linux-gnu, manifest 4c9d54fa (pinned), 8 threads/4 BLAS, jit build
----------------------------------------------------------------------------------------------------------
Quantity                                         db90e824d     7fd923d36     125f4a069     Δ prev   Status
----------------------------------------------------------------------------------------------------------
EFC overlap per kAt                              [1 elem]      [1 elem]      [1 elem]      0.0e+00  OK    
EFC whole-field NTV torque per kAt² [N·m]        [1 elem]      [1 elem]      [1 elem]      0.0e+00  OK    
EFC residual-field NTV torque per kAt² [N·m]     [1 elem]      [1 elem]      [1 elem]      0.0e+00  OK    
EFC reference rotation ω_ref [rad/s]             [1 elem]      [1 elem]      [1 elem]      0.0e+00  OK    
EFC rotation-scan shifts [rad/s]                 [9 elem]      [9 elem]      [9 elem]      0.0e+00  OK    
EFC residual torque against rotation [N·m/kAt²]  [9 elem]      [9 elem]      [9 elem]      0.0e+00  OK    
dominant-coupling singular values                [3 elem]      [3 elem]      [3 elem]      0.0e+00  OK    
|delta_nominal| of coil set 1                    1.406924e-06  1.406924e-06  1.406924e-06  0.0e+00  OK    
|Σ δ_as_designed| of the error-field coils       1.825296e-18  1.825296e-18  1.825296e-18  0.0e+00  OK    
Monte Carlo mean |δ| of the error-field coils    4.701300e-05  4.701300e-05  4.701300e-05  0.0e+00  OK    
Runtime (s)                                      272.7s        273.0s        268.9s                 --    
==========================================================================================================
Summary (last vs prev): 10 unchanged


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

Regression Tracking: diiid_multi_n
==================================================================================================================================
Ref 1: db90e824d  @ db90e824d (2026-10-26)
       env: julia 1.12.6, x86_64-linux-gnu, manifest 4c9d54fa (pinned), 8 threads/4 BLAS, jit build
Ref 2: 7fd923d36  @ 7fd923d36 (2026-10-27)
       env: julia 1.12.6, x86_64-linux-gnu, manifest 4c9d54fa (pinned), 8 threads/4 BLAS, jit build
Ref 3: 125f4a069  @ 125f4a069 (2026-10-27)
       env: julia 1.12.6, x86_64-linux-gnu, manifest 4c9d54fa (pinned), 8 threads/4 BLAS, jit build
----------------------------------------------------------------------------------------------------------------------------------
Quantity                                                      db90e824d        7fd923d36        125f4a069        Δ prev     Status
----------------------------------------------------------------------------------------------------------------------------------
total energy Re(et[1])                                        -5.750527e-01    -5.750527e-01    -5.750527e-01    0.0e+00    OK    
total energy (all)                                            [58 elem]        [58 elem]        [58 elem]        0.0e+00    OK    
ODE steps (saved)                                             625              625              625              0.0e+00    OK    
mpert                                                         29               29               29               0.0e+00    OK    
npert                                                         2                2                2                0.0e+00    OK    
toroidal mode label of each mode index (checksum)             8d8d42b8832d...  8d8d42b8832d...  8d8d42b8832d...  identical  OK    
permeability diagonal P~_ii (all n blocks)                    [58 elem]        [58 elem]        [58 elem]        0.0e+00    OK    
forcing b~ (root-area-weighted), n = 1, 2                     [58 elem]        [58 elem]        [58 elem]        0.0e+00    OK    
response b~ (root-area-weighted), n = 1, 2                    [58 elem]        [58 elem]        [58 elem]        0.0e+00    OK    
PE plasma energy (sum over n)                                 2.936559e+00     2.936559e+00     2.936559e+00     0.0e+00    OK    
PE vacuum energy (sum over n)                                 3.113946e+00     3.113946e+00     3.113946e+00     0.0e+00    OK    
PE surface energy (sum over n)                                3.523427e+00     3.523427e+00     3.523427e+00     0.0e+00    OK    
PE toroidal torque sum_n -2n Im(Phi_n' Lambda_nn^-1 Phi_n)/4  1.820339e-06     1.820339e-06     1.820339e-06     0.0e+00    OK    
resonant n per row (rows sorted by psi across n)              [7 elem]         [7 elem]         [7 elem]         0.0e+00    OK    
resonant m per row                                            [7 elem]         [7 elem]         [7 elem]         0.0e+00    OK    
resonant area-weighted field b^r per row                      [7 elem]         [7 elem]         [7 elem]         0.0e+00    OK    
island half-widths per row                                    [7 elem]         [7 elem]         [7 elem]         0.0e+00    OK    
Chirikov parameter per row                                    [7 elem]         [7 elem]         [7 elem]         0.0e+00    OK    
forcing-driven Delta' per row                                 [7 elem]         [7 elem]         [7 elem]         0.0e+00    OK    
Runtime (s)                                                   183.2s           179.4s           184.7s                      --    
==================================================================================================================================
Summary (last vs prev): 19 unchanged


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

Regression Tracking: diiid_n1_riccati_precompiled
===========================================================================================
Ref 1: db90e824d  @ db90e824d (2026-10-26)
       env: julia 1.12.6, x86_64-linux-gnu, manifest 4c9d54fa (pinned), 8 threads/4 BLAS, aot build
Ref 2: 7fd923d36  @ 7fd923d36 (2026-10-27)
       env: julia 1.12.6, x86_64-linux-gnu, manifest 4c9d54fa (pinned), 8 threads/4 BLAS, aot build
Ref 3: 125f4a069  @ 125f4a069 (2026-10-27)
       env: julia 1.12.6, x86_64-linux-gnu, manifest 4c9d54fa (pinned), 8 threads/4 BLAS, aot build
-------------------------------------------------------------------------------------------
Quantity                       db90e824d      7fd923d36      125f4a069      Δ prev   Status
-------------------------------------------------------------------------------------------
delta prime (BVP diagonal)     [5 elem]       [5 elem]       [5 elem]       0.0e+00  OK    
delta prime (raw side-major)   [10 elem]      [10 elem]      [10 elem]      0.0e+00  OK    
edge coil response delta_coil  [10 elem]      [10 elem]      [10 elem]      0.0e+00  OK    
total energy Re(et[1])         8.031971e-01   8.031971e-01   8.031971e-01   0.0e+00  OK    
plasma energy Re(ep[1])        -1.368534e+00  -1.368534e+00  -1.368534e+00  0.0e+00  OK    
vacuum energy Re(ev[1])        2.171732e+00   2.171732e+00   2.171732e+00   0.0e+00  OK    
total energy (all)             [35 elem]      [35 elem]      [35 elem]      0.0e+00  OK    
# singular surfaces            5              5              5              0.0e+00  OK    
singular psi locations         [5 elem]       [5 elem]       [5 elem]       0.0e+00  OK    
singular q values              [5 elem]       [5 elem]       [5 elem]       0.0e+00  OK    
ODE steps (saved)              94             94             94             0.0e+00  OK    
ODE steps (total)              2632           2632           2632           0.0e+00  OK    
mpert                          35             35             35             0.0e+00  OK    
npert                          1              1              1              0.0e+00  OK    
q0                             1.204212e+00   1.204212e+00   1.204212e+00   0.0e+00  OK    
q95                            4.781723e+00   4.781723e+00   4.781723e+00   0.0e+00  OK    
beta_n                         1.372511e+00   1.372511e+00   1.372511e+00   0.0e+00  OK    
Runtime (s)                    22.0s          23.4s          22.4s                   --    
===========================================================================================
Summary (last vs prev): 17 unchanged


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

Regression Tracking: diiid_n1_riccati
===========================================================================================
Ref 1: db90e824d  @ db90e824d (2026-10-26)
       env: julia 1.12.6, x86_64-linux-gnu, manifest 4c9d54fa (pinned), 8 threads/4 BLAS, jit build
Ref 2: 7fd923d36  @ 7fd923d36 (2026-10-27)
       env: julia 1.12.6, x86_64-linux-gnu, manifest 4c9d54fa (pinned), 8 threads/4 BLAS, jit build
Ref 3: 125f4a069  @ 125f4a069 (2026-10-27)
       env: julia 1.12.6, x86_64-linux-gnu, manifest 4c9d54fa (pinned), 8 threads/4 BLAS, jit build
-------------------------------------------------------------------------------------------
Quantity                       db90e824d      7fd923d36      125f4a069      Δ prev   Status
-------------------------------------------------------------------------------------------
delta prime (BVP diagonal)     [5 elem]       [5 elem]       [5 elem]       0.0e+00  OK    
delta prime (raw side-major)   [10 elem]      [10 elem]      [10 elem]      0.0e+00  OK    
edge coil response delta_coil  [10 elem]      [10 elem]      [10 elem]      0.0e+00  OK    
total energy Re(et[1])         8.031971e-01   8.031971e-01   8.031971e-01   0.0e+00  OK    
plasma energy Re(ep[1])        -1.368534e+00  -1.368534e+00  -1.368534e+00  0.0e+00  OK    
vacuum energy Re(ev[1])        2.171732e+00   2.171732e+00   2.171732e+00   0.0e+00  OK    
total energy (all)             [35 elem]      [35 elem]      [35 elem]      0.0e+00  OK    
# singular surfaces            5              5              5              0.0e+00  OK    
singular psi locations         [5 elem]       [5 elem]       [5 elem]       0.0e+00  OK    
singular q values              [5 elem]       [5 elem]       [5 elem]       0.0e+00  OK    
ODE steps (saved)              94             94             94             0.0e+00  OK    
ODE steps (total)              2632           2632           2632           0.0e+00  OK    
mpert                          35             35             35             0.0e+00  OK    
npert                          1              1              1              0.0e+00  OK    
q0                             1.204212e+00   1.204212e+00   1.204212e+00   0.0e+00  OK    
q95                            4.781723e+00   4.781723e+00   4.781723e+00   0.0e+00  OK    
beta_n                         1.372511e+00   1.372511e+00   1.372511e+00   0.0e+00  OK    
Runtime (s)                    176.0s         174.4s         174.1s                  --    
===========================================================================================
Summary (last vs prev): 17 unchanged


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

Regression Tracking: diiid_n1
==================================================================================================================
Ref 1: db90e824d  @ db90e824d (2026-10-26)
       env: julia 1.12.6, x86_64-linux-gnu, manifest 4c9d54fa (pinned), 8 threads/4 BLAS, jit build
Ref 2: 7fd923d36  @ 7fd923d36 (2026-10-27)
       env: julia 1.12.6, x86_64-linux-gnu, manifest 4c9d54fa (pinned), 8 threads/4 BLAS, jit build
Ref 3: 125f4a069  @ 125f4a069 (2026-10-27)
       env: julia 1.12.6, x86_64-linux-gnu, manifest 4c9d54fa (pinned), 8 threads/4 BLAS, jit build
------------------------------------------------------------------------------------------------------------------
Quantity                                      db90e824d        7fd923d36        125f4a069        Δ prev     Status
------------------------------------------------------------------------------------------------------------------
total energy Re(et[1])                        8.006122e-01     8.006122e-01     8.006122e-01     0.0e+00    OK    
total energy Im(et[1])                        7.924888e-05     7.924888e-05     7.924888e-05     0.0e+00    OK    
plasma energy Re(ep[1])                       -1.372261e+00    -1.372261e+00    -1.372261e+00    0.0e+00    OK    
vacuum energy Re(ev[1])                       2.172874e+00     2.172874e+00     2.172874e+00     0.0e+00    OK    
vacuum matrix min eigenvalue                  1.873975e-01     1.873975e-01     1.873975e-01     0.0e+00    OK    
plasma energy (all)                           [35 elem]        [35 elem]        [35 elem]        0.0e+00    OK    
vacuum energy (all)                           [35 elem]        [35 elem]        [35 elem]        0.0e+00    OK    
total energy (all)                            [35 elem]        [35 elem]        [35 elem]        0.0e+00    OK    
ODE steps (saved)                             792              792              792              0.0e+00    OK    
ODE steps (total)                             787              787              787              0.0e+00    OK    
q0                                            1.204212e+00     1.204212e+00     1.204212e+00     0.0e+00    OK    
q95                                           4.781723e+00     4.781723e+00     4.781723e+00     0.0e+00    OK    
beta_t                                        1.327024e-02     1.327024e-02     1.327024e-02     0.0e+00    OK    
beta_n                                        1.372511e+00     1.372511e+00     1.372511e+00     0.0e+00    OK    
internal inductance li1                       8.842268e-01     8.842268e-01     8.842268e-01     0.0e+00    OK    
internal inductance li2                       7.080757e-01     7.080757e-01     7.080757e-01     0.0e+00    OK    
internal inductance li3                       7.304340e-01     7.304340e-01     7.304340e-01     0.0e+00    OK    
poloidal beta betap1                          6.680739e-01     6.680739e-01     6.680739e-01     0.0e+00    OK    
poloidal beta betap2                          5.349836e-01     5.349836e-01     5.349836e-01     0.0e+00    OK    
poloidal beta betap3                          5.518764e-01     5.518764e-01     5.518764e-01     0.0e+00    OK    
# singular surfaces                           5                5                5                0.0e+00    OK    
singular psi locations                        [5 elem]         [5 elem]         [5 elem]         0.0e+00    OK    
singular q values                             [5 elem]         [5 elem]         [5 elem]         0.0e+00    OK    
current beta betaj                            4.236480e-01     4.236480e-01     4.236480e-01     0.0e+00    OK    
plasma volume                                 1.829472e+01     1.829472e+01     1.829472e+01     0.0e+00    OK    
plasma current                                1.152130e+00     1.152130e+00     1.152130e+00     0.0e+00    OK    
mpert                                         35               35               35               0.0e+00    OK    
npert                                         1                1                1                0.0e+00    OK    
toroidal field bt0                            2.006573e+00     2.006573e+00     2.006573e+00     0.0e+00    OK    
wall field bwall                              3.880145e-01     3.880145e-01     3.880145e-01     0.0e+00    OK    
aspect ratio                                  2.845746e+00     2.845746e+00     2.845746e+00     0.0e+00    OK    
elongation kappa                              1.708322e+00     1.708322e+00     1.708322e+00     0.0e+00    OK    
q profile (checksum)                          6da947d0754e...  6da947d0754e...  6da947d0754e...  identical  OK    
pressure profile (checksum)                   c9c6ca4072ca...  c9c6ca4072ca...  c9c6ca4072ca...  identical  OK    
Mercier D_I profile (checksum)                26babbe22505...  26babbe22505...  26babbe22505...  identical  OK    
resistive interchange D_R profile (checksum)  c46830151a0b...  c46830151a0b...  c46830151a0b...  identical  OK    
ballooning Delta' profile (checksum)          c27c6779804a...  c27c6779804a...  c27c6779804a...  identical  OK    
island half-widths                            [5 elem]         [5 elem]         [5 elem]         0.0e+00    OK    
Chirikov parameter                            [5 elem]         [5 elem]         [5 elem]         0.0e+00    OK    
||resonant area-weighted field||              5.288461e-04     5.288461e-04     5.288461e-04     0.0e+00    OK    
dominant-coupling singular values             [3 elem]         [3 elem]         [3 elem]         0.0e+00    OK    
|forcing overlap with dominant mode|          1.411548e-04     1.411548e-04     1.411548e-04     0.0e+00    OK    
|delta_nominal| of coil set 1                 7.034622e-05     7.034622e-05     7.034622e-05     0.0e+00    OK    
||ddelta/d(shift)|| over coil sets            1.245446e-04     1.245446e-04     1.245446e-04     0.0e+00    OK    
||ddelta/d(tilt)|| over coil sets             4.177337e-07     4.177337e-07     4.177337e-07     0.0e+00    OK    
PE plasma energy                              3.320466e+00     3.320466e+00     3.320466e+00     0.0e+00    OK    
PE vacuum energy                              3.174319e+00     3.174319e+00     3.174319e+00     0.0e+00    OK    
PE surface energy                             5.508585e+00     5.508585e+00     5.508585e+00     0.0e+00    OK    
PE toroidal torque                            1.119355e-04     1.119355e-04     1.119355e-04     0.0e+00    OK    
NTV torque FGAR [N·m]                         5.480580e-01     5.480580e-01     5.480580e-01     0.0e+00    OK    
NTV kinetic energy dW FGAR [J]                8.163220e-02     8.163220e-02     8.163220e-02     0.0e+00    OK    
Runtime (s)                                   217.5s           215.5s           209.9s                      --    
||forcing b~|| (root-area-weighted)           4.683171e-04     4.683171e-04     4.683171e-04     0.0e+00    OK    
resonant area-weighted field b^r              [5 elem]         [5 elem]         [5 elem]         0.0e+00    OK    
==================================================================================================================
Summary (last vs prev): 53 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 Tracking: diiid_slayer_n1_coupled
=============================================================================
Ref 1: db90e824d  @ db90e824d (2026-10-26)
       env: julia 1.12.6, x86_64-linux-gnu, manifest 4c9d54fa (pinned), 8 threads/4 BLAS, jit build
Ref 2: 7fd923d36  @ 7fd923d36 (2026-10-27)
       env: julia 1.12.6, x86_64-linux-gnu, manifest 4c9d54fa (pinned), 8 threads/4 BLAS, jit build
Ref 3: 125f4a069  @ 125f4a069 (2026-10-27)
       env: julia 1.12.6, x86_64-linux-gnu, manifest 4c9d54fa (pinned), 8 threads/4 BLAS, jit build
-----------------------------------------------------------------------------
Quantity                     db90e824d  7fd923d36  125f4a069  Δ prev   Status
-----------------------------------------------------------------------------
SLAYER tauk                  [6 elem]   [6 elem]   [6 elem]   0.0e+00  OK    
SLAYER q_shift               [6 elem]   [6 elem]   [6 elem]   0.0e+00  OK    
SLAYER coupled Q_root        [1 elem]   [1 elem]   [1 elem]   0.0e+00  OK    
SLAYER coupled ω             [1 elem]   [1 elem]   [1 elem]   0.0e+00  OK    
SLAYER coupled γ             [1 elem]   [1 elem]   [1 elem]   0.0e+00  OK    
SLAYER coupled no_root flag  [1 elem]   [1 elem]   [1 elem]   0.0e+00  OK    
SLAYER enabled flag          1          1          1          0.0e+00  OK    
Runtime (s)                  198.1s     204.2s     200.4s              --    
=============================================================================
Summary (last vs prev): 7 unchanged


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

Regression Tracking: diiid_slayer_n1
====================================================================================
Ref 1: db90e824d  @ db90e824d (2026-10-26)
       env: julia 1.12.6, x86_64-linux-gnu, manifest 4c9d54fa (pinned), 8 threads/4 BLAS, jit build
Ref 2: 7fd923d36  @ 7fd923d36 (2026-10-27)
       env: julia 1.12.6, x86_64-linux-gnu, manifest 4c9d54fa (pinned), 8 threads/4 BLAS, jit build
Ref 3: 125f4a069  @ 125f4a069 (2026-10-27)
       env: julia 1.12.6, x86_64-linux-gnu, manifest 4c9d54fa (pinned), 8 threads/4 BLAS, jit build
------------------------------------------------------------------------------------
Quantity                            db90e824d  7fd923d36  125f4a069  Δ prev   Status
------------------------------------------------------------------------------------
SLAYER surface indices              [6 elem]   [6 elem]   [6 elem]   0.0e+00  OK    
SLAYER poloidal m                   [6 elem]   [6 elem]   [6 elem]   0.0e+00  OK    
SLAYER toroidal n                   [6 elem]   [6 elem]   [6 elem]   0.0e+00  OK    
SLAYER minor radius rs              [6 elem]   [6 elem]   [6 elem]   0.0e+00  OK    
SLAYER r-based shear                [6 elem]   [6 elem]   [6 elem]   0.0e+00  OK    
SLAYER Lundquist S                  [6 elem]   [6 elem]   [6 elem]   0.0e+00  OK    
SLAYER D_norm                       [6 elem]   [6 elem]   [6 elem]   0.0e+00  OK    
SLAYER P_perp                       [6 elem]   [6 elem]   [6 elem]   0.0e+00  OK    
SLAYER tauk                         [6 elem]   [6 elem]   [6 elem]   0.0e+00  OK    
SLAYER iota_e                       [6 elem]   [6 elem]   [6 elem]   0.0e+00  OK    
SLAYER Q_e                          [6 elem]   [6 elem]   [6 elem]   0.0e+00  OK    
SLAYER Q_i                          [6 elem]   [6 elem]   [6 elem]   0.0e+00  OK    
SLAYER Q_root [2/1,3/1,4/1]         [3 elem]   [3 elem]   [3 elem]   0.0e+00  OK    
SLAYER ω_Hz [2/1,3/1,4/1]           [3 elem]   [3 elem]   [3 elem]   0.0e+00  OK    
SLAYER γ_Hz [2/1,3/1,4/1]           [3 elem]   [3 elem]   [3 elem]   0.0e+00  OK    
SLAYER no_root flags [2/1,3/1,4/1]  [3 elem]   [3 elem]   [3 elem]   0.0e+00  OK    
SLAYER enabled flag                 1          1          1          0.0e+00  OK    
Runtime (s)                         197.9s     195.5s     202.9s              --    
====================================================================================
Summary (last vs prev): 17 unchanged


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

Regression Tracking: diiid_truncation_n1
===================================================================================================
Ref 1: db90e824d  @ db90e824d (2026-10-26)
       env: julia 1.12.6, x86_64-linux-gnu, manifest 4c9d54fa (pinned), 8 threads/4 BLAS, jit build
Ref 2: 7fd923d36  @ 7fd923d36 (2026-10-27)
       env: julia 1.12.6, x86_64-linux-gnu, manifest 4c9d54fa (pinned), 8 threads/4 BLAS, jit build
Ref 3: 125f4a069  @ 125f4a069 (2026-10-27)
       env: julia 1.12.6, x86_64-linux-gnu, manifest 4c9d54fa (pinned), 8 threads/4 BLAS, jit build
---------------------------------------------------------------------------------------------------
Quantity                               db90e824d      7fd923d36      125f4a069      Δ prev   Status
---------------------------------------------------------------------------------------------------
layer-overlap cap applied              1              1              1              0.0e+00  OK    
layer-overlap psilim                   9.985081e-01   9.985081e-01   9.985081e-01   0.0e+00  OK    
first overlapping surface index        7              7              7              0.0e+00  OK    
diffusive-resistive layer widths (Δψ)  [7 elem]       [7 elem]       [7 elem]       0.0e+00  OK    
qlim                                   6.200000e+00   6.200000e+00   6.200000e+00   0.0e+00  OK    
psilim                                 9.949767e-01   9.949767e-01   9.949767e-01   0.0e+00  OK    
mpert                                  37             37             37             0.0e+00  OK    
# singular surfaces                    5              5              5              0.0e+00  OK    
singular q values                      [5 elem]       [5 elem]       [5 elem]       0.0e+00  OK    
singular psi locations                 [5 elem]       [5 elem]       [5 elem]       0.0e+00  OK    
plasma energy Re(ep[1])                -1.372379e+00  -1.372379e+00  -1.372379e+00  0.0e+00  OK    
total energy Re(et[1])                 8.005436e-01   8.005436e-01   8.005436e-01   0.0e+00  OK    
Runtime (s)                            174.0s         171.4s         170.6s                  --    
===================================================================================================
Summary (last vs prev): 12 unchanged


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

Regression Tracking: efit_fixedbdy_separatrix
=====================================================================================
Ref 1: db90e824d  @ db90e824d (2026-10-26)
       env: julia 1.12.6, x86_64-linux-gnu, manifest 4c9d54fa (pinned), 8 threads/4 BLAS, jit build
Ref 2: 7fd923d36  @ 7fd923d36 (2026-10-27)
       env: julia 1.12.6, x86_64-linux-gnu, manifest 4c9d54fa (pinned), 8 threads/4 BLAS, jit build
Ref 3: 125f4a069  @ 125f4a069 (2026-10-27)
       env: julia 1.12.6, x86_64-linux-gnu, manifest 4c9d54fa (pinned), 8 threads/4 BLAS, jit build
-------------------------------------------------------------------------------------
Quantity                    db90e824d     7fd923d36     125f4a069     Δ prev   Status
-------------------------------------------------------------------------------------
psio (total poloidal flux)  3.344390e-01  3.344390e-01  3.344390e-01  0.0e+00  OK    
q0                          1.155202e+00  1.155202e+00  1.155202e+00  0.0e+00  OK    
q95                         5.741022e+00  5.741022e+00  5.741022e+00  0.0e+00  OK    
beta_t                      3.945172e-05  3.945172e-05  3.945172e-05  0.0e+00  OK    
beta_n                      1.009505e-01  1.009505e-01  1.009505e-01  0.0e+00  OK    
Runtime (s)                 44.3s         42.7s         43.1s                  --    
=====================================================================================
Summary (last vs prev): 5 unchanged


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

Regression Tracking: gal_resistive_diiid_galinner
==================================================================================
Ref 1: db90e824d  @ db90e824d (2026-10-26)
       env: julia 1.12.6, x86_64-linux-gnu, manifest 4c9d54fa (pinned), 8 threads/4 BLAS, jit build
Ref 2: 7fd923d36  @ 7fd923d36 (2026-10-27)
       env: julia 1.12.6, x86_64-linux-gnu, manifest 4c9d54fa (pinned), 8 threads/4 BLAS, jit build
Ref 3: 125f4a069  @ 125f4a069 (2026-10-27)
       env: julia 1.12.6, x86_64-linux-gnu, manifest 4c9d54fa (pinned), 8 threads/4 BLAS, jit build
----------------------------------------------------------------------------------
Quantity                 db90e824d     7fd923d36     125f4a069     Δ prev   Status
----------------------------------------------------------------------------------
gal # singular surfaces  4             4             4             0.0e+00  OK    
gal singular q values    [4 elem]      [4 elem]      [4 elem]      0.0e+00  OK    
gal PEST3 Δ diagonal     [4 elem]      [4 elem]      [4 elem]      0.0e+00  OK    
||gal Δ′ matrix||        1.243812e+04  1.243812e+04  1.243812e+04  0.0e+00  OK    
||gal Δ_coil block||     2.437580e+02  2.437580e+02  2.437580e+02  0.0e+00  OK    
gal D_I per surface      [4 elem]      [4 elem]      [4 elem]      0.0e+00  OK    
gal α per surface        [4 elem]      [4 elem]      [4 elem]      0.0e+00  OK    
||gal inner-layer Δ||    1.474566e+06  1.474566e+06  1.474566e+06  0.0e+00  OK    
||gal match cout||       3.062036e-02  3.062036e-02  3.062036e-02  0.0e+00  OK    
||gal match bpen||       3.778795e+00  3.778795e+00  3.778795e+00  0.0e+00  OK    
gal match residual       2.281065e-16  2.281065e-16  2.281065e-16  0.0e+00  OK    
Runtime (s)              165.6s        168.9s        168.3s                 --    
==================================================================================
Summary (last vs prev): 11 unchanged


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

Regression Tracking: gal_resistive_diiid
==================================================================================
Ref 1: db90e824d  @ db90e824d (2026-10-26)
       env: julia 1.12.6, x86_64-linux-gnu, manifest 4c9d54fa (pinned), 8 threads/4 BLAS, jit build
Ref 2: 7fd923d36  @ 7fd923d36 (2026-10-27)
       env: julia 1.12.6, x86_64-linux-gnu, manifest 4c9d54fa (pinned), 8 threads/4 BLAS, jit build
Ref 3: 125f4a069  @ 125f4a069 (2026-10-27)
       env: julia 1.12.6, x86_64-linux-gnu, manifest 4c9d54fa (pinned), 8 threads/4 BLAS, jit build
----------------------------------------------------------------------------------
Quantity                 db90e824d     7fd923d36     125f4a069     Δ prev   Status
----------------------------------------------------------------------------------
gal # singular surfaces  4             4             4             0.0e+00  OK    
gal singular q values    [4 elem]      [4 elem]      [4 elem]      0.0e+00  OK    
gal PEST3 Δ diagonal     [4 elem]      [4 elem]      [4 elem]      0.0e+00  OK    
||gal Δ′ matrix||        1.243812e+04  1.243812e+04  1.243812e+04  0.0e+00  OK    
||gal Δ_coil block||     2.437580e+02  2.437580e+02  2.437580e+02  0.0e+00  OK    
gal D_I per surface      [4 elem]      [4 elem]      [4 elem]      0.0e+00  OK    
gal α per surface        [4 elem]      [4 elem]      [4 elem]      0.0e+00  OK    
||gal inner-layer Δ||    1.474577e+06  1.474577e+06  1.474577e+06  0.0e+00  OK    
||gal match cout||       3.062036e-02  3.062036e-02  3.062036e-02  0.0e+00  OK    
||gal match bpen||       3.778794e+00  3.778794e+00  3.778794e+00  0.0e+00  OK    
gal match residual       1.717368e-16  1.717368e-16  1.717368e-16  0.0e+00  OK    
Runtime (s)              168.9s        168.6s        173.2s                 --    
==================================================================================
Summary (last vs prev): 11 unchanged


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

Regression Tracking: gal_resistive_pe
=======================================================================
Ref 1: db90e824d  @ db90e824d (2026-10-26)
       env: julia 1.12.6, x86_64-linux-gnu, manifest 4c9d54fa (pinned), 8 threads/4 BLAS, jit build
Ref 2: 7fd923d36  @ 7fd923d36 (2026-10-27)
       env: julia 1.12.6, x86_64-linux-gnu, manifest 4c9d54fa (pinned), 8 threads/4 BLAS, jit build
Ref 3: 125f4a069  @ 125f4a069 (2026-10-27)
       env: julia 1.12.6, x86_64-linux-gnu, manifest 4c9d54fa (pinned), 8 threads/4 BLAS, jit build
-----------------------------------------------------------------------
Quantity                db90e824d  7fd923d36  125f4a069  Δ prev  Status
-----------------------------------------------------------------------
rational q values       N/A        N/A        N/A        N/A     N/A   
island half-widths      N/A        N/A        N/A        N/A     N/A   
Chirikov parameter      N/A        N/A        N/A        N/A     N/A   
||resonant b field||    N/A        N/A        N/A        N/A     N/A   
resonant b field (all)  N/A        N/A        N/A        N/A     N/A   
penetrated b field      N/A        N/A        N/A        N/A     N/A   
PE Δ' per surface       N/A        N/A        N/A        N/A     N/A   
||C resonant b field||  N/A        N/A        N/A        N/A     N/A   
Runtime (s)             171.7s     170.0s     169.8s             --    
=======================================================================
Summary (last vs prev): 8 missing/N/A


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

Regression Tracking: ggj_ray_q500i
=============================================================================
Ref 1: db90e824d  @ db90e824d (2026-10-26)
       env: julia 1.12.6, x86_64-linux-gnu, manifest 4c9d54fa (pinned), 8 threads/4 BLAS, jit build
Ref 2: 7fd923d36  @ 7fd923d36 (2026-10-27)
       env: julia 1.12.6, x86_64-linux-gnu, manifest 4c9d54fa (pinned), 8 threads/4 BLAS, jit build
Ref 3: 125f4a069  @ 125f4a069 (2026-10-27)
       env: julia 1.12.6, x86_64-linux-gnu, manifest 4c9d54fa (pinned), 8 threads/4 BLAS, jit build
-----------------------------------------------------------------------------
Quantity            db90e824d     7fd923d36     125f4a069     Δ prev   Status
-----------------------------------------------------------------------------
Re(Δ₊ interchange)  2.472007e+00  2.472007e+00  2.472007e+00  0.0e+00  OK    
Im(Δ₊ interchange)  1.335402e+01  1.335402e+01  1.335402e+01  0.0e+00  OK    
Re(Δ₋ tearing)      1.374966e-01  1.374966e-01  1.374966e-01  0.0e+00  OK    
Im(Δ₋ tearing)      7.427542e-01  7.427542e-01  7.427542e-01  0.0e+00  OK    
Runtime (s)         20.9s         20.1s         20.0s                  --    
=============================================================================
Summary (last vs prev): 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 Tracking: ggj_reference
================================================================================
Ref 1: db90e824d  @ db90e824d (2026-10-26)
       env: julia 1.12.6, x86_64-linux-gnu, manifest 4c9d54fa (pinned), 8 threads/4 BLAS, jit build
Ref 2: 7fd923d36  @ 7fd923d36 (2026-10-27)
       env: julia 1.12.6, x86_64-linux-gnu, manifest 4c9d54fa (pinned), 8 threads/4 BLAS, jit build
Ref 3: 125f4a069  @ 125f4a069 (2026-10-27)
       env: julia 1.12.6, x86_64-linux-gnu, manifest 4c9d54fa (pinned), 8 threads/4 BLAS, jit build
--------------------------------------------------------------------------------
Quantity            db90e824d      7fd923d36      125f4a069      Δ prev   Status
--------------------------------------------------------------------------------
Re(Δ₊ interchange)  1.225728e+03   1.225728e+03   1.225728e+03   0.0e+00  OK    
Im(Δ₊ interchange)  2.064823e+04   2.064823e+04   2.064823e+04   0.0e+00  OK    
Re(Δ₋ tearing)      -5.345663e+00  -5.345663e+00  -5.345663e+00  0.0e+00  OK    
Im(Δ₋ tearing)      2.592091e+01   2.592091e+01   2.592091e+01   0.0e+00  OK    
Runtime (s)         9.1s           9.2s           9.3s                    --    
================================================================================
Summary (last vs prev): 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 Tracking: solovev_kinetic_calculated
===============================================================================================
Ref 1: db90e824d  @ db90e824d (2026-10-26)
       env: julia 1.12.6, x86_64-linux-gnu, manifest 4c9d54fa (pinned), 8 threads/4 BLAS, jit build
Ref 2: 7fd923d36  @ 7fd923d36 (2026-10-27)
       env: julia 1.12.6, x86_64-linux-gnu, manifest 4c9d54fa (pinned), 8 threads/4 BLAS, jit build
Ref 3: 125f4a069  @ 125f4a069 (2026-10-27)
       env: julia 1.12.6, x86_64-linux-gnu, manifest 4c9d54fa (pinned), 8 threads/4 BLAS, jit build
-----------------------------------------------------------------------------------------------
Quantity                           db90e824d      7fd923d36      125f4a069      Δ prev   Status
-----------------------------------------------------------------------------------------------
vacuum energy Re(ev[1])            1.054739e+01   1.054739e+01   1.054739e+01   0.0e+00  OK    
q0                                 1.900003e+00   1.900003e+00   1.900003e+00   0.0e+00  OK    
NTV fgar quadrature torque [N·m]   2.267351e-03   2.267351e-03   2.267351e-03   0.0e+00  OK    
||xi_clebsch_alpha||               6.041963e-01   6.041963e-01   6.041963e-01   0.0e+00  OK    
total energy Re(et[1])             1.828278e+00   1.828278e+00   1.828278e+00   0.0e+00  OK    
total energy Im(et[1])             -1.326607e+00  -1.326607e+00  -1.326607e+00  0.0e+00  OK    
plasma energy Re(ep[1])            -8.719112e+00  -8.719112e+00  -8.719112e+00  0.0e+00  OK    
ODE steps (saved)                  608            608            608            0.0e+00  OK    
# singular surfaces                2              2              2              0.0e+00  OK    
boundary-response torque [N·m]     2.285518e-03   2.285518e-03   2.285518e-03   0.0e+00  OK    
singular psi locations             [2 elem]       [2 elem]       [2 elem]       0.0e+00  OK    
total energy (all)                 [32 elem]      [32 elem]      [32 elem]      0.0e+00  OK    
ODE steps (total)                  607            607            607            0.0e+00  OK    
mpert                              32             32             32             0.0e+00  OK    
q95                                3.147422e+00   3.147422e+00   3.147422e+00   0.0e+00  OK    
||Jb_theta_reg||                   3.945600e-03   3.945600e-03   3.945600e-03   0.0e+00  OK    
Runtime (s)                        203.3s         204.2s         205.6s                  --    
T_xe applied-forcing torque [N·m]  2.285518e-03   2.285518e-03   2.285518e-03   0.0e+00  OK    
||dxi_clebsch_psi/dpsi||           3.791914e+00   3.791914e+00   3.791914e+00   0.0e+00  OK    
singular q values                  [2 elem]       [2 elem]       [2 elem]       0.0e+00  OK    
npert                              1              1              1              0.0e+00  OK    
===============================================================================================
Summary (last vs prev): 20 unchanged


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

Regression Tracking: solovev_kinetic_multiion
=========================================================================================
Ref 1: db90e824d  @ db90e824d (2026-10-26)
       env: julia 1.12.6, x86_64-linux-gnu, manifest 4c9d54fa (pinned), 8 threads/4 BLAS, jit build
Ref 2: 7fd923d36  @ 7fd923d36 (2026-10-27)
       env: julia 1.12.6, x86_64-linux-gnu, manifest 4c9d54fa (pinned), 8 threads/4 BLAS, jit build
Ref 3: 125f4a069  @ 125f4a069 (2026-10-27)
       env: julia 1.12.6, x86_64-linux-gnu, manifest 4c9d54fa (pinned), 8 threads/4 BLAS, jit build
-----------------------------------------------------------------------------------------
Quantity                     db90e824d      7fd923d36      125f4a069      Δ prev   Status
-----------------------------------------------------------------------------------------
NTV total (D+T+imp+e) [N·m]  3.141767e+01   3.141767e+01   3.141767e+01   0.0e+00  OK    
NTV Deuterium [N·m]          1.973730e+01   1.973730e+01   1.973730e+01   0.0e+00  OK    
NTV Tritium [N·m]            2.046293e+01   2.046293e+01   2.046293e+01   0.0e+00  OK    
NTV electron [N·m]           -8.782557e+00  -8.782557e+00  -8.782557e+00  0.0e+00  OK    
total energy Re(et[1])       1.090560e-02   1.090560e-02   1.090560e-02   0.0e+00  OK    
# singular surfaces          2              2              2              0.0e+00  OK    
Runtime (s)                  202.5s         195.6s         196.9s                  --    
=========================================================================================
Summary (last vs prev): 6 unchanged


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

Regression Tracking: solovev_kinetic_ntv
====================================================================================================
Ref 1: db90e824d  @ db90e824d (2026-10-26)
       env: julia 1.12.6, x86_64-linux-gnu, manifest 4c9d54fa (pinned), 8 threads/4 BLAS, jit build
Ref 2: 7fd923d36  @ 7fd923d36 (2026-10-27)
       env: julia 1.12.6, x86_64-linux-gnu, manifest 4c9d54fa (pinned), 8 threads/4 BLAS, jit build
Ref 3: 125f4a069  @ 125f4a069 (2026-10-27)
       env: julia 1.12.6, x86_64-linux-gnu, manifest 4c9d54fa (pinned), 8 threads/4 BLAS, jit build
----------------------------------------------------------------------------------------------------
Quantity                                   db90e824d     7fd923d36     125f4a069     Δ prev   Status
----------------------------------------------------------------------------------------------------
NTV torque fgar [Re, Im]                   [1 elem]      [1 elem]      [1 elem]      0.0e+00  OK    
NTV ψ quadrature evaluations               45            45            45            0.0e+00  OK    
fluid CGL energy fcgl [J]                  1.552303e+01  1.552303e+01  1.552303e+01  0.0e+00  OK    
root-area-weighted total energy Re(et[1])  1.090560e-02  1.090560e-02  1.090560e-02  0.0e+00  OK    
# singular surfaces                        2             2             2             0.0e+00  OK    
singular psi locations                     [2 elem]      [2 elem]      [2 elem]      0.0e+00  OK    
q0                                         1.900006e+00  1.900006e+00  1.900006e+00  0.0e+00  OK    
Runtime (s)                                199.1s        196.6s        198.1s                 --    
====================================================================================================
Summary (last vs prev): 7 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 Tracking: solovev_kinetic_nuzero
=====================================================================================
Ref 1: db90e824d  @ db90e824d (2026-10-26)
       env: julia 1.12.6, x86_64-linux-gnu, manifest 4c9d54fa (pinned), 8 threads/4 BLAS, jit build
Ref 2: 7fd923d36  @ 7fd923d36 (2026-10-27)
       env: julia 1.12.6, x86_64-linux-gnu, manifest 4c9d54fa (pinned), 8 threads/4 BLAS, jit build
Ref 3: 125f4a069  @ 125f4a069 (2026-10-27)
       env: julia 1.12.6, x86_64-linux-gnu, manifest 4c9d54fa (pinned), 8 threads/4 BLAS, jit build
-------------------------------------------------------------------------------------
Quantity                 db90e824d      7fd923d36      125f4a069      Δ prev   Status
-------------------------------------------------------------------------------------
vacuum energy Re(ev[1])  1.058613e+01   1.058613e+01   1.058613e+01   0.0e+00  OK    
q0                       1.900003e+00   1.900003e+00   1.900003e+00   0.0e+00  OK    
total energy Re(et[1])   2.290965e+00   2.290965e+00   2.290965e+00   0.0e+00  OK    
total energy Im(et[1])   -1.564546e+00  -1.564546e+00  -1.564546e+00  0.0e+00  OK    
plasma energy Re(ep[1])  -8.295163e+00  -8.295163e+00  -8.295163e+00  0.0e+00  OK    
ODE steps (saved)        608            608            608            0.0e+00  OK    
# singular surfaces      2              2              2              0.0e+00  OK    
singular psi locations   [2 elem]       [2 elem]       [2 elem]       0.0e+00  OK    
total energy (all)       [32 elem]      [32 elem]      [32 elem]      0.0e+00  OK    
ODE steps (total)        607            607            607            0.0e+00  OK    
mpert                    32             32             32             0.0e+00  OK    
q95                      3.147422e+00   3.147422e+00   3.147422e+00   0.0e+00  OK    
Runtime (s)              208.9s         203.3s         201.2s                  --    
singular q values        [2 elem]       [2 elem]       [2 elem]       0.0e+00  OK    
npert                    1              1              1              0.0e+00  OK    
=====================================================================================
Summary (last vs prev): 14 unchanged


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

Regression Tracking: solovev_multi_n
==================================================================================================
Ref 1: db90e824d  @ db90e824d (2026-10-26)
       env: julia 1.12.6, x86_64-linux-gnu, manifest 4c9d54fa (pinned), 8 threads/4 BLAS, jit build
Ref 2: 7fd923d36  @ 7fd923d36 (2026-10-27)
       env: julia 1.12.6, x86_64-linux-gnu, manifest 4c9d54fa (pinned), 8 threads/4 BLAS, jit build
Ref 3: 125f4a069  @ 125f4a069 (2026-10-27)
       env: julia 1.12.6, x86_64-linux-gnu, manifest 4c9d54fa (pinned), 8 threads/4 BLAS, jit build
--------------------------------------------------------------------------------------------------
Quantity                      db90e824d        7fd923d36        125f4a069        Δ prev     Status
--------------------------------------------------------------------------------------------------
total energy Re(et[1])        -2.134718e+00    -2.134718e+00    -2.134718e+00    0.0e+00    OK    
total energy Im(et[1])        2.553238e-10     2.553238e-10     2.553238e-10     0.0e+00    OK    
vacuum matrix min eigenvalue  1.730832e+00     1.730832e+00     1.730832e+00     0.0e+00    OK    
plasma energy (all)           [70 elem]        [70 elem]        [70 elem]        0.0e+00    OK    
vacuum energy (all)           [70 elem]        [70 elem]        [70 elem]        0.0e+00    OK    
total energy (all)            [70 elem]        [70 elem]        [70 elem]        0.0e+00    OK    
ODE steps (saved)             56               56               56               0.0e+00    OK    
ODE steps (total)             1044             1044             1044             0.0e+00    OK    
q0                            1.900006e+00     1.900006e+00     1.900006e+00     0.0e+00    OK    
q95                           3.147422e+00     3.147422e+00     3.147422e+00     0.0e+00    OK    
# singular surfaces           3                3                3                0.0e+00    OK    
singular psi locations        [3 elem]         [3 elem]         [3 elem]         0.0e+00    OK    
mpert                         35               35               35               0.0e+00    OK    
npert                         2                2                2                0.0e+00    OK    
q profile (checksum)          2340b888d410...  2340b888d410...  2340b888d410...  identical  OK    
Runtime (s)                   175.1s           174.4s           183.8s                      --    
==================================================================================================
Summary (last vs prev): 15 unchanged


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

Regression Tracking: solovev_n1
==================================================================================================
Ref 1: db90e824d  @ db90e824d (2026-10-26)
       env: julia 1.12.6, x86_64-linux-gnu, manifest 4c9d54fa (pinned), 8 threads/4 BLAS, jit build
Ref 2: 7fd923d36  @ 7fd923d36 (2026-10-27)
       env: julia 1.12.6, x86_64-linux-gnu, manifest 4c9d54fa (pinned), 8 threads/4 BLAS, jit build
Ref 3: 125f4a069  @ 125f4a069 (2026-10-27)
       env: julia 1.12.6, x86_64-linux-gnu, manifest 4c9d54fa (pinned), 8 threads/4 BLAS, jit build
--------------------------------------------------------------------------------------------------
Quantity                      db90e824d        7fd923d36        125f4a069        Δ prev     Status
--------------------------------------------------------------------------------------------------
total energy Re(et[1])        1.090560e-02     1.090560e-02     1.090560e-02     0.0e+00    OK    
total energy Im(et[1])        1.308749e-10     1.308749e-10     1.308749e-10     0.0e+00    OK    
plasma energy Re(ep[1])       -1.041640e+01    -1.041640e+01    -1.041640e+01    0.0e+00    OK    
vacuum energy Re(ev[1])       1.042730e+01     1.042730e+01     1.042730e+01     0.0e+00    OK    
vacuum matrix min eigenvalue  2.170703e+00     2.170703e+00     2.170703e+00     0.0e+00    OK    
plasma energy (all)           [32 elem]        [32 elem]        [32 elem]        0.0e+00    OK    
vacuum energy (all)           [32 elem]        [32 elem]        [32 elem]        0.0e+00    OK    
total energy (all)            [32 elem]        [32 elem]        [32 elem]        0.0e+00    OK    
ODE steps (saved)             287              287              287              0.0e+00    OK    
ODE steps (total)             285              285              285              0.0e+00    OK    
q0                            1.900006e+00     1.900006e+00     1.900006e+00     0.0e+00    OK    
q95                           3.147422e+00     3.147422e+00     3.147422e+00     0.0e+00    OK    
beta_t                        4.621027e-02     4.621027e-02     4.621027e-02     0.0e+00    OK    
beta_n                        3.217775e+00     3.217775e+00     3.217775e+00     0.0e+00    OK    
# singular surfaces           2                2                2                0.0e+00    OK    
singular psi locations        [2 elem]         [2 elem]         [2 elem]         0.0e+00    OK    
singular q values             [2 elem]         [2 elem]         [2 elem]         0.0e+00    OK    
mpert                         32               32               32               0.0e+00    OK    
npert                         1                1                1                0.0e+00    OK    
q profile (checksum)          2340b888d410...  2340b888d410...  2340b888d410...  identical  OK    
pressure profile (checksum)   108b947087e6...  108b947087e6...  108b947087e6...  identical  OK    
ca_left (checksum)            21c2d085d11b...  21c2d085d11b...  21c2d085d11b...  identical  OK    
Runtime (s)                   181.9s           182.1s           177.0s                      --    
==================================================================================================
Summary (last vs prev): 22 unchanged

Notes for reviewers

Stacked on #569. The harness tracks develop, #569 and this branch in one run.

The split. Everything that depends only on the force-free-states result moves into plasma_response:

  • the flux matrix and flux-space Λ, L, P;
  • the field-space Λ̃, L̃, P̃, ϱ̃, S and A;
  • the singular-coupling loop (C̃ matrices, flux-space copies for applying a forcing, C_coeffs, rational metadata);
  • the dominant-mode SVD.

perturbed_equilibrium(resp, rmp) keeps everything per source: materializing the field, P·Φₓ, the three spectra, the energies, the profile reconstruction, the applied resonant vectors, the island widths and Chirikov, and the dominant overlap Vᴴ·b̃ₓ. Response.jl and SingularCoupling.jl are split along that line without changing the arithmetic. It still writes gpec.h5 itself, as before; moving the write is the consolidation's.

What else changes.

  • efc_couplings takes the run's PlasmaResponse and the run's regularization_width, and forces RMPField(modes). Before, it did two full PE solves per correction coil set, rebuilding Λ, L, P and the flux matrix each time with a hard-coded default control, so it always regularized at 0.05 whatever the run used. diiid_error_field sets 0.05, so the harness cannot see the fix.
  • regularization_width defaults to 0 for every result, matching the Fortran reg_flag = f template; default_regularization_width is gone. Regularization exists to converge the NTV torque of an ideal solve, so the decks that drive KineticForces with one (DIIID-like_ideal, DIIID-like_error_field, Solovev_kinetic_NTV, Solovev_kinetic_multiion) keep 0.05, and Solovev_ideal, DIIID-like_ideal_multi_n and DIIID-like_gal_resistive_pe go to 0.
  • The torque response from PerturbedEquilibrium - FEATURE - Add the psi-resolved torque response matrices T_xe and T_source #472 is ported onto the split and stays opt-in. plasma_response(ffs; compute_torque_response=true) builds T_xe(ψ) onto PlasmaResponse.T_xe (the ψ loop and its checks are unchanged), and each perturbed_equilibrium call contracts it with its own forcing into T_applied and T_source = B̃†·T_xe·B̃ with B̃ = R⁻¹·Φ_source, which equals PerturbedEquilibrium - FEATURE - Add the psi-resolved torque response matrices T_xe and T_source #472's per-source form algebraically.
  • The runtimes keyword is gone from both calls, as develop removed it from main.
  • The deck's [PerturbedEquilibrium] section is split by key between the two calls. compute_response joins the deprecated-key list and the hook, and is removed from the example decks and tests. The inert regularization_width line goes from Solovev_kinetic_calculated, the only kinetic example.
  • The forcing modes and coil sets now live on the returned state, which is what PerturbedEquilibriumInternal carried.
  • The PerturbedEquilibrium - BUGFIX! - Refuse Galerkin and matched results until they publish wp #556 refusal moves to plasma_response and is unconditional. The Galerkin PE example keeps its [PerturbedEquilibrium] section and now stops there, with its staged compute_singular_coupling = true restored; a follow-up makes it run. The gal_resistive_pe harness case ends after force-free states ([overrides] ForceFreeStates.force_termination = true), with a comment that the follow-up removes it.

Bits. Each version is exactly deterministic run to run. Between them, Equilibrium and ForceFreeStates are identical, and PerturbedEquilibrium agrees to rounding: the forcing amplitude differs by 1 ulp, most datasets by about 1e-14, at worst 1.8e-10 relative in Jb_zeta on the coarse Solovev fixture. In one process, materializing the forcing before or after building the response gives identical bits, so the seed comes from the reorganized flow itself, plausibly allocation-dependent vectorized reductions (not isolated). None of this reaches a tracked harness quantity (below).

Tests.

  • runtests_solve_api.jl now checks that one response forced twice is identical; that scale and 3A − A behave linearly on the reused response; that RMPField(pe.forcing_modes) reproduces the file-forced run exactly, takes a weight and sums with a file leaf; that the default width is 0 and an explicit 0.05 is respected; and that the deck and the two calls agree on hdf5 file forcing.
  • The Galerkin and matched refusal tests move to plasma_response. The island diagnostics are a pure function and tested as one.
  • The deprecated-key guard checks the PE keys against the two functions' keywords.
  • runtests_torque_response.jl drives the new two-step flow, checks a forcing file as one source and that a response built without the option contracts nothing, and checks that an explicit width is respected on its kinetic result.
  • Local runs at this head: torque response 44, solve API 135 (plus develop's one @test_broken), kinetic validity 21.

🤖 Generated with Claude Code

@matt-pharr matt-pharr self-assigned this Oct 23, 2026
@matt-pharr
matt-pharr requested a review from logan-nc October 23, 2026 19:01
@matt-pharr
matt-pharr added this pull request to stack #557 October 23, 2026 19:02
@github-actions github-actions Bot added api Config key, output dataset or exported name changed changed-results Results move or an interface breaks - read before upgrading labels Oct 23, 2026

@logan-nc logan-nc 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.

Read in full. One real bug, one stale example, and two behaviour changes to disclose; then ready to approve.

  1. benchmarks/benchmark_diiid_ideal_ntv_torque.jl:266 breaks: it builds PerturbedEquilibriumState(; psi_grid, xi_modes) and response::PlasmaResponse is now a required field (UndefKeywordError). Nothing tests it. Needs a stub response (or a constructor that takes ffs).
  2. Stale docstring example src/ForcingTerms/ForcingTerms.jl:292: pe = perturbed_equilibrium(ffs, total) no longer dispatches; should read perturbed_equilibrium(plasma_response(ffs), total). Not pushed (src, stamp).
  3. efc_couplings regularization is a silent numerical change. On develop it built its own PerturbedEquilibriumControl and therefore always used the default regularization_width = 0.05, whatever the deck said; now it takes the run's width (0 on a kinetic fit). That is the right behaviour, but any error-field deck with a non-default width, or any kinetic fit, moves; diiid_error_field sits at 0.05 so the harness cannot see it. One line in the release note, and arguably the ! already on the title covers it.
  4. Galerkin/matched results now error unconditionally at plasma_response, deleting the "both flags off" path and test #556 just added. Say in the Migration line that this supersedes #556's advice (the example moves to force_termination).

Also: no test that an explicit regularization_width is respected on a kinetic result (the release-note behaviour); docs/src/api.md "Entry points" does not list plasma_response/PlasmaResponse; docs/src/workflow.md Stage 5 still describes one stage. Stale comment in test/runtests_dominant_coupling.jl ~90 (the applied vector is no longer evaluated by the writer).

Pushed 85cf562 (docs only): kinetic_forces.md still said the width is forced to 0 and logged; it is now a default.

Checked and clean: the TOML key split at the driver matches the two signatures; no stale accessors of the moved operators anywhere (Analysis, Rerun, writers read HDF5 paths; KineticForces reads only xi_modes/psi_grid); every PerturbedEquilibriumControl/Internal field is accounted for; compute_dominant_coupling! → build_dominant_coupling! has no leftovers; the solve-API tests exercise the two-call path substantively (reuse, scale, algebra, spectrum leaf).

Collisions (git merge-tree): vs develop 3 files (hdf5-conventions.md, PerturbedEquilibrium.jl, PerturbedEquilibriumStructs.jl); vs #580 the efc_couplings call in the driver; vs the KineticForces stack and #588 the same files as #569. The harness stamp is d09bf3c under a later merge commit; CI accepts it.

@logan-nc

Copy link
Copy Markdown
Collaborator

Heads-up: GitHub did not start the pull-request workflows on 85cf562 (my push above); no check runs exist for it after an hour although Actions itself is fine. A close/reopen or your next push will re-fire them. The change is non-src, so the harness stamp is unaffected.

@matt-pharr

Copy link
Copy Markdown
Collaborator Author

Thanks, all addressed in 60ed66b except the kinetic-width test, which is in the next commit. Taking your items in order:

  1. Benchmark. benchmarks/benchmark_diiid_ideal_ntv_torque.jl now passes response=PE.PlasmaResponse(; ffs). Every other PlasmaResponse field has a default, so a stub is one line and needs no new constructor.
  2. Docstring example. ForcingTerms.jl now reads perturbed_equilibrium(plasma_response(ffs), total).
  3. efc_couplings width. Disclosed in the release note. Looking into it also changed the default: Matthew's convention is no regularization unless KineticForces computes torque from an ideal solve, as in the Fortran reg_flag = f template, so regularization_width now defaults to 0 for every result and default_regularization_width is gone. The decks that drive KineticForces with an ideal solve (DIIID-like_ideal, DIIID-like_error_field, Solovev_kinetic_NTV, Solovev_kinetic_multiion) keep 0.05 explicitly. Solovev_ideal, DIIID-like_ideal_multi_n and DIIID-like_gal_resistive_pe go to 0. Only the regularized profiles and the torque built from them can move, and the Migration line now says so. This also replaces what your 85cf562 wrote in kinetic_forces.md.
  4. PerturbedEquilibrium - BUGFIX! - Refuse Galerkin and matched results until they publish wp #556 superseded. Added to the Migration line: Galerkin and :matched results error at plasma_response whatever the flags, so stop such a run after force-free states.

The smaller ones:

  • Kinetic width test. runtests_torque_response.jl checks that its kinetic forward result defaults to 0 and that an explicit 0.05 reaches the Clebsch profiles while forcing_b stays put. It reuses that file's solve, so it costs no extra run.
  • docs/src/api.md. The entry points link plasma_response and PlasmaResponse. Their @docs blocks stay in perturbed_equilibrium.md, because listing them twice is a Documenter error.
  • docs/src/workflow.md. Stage 5 describes the two steps and which inputs each takes.
  • test/runtests_dominant_coupling.jl. The comment now says perturbed_equilibrium evaluates the applied resonant field from the flux-space coupling.

Develop's #472 landed in between, so the torque response is ported onto the split and stays opt-in. plasma_response(ffs; compute_torque_response=true) builds T_xe(ψ) once. Each perturbed_equilibrium call contracts it with its own forcing into T_applied and T_source = B̃†·T_xe·B̃, with B̃ = R⁻¹·Φ_source. That equals the per-source Ks form algebraically, and your test already asserts it.

Restamped at 60ed66b against #569's 58381b6, all 19 cases: nothing moves (263 quantities exactly 0, including TorqueResponse/total_torque).

@matt-pharr matt-pharr added this to the GPEC v2.0.0 milestone Oct 26, 2026

@logan-nc logan-nc 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.

Re-read 60ed66b and 5e49810. Every item from the first review is in: the benchmark passes a PlasmaResponse(; ffs) stub, the ForcingTerms docstring example is the two-call form, the width change in efc_couplings and the end of the #556 fallback are both in the Migration line, api.md links plasma_response/PlasmaResponse, workflow.md Stage 5 is two steps, the stale comment is fixed.

On the new default of 0 for every result: I checked the decks. The only kinetic-solve example (Solovev_kinetic_calculated, kinetic_factor = 1) leaves the width unset, so it stays at 0 as it was when the code forced it; the four decks that drive KineticForces from an ideal solve keep 0.05 explicitly; the three decks that went to 0.0 are ideal runs whose regularized profiles are not tracked. That matches the Numerical impact line. The kinetic-width test in runtests_torque_response.jl pins the explicit-value path. Ready from my side; lands after #569 and retargets to develop then.

Base automatically changed from refactor/deprecate-noop-control-keys to develop October 27, 2026 08:42
@matt-pharr
matt-pharr merged commit 3456e63 into develop Oct 27, 2026
11 checks passed
@matt-pharr
matt-pharr deleted the refactor/plasma-response branch October 27, 2026 08:43
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

api Config key, output dataset or exported name changed changed-results Results move or an interface breaks - read before upgrading

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants