Skip to content

Integrate collisionless resonances along pitch with an error budget shared over harmonics - #266

Merged
krystophny merged 3 commits into
mainfrom
pitch-integral
Nov 9, 2026
Merged

krystophny merged 3 commits into
mainfrom
pitch-integral

Conversation

@krystophny

@krystophny krystophny commented Nov 9, 2026 •

Copy link
Copy Markdown
Member

With vtol > 0 the thermal velocity integral of each resonance component (one poloidal harmonic mth of one orbit class: co-passing, counter-passing or trapped) was refined until its own error estimate was below vtol of its own value. Strongly cancelling high harmonics sit at the noise floor of the bounce integral, never reach that, and each ran to the 4000-panel limit. On the ripple-plateau case (test/ripple_plateau, harmonics up to |m| = 41) a run did not finish in 300 s, against 10 s with the midpoint rule. This is why #265, which makes vtol = 1e-3 the default, timed out in the merge queue.

Two changes:

  • Error budget shared over the sum. A coarse pass sizes every component. In the refining pass, component c of a species stops when, for each of D11, D12 and the torque, its error estimate is at most max(vtol*|I_c|, vtol*sum_k |I_k| / N), where I_k is the coarse value of component k and N is the species' component count.
  • Integral along pitch. Let R(u, eta) = mph*Om_ph + mth*Om_th be the resonance function, u = v/vth and eta the pitch variable. At fixed eta, R is a quadratic in u, because the frequencies are splines in eta times v and v**2. So the integral over u of the eta-roots weighted by 1/|dR/deta| equals the integral over eta of the closed-form u-roots weighted by 1/|dR/du|. The eta range of the component is split where two u-roots merge or a root crosses the speed limits vmin/vmax, all found from the splines alone. The substitution eta = m - h*cos(theta) on a piece [m - h, m + h] removes the 1/sqrt singularity where roots merge. Adaptive Gauss-Kronrod then runs in theta, starting with four panels per piece. Where R is not quadratic in u (e.g. supban), with a resonance cutout, or with the resonance ledger, the u-adaptive integral is used.

Ripple-plateau case, 4 threads. D11 and D12 are compared to the values on which the u-adaptive and pitch integrals agree at vtol = 1e-5 (D11 = 2.158387e-2, to 2e-6). Both use the same orbit physics, so this checks the quadrature, not the model.

velocity integral wall time D11 rel. error D12 rel. error
midpoint, 256 nodes 9.9 s 3.3e-4 3.6e-5
u-adaptive per component, vtol = 1e-3 (main) not finished in 300 s
u-adaptive, shared budget, vtol = 1e-3 27 s 1e-5 1e-5
pitch, shared budget, vtol = 1e-3 12.4 s 7e-7 2e-6
pitch, shared budget, vtol = 1e-4 13.4 s 1e-8 1e-7

ASDEX Upgrade 30835 deuterons, magnetic drift on, 32 threads. Toroidal torque on flux surfaces s = 0.105 and 0.302 (normalised toroidal flux), at the physical temperature and at temperature / 10:

case midpoint 256 pitch vtol = 1e-3 pitch vtol = 1e-5
s = 0.105, counter-passing -6.051e6 -5.96667e6 -5.96668e6
s = 0.302, trapped -8.55689e5 -8.55700e5 -8.55700e5
s = 0.302, T / 10, counter-passing -3.033e5 -2.81986e5 -2.81986e5

(NEO-RT torque output units.)

The serial driver used when no profile splines are loaded (test/ripple_plateau input with vth given, 8 threads) gets the same two-pass budget. It took over 20 minutes at vtol = 1e-3. It now takes 54 s, against 50 s for the midpoint rule, and agrees with vtol = 1e-5 to 2e-6, while the midpoint rule is off by 1.3e-3 (D11) and 2.3e-3 (D12).
Every run takes about 5 s. The pitch values agree with the earlier u-adaptive ones to about 1e-5 in these dominant components, and the midpoint rule is off by 1.4 % and 7.5 %.

test/adaptive_velocity gains a test that runs the ripple-plateau case at vtol = 1e-3 within a 120 s timeout and checks D11 to 1e-5; on main it times out. The circular-tokamak convergence test passes. Of the CTest suite 149 of 154 pass. The other five (test_profile_probe, test_species_mixture_output, test_species_mixture_cli, test_collisional_layer_table, test_collisional_layer_generator) stop with "No module named 'numpy'" in the interpreter CMake found here, and fail the same way on a main build. vtol = 0 stays the default, so golden records are unchanged.

Chris&AI

@krystophny
krystophny enabled auto-merge November 9, 2026 13:13
@krystophny
krystophny added this pull request to the merge queue Nov 9, 2026
@github-merge-queue
github-merge-queue Bot removed this pull request from the merge queue due to failed status checks Nov 9, 2026
@krystophny
krystophny added this pull request to the merge queue Nov 9, 2026
@github-merge-queue
github-merge-queue Bot removed this pull request from the merge queue due to failed status checks Nov 9, 2026
@krystophny
krystophny added this pull request to the merge queue Nov 9, 2026
@github-merge-queue
github-merge-queue Bot removed this pull request from the merge queue due to failed status checks Nov 9, 2026
@krystophny
krystophny added this pull request to the merge queue Nov 9, 2026
@github-merge-queue
github-merge-queue Bot removed this pull request from the merge queue due to failed status checks Nov 9, 2026
@krystophny
krystophny added this pull request to the merge queue Nov 9, 2026
@github-merge-queue
github-merge-queue Bot removed this pull request from the merge queue due to failed status checks Nov 9, 2026
@krystophny
krystophny added this pull request to the merge queue Nov 9, 2026
Merged via the queue into main with commit cde25f4 Nov 9, 2026
8 checks passed
@krystophny
krystophny deleted the pitch-integral branch November 9, 2026 16:46
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.

1 participant