Skip to content

KineticForces - PERFORMANCE - Panel NTV psi quadrature at rational and kinetic-resonance surfaces with rtol-primary tolerances#313

Open
logan-nc wants to merge 20 commits into
developfrom
performance/ntv-psi-quadrature-paneling
Open

KineticForces - PERFORMANCE - Panel NTV psi quadrature at rational and kinetic-resonance surfaces with rtol-primary tolerances#313
logan-nc wants to merge 20 commits into
developfrom
performance/ntv-psi-quadrature-paneling

Conversation

@logan-nc

@logan-nc logan-nc commented Jul 3, 2026

Copy link
Copy Markdown
Collaborator

Closes #303. Built on #312 (feature/two-pass-psi-grid is merged into this branch, so its commits appear in this diff until #312 lands — merge #312 first, after which this PR reduces to the KineticForces changes).

Problem

The outer ψ-integration of the NTV torque tpsi(ψ) used a single whole-domain adaptive quadrature with no interior breakpoints, no maxevals bound, and a discarded error estimate. The resonant torque-density peaks — at the rational surfaces and at the kinetic resonances (dominantly the ExB/superbanana-plateau resonance near ω_E ≈ 0) — forced deep adaptive bisection (1375+ evaluations, ~30 min reported in #303 on the DIII-D-like case). Separately, the atol_psi = 1e-2 N·m default was an amplitude-sensitive trap: NTV ∝ δB², so a 10× weaker applied field gives a 100× smaller torque and a fixed absolute tolerance can silently dominate termination with O(1) relative error.

Changes

ψ-quadrature paneling at resonant surfaces

  • Rational-surface ψ locations the stability run resolved (sing + kinsing) are threaded into KineticForcesInternal.sing_psis and passed as quadrature panel boundaries — Gauss–Kronrod handles peaks at interval endpoints natively instead of hunting them by bisection.
  • Kinetic-resonance locations are identified and paneled for the case's full bounce-harmonic range: kinetic_resonance_psi_nodes(kinetic_profiles, equil; n, nl, ...) scans for zeros of the trapped-branch resonance denominator at thermal energy, Ω_ℓ(x=1; ψ) = ℓ·ω_b(ψ) + n·(ω_E(ψ) + ω_d(ψ)) for every ℓ ∈ −nl:nl, using the pitch-averaged RLAR closed-form frequencies already in tpsi! (single spline evaluations, no bounce averaging). The ℓ=0 node is the ω_d-shifted ExB resonance; ℓ≠0 nodes capture the bounce resonances. On the DIII-D case this finds 8 in-range surfaces that line up with the observed pedestal dT/dψ structure (see figure) — including the previously unexplained bump at ψ_N ≈ 0.955.
  • Panel boundaries and located resonance surfaces are persisted to the output (kinetic_forces/<method>/panel_psi, resonance_psi) for diagnostics/plotting; the per-method log line reports torque, error estimate, evaluation count, and panel composition.
  • A fortran-physics-reviewer audit of the locator passed all checks: frequency conventions match tpsi!/torque.F90 exactly (the wdhat = q·T/(2εR₀²ZeB₀) closed form verified algebraically identical), the denominator correctly uses ω_E alone (diamagnetic terms are numerator-only), and leff = ℓ matches the trapped branch. Passing-branch (ℓ+nq transit) resonances are a documented non-goal (broad/Landau-like; quadrature resolves them without dedicated panels).

Unified helpers (one source of truth per concept, no drift)

Tolerance redesign (rtol-primary)

  • atol_psi: 1e-2 → 0.0. Convergence is controlled by rtol_psi = 1e-2 (~2 significant figures — the limit of the NTV model's validity; tighter tolerances buy digits the physics can't back).
  • New maxevals_psi = 2000 runaway guard; the error estimate is checked and a clear warning fires when the quadrature terminates without meeting tolerance, or when a user-set nonzero atol_psi dominates termination (the weak-field silent-garbage scenario).
  • psilims stays [0.0, 1.0]. (An interim commit floored it at 0.1 to dodge a near-axis dT/dψ spike; measurement showed that was over-optimization — at rtol=1e-2 only 7 of 345 develop evaluations land below ψ=0.1 and the core carries a real 0.3% of the torque — so the floor was reverted. The near-axis feature itself turns out to be two located ℓ≠0 resonance surfaces, now paneled like the rest.)

Coverage

  • New examples/Solovev_kinetic_NTV_example (ideal FFS → PE → NTV torque) — previously no shipped config exercised this code path — plus a solovev_kinetic_ntv regression case pinning the fgar torque and ψ evaluation count.
  • Removed the inert atol_psi/rtol_psi keys from the a10 example (it stops after kinetic stability and never reaches the torque quadrature).

Benchmarks (DIII-D-like case from #295, n=1, C-coil 1 kA, nl=6, 5 rationals)

Code Panels atol/rtol_psi Torque (N·m) ψ evals KF stage
develop 1e-3 / 1e-3 (pre-#303 mitigation) 1375+ ~30 min (reported)
develop 0 / 1e-2 82.93 − 14.80i 345 158 s
this PR 5 rational + 8 kinetic resonance defaults (0 / 1e-2) 83.16 − 14.92i 210 108 s
this PR 5 rational + 8 kinetic resonance 1e-9 / 1e-3 83.18 − 14.95i 450 296 s

The defaults run agrees with the tightly-converged answer to 0.024% in Re(T) at 1.6× fewer evaluations than develop at equal tolerance — and 210 = 14 panels × 15 nodes exactly: the initial pass alone converges, i.e. the panels sit precisely where the quadrature work is. Whole n=1 pipeline: ~3 minutes. Regularization note: the PE default reg_spot = 0.05 must stay on for this post-PE diagnostic — with raw (unregularized) ξ the "torque" becomes the grid-capped ideal-MHD 1/(m−nq)² divergence (~66,000× larger on a Solovev test) rather than a physical answer.

Torque density with the identified resonance locations (rationals dashed gray; located kinetic resonances Ω_ℓ(x=1)=0 dash-dot violet — note the match to the pedestal structure and the small near-axis feature):

NTV torque density

Quadrature evaluation clustering — develop (no panels) goes near-vertical at the edge resonances; the paneled defaults run spreads effort almost uniformly:

Evaluation clustering

Cumulative torque integral — all runs overlay; ~95% of the torque accumulates in the pedestal, with the sharp rise starting at the ℓ=0 kinetic resonance:

Cumulative torque

Regression

  • solovev_n1: 21/21 unchanged; diiid_n1: 46/46 unchanged vs feature/two-pass-psi-grid (this PR's changes are isolated to [KineticForces]-configured runs).
  • solovev_kinetic_ntv: NTV torque and evaluation count move intentionally with the quadrature improvements (final baseline pinned at this head).
  • Unit tests: 222 kinetic (new: root-scan, resonance-node scan with analytic locations, panel assembly, tolerance warnings) + 39 grid-refinement, all green.

Notes for reviewers

🤖 Generated with Claude Code

logan-nc and others added 18 commits July 2, 2026 17:22
…rfaces, rtol-primary tolerances with maxevals guard

Co-Authored-By: Claude Fable 5 <[email protected]>
…rium solver paths

Adds an override_psi_nodes keyword to setup_equilibrium and threads it through
the direct, arclength, inverse, and by-inversion solvers, bypassing the
config-driven grid with a validated externally supplied node vector. This is
the injection point for the two-pass auto-grid refinement.

Co-Authored-By: Claude Fable 5 <[email protected]>
…on, and mandatory-node merge

GridRefinement.jl derives the pass-2 knot density from the formed pass-1
equilibrium using the cubic h^4 error model on nodal fourth divided differences
(1D profiles, rzphi geometry channels at sampled theta lines, and kinetic
profiles when present), with a-priori edge/core geometric floors, then
equidistributes and pins mandatory knots with a delta_min snap guard. The
log_asymptotic auto path now forms a coarse fixed-128 pass-1 layout; the
one-pass a-priori heuristics (make_optimal_mpsi, probe log-slope, 300-point
mid-spacing sampling) are removed. All regions now scale as psi_accuracy^(-1/4),
so tightening the tolerance refines edge and mid proportionally.

Co-Authored-By: Claude Fable 5 <[email protected]>
… add rational_psi_nodes

The qextrema-interval Brent walk moves from sing_find! into
_find_rational_surfaces, which returns (m, n, psifac) tuples; sing_find!
rebuilds its SingType multiplicity bookkeeping on top. rational_psi_nodes
exposes the unique surface locations for the two-pass grid refinement.

Co-Authored-By: Claude Fable 5 <[email protected]>
…ession case covering the psi torque quadrature

Co-Authored-By: Claude Fable 5 <[email protected]>
…onal-surface packing

Validation on the DIIID-like example drove four corrections to the knot
density model:
- h^3 derivative error model (err(f') ~ h^3|f''''|/24) replaces the h^4 value
  model: the stability physics consumes spline derivatives (q' at rational
  surfaces, p' and V' in the EL and ballooning coefficients), and the value
  model under-resolved delta-prime by 2x at q=2.
- Curvature is measured against rho = sqrt(psi), where the equilibrium is
  regular at the axis; the psi-space geometry channels diverge as psi^(k/2-4)
  there and made the implied knot count grow without bound under refinement.
- Local packing around mandatory (rational) surfaces: spacing 0.06*tau^(1/3)
  at the surface with geometric growth, within radius 0.05 — converges the
  delta-prime BVP, which samples the psi-splined coefficient matrices around
  each singular surface.
- The core below psi=0.03 uses the a-priori geometric density exclusively:
  nodal data on the smallest flux surfaces is dominated by integration and
  axis-extrapolation error. Near-duplicate mandatory nodes (same surface via
  different m,n) collapse onto one knot. Noise floor scales as eps/h^4 on
  tightly packed sample grids.

Adds test/runtests_grid_refinement.jl covering the merge invariants,
equidistribution, quartic-exact divided differences, layer concentration,
tau^(-1/3) scaling, and a Solovev two-pass round-trip.

Co-Authored-By: Claude Fable 5 <[email protected]>
…ts in main driver

When grid_type=log_asymptotic with mpsi=0, the driver forms a coarse pass-1
equilibrium, pins knots on all rational surfaces in the requested n range,
derives the refined grid from the measured curvature (including kinetic
profiles when loaded), and re-forms from the in-memory input. The nn range
validation and the kinetic-profile load are hoisted above equilibrium
formation to feed the refinement; a consistency check warns when the refined
equilibrium implies substantially more knots than used.

Co-Authored-By: Claude Fable 5 <[email protected]>
…ha-boundary scan drivers

The alpha-boundary drivers now scan only psi_N in [0.1, min(0.99, psi_edge)],
reusing the existing NaN sentinel for skipped surfaces. Ballooning boundaries
are physically relevant in the mid-radius and pedestal; the packed axis and
far-edge surfaces dominated the scan cost. The locstab path
(compute_ballooning_stability!) is unchanged.

Co-Authored-By: Claude Fable 5 <[email protected]>
Quantifies knots-vs-accuracy for cubic splines of q versus iota = 1/q on the
DIII-D-like example: iota gives a modest constant-factor improvement (~1.2-2x
at coarse N) but the same convergence order, confirming that wholesale iota
replacement is not warranted for grids ending inside the separatrix.

Co-Authored-By: Claude Fable 5 <[email protected]>
…md, example annotations)

Co-Authored-By: Claude Fable 5 <[email protected]>
…psi=256 grid

These testsets target the bidirectional FM integration and STRIDE BVP
machinery, so they now pin the radial grid instead of inheriting the example
default (mpsi=0), which previously baked the defective one-pass auto grid into
the pinned values and would otherwise move whenever the auto grid evolves.
Re-pins et_par and the delta-prime diagonals to the ldp-256 values: q=2,3,4
real parts are grid-converged and pinned tightly; the near-separatrix q=5,6
entries are not grid-converged (value and sign vary O(1) between grids) and
are now asserted finite and non-zero only.

Co-Authored-By: Claude Fable 5 <[email protected]>
… equidistribution, IMAS rerun note

Co-Authored-By: Claude Fable 5 <[email protected]>
The two-pass grid is a measured spline-derivative-error density with geometric
floors, not a log-asymptotics model — q stays finite everywhere on the grid —
so the old name misdescribed it. grid_type="auto" is the new default;
"log_asymptotic" remains a working alias (two-pass when mpsi=0, the
three-region log layout when mpsi>0), so no existing TOML breaks.

Co-Authored-By: Claude Fable 5 <[email protected]>
…roduction auto grid

Per review: the auto grid is the production default, so the machinery testsets
now build it exactly as the main driver does (rational_psi_nodes +
refined_psi_grid + ingest re-form) and pin its values. The auto-vs-ldp512
convergence evidence is recorded on the PR; tightening psi_accuracy converges
the pinned delta-prime entries toward the dense-reference values.

Co-Authored-By: Claude Fable 5 <[email protected]>
…-crossing quadrature panels, shared sign-change root scan, psilims floor above axis

Co-Authored-By: Claude Fable 5 <[email protected]>
…scription and future settings docs

Co-Authored-By: Claude Fable 5 <[email protected]>
logan-nc and others added 2 commits July 3, 2026 13:33
…nances for quadrature panels, revert psilims floor, persist panel data to HDF5

Co-Authored-By: Claude Fable 5 <[email protected]>
…ance surfaces, annotate epsilon clamp

Co-Authored-By: Claude Fable 5 <[email protected]>
@logan-nc logan-nc requested a review from d-burg July 6, 2026 16:19
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

NTV torque psi-quadrature over-refines at rational surfaces, dominating runtime

1 participant