Skip to content

Equilibrium - g-file reader differentiates FPOL and PRES and discards FFPRIM and PPRIME, putting rounding noise on Δ′ #504

Description

@d-burg

Summary

For eq_type = "efit", read_efit parses FFPRIM and PPRIME and discards them. F′ and p′ then come from cubic splines of FPOL and PRES. F′ enters the Euler-Lagrange matrices directly (jtheta = -F′), and Δ′ depends on how F′ varies across each rational surface. F changes by only a few percent across the plasma, so rounding noise in FPOL leaves F′ nearly right in value (0.04 % rms) but wrong in slope at the node scale: the error in dF′/dψ grows as roughly 1/(h²δ) (h = node spacing, δ = fractional variation of F). On 257-node g-files written in single precision this puts noise of a few units on Δ′(2/1).

Evidence

Static, in-repo file. examples/DIIID-like_ideal_example/TkMkr_D3Dlike_Hmode.geqdsk (257 nodes; every FPOL value is exactly a single-precision number). The spline F′ matches FFPRIM/F to 0.04 % rms, but its slope scatters about the FFPRIM-derived slope by up to 37 % near q = 2. No F″ is formed explicitly; the slope enters through the ψ-variation of the splined coefficient matrices:

Image

Same state, two g-files. Five pairs of g-files of one equilibrium state (inputs agree to 1e-5) gave Δ′(2/1) differing by up to 6.2 (rms 3.7). The gap is unchanged on develop, on an identical fixed ψ grid, and with #398, #480 and #491 applied. Swapping only the FPOL block between the two files moves 82–101 % of the gap with it. Rebuilding FPOL as the integral of the file's own FFPRIM closes it (rms 0.17).

Noise ladder. Seeded relative noise on FPOL shifts Δ′(2/1) linearly, about 9e7 × noise: 0.15 at 1e-9, 2.1 at single precision (2.4e-8). The same experiment on FFPRIM is about 900 times less sensitive.

Image

Ten g-files of different provenance. Δ′(2/1), n = 1, Riccati, auto grid:

writer, nodes, precision of FPOL as written F from FFPRIM F and P from FFPRIM, PPRIME
TokaMaker 257, single (the in-repo example above) 9.21 7.27 7.29
TokaMaker 257, single 5.89 6.25 6.11
TokaMaker 257, single 16.48 14.40 14.52
TokaMaker 257, single 9.43 9.12 9.10
TokaMaker 257, single (near a Δ′ pole) −29.1 −0.03 −39.0
EFIT 257, double −1.56 −1.42 −1.40
kinetic EFIT 257, single −10.10 −6.83 −5.46
EFIT 129, single 2.76 2.93 2.96
kinetic EFIT 129, single 3.03 2.86 3.00
EFIT 65, double −3.981 −3.974 −3.974

The effect grows with g-file resolution and with single precision: negligible at 65 nodes, about ±0.2 at 129, units at 257 single precision. Rebuilding P as well changes 2/1 by ≤ 0.14 on eight of ten files.

Caveats for a fix

  • FFPRIM is not clean at the end nodes of TokaMaker files (axis-node spike, last-node drop). The 2/1 result is insensitive to how these are integrated (12.35 spline quadrature, 12.50 trapezoid), but an edge 4/1 entry is not (13 as written, 35 or 50 rebuilt). A fix needs an explicit end-node treatment.
  • For P the question is consistency, not noise: where PRES and PPRIME disagree the result moves (kinetic EFIT 257 above, and outer surfaces), and these tests do not say which array is right.
  • Every efit-type result will move, including the regression cases built on the in-repo example.

Notes

  • Upstream: TokaMaker's gs_save_eqdsk writes every array as REAL(x,4). Writing doubles would reduce the noise to the 9-digit print limit (about ±0.1 here), but would not help existing files or single-precision EFIT output.
  • The Fortran reader has the same behaviour, and its CHEASE reader already builds P by integrating the file's dp/dψ.
  • Runs: commit 1b385a504; read_efit is unchanged on develop 57ec7e16a. Settings: psilow = 0.01, psihigh = 0.998, mtheta = 512, delta_mlow = delta_mhigh = 8, qlow = 1.02, dmlim = 0.2, sing_order = 6.

Activity

  1. d-burg commented on Oct 5, 2026

    @d-burg
    CollaboratorAuthor

    Correction to the first caveat above. The large 4/1 changes (13 as written, 35 or 50 rebuilt) came from rebuilding F alone, which leaves it inconsistent with the as-written P near the edge. With F and P both rebuilt from FFPRIM and PPRIME:

    • the same-state gap stays closed on all three surfaces (rms B − A: 2/1 0.16, 3/1 0.17, 4/1 0.22; as written 3.70, 0.67, 1.20);
    • 4/1 returns to or near its as-written value in three of five pairs (for example −16.7 → −16.6) and is 4–7 away in the others.

    So a fix should take F and P together from FFPRIM and PPRIME, never one alone. The end-node features remain an open but smaller question. Rebuilding P alone moves Δ′(2/1) by ≤ 0.27 on eight of the ten files; the kinetic EFIT 257 file moves by 2.1, cause not yet identified.

  2. d-burg commented on Oct 9, 2026

    @d-burg
    CollaboratorAuthor

    Update: the writer fix is enough for new files; the GPEC-side change (#506) is parked

    OpenFUSIONToolkit/OpenFUSIONToolkit#358 (merged 2026-10-07) makes TokaMaker's gs_save_eqdsk write doubles instead of single precision. I tested it with GPEC unchanged.

    Test. bouquet's public D3D-like H-mode example: four equilibria, each written by the old and the new writer from the same solver state (one OFT build with only that change added). develop 0e68a0553, n = 1, Riccati, settings as in the issue.

    Same state, two g-files whose inputs differ only in the last digits. rms gap in Δ′ over three states:

    grid writer 2/1 3/1 4/1
    ldp 256 single 0.29 0.83 1.08
    ldp 256 double 0.014 0.021 0.088
    ldp 512 single 1.28 1.98 1.26
    ldp 512 double 0.07 0.08 0.13
    auto single 1.76 2.25 1.59
    auto double 0.42 0.14 0.41

    Why #506 is parked. Integrating FF′ and p′ needs an assumed shape between nodes, and near profile kinks that assumption moves Δ′ by more than the noise it removes.

    Still open.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions