Sub-issue of #302. #302 covers auto-mpsi under-resolving the edge (spurious dW / Δ′); this issue covers the ballooning-stability consequences and a paired performance default.
1. Auto-gridding must guarantee pedestal resolution for ballooning physics
High-n ballooning stability (Δ′, the s–α first/second boundaries in src/ForceFreeStates/Ballooning.jl) is physically most relevant in the pedestal, ψ_N ≈ 0.8–0.98. The edge under-resolution in #302 (N_edge ≈ 5 at the default psi_accuracy = 1e-3) under-resolves this whole band, not just the last rational surface — so the ballooning boundary profile there is unreliable. Whatever fix lands for the N_edge/N_mid imbalance in make_optimal_mpsi should explicitly ensure adequate, efficient resolution across the 0.8–0.98 pedestal band (not merely a handful of points at ψ→1), for log_asymptotic auto-mpsi as well as ldp / power gridding.
2. Make a default psi-window the standard for ballooning scans (performance)
The α-boundary drivers (ballooning_alpha_boundary / ballooning_alpha_boundaries) loop over every equilibrium ψ node and run up to n_scan (~24) ODE shooting solves per surface — the dominant local-stability cost (~24.5 s / 54 GB on the DIII-D case). The tightly packed axis (ψ<0.1) and far-edge (ψ>0.98) nodes produced by ldp / log_asymptotic / power gridding waste solves where ballooning boundaries are rarely used. Proposal: by default evaluate the ballooning α-boundary scan only on
ψ_N ∈ [0.1, min(0.99, psi_edge, psihigh)]
which trims the worst axis and edge packing across all grid types while retaining the pedestal.
Ordering / dependency
(2) depends on (1). Windowing a grid that is under-resolved in the pedestal just locks in the spurious values from #302, so the pedestal-resolution fix must land before or together with the default window.
Implementation notes (from prior analysis)
- Clean approach for (2) is an index window/mask over the existing grid in the two α-boundary drivers, reusing the existing NaN sentinel (the drivers already
fill(NaN, npsi) and continue on xs[i] > 1.0; outputs stay length-npsi, aligned to the ψ axis). A separate ballooning grid is too dirty: prepare_ballooning_coefficients, salpha_reference, and resistive_interchange_h read precomputed nodal bicubic partials (rzphi_*.nodal_derivs.partials[k, idx, itheta]) and spline node values (profiles.<spline>.y[idx]) that exist only at grid nodes — off-node evaluation re-architects all three and pays the geometry-bicubic cost.
- Leave
compute_ballooning_stability! (di / dr / Δ′, locstab cols 1/2/4) un-windowed or finite-filled: its locstab_fs is splined and evaluated at singular surfaces (intr.locstab(sing.psifac)), so a NaN at a skipped node would poison the whole profile.
Config question for reviewers (please weigh in)
I'd prefer not to add TOML window specifiers if everyone agrees the hard-coded default [0.1, min(0.99, psi_edge, psihigh)] is sufficient. Two things to confirm:
- Is a fixed default window acceptable, or do we need a
[ForceFreeStates] config knob?
- Does
min(0.99, psi_edge, psihigh) still span the full pedestal band of interest in your cases (i.e. it must not clip ψ_N ≈ 0.8–0.98)?
Sub-issue of #302. #302 covers auto-mpsi under-resolving the edge (spurious dW / Δ′); this issue covers the ballooning-stability consequences and a paired performance default.
1. Auto-gridding must guarantee pedestal resolution for ballooning physics
High-n ballooning stability (Δ′, the s–α first/second boundaries in
src/ForceFreeStates/Ballooning.jl) is physically most relevant in the pedestal, ψ_N ≈ 0.8–0.98. The edge under-resolution in #302 (N_edge ≈ 5 at the defaultpsi_accuracy = 1e-3) under-resolves this whole band, not just the last rational surface — so the ballooning boundary profile there is unreliable. Whatever fix lands for the N_edge/N_mid imbalance inmake_optimal_mpsishould explicitly ensure adequate, efficient resolution across the 0.8–0.98 pedestal band (not merely a handful of points at ψ→1), forlog_asymptoticauto-mpsi as well asldp/ power gridding.2. Make a default psi-window the standard for ballooning scans (performance)
The α-boundary drivers (
ballooning_alpha_boundary/ballooning_alpha_boundaries) loop over every equilibrium ψ node and run up ton_scan(~24) ODE shooting solves per surface — the dominant local-stability cost (~24.5 s / 54 GB on the DIII-D case). The tightly packed axis (ψ<0.1) and far-edge (ψ>0.98) nodes produced byldp/log_asymptotic/ power gridding waste solves where ballooning boundaries are rarely used. Proposal: by default evaluate the ballooning α-boundary scan only onwhich trims the worst axis and edge packing across all grid types while retaining the pedestal.
Ordering / dependency
(2) depends on (1). Windowing a grid that is under-resolved in the pedestal just locks in the spurious values from #302, so the pedestal-resolution fix must land before or together with the default window.
Implementation notes (from prior analysis)
fill(NaN, npsi)andcontinueonxs[i] > 1.0; outputs stay length-npsi, aligned to the ψ axis). A separate ballooning grid is too dirty:prepare_ballooning_coefficients,salpha_reference, andresistive_interchange_hread precomputed nodal bicubic partials (rzphi_*.nodal_derivs.partials[k, idx, itheta]) and spline node values (profiles.<spline>.y[idx]) that exist only at grid nodes — off-node evaluation re-architects all three and pays the geometry-bicubic cost.compute_ballooning_stability!(di / dr / Δ′, locstab cols 1/2/4) un-windowed or finite-filled: itslocstab_fsis splined and evaluated at singular surfaces (intr.locstab(sing.psifac)), so a NaN at a skipped node would poison the whole profile.Config question for reviewers (please weigh in)
I'd prefer not to add TOML window specifiers if everyone agrees the hard-coded default
[0.1, min(0.99, psi_edge, psihigh)]is sufficient. Two things to confirm:[ForceFreeStates]config knob?min(0.99, psi_edge, psihigh)still span the full pedestal band of interest in your cases (i.e. it must not clip ψ_N ≈ 0.8–0.98)?