Process reference: magnetic_island

Generated from the docstrings of vaft.process.magnetic_island: 4 public functions. Each entry is what vaft.process.describe("magnetic_island.<name>") prints. All process categories

Overview

The equilibrium is the only source of plasma geometry. Nothing here takes a major radius, an elongation or a Shafranov shift: the resonant surface comes from the equilibrium’s safety factor, the poloidal angle from its straight-field-line map, and the island’s extent from the flux surfaces’ spacing on the outboard midplane. The island is a prescribed constant-psi perturbation on top of that, not a solution of anything.

Three objects are kept apart, because they are different physics and a phantom that conflates them cannot say which one a synthetic signal is sensitive to::

equilibrium      psi(R, Z), q(psi_N)                       (input)
island topology  helical flux Omega(R, Z; t, phi)          magnetic_island_topology
emissivity       epsilon(R, Z; t, phi)                      island_emissivity

The diagnostic response, a line integral of the emissivity, lives in vaft.process.line_of_sight and vaft.process.soft_x_rays.

SymbolMeaningUnit
psi_Nnormalized poloidal flux, 0 on axis and 1 on the boundary-
psi_N,spsi_N of the resonant surface q = m/n-
theta*PEST straight-field-line poloidal anglerad
phiIMAS toroidal angle, counter-clockwise seen from aboverad
xihelical phase m theta* - sigma n phi - alpha(t)rad
xoutboard-midplane distance of a point's flux surface from the
Wfull island width at the outboard midplanem
Omegahelical flux 8 (x/W)^2 - cos xi, -1 at the O-point, 1 on the

W is the full width at the outboard midplane. x is a flux label measured in metres: the outboard-midplane distance between the flux surface through a point and the resonant surface. On the outboard midplane it is the exact radial distance, so the separatrix branches through an outboard O-point are exactly W apart; elsewhere the island is bounded by the same flux surfaces, as a constant-psi island is, and its geometric width follows the flux expansion, wider where the surfaces spread.

The helical phase is resonant by construction. sigma is the sign of d phi / d theta* along a field line, read from the equilibrium’s field direction, so xi is constant along every field line on the resonant surface whichever way the current and the toroidal field point. phi is the IMAS toroidal angle, the frame of soft_x_rays.channel.line_of_sight.phi.

O-point at xi = 0, X-point at xi = pi. alpha(t) = phase + angular_frequency (t - t0) rotates the island rigidly; at fixed phi the O-point moves to larger theta* when alpha grows. The sign of angular_frequency is therefore a poloidal direction, not a toroidal one: at fixed theta* the pattern moves in the IMAS toroidal angle at d phi / dt = -angular_frequency / (sigma n), so the same spec propagates the opposite way toroidally when the helicity flips (reversed plasma current or toroidal field). A caller matching a measured toroidal phase velocity must fold IslandTopology.helicity in.

Functions

equilibrium_safety_factorThe magnitude of the safety factor on normalized flux, as the equilibrium knows it. Convention
island_emissivityA soft-X-ray emissivity phantom from an island topology. Convention
magnetic_island_topologyThe helical flux of an m/n island placed on an equilibrium. Convention
resolve_rational_surfaceWhere the equilibrium’s own safety factor equals m/n. Convention

equilibrium_safety_factor

Machine-independentConvention-sensitive source
equilibrium_safety_factor(equilibrium)
Show source vaft/process/magnetic_island.py, lines 209–269
def equilibrium_safety_factor(equilibrium) -> tuple[np.ndarray, np.ndarray]:
    """The magnitude of the safety factor on normalized flux, as the equilibrium knows it.

    Parameters
    ----------
    equilibrium : EquilibriumData or source
        An equilibrium record, or anything
        :func:`vaft.process.equilibrium.as_equilibrium` accepts [-].

    Returns
    -------
    tuple of numpy.ndarray
        ``(psi_n, abs(q))``, sorted by increasing ``psi_n`` [-].

    Raises
    ------
    ValueError
        The record carries neither a q profile nor the flux map and poloidal
        current function to compute one, or its flux storage family is unknown.

    Convention
    ----------
    The record's own profile when it has one; otherwise q is computed from the
    flux map and ``F`` by :func:`calculate_q_profile_from_psi` on 97 interior
    levels, which is the case for an analytic Solov'ev export. Only the
    magnitude is returned: resonance is ``|q| = m/n``, and the direction is the
    helicity's job.

    Applicability
    -------------
    Machine-independent.

    Limitations
    -----------
    A computed profile starts at ``psi_n = 0.02`` and ends at ``0.98``, so a
    resonance closer to the axis or the boundary than that is not found.

    Provenance
    ----------
    .. [1] :func:`vaft.process.equilibrium.calculate_q_profile_from_psi`, the
       contour-integral safety factor it falls back to.
    """
    eq = _coerce(equilibrium)
    span = eq.psi_boundary - eq.psi_axis
    if eq.q is not None and eq.psi_1d is not None and eq.q.size == eq.psi_1d.size:
        psi_n = (eq.psi_1d - eq.psi_axis) / span
        q = np.abs(eq.q)
    else:
        if eq.psi is None or eq.f is None or eq.psi_1d is None:
            raise ValueError(
                "the equilibrium has no q profile and lacks the flux map or F to compute one"
            )
        psi_n = np.linspace(0.02, 0.98, 97)
        q = np.abs(np.asarray(calculate_q_profile_from_psi(
            eq.psi, eq.r, eq.z, (eq.psi_1d, eq.f), eq.psi_axis, eq.psi_boundary, psi_n,
            axis_rz=eq.magnetic_axis, cocos=_cocos_for_q(eq),
        ), dtype=float))
    order = np.argsort(psi_n)
    psi_n, q = psi_n[order], q[order]
    keep = np.isfinite(q)
    return psi_n[keep], q[keep]

The magnitude of the safety factor on normalized flux, as the equilibrium knows it.

NameTypeUnitDescription
equilibriumEquilibriumData or source-

An equilibrium record, or anything vaft.process.equilibrium.as_equilibrium accepts.

Returns
—tuple of numpy.ndarray-

(psi_n, abs(q)), sorted by increasing psi_n.

Convention

The record’s own profile when it has one; otherwise q is computed from the flux map and F by calculate_q_profile_from_psi on 97 interior levels, which is the case for an analytic Solov’ev export. Only the magnitude is returned: resonance is |q| = m/n, and the direction is the helicity’s job.

Raises

  • ValueError The record carries neither a q profile nor the flux map and poloidal current function to compute one, or its flux storage family is unknown.
Applicability · Limitations · Provenance

Applicability

Machine-independent.

Limitations

A computed profile starts at psi_n = 0.02 and ends at 0.98, so a resonance closer to the axis or the boundary than that is not found.

Provenance

  1. vaft.process.equilibrium.calculate_q_profile_from_psi, the contour-integral safety factor it falls back to.

island_emissivity

Machine-independentConvention-sensitive source
island_emissivity(topology, *, profile=None, model='flatten', amplitude=1.0, smoothing=0.1, hard_mask=False)

A soft-X-ray emissivity phantom from an island topology.

NameTypeUnitDescription
topologyIslandTopology-

The island on its equilibrium grid, from magnetic_island_topology.

profilecallable or tuple of array_like, optionalemissivity unit

Axisymmetric background epsilon_0(psi_N), as a callable or a (psi_N, values) table; required by model="flatten", zero when omitted for model="island".

modelstr, optional-

"flatten" drives the emissivity inside the island toward its resonant-surface value; "island" adds amplitude times the island mask.

amplitudefloat, optional- or emissivity unit

A: the flattening fraction for "flatten", the added emissivity for "island".

smoothingfloat, optional-

Width of the tanh edge of the island mask, in helical-flux units.

hard_maskbool, optional-

Use the binary mask Omega <= 1 instead of the smooth one.

Returns
—tuple of numpy.ndarrayemissivity unit

(epsilon, delta_epsilon) on the equilibrium grid, indexed (R, Z), zero outside the boundary; delta_epsilon is epsilon - epsilon_0.

Convention

The mask is M = (1 - tanh((Omega - 1)/smoothing)) / 2, one inside the separatrix and zero outside it. "island": delta_epsilon = A M. "flatten": delta_epsilon = A M (epsilon_0(psi_N,s) - epsilon_0(psi_N)), so A = 0 returns the axisymmetric background and A = 1 flattens it to the resonant-surface value inside the island.

Raises

  • ValueError An unknown model, a flattening model without a profile, a non-positive smoothing, or a malformed profile table.
Applicability · Limitations · Provenance

Applicability

Machine-independent.

Limitations

A phenomenological response, not a transport calculation: the flattening is instantaneous and complete to the separatrix, with no dependence on the island’s size against a critical width, and no atomic or filter physics.

Provenance

  1. Le, T. X. K. et al., Plasma Phys. Control. Fusion 68, 065003 (2026), for modelling an island’s SXR signature as flattened emissivity.
  2. Dreval, M. B. et al., Plasma Phys. Control. Fusion 65, 035001 (2023), for a prescribed emissivity perturbation on magnetic surfaces.

magnetic_island_topology

Machine-independentConvention-sensitive source
magnetic_island_topology(equilibrium, island, *, time=0.0, phi=0.0, sfl_map=None)

The helical flux of an m/n island placed on an equilibrium.

NameTypeUnitDescription
equilibriumEquilibriumData or source-

The axisymmetric equilibrium, the only source of geometry; anything vaft.process.equilibrium.as_equilibrium accepts.

islandMagneticIslandSpec-

Mode numbers, outboard-midplane full width and phase.

timefloat, optionals

Time at which to evaluate the island phase.

phifloat, optionalrad

IMAS toroidal angle of the poloidal plane.

sfl_mapStraightFieldLineMap, optional-

A straight-field-line map already built for this equilibrium, to reuse

Returns
—IslandTopology-

The resonant surface, the helicity, the flux width, and on the equilibrium grid theta_star, normal_displacement, helical_phase, helical_flux and inside_separatrix, with the O- and X-point positions.

Convention

Omega = 8 (x/W)^2 - cos(xi) with xi = m theta* - sigma n phi - alpha(t): Omega = -1 at the O-point (xi = 0, x = 0) and Omega = 1 on the separatrix and at the X-point (xi = pi), and the separatrix branches through an outboard O-point are exactly W apart. x = R_out(psi) - R_out(psi_s), where R_out is the outboard-midplane radius of a flux surface, so x is a flux label in metres, exact on the outboard midplane and growing outward; theta* is PEST, zero on the outboard midplane; phi is the IMAS toroidal angle. sigma is the sign of d phi / d theta* along a field line from the equilibrium’s field, so xi is constant along field lines on the resonant surface.

Raises

  • ValueError The resonant surface does not exist, the boundary is not closed on the grid, or the helicity cannot be read from the record and was not given.
Processing steps · Applicability · Limitations · Provenance

Processing steps

  1. Build (or reuse) the straight-field-line map of the equilibrium.
  2. Find psi_N,s from q = m/n, unless the spec overrides it.
  3. Solve the resonant surface; take the helicity from the field direction at its outboard-midplane point.
  4. Form the outboard-midplane displacement and the helical phase on the grid, and from them the helical flux and the separatrix mask.
  5. Locate the O- and X-points on the resonant surface.

Applicability

Machine-independent.

Limitations

A prescribed constant-psi island: no island-induced change of the equilibrium, no finite-width distortion beyond the quadratic flux model, and no island that crosses the boundary is treated specially. The displacement is first order in the flux offset, so an island wide against the local flux-surface curvature is only approximately symmetric.

Provenance

  1. Choi, G. J., Rev. Mod. Plasma Phys. 8, 11 (2024), the constant-psi helical flux.
  2. Le, T. X. K. et al., Plasma Phys. Control. Fusion 68, 065003 (2026), a rotating-island SXR forward model of the same scope on a spherical tokamak.

resolve_rational_surface

Machine-independentConvention-sensitive source
resolve_rational_surface(equilibrium, m, n, *, index=0)
Show source vaft/process/magnetic_island.py, lines 272–347
def resolve_rational_surface(equilibrium, m: int, n: int, *, index: int = 0) -> tuple[float, float]:
    """Where the equilibrium's own safety factor equals ``m/n``.

    Parameters
    ----------
    equilibrium : EquilibriumData or source
        An equilibrium record, or anything
        :func:`vaft.process.equilibrium.as_equilibrium` accepts [-].
    m : int
        Poloidal mode number [-].
    n : int
        Toroidal mode number [-].
    index : int, optional
        Which crossing when ``q`` crosses ``m/n`` more than once, innermost
        first [-].

    Returns
    -------
    tuple of float
        ``(psi_n_s, q_s)``: the normalized flux of the resonant surface and the
        profile's value there, which equals ``m/n`` to the root tolerance [-].

    Raises
    ------
    ValueError
        ``q = m/n`` does not occur in the profile, or ``index`` asks for a
        crossing that does not exist.

    Convention
    ----------
    Resonance is ``|q| = m/n``. The crossings are bracketed by
    :func:`find_rational_surfaces` and each is refined by a root solve on a
    cubic spline through the profile, so the answer is not limited to the
    linear interpolation between samples.

    Applicability
    -------------
    Machine-independent.

    Limitations
    -----------
    Only as good as the profile the equilibrium carries; a reconstruction with
    a poorly constrained core q places a core resonance equally poorly.

    Provenance
    ----------
    .. [1] :func:`vaft.process.equilibrium.find_rational_surfaces` for the
       bracketing.
    """
    from scipy.interpolate import CubicSpline
    from scipy.optimize import brentq

    psi_n, q = equilibrium_safety_factor(equilibrium)
    target = float(m) / float(n)
    found = find_rational_surfaces(psi_n, q, n, m_range=(m, m))
    coarse = np.asarray(found["psi_n_rational"], dtype=float)
    coarse = coarse[np.asarray(found["m"]) == m]
    if coarse.size == 0:
        raise ValueError(
            f"q = {m}/{n} = {target:.4g} does not occur in this equilibrium: |q| spans "
            f"[{np.min(q):.4g}, {np.max(q):.4g}] over psi_N in [{psi_n[0]:.3g}, {psi_n[-1]:.3g}]"
        )
    coarse = np.sort(coarse)
    if not 0 <= index < coarse.size:
        raise ValueError(f"q = {m}/{n} crosses {coarse.size} time(s); index {index} does not exist")
    guess = float(coarse[index])
    unique, first = np.unique(psi_n, return_index=True)
    # anti-alias: not time-domain -- q over normalized flux.
    spline = CubicSpline(unique, q[first])
    j = int(np.clip(np.searchsorted(unique, guess), 1, unique.size - 1))
    lo, hi = unique[j - 1], unique[j]
    f_lo, f_hi = spline(lo) - target, spline(hi) - target
    if f_lo * f_hi > 0.0:
        return guess, float(spline(guess))
    root = float(brentq(lambda s: float(spline(s)) - target, lo, hi, xtol=1e-12))
    return root, float(spline(root))

Where the equilibrium’s own safety factor equals m/n.

NameTypeUnitDescription
equilibriumEquilibriumData or source-

An equilibrium record, or anything vaft.process.equilibrium.as_equilibrium accepts.

mint-

Poloidal mode number.

nint-

Toroidal mode number.

indexint, optional-

Which crossing when q crosses m/n more than once, innermost first.

Returns
—tuple of float-

(psi_n_s, q_s): the normalized flux of the resonant surface and the profile’s value there, which equals m/n to the root tolerance.

Convention

Resonance is |q| = m/n. The crossings are bracketed by find_rational_surfaces and each is refined by a root solve on a cubic spline through the profile, so the answer is not limited to the linear interpolation between samples.

Raises

  • ValueError q = m/n does not occur in the profile, or index asks for a crossing that does not exist.
Applicability · Limitations · Provenance

Applicability

Machine-independent.

Limitations

Only as good as the profile the equilibrium carries; a reconstruction with a poorly constrained core q places a core resonance equally poorly.

Provenance

  1. vaft.process.equilibrium.find_rational_surfaces for the bracketing.

results matching ""

    No results matching ""