Skip to content

Ballooning: guarantee pedestal resolution in auto-gridding, and make a default psi-window the standard for ballooning scans #308

Closed

Description

@logan-nc

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:

  1. Is a fixed default window acceptable, or do we need a [ForceFreeStates] config knob?
  2. 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)?

Metadata

Metadata

Assignees

No one assigned

    Labels

    featureNew capabilityperfSame answers, less time or memory

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions