Skip to content

q(psi) from a psi map and F(psi) #647

Description

@HongSik-Yun-Fusion

The gap

Nothing in VAFT computes q(psi) from a psi map and an F(psi) profile.
Verified by searching claude/vaft-vfit-foundation for safety factor,
q_profile, def q, qpsi, q_95: everything that exists runs the other
way, or consumes a q that came from somewhere else.

  • vaft/formula/equilibrium.py:335 q_from_phi(psi, phi) — needs the toroidal
    flux already.
  • vaft/omas/update.py:629 update_equilibrium_profiles_1d_toroidal_flux — goes
    q -> Phi -> rho_tor, i.e. it consumes q.
  • vaft/omas/update.py:270 update_equilibrium_global_quantities_q_min — reads
    profiles_1d.q.min().
  • vaft/data/eqdsk.py:937,964q and q_95 are only ever read in from a
    g-file's QPSI.

So any ODS whose equilibrium was computed natively rather than imported from a
g-file has no route to q at all.

Proposed addition

q(psi) = sigma * F(psi) * <1/R^2> * (dV/dpsi) / (2*pi)^2

All three inputs are already outputs of
vaft.process.equilibrium.flux_surface_quantities
(vaft/process/equilibrium.py:1385): gm1 = <1/R^2>, dvolume_dpsi, and
f_profile is already an accepted keyword argument on the same call. So this is
a small, well-posed addition on top of machinery that exists and is tested.

Points to settle in review:

  • Units. flux_surface_quantities returns dvolume_dpsi per radian, and
    its psi_grid contract is Wb/rad. The (2*pi)^2 above assumes that; state the
    convention explicitly and test it, since a 2π slip here is invisible in the
    profile shape and only shows up in the magnitude.
  • Sign (sigma) follows the COCOS convention already resolved by
    vaft.process.equilibrium.as_equilibrium(...).convention.
  • On-axis limit. flux_surface_quantities documents that its innermost one
    or two levels are the least accurate anywhere, and that volume/area are
    exactly 0 at levels_norm == 0. q_axis needs an explicit extrapolation
    policy rather than whatever falls out of a 0/0.

Why now

Three consumers, immediately:

  1. VFIT's FluxGSResult.q_profile is a nan placeholder
    (vfit/flux_gs.py:769) with nothing to fill it.
  2. update_equilibrium_derived_profiles chains through the toroidal-flux step,
    which consumes q — so a natively-computed equilibrium may not complete the
    chain (see VEST-Tokamak/vfit#43).
  3. A q-on-a-surface reconstruction constraint (EFIT-style) needs it.

Per VFIT's CLAUDE.md responsibility split, this is a physics formula useful to any
VEST analysis code, so it belongs here rather than in VFIT.

Activity

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

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions