Skip to content

ErrorFields - BUGFIX! - Sum the NTV couplings over the resolved kinetic species - #580

Merged
matt-pharr merged 5 commits into
developfrom
bugfix/ef-ntv-species-sum
Nov 12, 2026
Merged

matt-pharr merged 5 commits into
developfrom
bugfix/ef-ntv-species-sum

Conversation

@logan-nc

@logan-nc logan-nc commented Oct 24, 2026 •

Copy link
Copy Markdown
Collaborator

Release note

  • Audience: users
  • Numerical impact: ErrorFields/NTV/* moves for runs whose kinetic data resolve more than one NTV species (several ion_species on the equilibrium, a partial or explicit main-ion density, or [KineticForces] electron = true); single-ion runs are unchanged (harness @ 2323fbd)
  • Migration: a multi-species or electron run with [ErrorFields.NTV] gets species-summed correction-coil torques, rotation scans and NTV current limits on rerun; no input changes

The ErrorFields (EF) NTV couplings evaluated every correction array's torque for the main ion alone, while the KineticForces diagnostics of the same run summed over the resolved species. The couplings now resolve the same species set from the kinetic profiles attached to the equilibrium, so their torque at every rotation shift is the same species sum.

Regression report

Full fan-out on ITER's SDCC cluster (regress_fanout.sh --refs a1149c5c2,2323fbdf6, all 27 cases, Julia 1.12.6, pinned manifest), branch 2323fbdf6 against develop a1149c5c2. 385 tracked quantities, all unchanged; no stale-baseline banner — as predicted, since no case runs the error-field NTV couplings with more than one species.

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: a1149c5c2  @ a1149c5c2 (2026-11-07)
       env: julia 1.12.6, x86_64-linux-gnu, manifest 4c9d54fa (pinned), 2 threads/1 BLAS, jit build, warm
Ref 2: 2323fbdf6  @ 2323fbdf6 (2026-11-12)
       env: julia 1.12.6, x86_64-linux-gnu, manifest 4c9d54fa (pinned), 2 threads/1 BLAS, jit build, warm
--------------------------------------------------------------------------------------------
Quantity                                         a1149c5c2     2323fbdf6     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.414981e-06  1.414981e-06  0.0e+00  OK
|Σ δ_as_designed| of the error-field coils       1.289590e-18  1.289590e-18  0.0e+00  OK
Monte Carlo mean |δ| of the error-field coils    4.701440e-05  4.701440e-05  0.0e+00  OK
Runtime (s)                                      188.1s        188.4s                 --
Summary: 10 unchanged

Case: tj_kinetic_multiion — TJ-analytic n=1, no wall, ideal + PE + multi-ion NTV (D + T + electron summed)

Regression Report: tj_kinetic_multiion
Ref 1: a1149c5c2  @ a1149c5c2 (2026-11-07)
       env: julia 1.12.6, x86_64-linux-gnu, manifest 4c9d54fa (pinned), 2 threads/1 BLAS, jit build, warm
Ref 2: 2323fbdf6  @ 2323fbdf6 (2026-11-12)
       env: julia 1.12.6, x86_64-linux-gnu, manifest 4c9d54fa (pinned), 2 threads/1 BLAS, jit build, warm
------------------------------------------------------------------------
Quantity                     a1149c5c2     2323fbdf6     Diff     Status
------------------------------------------------------------------------
NTV total (D+T+imp+e) [N·m]  8.956218e-04  8.956218e-04  0.0e+00  OK
NTV Deuterium [N·m]          4.759094e-04  4.759094e-04  0.0e+00  OK
NTV Tritium [N·m]            4.133763e-04  4.133763e-04  0.0e+00  OK
NTV electron [N·m]           6.336120e-06  6.336120e-06  0.0e+00  OK
total energy Re(et[1])       4.350277e-01  4.350277e-01  0.0e+00  OK
# singular surfaces          2             2             0.0e+00  OK
Runtime (s)                  7.5s          5.4s                   --
Summary: 6 unchanged

Case: tj_kinetic_ntv — TJ-analytic equilibrium, n=1, no wall, ideal + PE + NTV torque quadrature

Regression Report: tj_kinetic_ntv
Ref 1: a1149c5c2  @ a1149c5c2 (2026-11-07)
       env: julia 1.12.6, x86_64-linux-gnu, manifest 4c9d54fa (pinned), 2 threads/1 BLAS, jit build, warm
Ref 2: 2323fbdf6  @ 2323fbdf6 (2026-11-12)
       env: julia 1.12.6, x86_64-linux-gnu, manifest 4c9d54fa (pinned), 2 threads/1 BLAS, jit build, warm
--------------------------------------------------------------------------------------
Quantity                                   a1149c5c2     2323fbdf6     Diff     Status
--------------------------------------------------------------------------------------
NTV torque fgar [Re, Im]                   [1 elem]      [1 elem]      0.0e+00  OK
NTV ψ quadrature evaluations               75            75            0.0e+00  OK
fluid CGL energy fcgl [J]                  5.446364e-04  5.446364e-04  0.0e+00  OK
root-area-weighted total energy Re(et[1])  4.350277e-01  4.350277e-01  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.599966e+00  1.599966e+00  0.0e+00  OK
Runtime (s)                                3.3s          3.2s                   --
Summary: 7 unchanged

All cases:
  diiid_error_field: 10 unchanged
  diiid_kinetic_multi_n: 8 unchanged
  diiid_multi_n: 19 unchanged
  diiid_n1: 53 unchanged
  diiid_n1_riccati: 17 unchanged
  diiid_n1_riccati_precompiled: 17 unchanged
  diiid_slayer_n1: 22 unchanged
  diiid_slayer_n1_chi_perp_e: 22 unchanged
  diiid_slayer_n1_coupled: 7 unchanged
  diiid_slayer_n1_toroidal: 5 unchanged
  diiid_slayer_n1_winding: 22 unchanged
  diiid_truncation_n1: 12 unchanged
  efit_fixedbdy_separatrix: 5 unchanged
  gal_resistive_diiid: 11 unchanged
  gal_resistive_diiid_galinner: 11 unchanged
  ggj_ray_q500i: 4 unchanged
  ggj_reference: 4 unchanged
  lar_ggj_tearing_n1: 3 unchanged
  lar_reversed_shear_n1: 22 unchanged
  solovev_kinetic_nuzero: 14 unchanged
  solovev_multi_n: 15 unchanged
  solovev_n1: 22 unchanged
  tj_kinetic_calculated: 20 unchanged
  tj_kinetic_multiion: 6 unchanged
  tj_kinetic_ntv: 7 unchanged
  tj_kinetic_ntv_rates: 2 unchanged
  tj_n1: 25 unchanged

Notes for reviewers

  • The gap. efc_couplings called compute_torque_all_methods! once, with the equilibrium's main ion on the full-composition NTV profiles. A D-T or electron run therefore wrote NTV diagnostics summed over species but NTV couplings for the main ion only, silently.
  • The fix. efc_couplings (src/ErrorFields/NTVLimits.jl) resolves the species set with KineticForces.ntv_species(kf_ctrl, equil), as it already builds its profile view with ntv_profiles. The torque of each perturbation at each rotation shift is the new ErrorFields.ntv_torque_state, which with a species set loops the species exactly as KineticForces.kinetic_torque does: each species' own profiles shifted, its identity passed as z/m/electron, then combine_species_states. Without a set nothing changes: the Δ = 0 short-circuit on the unshifted profiles is kept, so the single-ion path is the same code on the same inputs.
  • Reference rotation. ω_ref and the scan span still come from the main ion of the full-composition NTV view, now stated in the docstring. If you want ω_ref itself species-resolved, that is a separate, deliberate change.
  • Pre-existing difference left alone. kinetic_torque passes the near-axis validity boundary axis_psi_c to the torque; efc_couplings never has (suppression off). Folding it in would move the single-ion diiid_error_field rows, so it is flagged here rather than changed.
  • Tests. runtests_error_fields.jl checks ntv_torque_state on the fixture run's own perturbation (no extra plasma-response solves): the main ion resolved on its own reproduces the single-ion torque (rtol 1e-6, the agreement between the resolved view and the NTV view of the same attached profiles), and a D-T set's torque equals the sum of its members' own torques (rtol 1e-12).
  • Develop merge (2323fbdf6). Since the last stamp develop moved efc_couplings out of the driver into ErrorFields/NTVLimits.jl, took the species composition off KineticForcesControl onto the equilibrium's kinetic data, and passes the species identity to compute_torque_all_methods! as keywords. The fix was ported onto that layout: species_control (a per-species copy of the control) and its runtests_multiion.jl test are gone, since nothing builds a per-species control any more, and the error-fields test now takes its species from ffs.equil.kinetic and KineticForces.main_ion.
  • Harness. No case runs the error-field NTV couplings with more than one species, so every tracked ErrorFields/NTV/* row must be unchanged; tj_kinetic_multiion exercises the species sum on the diagnostics path. A multi-species error-field case could be added if those numbers should be tracked.

No review package: a small bug fix, below the threshold for one.

🤖 Generated with Claude Code

https://claude.ai/code/session_0186CLfjeJeSusNTva5RMfGU

…ic species

The error-field NTV couplings computed every correction array's torque for the deck's main
ion alone, while the KineticForces diagnostics of the same run summed over the resolved
species. The run's species list now reaches efc_couplings, whose torque at every rotation
shift is the same species sum with each species' own profiles shifted, and the per-species
control construction is shared by both paths. Single-ion decks are unchanged; the reference
rotation stays the full-composition main ion's.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0186CLfjeJeSusNTva5RMfGU
@logan-nc logan-nc self-assigned this Oct 24, 2026
@github-actions github-actions Bot added bugfix Something was wrong and now is not changed-results Results move or an interface breaks - read before upgrading labels Oct 24, 2026
logan-nc and others added 2 commits October 24, 2026 14:51
…faults with isequal

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0186CLfjeJeSusNTva5RMfGU
…ings into ntv_torque_state

The species sum at one rotation shift becomes a module-level function the couplings call, so the
test can check it on the run's own perturbation instead of re-solving the plasma response.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0186CLfjeJeSusNTva5RMfGU
Resolve against the kinetic profiles now living on the equilibrium: efc_couplings derives the resolved species from the control and the equilibrium instead of taking a species argument, so run_error_fields keeps develop's signature.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0186CLfjeJeSusNTva5RMfGU
@logan-nc
logan-nc requested a review from matt-pharr October 29, 2026 18:36
@logan-nc logan-nc added this to the GPEC v2.1.0 milestone Oct 30, 2026
Port the species sum onto develop's layout: efc_couplings now lives in
ErrorFields/NTVLimits.jl and the species identity is passed to
compute_torque_all_methods! as z/m/electron, so species_control and its
test are dropped and the error-fields test resolves species from the
equilibrium's kinetic data.

@matt-pharr matt-pharr left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good fix that aligns the code with expected behavior. Approve

@matt-pharr
matt-pharr enabled auto-merge November 12, 2026 15:12
@matt-pharr
matt-pharr added this pull request to the merge queue Nov 12, 2026
Merged via the queue into develop with commit 052978b Nov 12, 2026
17 of 18 checks passed
@matt-pharr
matt-pharr deleted the bugfix/ef-ntv-species-sum branch November 12, 2026 15:45
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bugfix Something was wrong and now is not changed-results Results move or an interface breaks - read before upgrading

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants