Skip to content

Tearing - FEATURE - Add critical resonant field calculations to the tearing workflow - #415

Merged
matt-pharr merged 34 commits into
developfrom
feature/b_crit_calculation
Oct 28, 2026
Merged

matt-pharr merged 34 commits into
developfrom
feature/b_crit_calculation

Conversation

@ebursch

@ebursch ebursch commented Aug 20, 2026 •

Copy link
Copy Markdown
Collaborator

Release note

  • Audience: users
  • Numerical impact: none; the critical resonant field is off by default (harness @ 3a6435d)
  • Migration: none

Tearing can now compute the critical resonant field b_r/B_φ for error-field penetration at each SLAYER surface, from the torque balance of Cole and Fitzpatrick, Phys. Plasmas 13, 032503 (2006), Eqs. 61–62. Turn it on with [SLAYER.CriticalResonantField] enabled = true. Each surface uses its own SLAYER layer: P is its P_tor, α its outer stability, and Q0 = τ_k·n·Ω_E its E×B rotation. The threshold is the penetration fold (Fitzpatrick, Nucl. Fusion 33, 1049 (1993), Sec. 7.4). A surface with no fold, which slows smoothly instead, reports NaN. Results go to Tearing/CriticalResonantField/ in gpec.h5. Resolves #371.

Original implementation by @ebursch; ported onto develop's TearingProblem and reworked by @d-burg.

Changes

  • Tearing.CriticalResonantField (TorqueBalance.jl) evaluates Cole's balance 2P(Q0 − Q)/(Sκ̂ Im[−1/(α + Δ̂)]) on the real Q axis, with Δ̂ from the surface's SLAYER layer.
    • α = S^(−1/3)(Δ_crit − r_s Δ′), instead of Fortran's fixed 10⁻², so α + Δ̂ is the dispersion relation's residual and the torque balance shares its poles with SLAYER's free modes. Cole and Fitzpatrick have no Δ_crit; including it treats the curvature offset as independent of frequency. It is zero unless D_c_type is set. A tearing-unstable surface (α ≤ 0) is skipped with a warning.
    • Threshold: the first saddle-node on the shielded branch followed from Q0 toward Q_e: the first running maximum of the balance that the path then drops more than 0.1 % below. Points with |Δ̂| ≤ α, the unshielded zone next to Q_e, are not candidates. With no resolved fold the surface reports NaN and a warning.
    • κ̂ = 2/s², i.e. the viscosity integral fixed at ½, as in Fortran. The profile integral is tracked in Tearing - Compute κ̂ from the viscosity profile in the critical resonant field #510.
  • Rotation. Q0 = τ_k·n·Ω_E uses the kinetic file's omega_E or the omega_E_kHz override. The run stops if no surface has a known Ω_E and skips a surface without one. An explicit zero is valid and gives Cole's diamagnetic-only threshold.
  • Runner. The analysis runs inside run_slayer_from_inputs, so script callers get it too. The [SLAYER.CriticalResonantField] section takes enabled, n, store_scan and optional Qmin/Qmax. HDF5 outputs: br_crit (b_r/B_φ), br_crit_tesla, Q_peak, Q0 and rational_index, and with store_scan the per-surface Scan/Surface_<k>/{Q, balance, Delta}.
  • Tests (runtests_critical_resonant_field.jl, 49):
    • Cole's analytic visco-resistive limits: Q0/2 with coefficient √(2.104/2), and 7Q_e/12 with diamagnetic rotation only.
    • Fold selection, including a fold followed by a dip and a rise past its height (@matt-pharr's counterexample shape), and the unshielded-zone cases.
    • Zero rotation, the skip conditions, TOML parsing and the HDF5 contract.
  • Harness: diiid_slayer_n1 pins br_crit, br_crit_tesla, Q_peak and Q0 on the inner three surfaces.
  • Docs: a "Critical resonant field" section in inner_layer.md, with the Fortran benchmark, and Fitzpatrick 1993 in references.md.

On the DIII-D-like example

examples/DIIID-like_SLAYER_example with the analysis on, at 5d1079d52; the fold-selection fix in 753986fd1 leaves every value unchanged:

surface 2/1 3/1 4/1 5/1 6/1 7/1
br_crit (b_r/B_φ) skipped 1.40e-3 NaN NaN NaN NaN
br_crit_tesla [T] skipped 2.73e-3 NaN NaN NaN NaN
Q_peak 0.716
Q0 2.463 1.121 0.206 −0.455 −0.036 −0.005
Q_e 0.625 0.353 0.273 1.694 0.097 0.023
Q_i −0.948 −0.324 −0.683 −1.198 −0.159 −0.050
  • 2/1 is skipped with a warning: at the default D_c_type = "none" it is tearing-unstable (α = −0.040), so there is no shielded state to penetrate.
  • 3/1 has the one fold, at Q = 0.716 between Q0 and Q_e: b_r/B_φ = 1.40e-3, or 2.7 mT.
  • 4/1–7/1 have no resolved fold: the balance never falls more than 0.1 % below a maximum between Q0 and Q_e, so they report NaN.
  • The 3/1 value is 13 % lower than at the port (6d0c7dd7c, 1.61e-3). That comes from develop 0b4b9fbfb: InnerLayer.SLAYER - FEATURE! - Build P_perp from the perpendicular particle diffusivity by default and add an ion heat diffusivity profile #501's D_perp default lowers P_perp 3–4× on every surface, which changes Δ̂(Q). Every other layer input is unchanged, and Q_peak moves by 0.4 %.

Regression report

Latest SDCC fanout rerun: develop 7817f0e7a vs 3a6435d60 — 21 cases; no changed comparable quantities; four new CRF quantities in each of two SLAYER cases have no develop baseline; harness exit 0. Full report and limitations. gal_resistive_pe has all eight quantities missing on both refs and provides no numerical validation. Earlier reports are retained below.

Full harness by @matt-pharr on SDCC (report), develop 057c4af0d vs da6926142, Julia 1.12.6, manifest pinned: 21 cases, harness exit code 0. Every existing quantity in every case is unchanged. The four new pins (br_crit, br_crit_tesla, Q_peak, Q0 on the inner three surfaces of diiid_slayer_n1 and diiid_slayer_n1_chi_perp_e) are N/A on develop, which has no such output. gal_resistive_pe is N/A on both refs, as on develop. runtests_critical_resonant_field.jl (49) passes at 753986fd1, and CI passes at da6926142.

Notes for reviewers

  • Saddle-node counterexample (@matt-pharr, above). On the 3/1 layer with Q0 = 2 and α = 0.48 the threshold is now 2.54987e-3 at Q = 0.974, matching his 2.54975e-3 at Q ≈ 0.972; the old global-maximum rule returned NaN there and on his α = 0.3 case.

  • Fortran benchmark at Fortran's settings. Given Fortran's normalized inputs and α = 10⁻², the Julia balance reproduces Fortran's from Fortran's own Δ(Q) table to all printed digits. The thresholds differ only through the selection rule. Fortran takes the global maximum on its window, which is the balance spike within 0.003 of the Q_e pole on 2/1, 3/1, 4/1 and 6/1. The two layer models (Park's drift-MHD in Fortran, Fitzpatrick's in Julia) give Δ(Q) a median 24–78 % apart between Q_i and Q_e. Figure and details are in the docs section.

  • Units. br_crit is the dimensionless b_r/B_φ used by Cole and Fitzpatrick (2006, Eqs. 61–68) and by Fitzpatrick, Phys. Plasmas 30, 092512 (2023), Eq. 120. Both normalize the resonant field by the toroidal field. br_crit_tesla = br_crit·|B0|, with the layer's own B0, is there for comparison with resonant_area_weighted_field. That is GPEC's total resonant field with the ideal plasma response, and Park et al., PRL 99, 195003 (2007) identify it, rather than the external vacuum field, as the field that opens islands. Fitzpatrick's drive likewise includes the outer plasma's amplification. The comparison is approximate: the theory's b_r is a cylindrical field at the layer, and no reference maps it onto GPEC's area-weighted toroidal field. Do not compare it with penetrated_area_weighted_field, which already includes the layer response. Fortran's gpout.f labels the ratio "Tesla" but leaves out the B_φ factor; @logan-nc confirmed that reading above.

  • Stability test. A surface is used only when α > 0, i.e. r_s Δ′ < Δ_crit. Two limits:

    • it is the classical criterion; SLAYER's drift layer shifts stability, so near marginal stability α > 0 can disagree with whether the surface's free-mode dispersion relation has a growing root;
    • it uses only the diagonal of Δ′, so a surface stable on its own but unstable through coupling to its neighbors is still used.

    Skipping any surface where SLAYER finds a growing root would close both; it is left for a follow-up.

  • InnerLayer.SLAYER - API! - Default the layer radial label to the toroidal-flux label #599 (flux radial label). No conflict, and the tests here pass on the combined tree, but the label moves these pins: br_crit by 5.8 %, Q_peak by 40.8 %, Q0 by 29.6 % (through τ_k). Whichever of the two merges second needs a new stamp.

  • Open questions (from the thread):


🤖 Generated with Claude Code

@ebursch
ebursch requested review from d-burg and logan-nc August 20, 2026 18:50
@ebursch
ebursch enabled auto-merge (squash) August 20, 2026 18:53
@ebursch ebursch changed the title TEARING - NEW FEATURE - Add critical resonant field calculations to the tearing workflow TEARING - FEATURE - Add critical resonant field calculations to the tearing workflow Aug 20, 2026
@github-actions github-actions Bot added the feature New capability label Aug 20, 2026
@ebursch ebursch changed the title TEARING - FEATURE - Add critical resonant field calculations to the tearing workflow Tearing - Feature - Add critical resonant field calculations to the tearing workflow Aug 20, 2026
@ebursch ebursch changed the title Tearing - Feature - Add critical resonant field calculations to the tearing workflow Tearing - FEATURE - Add critical resonant field calculations to the tearing workflow Aug 20, 2026
@logan-nc

logan-nc commented Aug 20, 2026 •

Copy link
Copy Markdown
Collaborator

Currently takes either an array or a scalar for all surfaces but will easily be updated to a true profile once I have angular momentum diffusivity profile data on hand to test with.

Sounds like this should be marked draft until this is done

This should perform as well as or better than the Fortran implementation.

"Should" is scary - benchmark it! There is a benchmark script for comparing to fortran - modify that for your needs (using scratch scripts - no need to commit run scripts)

Other improvements to the model and the numerical methods are in progress, but I wanted to have a working version available to users.

Mark this as draft until the IO and benchmarks are done then ping us for reviews. You can make a "Task" type issue describing future plans (and assign yourself) so we have it on record as work in progress.

@ebursch
ebursch marked this pull request as draft August 20, 2026 19:14
auto-merge was automatically disabled August 20, 2026 19:14

Pull request was converted to draft

@ebursch
ebursch marked this pull request as ready for review August 21, 2026 14:59
@ebursch

ebursch commented Aug 21, 2026

Copy link
Copy Markdown
Collaborator Author

@logan-nc @d-burg Should be ready for review now. Added profile inputs and a Fortran comparison plot.

@d-burg

d-burg commented Sep 3, 2026

Copy link
Copy Markdown
Collaborator

Review (combining my findings with Claude's)

Structure is sound and Cole Eq. 62 is the right target. Physics claims below were checked numerically against a DIII-D-like 2/1 SLAYERParameters (n_e 5e19, T_e=T_i 1 keV, q 2, s 1, B_t 2 T, r_s 0.5, R_0 1.7, ω_*e −1e4, ω_*i 5e3, ω_E 3e4), not just read.

Checked, no action needed

  • Q_e / Q_i signs check out. The scan axis is Q = +tauk·ω (Cole's convention), Q0_here matches it, and the odd-looking argmin(abs.(Qs .+ Q_e)) correctly locates Q = −Q_e (Im Δ changes sign at −0.860 vs predicted −0.8602).
  • The positive-balance branch lands exactly on [−Q_e, Q0] = [−0.86, +2.58] — Cole's physical picture falling out on its own. Good self-consistency signal, and worth an assertion (see item 1).
  • alpha = 1e-2 is not a free parameter: b_crit moves 4% across 1e-4 → 1e-1 with Qpeak unchanged. The max is interior, far from the branch edge. Defensible as-is; just state the measured insensitivity instead of leaving a bare literal.
  • Grid resolution is benign for b_crit: n=200 → 4.5582e-3 vs n=2000 → 4.5593e-3.

Blocking

  1. The conjugation in Riccati.jl is now significant but documented as cosmetic. solve_inner returns conj(Δ̂_s), justified as harmless because "conjugation maps zeros to zeros" — true for root-finding, which was the only consumer until now. Torque balance is the first consumer that depends on the sign of Im Δ. Undoing it: positive branch becomes the entire [−10, +10] window, Qpeak −2.246, b_crit 4.915e-3 — i.e. the max becomes an artifact of Qmin/Qmax. The code is correct as written, but nothing guards that. Please add a test pinning the Im Δ sign (or Qpeak ∈ (-Q_e, Q0)) and a note in Riccati.jl that the reflection is load-bearing for CriticalResonantField.

  2. κ̂ is silently hardcoded. TorqueBalance.jl:131 does sqrt(maximum / lu * (sval^2/2)), i.e. 1/κ̂ → s²/2 (I think this is correct but double check for me), fixing Cole's viscosity integral ∫[μ(r_s)/μ(r)]dr/r at exactly 1/2. For flat μ that integral is ln(a/r_s): ≈0.51 at r_s/a≈0.6, but 1.20 at r_s/a=0.3 — κ̂ off 2.4×, b_crit off ~1.55× on inner surfaces. Also self-defeating: the viscosity profile is the headline new input, and κ̂ is the one place it's physically required.

  3. Q0 is E×B only. run_slayer.jl:512 uses profiles(psi).omega, and _load_profiles sets omega_e/omega_i to zeros. Cole's ω₀ is the natural mode rotation frequency; his §III D specialises to ω_*=0, which isn't the regime here. Since the branch is [−Q_e, Q0], Q0 sets its upper edge and so resizes the domain of the max — this isn't just a shifted number.

  4. Default viscous_input = 1.0 fabricates χ = 1.0 m²/s at every surface, silently, straight into b_crit ∝ √P. Remove the default and error if unset.

Should fix

  • The "second local maximum" logic doesn't find local maxima (latent — never fired in my case). min_ΔQ = 0.001*|Qmax-Qmin| = 0.02, while grid spacing is 0.10 at the default n=200 (filter is a no-op, "second maximum" is the grid neighbour) and 0.010 at n=2000 (≥3 points away, still the same peak's flank). Broken at any resolution when it does fire. Sign change in the discrete derivative is a few lines. Related: pole detection uses exact index equality, and Q_e/Q_i are n=1 values so it degrades at n≥2.
  • Scan window is user-fixed but the branch is physics-set. Only [−Q_e, Q0] contributes (~17% of samples here), so most of n is wasted and a surface with Q0 outside [−10,10] silently under-resolves. Derive the window from (−Q_e, Q0) with margin.
  • File-header equation is wrong: it writes T_v = 2P(Q0−Q)/((S·κ̂)·(b_r/B_φ))² with S·κ̂ inside the square. Cole Eq. 61 is linear in S·κ̂, which is what the code implements.

Example is internally inconsistent

gpec.toml sets viscous_input_type = "magnetic_prandtl_number" with viscous_input = "test_ang_mom_diff" — a dataset named angular-momentum-diffusivity fed in as a Prandtl number. Values are 1.25–3.0: plausible as χ_φ (though it's a pointname inherited from ONETWO), implausible as P (the code's own P < 1 warning sits right next to it). Correct path gives P ≈ 33 at this case's η (7.5e-8 Ω·m) — about an order out, so ~3× in b_crit. The notebook confirms the round trip is broken: ang_mom_diff = P .* eta / (4π*1e-7) recovers ~0.1 m²/s, not the 1.25–3.0 fed in. If the validation figure in the PR body came from this deck, please re-run it before we treat it as validation.

Separately, test_ang_mom_diff was injected into TkMkr_D3Dlike_Hmode_kinetic.h5 — a test-prefixed dataset added to a file shared with the sibling ideal example, outside the documented kinetic schema.

Merge readiness

  • PR is CONFLICTING with develop; branch is 37 commits behind.
  • Regression report pinned at c42d558 is stale — re-run after conflicts are resolved.
  • CI "Title and release note" failing (4 runs).
  • No tests and no regression case for ~430 lines of new physics + workflow. Item 1 names the invariant most worth pinning.

Cleanup

  • All four new docstrings are detached — blank line between the closing """ and the definition (TorqueBalance, torque_balance_scan, CriticalResonantFieldResult, run_critical_resonant_field). Verified: @doc returns nothing. Invisible to ? and Documenter. torque_balance_value has none at all, and CriticalResonantField isn't in any @autodocs block.
  • store_scan is dead. Never read; scan_data is always populated and the writer gates only on !isempty, so the full Q/Δ/balance grid always lands in gpec.h5 (n=2000 in the example), contradicting both docstrings.
  • ASCII profile files crash: the error text advertises "HDF5 or ASCII table" but the viscous loader does an unconditional HDF5.h5open.
  • torque_balance_scan docstring mismatches code: documents an 8-tuple return (actual 6), a (model, params, Q0, P, lu, sval) signature (actual (tb;)), and n=200 (actual default 2000).
  • Abstract field types: viscous_input::Any, params::AbstractVector{<:InnerLayerParameters}, scan_data::Vector{NamedTuple}; the last also stores the whole params struct per surface.
  • combined_result = SLAYERResult(...) re-lists all 13 fields positionally; adding a field breaks it silently.
  • μ₀ hardcoded as 4π*1e-7 at run_slayer.jl:528 and :535 despite PhysicalConstants.jl (touched by this PR).
  • abs(chi_here) swallows negative/garbage input instead of erroring.
  • viscous_input has two undocumented semantics: array must be length nsurfaces (unknowable in advance), string resolves to a per-ψ interpolant.
  • Dead code in torque_balance_scan: positive recomputed as idx_maxima; maxima unused; isempty(selected) unreachable; maximum shadows Base; println should be @info.
  • Unused imports in the CriticalResonantField module: LinearAlgebra, StaticArrays, GGJModel, GGJParameters, SLAYERModel, SLAYERParameters.
  • critical_resonant_field_control_from_toml has a vestigial :inner_model branch for a nonexistent field; flat is a verbatim copy; unknown keys give an opaque kwarg MethodError.
  • HDF5: Qpeak/Q0/P aren't snake_case, and no new dataset is in the annotation table — br_crit ships with no units="T".

Hygiene

  • .gitignore adds src/Tearing/CriticalResonantField/CRF Dev/, a scratch dir inside the source tree.
  • ~1500 lines of trailing-whitespace stripping across 7 fixed-format coil .dat files, plus formatter churn in ~90 unrelated files. First-touch normalisation is expected, but at this scale splitting it into its own commit would make the diff reviewable.
  • Notebook: hardcoded Pkg.activate("/Users/bursche/Documents/GitHub/JPEC_BCRIT"); for i in 1:6 when the case has 5 surfaces (KeyError); using Plots/h5open without using HDF5; ad-hoc plotting when the last cell already uses Analysis.Equilibrium.plot_equilibrium_summary.
  • Typos: "eqution", "Cole PopP 2006" (x2, should be PoP), "resoant", "sufficent", "Prandlt".

Summary

Core calculation holds up better than expected: conventions consistent, branch lands where it should, α is a 4% effect. Before sign-off I'd want the item-1 test, κ̂, the example's viscous_input_type mismatch plus a re-run figure, and conflicts resolved with a fresh harness run. Cleanup can ride along.

Drafted with assistance from Claude Code; physics verified numerically against origin/feature/b_crit_calculation.

@logan-nc

logan-nc commented Sep 3, 2026

Copy link
Copy Markdown
Collaborator

Chiming in without having read all of the more thorough review 😝

ebursch and others added 2 commits October 6, 2026 11:05
Take develop's version of every file outside the critical resonant field
code: drops the formatter and whitespace churn, the edits to
ForceFreeStates files develop has reorganized, the notebook, the Cole
PDF, the test_ang_mom_diff kinetic dataset and the .gitignore entry.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…e on Cole's Q axis

solve_inner mirrors the real-Q axis, so the torque balance paired a mirrored
Δ with an unmirrored Q0 and put the diamagnetic poles at −Q_e, −Q_i. Map
back with conj(Δ(−Q)) so the branch lies between Q_e and Q0 as in Cole and
Fitzpatrick 2006 and Fortran gslayer.f. Replace the two-largest-samples
search with true local maxima, reject maxima within one grid step of a pole,
derive the scan window from Q0, Q_e, Q_i as gslayer.f does, and carry κ̂
explicitly (held at 2/s² for Fortran parity). Fix the header equation and
attach the docstrings.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
d-burg and others added 3 commits October 27, 2026 12:28
…ithout the removed pole exclusion

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…omparison with the total resonant field

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@d-burg
d-burg requested review from matt-pharr and removed request for d-burg October 27, 2026 18:07
…assumes

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@matt-pharr

matt-pharr commented Oct 28, 2026 •

Copy link
Copy Markdown
Collaborator

@d-burg @ebursch — I investigated the threshold selection using actual SLAYER responses. There is a reproducible case where the torque curves contain a saddle-node bifurcation of the higher-rotation equilibrium, but the current selector returns NaN for bcrit and reports smooth slowdown.

Reproducer

This uses the SLAYER layer parameters extracted from the DIII-D-like example's 3/1 surface, with Q₀ = 2 and α = 0.48. These are controlled changes to the rotation and outer stability input, not a self-consistent new equilibrium. The unmodified example does not exhibit this failure. The code tested was 263f190624231a50561ed804ae84550d88ae9dd6.

The net-torque curves show a saddle-node bifurcation at approximately:

  • Ω_E/(2π) = 4.24 kHz (Q ≈ 0.97236);
  • b_r^vac/B_φ = 2.54975 × 10⁻³.
net_torque_discharge_case2

In this plot, each curve holds the vacuum resonant driving field fixed. The rotation-dependent plasma response is included through Δ̂(Q); the penetrated field is not held fixed. The orange curve touches zero at the saddle-node bifurcation, and increasing the vacuum field removes the higher-rotation equilibrium.

A remaining lower-rotation equilibrium in the linear extrapolation does not rule out calling this the penetration threshold: loss of the shielded equilibrium can lead into nonlinear penetration physics. We should not require the linear calculation to predict exactly zero rotation.

Why the selector misses it

TorqueBalance.jl:110–115 constructs the retained path, takes a single global maximum, and accepts it only if it is interior and followed by a sufficient drop. It does not examine earlier local maxima when that global maximum is rejected.

For this case, the required vacuum field reaches the saddle-node value above, decreases, then turns upward again at lower rotation. The last retained sample, at Q ≈ 0.55345, requires b_r^vac/B_φ ≈ 2.55037 × 10⁻³—slightly more than the earlier local maximum. Consequently:

  1. argmax(bal[path]) selects the last retained sample.
  2. 1 < j < length(path) fails.
  3. idx remains zero, and the routine returns NaN without evaluating the earlier saddle-node bifurcation.

The earlier local maximum is followed by a 5.77% drop in the field-squared balance, comfortably above the existing 0.1% criterion. It also survives the mask: |Δ̂|/α ≈ 2.50 there. The warning that the required field “rises monotonically” is therefore incorrect for this curve.

Validation and suggested correction

The failure occurs at the default 2,000 samples and persists at 32,000 samples, with solver tolerances tightened to 10⁻¹³ and with integration-boundary checks. These calculations ran on SDCC through Slurm. A separate case keeps the example's original rotation and changes only α to 0.3; it exhibits the same rejection mechanism.

The selector needs to identify the first resolved saddle-node bifurcation on the stable branch followed from Q₀, rather than requiring the global maximum over every retained equilibrium to be interior. Candidate extrema still need a significance/convergence check so solver noise does not become a threshold; simply taking the first raw sample-to-sample maximum would not be sufficient. The warning should also distinguish failure to identify a threshold from a verified absence of a saddle-node bifurcation.

A diagnostic selection on the saved data recovers both counterexamples and preserves the unmodified example's 3/1 threshold to sampling accuracy. No production source changes have been made. This diagnoses the selection failure; it does not independently establish that the |Δ̂| > α cutoff is physically wrong.

d-burg and others added 2 commits October 28, 2026 11:22
@d-burg

d-burg commented Oct 28, 2026

Copy link
Copy Markdown
Collaborator

@matt-pharr thanks, confirmed and fixed in 753986fd1 (with develop merged at da6926142). The selector now follows the branch from Q0 and takes the first running maximum that the balance then falls more than 0.1 % below, the same significance test as before, instead of the global maximum.

Case (3/1 layer of the example) samples before after
Q0 = 2, α = 0.48 (yours: 2.54975e-3 at Q ≈ 0.972) 2 000 NaN 2.54986e-3 at Q = 0.974
32 000 NaN 2.54987e-3 at Q = 0.974
Example Q0, α = 0.3 2 000 NaN 1.35678e-3 at Q = 0.640
32 000 NaN 1.35679e-3 at Q = 0.641
Unmodified 3/1 2 000 1.40157e-3 at Q = 0.716 unchanged
Unmodified 4/1–7/1 2 000 NaN NaN

Values are b_r/B_φ. The warning now says no fold was resolved on the sampled path instead of claiming the curve rises monotonically. A stub test reproduces your shape (a fold, a dip, then a rise past the fold's height toward Q_e); the old rule returns NaN on it.

Would you be able to run the harness on #415, #441 and #489 against develop 057c4af0d? Heads: #489 a319ed295, #441 a0305d167, #415 da6926142.

@matt-pharr

Copy link
Copy Markdown
Collaborator

On it @d-burg

@matt-pharr

Copy link
Copy Markdown
Collaborator

@d-burg — completed the requested full SDCC fanout comparison against develop 057c4af0d, testing PR head da6926142 on 2026-10-28.

Result: no changes in comparable quantities; harness exit code 0.

  • 18 cases are entirely unchanged.
  • diiid_slayer_n1 and diiid_slayer_n1_chi_perp_e: all 17 existing quantities are unchanged in each. The four new CRF quantities are present on this head but absent on develop, so the report correctly marks them N/A for a cross-ref comparison. These are new outputs, not four failed runs.
  • gal_resistive_pe: all eight quantities are missing on both refs. It supplies no numerical validation.
  • This full harness run checks the shipped cases; it does not replace the focused saddle-node bifurcation counterexample tests discussed above.

Environment: Julia 1.12.6, x86_64 Linux, CI manifest pin 4c9d54fa, partition sirius. There were 21 cases / 42 per-ref tasks. Each case used the same allocation at both refs: 2 Julia threads / 1 BLAS thread normally, and 16 / 8 for diiid_error_field. The precompiled Riccati case was compared in its precompiled build at both refs. Each PR head's own harness case definitions were used.

./regress_fanout.sh --refs 057c4af0d,da6926142 --harness-ref da6926142 --name pr415_da6926142_vs_057c4af0d_20261028

SDCC report: /home/ITER/pharrm/Projects/GPEC_dev/regress-fanout/runs/pr415_da6926142_vs_057c4af0d_20261028/report.txt; report job 1298986.

Full regression report (21 cases)

================================================================
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: 057c4af0d  @ 057c4af0d (2026-10-28)
       env: julia 1.12.6, x86_64-linux-gnu, manifest 4c9d54fa (pinned), 16 threads/8 BLAS, jit build
Ref 2: da6926142  @ da6926142 (2026-10-28)
       env: julia 1.12.6, x86_64-linux-gnu, manifest 4c9d54fa (pinned), 16 threads/8 BLAS, jit build
--------------------------------------------------------------------------------------------
Quantity                                         057c4af0d     da6926142     Diff     Status
--------------------------------------------------------------------------------------------
EFC overlap per kAt                              [1 elem]      [1 elem]      0.0e+00  OK    
EFC whole-field NTV torque per kAt² [N·m]        [1 elem]      [1 elem]      0.0e+00  OK    
EFC residual-field NTV torque per kAt² [N·m]     [1 elem]      [1 elem]      0.0e+00  OK    
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]      0.0e+00  OK    
dominant-coupling singular values                [3 elem]      [3 elem]      0.0e+00  OK    
|delta_nominal| of coil set 1                    1.406930e-06  1.406930e-06  0.0e+00  OK    
|Σ δ_as_designed| of the error-field coils       1.358875e-18  1.358875e-18  0.0e+00  OK    
Monte Carlo mean |δ| of the error-field coils    4.701300e-05  4.701300e-05  0.0e+00  OK    
Runtime (s)                                      264.0s        248.5s                 --    
============================================================================================
Summary: 10 unchanged


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

Regression Report: diiid_multi_n
=================================================================================================================
Ref 1: 057c4af0d  @ 057c4af0d (2026-10-28)
       env: julia 1.12.6, x86_64-linux-gnu, manifest 4c9d54fa (pinned), 2 threads/1 BLAS, jit build
Ref 2: da6926142  @ da6926142 (2026-10-28)
       env: julia 1.12.6, x86_64-linux-gnu, manifest 4c9d54fa (pinned), 2 threads/1 BLAS, jit build
-----------------------------------------------------------------------------------------------------------------
Quantity                                                      057c4af0d        da6926142        Diff       Status
-----------------------------------------------------------------------------------------------------------------
total energy Re(et[1])                                        -5.750527e-01    -5.750527e-01    0.0e+00    OK    
total energy (all)                                            [58 elem]        [58 elem]        0.0e+00    OK    
ODE steps (saved)                                             628              628              0.0e+00    OK    
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]        0.0e+00    OK    
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]        0.0e+00    OK    
PE plasma energy (sum over n)                                 2.936559e+00     2.936559e+00     0.0e+00    OK    
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.523427e+00     0.0e+00    OK    
PE toroidal torque sum_n -2n Im(Phi_n' Lambda_nn^-1 Phi_n)/4  1.820337e-06     1.820337e-06     0.0e+00    OK    
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]         0.0e+00    OK    
island half-widths per row                                    [7 elem]         [7 elem]         0.0e+00    OK    
Chirikov parameter per row                                    [7 elem]         [7 elem]         0.0e+00    OK    
forcing-driven Delta' per row                                 [7 elem]         [7 elem]         0.0e+00    OK    
Runtime (s)                                                   191.4s           193.5s                      --    
=================================================================================================================
Summary: 19 unchanged


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

Regression Report: diiid_n1
=================================================================================================
Ref 1: 057c4af0d  @ 057c4af0d (2026-10-28)
       env: julia 1.12.6, x86_64-linux-gnu, manifest 4c9d54fa (pinned), 2 threads/1 BLAS, jit build
Ref 2: da6926142  @ da6926142 (2026-10-28)
       env: julia 1.12.6, x86_64-linux-gnu, manifest 4c9d54fa (pinned), 2 threads/1 BLAS, jit build
-------------------------------------------------------------------------------------------------
Quantity                                      057c4af0d        da6926142        Diff       Status
-------------------------------------------------------------------------------------------------
total energy Re(et[1])                        8.006122e-01     8.006122e-01     0.0e+00    OK    
total energy Im(et[1])                        7.924882e-05     7.924882e-05     0.0e+00    OK    
plasma energy Re(ep[1])                       -1.372261e+00    -1.372261e+00    0.0e+00    OK    
vacuum energy Re(ev[1])                       2.172874e+00     2.172874e+00     0.0e+00    OK    
vacuum matrix min eigenvalue                  1.873975e-01     1.873975e-01     0.0e+00    OK    
plasma energy (all)                           [35 elem]        [35 elem]        0.0e+00    OK    
vacuum energy (all)                           [35 elem]        [35 elem]        0.0e+00    OK    
total energy (all)                            [35 elem]        [35 elem]        0.0e+00    OK    
ODE steps (saved)                             788              788              0.0e+00    OK    
ODE steps (total)                             783              783              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_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]         0.0e+00    OK    
Chirikov parameter                            [5 elem]         [5 elem]         0.0e+00    OK    
||resonant area-weighted field||              5.288412e-04     5.288412e-04     0.0e+00    OK    
dominant-coupling singular values             [3 elem]         [3 elem]         0.0e+00    OK    
|forcing overlap with dominant mode|          1.411553e-04     1.411553e-04     0.0e+00    OK    
|delta_nominal| of coil set 1                 7.034649e-05     7.034649e-05     0.0e+00    OK    
||ddelta/d(shift)|| over coil sets            1.245448e-04     1.245448e-04     0.0e+00    OK    
||ddelta/d(tilt)|| over coil sets             4.177341e-07     4.177341e-07     0.0e+00    OK    
PE plasma energy                              3.320466e+00     3.320466e+00     0.0e+00    OK    
PE vacuum energy                              3.174319e+00     3.174319e+00     0.0e+00    OK    
PE surface energy                             5.508585e+00     5.508585e+00     0.0e+00    OK    
PE toroidal torque                            1.119354e-04     1.119354e-04     0.0e+00    OK    
NTV torque FGAR [N·m]                         5.480614e-01     5.480614e-01     0.0e+00    OK    
NTV kinetic energy dW FGAR [J]                8.163291e-02     8.163291e-02     0.0e+00    OK    
Runtime (s)                                   235.8s           236.2s                      --    
||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]         0.0e+00    OK    
=================================================================================================
Summary: 53 unchanged


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

Regression Report: diiid_n1_riccati
============================================================================
Ref 1: 057c4af0d  @ 057c4af0d (2026-10-28)
       env: julia 1.12.6, x86_64-linux-gnu, manifest 4c9d54fa (pinned), 2 threads/1 BLAS, jit build
Ref 2: da6926142  @ da6926142 (2026-10-28)
       env: julia 1.12.6, x86_64-linux-gnu, manifest 4c9d54fa (pinned), 2 threads/1 BLAS, jit build
----------------------------------------------------------------------------
Quantity                       057c4af0d      da6926142      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)              93             93             0.0e+00  OK    
ODE steps (total)              2631           2631           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)                    194.9s         194.9s                  --    
============================================================================
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: 057c4af0d  @ 057c4af0d (2026-10-28)
       env: julia 1.12.6, x86_64-linux-gnu, manifest 4c9d54fa (pinned), 2 threads/1 BLAS, aot build
Ref 2: da6926142  @ da6926142 (2026-10-28)
       env: julia 1.12.6, x86_64-linux-gnu, manifest 4c9d54fa (pinned), 2 threads/1 BLAS, aot build
----------------------------------------------------------------------------
Quantity                       057c4af0d      da6926142      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)              93             93             0.0e+00  OK    
ODE steps (total)              2631           2631           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)                    27.2s          26.4s                   --    
============================================================================
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: 057c4af0d  @ 057c4af0d (2026-10-28)
       env: julia 1.12.6, x86_64-linux-gnu, manifest 4c9d54fa (pinned), 2 threads/1 BLAS, jit build
Ref 2: da6926142  @ da6926142 (2026-10-28)
       env: julia 1.12.6, x86_64-linux-gnu, manifest 4c9d54fa (pinned), 2 threads/1 BLAS, jit build
--------------------------------------------------------------------------
Quantity                             057c4af0d  da6926142  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]       N/A        [3 elem]   N/A      N/A   
CRF Q_peak [2/1,3/1,4/1]             N/A        [3 elem]   N/A      N/A   
CRF Q0 [2/1,3/1,4/1]                 N/A        [3 elem]   N/A      N/A   
CRF b_r crit in tesla [2/1,3/1,4/1]  N/A        [3 elem]   N/A      N/A   
SLAYER enabled flag                  1          1          0.0e+00  OK    
Runtime (s)                          224.7s     236.8s              --    
==========================================================================
Summary: 17 unchanged, 4 missing/N/A


================================================================
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: 057c4af0d  @ 057c4af0d (2026-10-28)
       env: julia 1.12.6, x86_64-linux-gnu, manifest 4c9d54fa (pinned), 2 threads/1 BLAS, jit build
Ref 2: da6926142  @ da6926142 (2026-10-28)
       env: julia 1.12.6, x86_64-linux-gnu, manifest 4c9d54fa (pinned), 2 threads/1 BLAS, jit build
--------------------------------------------------------------------------
Quantity                             057c4af0d  da6926142  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]       N/A        [3 elem]   N/A      N/A   
CRF Q_peak [2/1,3/1,4/1]             N/A        [3 elem]   N/A      N/A   
CRF Q0 [2/1,3/1,4/1]                 N/A        [3 elem]   N/A      N/A   
CRF b_r crit in tesla [2/1,3/1,4/1]  N/A        [3 elem]   N/A      N/A   
SLAYER enabled flag                  1          1          0.0e+00  OK    
Runtime (s)                          232.2s     239.0s              --    
==========================================================================
Summary: 17 unchanged, 4 missing/N/A


================================================================
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: 057c4af0d  @ 057c4af0d (2026-10-28)
       env: julia 1.12.6, x86_64-linux-gnu, manifest 4c9d54fa (pinned), 2 threads/1 BLAS, jit build
Ref 2: da6926142  @ da6926142 (2026-10-28)
       env: julia 1.12.6, x86_64-linux-gnu, manifest 4c9d54fa (pinned), 2 threads/1 BLAS, jit build
------------------------------------------------------------------
Quantity                     057c4af0d  da6926142  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)                  238.3s     248.2s              --    
==================================================================
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: 057c4af0d  @ 057c4af0d (2026-10-28)
       env: julia 1.12.6, x86_64-linux-gnu, manifest 4c9d54fa (pinned), 2 threads/1 BLAS, jit build
Ref 2: da6926142  @ da6926142 (2026-10-28)
       env: julia 1.12.6, x86_64-linux-gnu, manifest 4c9d54fa (pinned), 2 threads/1 BLAS, jit build
------------------------------------------------------------------------------------
Quantity                               057c4af0d      da6926142      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.372379e+00  0.0e+00  OK    
total energy Re(et[1])                 8.005437e-01   8.005437e-01   0.0e+00  OK    
Runtime (s)                            197.1s         196.0s                  --    
====================================================================================
Summary: 12 unchanged


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

Regression Report: efit_fixedbdy_separatrix
=======================================================================
Ref 1: 057c4af0d  @ 057c4af0d (2026-10-28)
       env: julia 1.12.6, x86_64-linux-gnu, manifest 4c9d54fa (pinned), 2 threads/1 BLAS, jit build
Ref 2: da6926142  @ da6926142 (2026-10-28)
       env: julia 1.12.6, x86_64-linux-gnu, manifest 4c9d54fa (pinned), 2 threads/1 BLAS, jit build
-----------------------------------------------------------------------
Quantity                    057c4af0d     da6926142     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)                 47.2s         47.2s                  --    
=======================================================================
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: 057c4af0d  @ 057c4af0d (2026-10-28)
       env: julia 1.12.6, x86_64-linux-gnu, manifest 4c9d54fa (pinned), 2 threads/1 BLAS, jit build
Ref 2: da6926142  @ da6926142 (2026-10-28)
       env: julia 1.12.6, x86_64-linux-gnu, manifest 4c9d54fa (pinned), 2 threads/1 BLAS, jit build
--------------------------------------------------------------------
Quantity                 057c4af0d     da6926142     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.709610e-16  1.709610e-16  0.0e+00  OK    
Runtime (s)              192.9s        192.6s                 --    
====================================================================
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: 057c4af0d  @ 057c4af0d (2026-10-28)
       env: julia 1.12.6, x86_64-linux-gnu, manifest 4c9d54fa (pinned), 2 threads/1 BLAS, jit build
Ref 2: da6926142  @ da6926142 (2026-10-28)
       env: julia 1.12.6, x86_64-linux-gnu, manifest 4c9d54fa (pinned), 2 threads/1 BLAS, jit build
--------------------------------------------------------------------
Quantity                 057c4af0d     da6926142     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       1.872671e-16  1.872671e-16  0.0e+00  OK    
Runtime (s)              192.7s        191.1s                 --    
====================================================================
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: 057c4af0d  @ 057c4af0d (2026-10-28)
       env: julia 1.12.6, x86_64-linux-gnu, manifest 4c9d54fa (pinned), 2 threads/1 BLAS, jit build
Ref 2: da6926142  @ da6926142 (2026-10-28)
       env: julia 1.12.6, x86_64-linux-gnu, manifest 4c9d54fa (pinned), 2 threads/1 BLAS, jit build
----------------------------------------------------------
Quantity                057c4af0d  da6926142  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)             193.2s     192.9s           --    
==========================================================
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: 057c4af0d  @ 057c4af0d (2026-10-28)
       env: julia 1.12.6, x86_64-linux-gnu, manifest 4c9d54fa (pinned), 2 threads/1 BLAS, jit build
Ref 2: da6926142  @ da6926142 (2026-10-28)
       env: julia 1.12.6, x86_64-linux-gnu, manifest 4c9d54fa (pinned), 2 threads/1 BLAS, jit build
---------------------------------------------------------------
Quantity            057c4af0d     da6926142     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)         21.8s         21.9s                  --    
===============================================================
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: 057c4af0d  @ 057c4af0d (2026-10-28)
       env: julia 1.12.6, x86_64-linux-gnu, manifest 4c9d54fa (pinned), 2 threads/1 BLAS, jit build
Ref 2: da6926142  @ da6926142 (2026-10-28)
       env: julia 1.12.6, x86_64-linux-gnu, manifest 4c9d54fa (pinned), 2 threads/1 BLAS, jit build
-----------------------------------------------------------------
Quantity            057c4af0d      da6926142      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)         10.4s          10.3s                   --    
=================================================================
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: 057c4af0d  @ 057c4af0d (2026-10-28)
       env: julia 1.12.6, x86_64-linux-gnu, manifest 4c9d54fa (pinned), 2 threads/1 BLAS, jit build
Ref 2: da6926142  @ da6926142 (2026-10-28)
       env: julia 1.12.6, x86_64-linux-gnu, manifest 4c9d54fa (pinned), 2 threads/1 BLAS, jit build
--------------------------------------------------------------------------------
Quantity                           057c4af0d      da6926142      Diff     Status
--------------------------------------------------------------------------------
vacuum energy Re(ev[1])            1.054739e+01   1.054739e+01   0.0e+00  OK    
q0                                 1.900003e+00   1.900003e+00   0.0e+00  OK    
NTV fgar quadrature torque [N·m]   2.267351e-03   2.267351e-03   0.0e+00  OK    
||xi_clebsch_alpha||               6.041963e-01   6.041963e-01   0.0e+00  OK    
total energy Re(et[1])             1.828278e+00   1.828278e+00   0.0e+00  OK    
total energy Im(et[1])             -1.326607e+00  -1.326607e+00  0.0e+00  OK    
plasma energy Re(ep[1])            -8.719112e+00  -8.719112e+00  0.0e+00  OK    
ODE steps (saved)                  608            608            0.0e+00  OK    
# singular surfaces                2              2              0.0e+00  OK    
boundary-response torque [N·m]     2.285518e-03   2.285518e-03   0.0e+00  OK    
singular psi locations             [2 elem]       [2 elem]       0.0e+00  OK    
total energy (all)                 [32 elem]      [32 elem]      0.0e+00  OK    
ODE steps (total)                  607            607            0.0e+00  OK    
mpert                              32             32             0.0e+00  OK    
q95                                3.147422e+00   3.147422e+00   0.0e+00  OK    
||Jb_theta_reg||                   3.945600e-03   3.945600e-03   0.0e+00  OK    
Runtime (s)                        234.0s         236.1s                  --    
T_xe applied-forcing torque [N·m]  2.285518e-03   2.285518e-03   0.0e+00  OK    
||dxi_clebsch_psi/dpsi||           3.791914e+00   3.791914e+00   0.0e+00  OK    
singular q values                  [2 elem]       [2 elem]       0.0e+00  OK    
npert                              1              1              0.0e+00  OK    
================================================================================
Summary: 20 unchanged


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

Regression Report: solovev_kinetic_multiion
==========================================================================
Ref 1: 057c4af0d  @ 057c4af0d (2026-10-28)
       env: julia 1.12.6, x86_64-linux-gnu, manifest 4c9d54fa (pinned), 2 threads/1 BLAS, jit build
Ref 2: da6926142  @ da6926142 (2026-10-28)
       env: julia 1.12.6, x86_64-linux-gnu, manifest 4c9d54fa (pinned), 2 threads/1 BLAS, jit build
--------------------------------------------------------------------------
Quantity                     057c4af0d      da6926142      Diff     Status
--------------------------------------------------------------------------
NTV total (D+T+imp+e) [N·m]  3.141767e+01   3.141767e+01   0.0e+00  OK    
NTV Deuterium [N·m]          1.973730e+01   1.973730e+01   0.0e+00  OK    
NTV Tritium [N·m]            2.046293e+01   2.046293e+01   0.0e+00  OK    
NTV electron [N·m]           -8.782557e+00  -8.782557e+00  0.0e+00  OK    
total energy Re(et[1])       1.090560e-02   1.090560e-02   0.0e+00  OK    
# singular surfaces          2              2              0.0e+00  OK    
Runtime (s)                  229.9s         225.9s                  --    
==========================================================================
Summary: 6 unchanged


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

Regression Report: solovev_kinetic_ntv
======================================================================================
Ref 1: 057c4af0d  @ 057c4af0d (2026-10-28)
       env: julia 1.12.6, x86_64-linux-gnu, manifest 4c9d54fa (pinned), 2 threads/1 BLAS, jit build
Ref 2: da6926142  @ da6926142 (2026-10-28)
       env: julia 1.12.6, x86_64-linux-gnu, manifest 4c9d54fa (pinned), 2 threads/1 BLAS, jit build
--------------------------------------------------------------------------------------
Quantity                                   057c4af0d     da6926142     Diff     Status
--------------------------------------------------------------------------------------
NTV torque fgar [Re, Im]                   [1 elem]      [1 elem]      0.0e+00  OK    
NTV ψ quadrature evaluations               45            45            0.0e+00  OK    
fluid CGL energy fcgl [J]                  1.552303e+01  1.552303e+01  0.0e+00  OK    
root-area-weighted total energy Re(et[1])  1.090560e-02  1.090560e-02  0.0e+00  OK    
# 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)                                226.5s        226.3s                 --    
======================================================================================
Summary: 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 Report: solovev_kinetic_nuzero
======================================================================
Ref 1: 057c4af0d  @ 057c4af0d (2026-10-28)
       env: julia 1.12.6, x86_64-linux-gnu, manifest 4c9d54fa (pinned), 2 threads/1 BLAS, jit build
Ref 2: da6926142  @ da6926142 (2026-10-28)
       env: julia 1.12.6, x86_64-linux-gnu, manifest 4c9d54fa (pinned), 2 threads/1 BLAS, jit build
----------------------------------------------------------------------
Quantity                 057c4af0d      da6926142      Diff     Status
----------------------------------------------------------------------
vacuum energy Re(ev[1])  1.058613e+01   1.058613e+01   0.0e+00  OK    
q0                       1.900003e+00   1.900003e+00   0.0e+00  OK    
total energy Re(et[1])   2.290965e+00   2.290965e+00   0.0e+00  OK    
total energy Im(et[1])   -1.564546e+00  -1.564546e+00  0.0e+00  OK    
plasma energy Re(ep[1])  -8.295163e+00  -8.295163e+00  0.0e+00  OK    
ODE steps (saved)        608            608            0.0e+00  OK    
# 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]      0.0e+00  OK    
ODE steps (total)        607            607            0.0e+00  OK    
mpert                    32             32             0.0e+00  OK    
q95                      3.147422e+00   3.147422e+00   0.0e+00  OK    
Runtime (s)              234.2s         234.5s                  --    
singular q values        [2 elem]       [2 elem]       0.0e+00  OK    
npert                    1              1              0.0e+00  OK    
======================================================================
Summary: 14 unchanged


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

Regression Report: solovev_multi_n
=================================================================================
Ref 1: 057c4af0d  @ 057c4af0d (2026-10-28)
       env: julia 1.12.6, x86_64-linux-gnu, manifest 4c9d54fa (pinned), 2 threads/1 BLAS, jit build
Ref 2: da6926142  @ da6926142 (2026-10-28)
       env: julia 1.12.6, x86_64-linux-gnu, manifest 4c9d54fa (pinned), 2 threads/1 BLAS, jit build
---------------------------------------------------------------------------------
Quantity                      057c4af0d        da6926142        Diff       Status
---------------------------------------------------------------------------------
total energy Re(et[1])        -2.134718e+00    -2.134718e+00    0.0e+00    OK    
total energy Im(et[1])        1.968592e-10     1.968592e-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)                   201.9s           201.7s                      --    
=================================================================================
Summary: 15 unchanged


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

Regression Report: solovev_n1
=================================================================================
Ref 1: 057c4af0d  @ 057c4af0d (2026-10-28)
       env: julia 1.12.6, x86_64-linux-gnu, manifest 4c9d54fa (pinned), 2 threads/1 BLAS, jit build
Ref 2: da6926142  @ da6926142 (2026-10-28)
       env: julia 1.12.6, x86_64-linux-gnu, manifest 4c9d54fa (pinned), 2 threads/1 BLAS, jit build
---------------------------------------------------------------------------------
Quantity                      057c4af0d        da6926142        Diff       Status
---------------------------------------------------------------------------------
total energy Re(et[1])        1.090560e-02     1.090560e-02     0.0e+00    OK    
total energy Im(et[1])        1.350301e-10     1.350301e-10     0.0e+00    OK    
plasma energy Re(ep[1])       -1.041640e+01    -1.041640e+01    0.0e+00    OK    
vacuum energy Re(ev[1])       1.042730e+01     1.042730e+01     0.0e+00    OK    
vacuum matrix min eigenvalue  2.170703e+00     2.170703e+00     0.0e+00    OK    
plasma energy (all)           [32 elem]        [32 elem]        0.0e+00    OK    
vacuum energy (all)           [32 elem]        [32 elem]        0.0e+00    OK    
total energy (all)            [32 elem]        [32 elem]        0.0e+00    OK    
ODE steps (saved)             287              287              0.0e+00    OK    
ODE steps (total)             285              285              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    
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)            b7a5bbc5f549...  b7a5bbc5f549...  identical  OK    
Runtime (s)                   206.2s           213.2s                      --    
=================================================================================
Summary: 22 unchanged

Third-party human review and approval are required before merge.

…om Q0

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@d-burg

d-burg commented Oct 28, 2026

Copy link
Copy Markdown
Collaborator

@logan-nc, the port is on the branch now, and this answers your question 2; @matt-pharr is reviewing it. It went in at 6d0c7dd7c, rebased onto develop and joined to the old head by a merge commit, so the earlier history is kept and the diff against develop is the port alone. Since then @matt-pharr and I have merged develop (d01c99346), b873f5e58 brings the docs' Fortran-benchmark paragraph in line with the new selection rule, 5d1079d52 adds the tesla output, 263f19062 states in the docs what including Δ_crit in α assumes, 753986fd1 fixes the fold selection @matt-pharr found (above; develop merged at da6926142), and d965973d9 updates the docs to match. Compared with d3692274d:

  • TORQUE_BALANCE_ALPHA = 1e-2 is gone; each surface uses its own α = S^(−1/3)(Δ_crit − r_s Δ′).
  • The global argmax is replaced by the first saddle-node on the branch followed from Q0 toward Q_e: the first maximum the balance then drops more than 0.1 % below.
  • A missing omega_E is no longer zero-filled: the run stops if no surface has one, and skips a surface without one.
  • run_slayer_from_inputs returns the computed critical field.

The description is rewritten for the port. Tests pass (49 in the critical-resonant-field file) and CI is green. @matt-pharr's harness against develop 057c4af0d leaves every existing quantity unchanged, with the four new pins N/A on develop.

On question 2, thanks for checking the Fortran. I've added br_crit_tesla = (b_r/B_φ)·|B0|, with the layer's own B0, for comparison with resonant_area_weighted_field; the reviewer notes in the description give the references and the caveat.

@matt-pharr

Copy link
Copy Markdown
Collaborator

@d-burg — the original counterexamples are addressed, but I found one additional selector edge case that I’d like corrected before approval.

I checked this against the actual Julia function at da69261 on SDCC, using the same discharge-derived 3/1 layer with Q0 = 2, alpha = 0.48, and:

torque_balance_scan(tb; Qmin=0.9, Qmax=0.75, n=401)

The sampled balance is strictly decreasing throughout this interval, yet the routine returns:

Q_peak = 0.892910447761194
bcrit = 0.0025415228559857164

The balance values immediately around the selected point are:

36.73998060, 36.73751588, 36.73533196

There is no interior maximum or saddle-node bifurcation in this window.

The cause appears to be the running-maximum reset: after a sufficiently large fall from the first sample, peak is reset to a descending point. A subsequent fall then accepts that point because it is no longer path[1], even though the curve never rose to it.

I am going to implement a change for this and then approve this PR.

@d-burg

d-burg commented Oct 28, 2026

Copy link
Copy Markdown
Collaborator

@matt-pharr good catch, I was still worried that the patch I put in wasn't exhaustive, looks like the restart after a fall from the first sample let a purely descending curve report a peak. Requiring the balance to have risen to the maximum before a drop counts closes it. Thanks for the fix. Do you think the selection logic is in a place that makes sense re: the physics, or have we possibly built ourselves into a corner here?

Reject monotonic clipped windows and subthreshold bumps by requiring a significant rise and fall around an interior maximum. Reset the search across excluded samples and retain the first resolved saddle-node bifurcation. Add regression coverage and document the selection criterion.
@matt-pharr

Copy link
Copy Markdown
Collaborator

@d-burg — completed the requested full SDCC fanout against develop 7817f0e7a, testing head 3a6435d60.

Result: no changes in comparable quantities; harness exit code 0.

This tests the actual PR branch after the selector correction and develop merge, at 3a6435d60.

  • 18 cases are entirely unchanged.
  • diiid_slayer_n1 and diiid_slayer_n1_chi_perp_e: all 17 existing quantities are unchanged in each. Four new CRF quantities in each case are present on the PR but absent from develop, so their cross-ref comparison is N/A.
  • gal_resistive_pe: all eight quantities are missing on both refs and provide no numerical validation.
  • Separately, the selector suite passed 71/71 assertions on Julia 1.11.7 and 1.12.6. Actual SLAYER checks reject the monotonic clipped window in both grid directions while preserving the original 3/1 threshold and both genuine saddle-node bifurcation cases at 2,000 and 32,000 samples. Those focused checks complement the full harness; they are not inferred from the N/A rows.

Environment: Julia 1.12.6, x86_64 Linux, CI manifest 4c9d54fa pinned at both refs, partition sirius. 21 cases / 42 tasks. Matching allocations at each ref: 2 Julia threads / 1 BLAS thread normally; diiid_error_field uses 16 / 8. The precompiled Riccati case was compared in the same build mode at both refs. Each PR's own harness case definitions were used.

./regress_fanout.sh --refs 7817f0e7a,3a6435d60 --harness-ref 3a6435d60 --name pr415_3a6435d60_vs_7817f0e7a_20261028

SDCC report: /home/ITER/pharrm/Projects/GPEC_dev/regress-fanout/runs/pr415_3a6435d60_vs_7817f0e7a_20261028/report.txt; report job 1299357.

Full regression report (21 cases)

================================================================
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: 7817f0e7a  @ 7817f0e7a (2026-10-28)
       env: julia 1.12.6, x86_64-linux-gnu, manifest 4c9d54fa (pinned), 16 threads/8 BLAS, jit build
Ref 2: 3a6435d60  @ 3a6435d60 (2026-10-28)
       env: julia 1.12.6, x86_64-linux-gnu, manifest 4c9d54fa (pinned), 16 threads/8 BLAS, jit build
--------------------------------------------------------------------------------------------
Quantity                                         7817f0e7a     3a6435d60     Diff     Status
--------------------------------------------------------------------------------------------
EFC overlap per kAt                              [1 elem]      [1 elem]      0.0e+00  OK    
EFC whole-field NTV torque per kAt² [N·m]        [1 elem]      [1 elem]      0.0e+00  OK    
EFC residual-field NTV torque per kAt² [N·m]     [1 elem]      [1 elem]      0.0e+00  OK    
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]      0.0e+00  OK    
dominant-coupling singular values                [3 elem]      [3 elem]      0.0e+00  OK    
|delta_nominal| of coil set 1                    1.406930e-06  1.406930e-06  0.0e+00  OK    
|Σ δ_as_designed| of the error-field coils       1.358875e-18  1.358875e-18  0.0e+00  OK    
Monte Carlo mean |δ| of the error-field coils    4.701300e-05  4.701300e-05  0.0e+00  OK    
Runtime (s)                                      252.9s        251.4s                 --    
============================================================================================
Summary: 10 unchanged


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

Regression Report: diiid_multi_n
=================================================================================================================
Ref 1: 7817f0e7a  @ 7817f0e7a (2026-10-28)
       env: julia 1.12.6, x86_64-linux-gnu, manifest 4c9d54fa (pinned), 2 threads/1 BLAS, jit build
Ref 2: 3a6435d60  @ 3a6435d60 (2026-10-28)
       env: julia 1.12.6, x86_64-linux-gnu, manifest 4c9d54fa (pinned), 2 threads/1 BLAS, jit build
-----------------------------------------------------------------------------------------------------------------
Quantity                                                      7817f0e7a        3a6435d60        Diff       Status
-----------------------------------------------------------------------------------------------------------------
total energy Re(et[1])                                        -5.750527e-01    -5.750527e-01    0.0e+00    OK    
total energy (all)                                            [58 elem]        [58 elem]        0.0e+00    OK    
ODE steps (saved)                                             628              628              0.0e+00    OK    
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]        0.0e+00    OK    
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]        0.0e+00    OK    
PE plasma energy (sum over n)                                 2.936559e+00     2.936559e+00     0.0e+00    OK    
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.523427e+00     0.0e+00    OK    
PE toroidal torque sum_n -2n Im(Phi_n' Lambda_nn^-1 Phi_n)/4  1.820337e-06     1.820337e-06     0.0e+00    OK    
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]         0.0e+00    OK    
island half-widths per row                                    [7 elem]         [7 elem]         0.0e+00    OK    
Chirikov parameter per row                                    [7 elem]         [7 elem]         0.0e+00    OK    
forcing-driven Delta' per row                                 [7 elem]         [7 elem]         0.0e+00    OK    
Runtime (s)                                                   194.5s           194.4s                      --    
=================================================================================================================
Summary: 19 unchanged


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

Regression Report: diiid_n1
=================================================================================================
Ref 1: 7817f0e7a  @ 7817f0e7a (2026-10-28)
       env: julia 1.12.6, x86_64-linux-gnu, manifest 4c9d54fa (pinned), 2 threads/1 BLAS, jit build
Ref 2: 3a6435d60  @ 3a6435d60 (2026-10-28)
       env: julia 1.12.6, x86_64-linux-gnu, manifest 4c9d54fa (pinned), 2 threads/1 BLAS, jit build
-------------------------------------------------------------------------------------------------
Quantity                                      7817f0e7a        3a6435d60        Diff       Status
-------------------------------------------------------------------------------------------------
total energy Re(et[1])                        8.006122e-01     8.006122e-01     0.0e+00    OK    
total energy Im(et[1])                        7.924882e-05     7.924882e-05     0.0e+00    OK    
plasma energy Re(ep[1])                       -1.372261e+00    -1.372261e+00    0.0e+00    OK    
vacuum energy Re(ev[1])                       2.172874e+00     2.172874e+00     0.0e+00    OK    
vacuum matrix min eigenvalue                  1.873975e-01     1.873975e-01     0.0e+00    OK    
plasma energy (all)                           [35 elem]        [35 elem]        0.0e+00    OK    
vacuum energy (all)                           [35 elem]        [35 elem]        0.0e+00    OK    
total energy (all)                            [35 elem]        [35 elem]        0.0e+00    OK    
ODE steps (saved)                             788              788              0.0e+00    OK    
ODE steps (total)                             783              783              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_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]         0.0e+00    OK    
Chirikov parameter                            [5 elem]         [5 elem]         0.0e+00    OK    
||resonant area-weighted field||              5.288412e-04     5.288412e-04     0.0e+00    OK    
dominant-coupling singular values             [3 elem]         [3 elem]         0.0e+00    OK    
|forcing overlap with dominant mode|          1.411553e-04     1.411553e-04     0.0e+00    OK    
|delta_nominal| of coil set 1                 7.034649e-05     7.034649e-05     0.0e+00    OK    
||ddelta/d(shift)|| over coil sets            1.245448e-04     1.245448e-04     0.0e+00    OK    
||ddelta/d(tilt)|| over coil sets             4.177341e-07     4.177341e-07     0.0e+00    OK    
PE plasma energy                              3.320466e+00     3.320466e+00     0.0e+00    OK    
PE vacuum energy                              3.174319e+00     3.174319e+00     0.0e+00    OK    
PE surface energy                             5.508585e+00     5.508585e+00     0.0e+00    OK    
PE toroidal torque                            1.119354e-04     1.119354e-04     0.0e+00    OK    
NTV torque FGAR [N·m]                         5.480614e-01     5.480614e-01     0.0e+00    OK    
NTV kinetic energy dW FGAR [J]                8.163291e-02     8.163291e-02     0.0e+00    OK    
Runtime (s)                                   233.5s           236.1s                      --    
||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]         0.0e+00    OK    
=================================================================================================
Summary: 53 unchanged


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

Regression Report: diiid_n1_riccati
============================================================================
Ref 1: 7817f0e7a  @ 7817f0e7a (2026-10-28)
       env: julia 1.12.6, x86_64-linux-gnu, manifest 4c9d54fa (pinned), 2 threads/1 BLAS, jit build
Ref 2: 3a6435d60  @ 3a6435d60 (2026-10-28)
       env: julia 1.12.6, x86_64-linux-gnu, manifest 4c9d54fa (pinned), 2 threads/1 BLAS, jit build
----------------------------------------------------------------------------
Quantity                       7817f0e7a      3a6435d60      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)              93             93             0.0e+00  OK    
ODE steps (total)              2631           2631           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)                    190.5s         201.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: 7817f0e7a  @ 7817f0e7a (2026-10-28)
       env: julia 1.12.6, x86_64-linux-gnu, manifest 4c9d54fa (pinned), 2 threads/1 BLAS, aot build
Ref 2: 3a6435d60  @ 3a6435d60 (2026-10-28)
       env: julia 1.12.6, x86_64-linux-gnu, manifest 4c9d54fa (pinned), 2 threads/1 BLAS, aot build
----------------------------------------------------------------------------
Quantity                       7817f0e7a      3a6435d60      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)              93             93             0.0e+00  OK    
ODE steps (total)              2631           2631           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)                    25.6s          25.5s                   --    
============================================================================
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: 7817f0e7a  @ 7817f0e7a (2026-10-28)
       env: julia 1.12.6, x86_64-linux-gnu, manifest 4c9d54fa (pinned), 2 threads/1 BLAS, jit build
Ref 2: 3a6435d60  @ 3a6435d60 (2026-10-28)
       env: julia 1.12.6, x86_64-linux-gnu, manifest 4c9d54fa (pinned), 2 threads/1 BLAS, jit build
--------------------------------------------------------------------------
Quantity                             7817f0e7a  3a6435d60  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]       N/A        [3 elem]   N/A      N/A   
CRF Q_peak [2/1,3/1,4/1]             N/A        [3 elem]   N/A      N/A   
CRF Q0 [2/1,3/1,4/1]                 N/A        [3 elem]   N/A      N/A   
CRF b_r crit in tesla [2/1,3/1,4/1]  N/A        [3 elem]   N/A      N/A   
SLAYER enabled flag                  1          1          0.0e+00  OK    
Runtime (s)                          234.0s     241.9s              --    
==========================================================================
Summary: 17 unchanged, 4 missing/N/A


================================================================
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: 7817f0e7a  @ 7817f0e7a (2026-10-28)
       env: julia 1.12.6, x86_64-linux-gnu, manifest 4c9d54fa (pinned), 2 threads/1 BLAS, jit build
Ref 2: 3a6435d60  @ 3a6435d60 (2026-10-28)
       env: julia 1.12.6, x86_64-linux-gnu, manifest 4c9d54fa (pinned), 2 threads/1 BLAS, jit build
--------------------------------------------------------------------------
Quantity                             7817f0e7a  3a6435d60  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]       N/A        [3 elem]   N/A      N/A   
CRF Q_peak [2/1,3/1,4/1]             N/A        [3 elem]   N/A      N/A   
CRF Q0 [2/1,3/1,4/1]                 N/A        [3 elem]   N/A      N/A   
CRF b_r crit in tesla [2/1,3/1,4/1]  N/A        [3 elem]   N/A      N/A   
SLAYER enabled flag                  1          1          0.0e+00  OK    
Runtime (s)                          236.4s     248.9s              --    
==========================================================================
Summary: 17 unchanged, 4 missing/N/A


================================================================
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: 7817f0e7a  @ 7817f0e7a (2026-10-28)
       env: julia 1.12.6, x86_64-linux-gnu, manifest 4c9d54fa (pinned), 2 threads/1 BLAS, jit build
Ref 2: 3a6435d60  @ 3a6435d60 (2026-10-28)
       env: julia 1.12.6, x86_64-linux-gnu, manifest 4c9d54fa (pinned), 2 threads/1 BLAS, jit build
------------------------------------------------------------------
Quantity                     7817f0e7a  3a6435d60  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)                  236.5s     246.6s              --    
==================================================================
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: 7817f0e7a  @ 7817f0e7a (2026-10-28)
       env: julia 1.12.6, x86_64-linux-gnu, manifest 4c9d54fa (pinned), 2 threads/1 BLAS, jit build
Ref 2: 3a6435d60  @ 3a6435d60 (2026-10-28)
       env: julia 1.12.6, x86_64-linux-gnu, manifest 4c9d54fa (pinned), 2 threads/1 BLAS, jit build
------------------------------------------------------------------------------------
Quantity                               7817f0e7a      3a6435d60      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.372379e+00  0.0e+00  OK    
total energy Re(et[1])                 8.005437e-01   8.005437e-01   0.0e+00  OK    
Runtime (s)                            195.0s         196.3s                  --    
====================================================================================
Summary: 12 unchanged


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

Regression Report: efit_fixedbdy_separatrix
=======================================================================
Ref 1: 7817f0e7a  @ 7817f0e7a (2026-10-28)
       env: julia 1.12.6, x86_64-linux-gnu, manifest 4c9d54fa (pinned), 2 threads/1 BLAS, jit build
Ref 2: 3a6435d60  @ 3a6435d60 (2026-10-28)
       env: julia 1.12.6, x86_64-linux-gnu, manifest 4c9d54fa (pinned), 2 threads/1 BLAS, jit build
-----------------------------------------------------------------------
Quantity                    7817f0e7a     3a6435d60     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)                 52.9s         57.2s                  --    
=======================================================================
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: 7817f0e7a  @ 7817f0e7a (2026-10-28)
       env: julia 1.12.6, x86_64-linux-gnu, manifest 4c9d54fa (pinned), 2 threads/1 BLAS, jit build
Ref 2: 3a6435d60  @ 3a6435d60 (2026-10-28)
       env: julia 1.12.6, x86_64-linux-gnu, manifest 4c9d54fa (pinned), 2 threads/1 BLAS, jit build
--------------------------------------------------------------------
Quantity                 7817f0e7a     3a6435d60     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.709610e-16  1.709610e-16  0.0e+00  OK    
Runtime (s)              191.1s        192.9s                 --    
====================================================================
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: 7817f0e7a  @ 7817f0e7a (2026-10-28)
       env: julia 1.12.6, x86_64-linux-gnu, manifest 4c9d54fa (pinned), 2 threads/1 BLAS, jit build
Ref 2: 3a6435d60  @ 3a6435d60 (2026-10-28)
       env: julia 1.12.6, x86_64-linux-gnu, manifest 4c9d54fa (pinned), 2 threads/1 BLAS, jit build
--------------------------------------------------------------------
Quantity                 7817f0e7a     3a6435d60     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       1.872671e-16  1.872671e-16  0.0e+00  OK    
Runtime (s)              180.9s        180.9s                 --    
====================================================================
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: 7817f0e7a  @ 7817f0e7a (2026-10-28)
       env: julia 1.12.6, x86_64-linux-gnu, manifest 4c9d54fa (pinned), 2 threads/1 BLAS, jit build
Ref 2: 3a6435d60  @ 3a6435d60 (2026-10-28)
       env: julia 1.12.6, x86_64-linux-gnu, manifest 4c9d54fa (pinned), 2 threads/1 BLAS, jit build
----------------------------------------------------------
Quantity                7817f0e7a  3a6435d60  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)             183.5s     181.9s           --    
==========================================================
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: 7817f0e7a  @ 7817f0e7a (2026-10-28)
       env: julia 1.12.6, x86_64-linux-gnu, manifest 4c9d54fa (pinned), 2 threads/1 BLAS, jit build
Ref 2: 3a6435d60  @ 3a6435d60 (2026-10-28)
       env: julia 1.12.6, x86_64-linux-gnu, manifest 4c9d54fa (pinned), 2 threads/1 BLAS, jit build
---------------------------------------------------------------
Quantity            7817f0e7a     3a6435d60     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)         21.9s         21.9s                  --    
===============================================================
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: 7817f0e7a  @ 7817f0e7a (2026-10-28)
       env: julia 1.12.6, x86_64-linux-gnu, manifest 4c9d54fa (pinned), 2 threads/1 BLAS, jit build
Ref 2: 3a6435d60  @ 3a6435d60 (2026-10-28)
       env: julia 1.12.6, x86_64-linux-gnu, manifest 4c9d54fa (pinned), 2 threads/1 BLAS, jit build
-----------------------------------------------------------------
Quantity            7817f0e7a      3a6435d60      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)         10.4s          10.4s                   --    
=================================================================
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: 7817f0e7a  @ 7817f0e7a (2026-10-28)
       env: julia 1.12.6, x86_64-linux-gnu, manifest 4c9d54fa (pinned), 2 threads/1 BLAS, jit build
Ref 2: 3a6435d60  @ 3a6435d60 (2026-10-28)
       env: julia 1.12.6, x86_64-linux-gnu, manifest 4c9d54fa (pinned), 2 threads/1 BLAS, jit build
--------------------------------------------------------------------------------
Quantity                           7817f0e7a      3a6435d60      Diff     Status
--------------------------------------------------------------------------------
vacuum energy Re(ev[1])            1.054739e+01   1.054739e+01   0.0e+00  OK    
q0                                 1.900003e+00   1.900003e+00   0.0e+00  OK    
NTV fgar quadrature torque [N·m]   2.267351e-03   2.267351e-03   0.0e+00  OK    
||xi_clebsch_alpha||               6.041963e-01   6.041963e-01   0.0e+00  OK    
total energy Re(et[1])             1.828278e+00   1.828278e+00   0.0e+00  OK    
total energy Im(et[1])             -1.326607e+00  -1.326607e+00  0.0e+00  OK    
plasma energy Re(ep[1])            -8.719112e+00  -8.719112e+00  0.0e+00  OK    
ODE steps (saved)                  608            608            0.0e+00  OK    
# singular surfaces                2              2              0.0e+00  OK    
boundary-response torque [N·m]     2.285518e-03   2.285518e-03   0.0e+00  OK    
singular psi locations             [2 elem]       [2 elem]       0.0e+00  OK    
total energy (all)                 [32 elem]      [32 elem]      0.0e+00  OK    
ODE steps (total)                  607            607            0.0e+00  OK    
mpert                              32             32             0.0e+00  OK    
q95                                3.147422e+00   3.147422e+00   0.0e+00  OK    
||Jb_theta_reg||                   3.945600e-03   3.945600e-03   0.0e+00  OK    
Runtime (s)                        224.6s         238.7s                  --    
T_xe applied-forcing torque [N·m]  2.285518e-03   2.285518e-03   0.0e+00  OK    
||dxi_clebsch_psi/dpsi||           3.791914e+00   3.791914e+00   0.0e+00  OK    
singular q values                  [2 elem]       [2 elem]       0.0e+00  OK    
npert                              1              1              0.0e+00  OK    
================================================================================
Summary: 20 unchanged


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

Regression Report: solovev_kinetic_multiion
==========================================================================
Ref 1: 7817f0e7a  @ 7817f0e7a (2026-10-28)
       env: julia 1.12.6, x86_64-linux-gnu, manifest 4c9d54fa (pinned), 2 threads/1 BLAS, jit build
Ref 2: 3a6435d60  @ 3a6435d60 (2026-10-28)
       env: julia 1.12.6, x86_64-linux-gnu, manifest 4c9d54fa (pinned), 2 threads/1 BLAS, jit build
--------------------------------------------------------------------------
Quantity                     7817f0e7a      3a6435d60      Diff     Status
--------------------------------------------------------------------------
NTV total (D+T+imp+e) [N·m]  3.141767e+01   3.141767e+01   0.0e+00  OK    
NTV Deuterium [N·m]          1.973730e+01   1.973730e+01   0.0e+00  OK    
NTV Tritium [N·m]            2.046293e+01   2.046293e+01   0.0e+00  OK    
NTV electron [N·m]           -8.782557e+00  -8.782557e+00  0.0e+00  OK    
total energy Re(et[1])       1.090560e-02   1.090560e-02   0.0e+00  OK    
# singular surfaces          2              2              0.0e+00  OK    
Runtime (s)                  226.1s         226.5s                  --    
==========================================================================
Summary: 6 unchanged


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

Regression Report: solovev_kinetic_ntv
======================================================================================
Ref 1: 7817f0e7a  @ 7817f0e7a (2026-10-28)
       env: julia 1.12.6, x86_64-linux-gnu, manifest 4c9d54fa (pinned), 2 threads/1 BLAS, jit build
Ref 2: 3a6435d60  @ 3a6435d60 (2026-10-28)
       env: julia 1.12.6, x86_64-linux-gnu, manifest 4c9d54fa (pinned), 2 threads/1 BLAS, jit build
--------------------------------------------------------------------------------------
Quantity                                   7817f0e7a     3a6435d60     Diff     Status
--------------------------------------------------------------------------------------
NTV torque fgar [Re, Im]                   [1 elem]      [1 elem]      0.0e+00  OK    
NTV ψ quadrature evaluations               45            45            0.0e+00  OK    
fluid CGL energy fcgl [J]                  1.552303e+01  1.552303e+01  0.0e+00  OK    
root-area-weighted total energy Re(et[1])  1.090560e-02  1.090560e-02  0.0e+00  OK    
# 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)                                226.2s        226.6s                 --    
======================================================================================
Summary: 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 Report: solovev_kinetic_nuzero
======================================================================
Ref 1: 7817f0e7a  @ 7817f0e7a (2026-10-28)
       env: julia 1.12.6, x86_64-linux-gnu, manifest 4c9d54fa (pinned), 2 threads/1 BLAS, jit build
Ref 2: 3a6435d60  @ 3a6435d60 (2026-10-28)
       env: julia 1.12.6, x86_64-linux-gnu, manifest 4c9d54fa (pinned), 2 threads/1 BLAS, jit build
----------------------------------------------------------------------
Quantity                 7817f0e7a      3a6435d60      Diff     Status
----------------------------------------------------------------------
vacuum energy Re(ev[1])  1.058613e+01   1.058613e+01   0.0e+00  OK    
q0                       1.900003e+00   1.900003e+00   0.0e+00  OK    
total energy Re(et[1])   2.290965e+00   2.290965e+00   0.0e+00  OK    
total energy Im(et[1])   -1.564546e+00  -1.564546e+00  0.0e+00  OK    
plasma energy Re(ep[1])  -8.295163e+00  -8.295163e+00  0.0e+00  OK    
ODE steps (saved)        608            608            0.0e+00  OK    
# 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]      0.0e+00  OK    
ODE steps (total)        607            607            0.0e+00  OK    
mpert                    32             32             0.0e+00  OK    
q95                      3.147422e+00   3.147422e+00   0.0e+00  OK    
Runtime (s)              233.8s         235.9s                  --    
singular q values        [2 elem]       [2 elem]       0.0e+00  OK    
npert                    1              1              0.0e+00  OK    
======================================================================
Summary: 14 unchanged


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

Regression Report: solovev_multi_n
=================================================================================
Ref 1: 7817f0e7a  @ 7817f0e7a (2026-10-28)
       env: julia 1.12.6, x86_64-linux-gnu, manifest 4c9d54fa (pinned), 2 threads/1 BLAS, jit build
Ref 2: 3a6435d60  @ 3a6435d60 (2026-10-28)
       env: julia 1.12.6, x86_64-linux-gnu, manifest 4c9d54fa (pinned), 2 threads/1 BLAS, jit build
---------------------------------------------------------------------------------
Quantity                      7817f0e7a        3a6435d60        Diff       Status
---------------------------------------------------------------------------------
total energy Re(et[1])        -2.134718e+00    -2.134718e+00    0.0e+00    OK    
total energy Im(et[1])        1.968592e-10     1.968592e-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)                   199.7s           203.8s                      --    
=================================================================================
Summary: 15 unchanged


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

Regression Report: solovev_n1
=================================================================================
Ref 1: 7817f0e7a  @ 7817f0e7a (2026-10-28)
       env: julia 1.12.6, x86_64-linux-gnu, manifest 4c9d54fa (pinned), 2 threads/1 BLAS, jit build
Ref 2: 3a6435d60  @ 3a6435d60 (2026-10-28)
       env: julia 1.12.6, x86_64-linux-gnu, manifest 4c9d54fa (pinned), 2 threads/1 BLAS, jit build
---------------------------------------------------------------------------------
Quantity                      7817f0e7a        3a6435d60        Diff       Status
---------------------------------------------------------------------------------
total energy Re(et[1])        1.090560e-02     1.090560e-02     0.0e+00    OK    
total energy Im(et[1])        1.350301e-10     1.350301e-10     0.0e+00    OK    
plasma energy Re(ep[1])       -1.041640e+01    -1.041640e+01    0.0e+00    OK    
vacuum energy Re(ev[1])       1.042730e+01     1.042730e+01     0.0e+00    OK    
vacuum matrix min eigenvalue  2.170703e+00     2.170703e+00     0.0e+00    OK    
plasma energy (all)           [32 elem]        [32 elem]        0.0e+00    OK    
vacuum energy (all)           [32 elem]        [32 elem]        0.0e+00    OK    
total energy (all)            [32 elem]        [32 elem]        0.0e+00    OK    
ODE steps (saved)             287              287              0.0e+00    OK    
ODE steps (total)             285              285              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    
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)            b7a5bbc5f549...  b7a5bbc5f549...  identical  OK    
Runtime (s)                   188.2s           186.3s                      --    
=================================================================================
Summary: 22 unchanged

Third-party human review and approval are required before merge.

@matt-pharr
matt-pharr enabled auto-merge October 28, 2026 22:40
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

feature New capability

Projects

None yet

Development

Successfully merging this pull request may close these issues.

SLAYER based b_crit calculations need to be ported

4 participants