Skip to content

efit_to_boozer assumes a poloidal-field sign convention, so the lhs/rhs handedness labels are exchanged for half of valid GEQDSK inputs #405

Description

@krystophny

efit_to_boozer derives the field-line helicity from a hard-coded poloidal-field rule, so it is wrong for half of all valid GEQDSK inputs, and it names the two handedness output files accordingly.

What happens

src/magfie/field_divB0.f90:245-246 forms the poloidal field as

Brad = -dpsidz/rrr
Bzet =  dpsidr/rrr

That is one specific choice of the Sauter–Medvedev sigma_Bp (Computer Physics Communications 184 (2013) 293, Table I). A GEQDSK does not carry a COCOS label, and both signs of sigma_Bp occur in files that are otherwise perfectly valid. When the input uses the other one, every poloidal-field component libneo derives from it is reversed.

That reversal reaches the output through src/efit_to_boozer/field_line_integration_for_Boozer.f90:108:

sigma = sign(1.d0, Bz*Bp)

sigma is the field-line screw direction, and app/efit_to_boozer.f90:96-97,202-207,214-220 uses it to decide which of fromefit_neo_lhs.bc and fromefit_neo_rhs.bc receives the flipped sine coefficients, the flipped iota and the flipped Jpol. With the poloidal field reversed, sigma comes out with the wrong sign and the two named output files are exchanged.

Evidence

An ITER CHEASE equilibrium (nw=nh=513) declaring current = +1.5563913e7 A, bcentr = +5.3 T, fpol > 0, with psi increasing outward. Ampère's law on the file's own psi, integrated on closed psi contours, under the two candidate rules:

psi_n Bzet = -dpsidr/rrr Bzet = +dpsidr/rrr (libneo)
0.60 +1.0208e7 A -1.0208e7 A
0.90 +1.3470e7 A -1.3470e7 A
0.98 +1.5113e7 A -1.5113e7 A

Only the first reproduces the declared +1.5564e7 A, closing to 97.1% at psi_n = 0.98 and rising. The magnitude agreement also confirms psi is per radian. So this file needs the rule libneo does not use.

Measuring the emitted charts against a field line traced from the same EQDSK — sigma_theta from the signed poloidal area the file's own rmnc/rmns/zmnc/zmns sweep, sigma_phi from sign(iota_file/iota_traced):

file name claims measured sigma_theta measured sigma_phi measured handedness
fromefit_neo_lhs.bc left-handed (s,theta,phi) +1 -1 right
fromefit_neo_rhs.bc right-handed (s,theta,phi) -1 -1 left

The traced |iota| matches the printed |iota| to 1.2e-4, so the geometry and the transform itself are fine. Only the handedness bookkeeping is wrong.

Why it matters

Consumers act on the file name and on the sign of iota. NEO-RT, for instance, fixes sign_theta = -1.0 at compile time for a left-handed (s,theta,phi) and applies no check, so it will silently consume the file that is labelled left-handed but is not.

Suggested fix

Do not assume the rule. A GEQDSK carries current and bcentr redundantly with psi, and that redundancy determines the rule uniquely: integrate B_pol . dl on a closed psi contour under both signs and keep the one whose enclosed current matches the declared current in sign. It costs one contour integral at startup, and it converts a silent wrong answer into a derived one. Refusing outright when the two disagree would also be an improvement over the present behaviour.

Reproducer

diagnostics/python/verify_eqdsk_boozer_chart_helicity.py in https://gitlab.tugraz.at/plasma/proj/plasma-sign-conventions (private), with a manufactured large-aspect-ratio oracle in tests/test_eqdsk_boozer_chart_helicity.py. Happy to extract a standalone script if that is useful.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions