Fix inverted q95 to qbar transform in Peng TART scalings - #4533
Conversation
calculate_plasma_current_peng (i_plasma_current=2) and the TART branch of calculate_surface_averaged_poloidal_field derived qbar as q95 * 1.3 * (1 - eps)^0.6. The documented Peng/STAR relation is q95 = 1.3 * qbar * (1 - eps)^0.6, so recovering qbar from q95 requires division; before the pure-Python refactor (ukaea#3320) the input safety factor was interpreted as qbar directly and q95 was derived from it with exactly this forward relation, keeping the pair self-consistent. The multiply/divide inversion under-computed qbar by (1.3 * (1 - eps)^0.6)^2, overestimating plasma current by ~57% at A=1.8. With the fix, the Peng scaling at the ST regression geometry (q95=6, A=1.8, a=2.5 m, B_T=3 T, kappa=2.8) gives 22.5 MA, consistent with the 22.9 MA the independent i_plasma_current=9 scaling produces for the same machine; the inverted transform gave 35.2 MA. Adds the first unit tests for plasma_current.py: hand-derived reference values for the current and bpol, a round-trip check on the transform, and a consistency check that both call sites share the same qbar. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
Correction to the 'Behavioural impact' section above: the regression MFILEs are not fully unchanged — the diagnostic comparison entry |
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #4533 +/- ##
=======================================
Coverage 49.32% 49.32%
=======================================
Files 150 150
Lines 29802 29802
=======================================
Hits 14700 14700
Misses 15102 15102 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
|
@chris-ashe @ajpearcey |
…st rationale - Attribute the relation q95 = 1.3*qbar*(1-eps)^0.6 to Muldrew et al., Fusion Eng. Des. 154 (2020) 111530, Eq. (19), in both call-site comments (previously attributed to Peng, Galambos & Shipe 1992, which was not verified). - Correct the STAR/Peng section of plasma_current.md, which stated the inverse (qbar = q95 * 1.3(1-eps)^0.6, describing the post-ukaea#3320 code), and cite [^10]. Fix the mis-parenthesised formula in the interactive figure's callback and in documentation/scripts/plotting_scripts/ profile_peng_qbar.py ((1 - eps^0.6) -> (1-eps)^0.6, and the direction); the figure's baked-in initial data array should be regenerated from the script at the next docs build. - Remove the physical-ordering rationale ('qbar > q95 for any eps > 0') from the test docstring and the corresponding assert: the relation gives qbar > q95 only for A < 2.82, and the ordering is a property of the fit, not a first-principles requirement. The fix rests on Muldrew Eq. (19) and the pre-ukaea#3320 implementation. - Remove the stale '(= q-bar for i_plasma_current=2)' from the q95 parameter docstring in calculate_plasma_current. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Closes #4532
Overview
The q95 → q̄ transform in the two
i_plasma_current=2(Peng TART/STAR) call sites multiplied by1.3*(1-eps)^0.6where inverting the relationq95 = 1.3*q̄*(1-eps)^0.6requires division.Source for the direction of the relation: Muldrew et al., "PROCESS": Systems studies of spherical tokamaks, Fusion Eng. Des. 154 (2020) 111530, Eq. (19): "q̄ is the 'edge' safety factor and is related to q95 through q₉₅ = 1.3 q̄ (1.0 − ε)^0.6", with the Peng current in Eq. (18) written in terms of q̄. The pre-#3320 code implemented exactly this direction: the input safety factor was taken as q̄ and q95 was derived as
q * 1.3*(1-eps)**0.6(v2.5.0process/physics.py:52-55; Fortranphysics_variables.f90documentsqas "mean edge safety factor qbar" for icurr=2). #3320 (Oct 2024) removed that branch and introducedqbar = q95 * 1.3*(1-eps)**0.6at both call sites, and rewrote the docs section to match — so the current docs page describes the inverted code rather than Muldrew Eq. (19). Detail in the issue.Changes
process/models/physics/plasma_current.py(calculate_plasma_current_peng) andprocess/models/physics/plasma_fields.py(calculate_surface_averaged_poloidal_field, TART branch): divide by1.3e0 * (1 - eps)**0.6e0; comments cite Muldrew Eq. (19). Also removes the stale "(= q-bar for i_plasma_current=2)" from theq95parameter docstring (a vestige of the two-variable scheme; wrong under either form).documentation/source/physics-models/plasma_current/plasma_current.md(STAR/Peng section): the printed relation corrected to Muldrew Eq. (19) with the existing [^10] citation; the embedded interactive figure's callback corrected. The same formula indocumentation/scripts/plotting_scripts/profile_peng_qbar.pywas also mis-parenthesised ((1 − ε^0.6)for(1−ε)^0.6) — fixed; the figure's baked-in initial data array should be regenerated from the script when the docs are next built.tests/unit/models/physics/test_plasma_current.py(first dedicated test file for this module — Peng/bpol goldens already existed intest_physics.py): reference values for the corrected current and bpol at ST parameters, an algebraic round-trip on the transform, and a consistency check that both call sites share the same q̄.tests/unit/models/physics/test_physics.py: the four existing Peng/bpol expected values at A=2.7 and A=3.0 are updated. Justification per CONTRIBUTING: they were generated from the inverted code and pinned it; fixed/old ratios are 0.970038 (−3.00%) and 1.038908 (+3.89%) respectively, i.e.(1.3*(1-eps)^0.6)^2.Behavioural impact
Selected-model outputs change only for
i_plasma_current=2runs; none of the eight shipped regression inputs selects it. At fixed inputs the corrected Peng current and bpol scale by(1.3*(1-eps)^0.6)^2relative to the old code: −62% at A=1.4, −36% at A=1.8, −3.0% at A=2.7, +3.9% at A=3.0. A re-optimised design need not show that drop directly — on the shipped ST case switched to icurr=2 the optimiser holds Ip nearly constant and moves q95 instead (Ip 23.2 → 22.9 MA; q95 9.08 → 5.89; P_net 132 → 102 MW), i.e. the old code was reporting ~55% more edge-q margin than the machine had.Cross-check at fixed inputs (shipped ST geometry, q95 = 6.41): corrected Peng 21.0 MA vs the independent icurr=9 FIESTA scaling 22.9 MA (−8%), IPDG89 23.0 MA, Peng-analytic 22.1 MA; the old code gave 32.9 MA (+43% vs FIESTA). The −8% is consistent with Muldrew's own Peng-vs-FIESTA comparison (Fig. 2, up to 20% under at high κ).
Regression CI: the always-on diagnostic
c_plasma_peng_double_null(Peng current reported for every tokamak run regardless of the selected model) changes by the fix's factor on the five tokamak inputs (e.g. st_regression 3.291e7 → 2.102e7 A; +3.9% on the A=3 machines). In the CI logs each failing regression comparison shows exactly that one variable; on the local st_regression run it is the only non-metadata MFILE difference. Those references need re-baselining on merge.improve_quality_checkalso fails on this branch:calculate_plasma_currentC901 complexity 13 > 12 — pre-existing onmain, the function is untouched.Verification
unit-test(ubuntu, macos) green.q95againstq95_mincomputed from Muldrew's Eq. (17) q̄ᵐⁱⁿ = 3(1+2.6ε^2.8) — a q̄ quantity — since :3263 update the plasma current section of the docs to show and explain all models #3320 mergedqintoq95; and the icurr=2 OUT.DAT label "Mean edge safety factor (q95)" (plasma_current.py:158) is another vestige of the same scheme.Correction to an earlier version of this description
An earlier version of this text, and the test docstring, justified the direction with "q̄ > q95, which the forward relation requires for any ε > 0". That was wrong as stated — the relation gives q̄ > q95 only for A < 2.82 (1.3(1−ε)^0.6 < 1), and q̄ < q95 at A = 3 — and was in any case a property of the fitted relation, not physics. It has been removed from the docstring in this branch's second commit. The fix rests on Muldrew Eq. (19) and the pre-#3320 implementation.
Found during an independent audit of v3.4.2.