Process reference: q_profile_context

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

Overview

Descriptors only. core_q_context answers what the equilibrium looks like where core n=1 physics lives: q landmarks and the shape of the profile, every rational crossing with its signed local shear, the q=1 surfaces, how far q_min sits from low-order rationals, same-helicity (double-resonant) pairs, low-shear regions under an explicit threshold, the plasma-boundary topology with q95 and q_boundary kept apart, and the pressure context of those regions where the profiles exist. It never says that an internal kink, infernal mode, fishbone, sawtooth or double tearing is present: that needs a stability calculation (#1635 reduced theory, #1429 DCON/RDCON, #1800 branch tracking) consuming this context.

Built on the canonical primitives rather than beside them: vaft.process.equilibrium.rational_surfaces for every crossing (|q| = |m/n|, never bridging a NaN gap), vaft.formula.equilibrium.shear_from_r_q for shear, and vaft.process.equilibrium.derive_boundary_representation with vaft.data.equilibrium.Topology for the boundary.

Functions

core_q_contextCore q / rational / low-shear / boundary context of one ODS equilibrium slice. Convention
core_q_context_from_profilesCore q-profile, rational-surface, low-shear and boundary context from 1-D profiles. Convention
low_shear_regionsConnected radial intervals where |s| < threshold.

core_q_context

Machine-independentConvention-sensitive source
core_q_context(ods, time_slice=0, **options)

Core q / rational / low-shear / boundary context of one ODS equilibrium slice.

NameTypeUnitDescription
odsODS-

Holding equilibrium.time_slice[time_slice].profiles_1d psi and q, and global_quantities psi_axis/psi_boundary.

time_sliceint, optional-

The slice to read; any further keyword (rationals, shear_thresholds, …) is passed to core_q_context_from_profiles.

Returns
contextCoreQContext-

The descriptors of that slice.

Convention

As core_q_context_from_profiles. psi_n = (psi - psi_axis) / (psi_boundary - psi_axis), which is COCOS-independent.

Raises

  • KeyError The slice has no profiles_1d.psi or q, or no axis/boundary flux.
  • ValueError psi_axis equals psi_boundary (an empty slice).
Processing steps · Input semantics · Output semantics · Applicability · Limitations · Provenance

Processing steps

  1. Read psi, q and, where present, rho_tor_norm, pressure and volume from profiles_1d; normalize psi by the axis and boundary flux.
  2. Classify the boundary with derive_boundary_representation; an equilibrium it cannot classify is unknown with the reason.
  3. Hand everything to core_q_context_from_profiles.

Input semantics

One reconstructed equilibrium slice; read without creating ODS paths.

Output semantics

Descriptors of that equilibrium; no mode label.

Applicability

Machine-independent.

Limitations

A profile missing from the slice is omitted, never synthesized: without volume there is no enclosed pressure, without pressure no drive context.

Provenance

  1. Issue #1798, core q / rational / low-shear / boundary context.

core_q_context_from_profiles

Machine-independentConvention-sensitive source
core_q_context_from_profiles(psi_n, q, *, rho_tor_norm=None, pressure=None, volume=None, rationals=((1, 1), (3, 2), (2, 1), (5, 2), (3, 1)), shear_thresholds=(0.1,), near_rational_delta_q=0.1, weak_shear=0.1, tangency_atol=0.001, q_noise_atol=0.02, q_noise_rtol=0.02, boundary_topology='unknown', boundary_reason='not supplied', time_slice=None, time=None)

Core q-profile, rational-surface, low-shear and boundary context from 1-D profiles.

NameTypeUnitDescription
psi_narray_like-

Normalized poloidal flux, increasing, 0 on axis and 1 at the boundary.

qarray_like-

Safety factor on psi_n, of either sign.

rho_tor_normarray_like, optional-

Normalized toroidal-flux radius on the same grid; without it every radius and shear is in sqrt(psi_n) and named so.

pressurearray_like, optionalPa

Pressure on the same grid, for the region drive context.

volumearray_like, optionalm^3

Volume enclosed by each surface, for the pressure inside q=1.

rationalssequence of (int, int), optional-

The (m, n) to locate and measure q_min against.

shear_thresholdssequence of float, optional-

Each |s| bound to report low-shear regions for; a scan, not one universal value.

near_rational_delta_qfloat, optional-

The |q - m/n| bound of the near-rational low-shear regions.

weak_shearfloat, optional-

|s| below which a profile with no extremum is called weak_shear rather than monotonic.

tangency_atolfloat, optional-

|q - m/n| at q_min or at a turning point within which an uncrossed rational is flagged as a possible tangency between samples.

q_noise_atolfloat, optional-

How far |q| must move back from an extremum before the profile is said to turn there; wiggles smaller than this are not shape.

q_noise_rtolfloat, optional-

The same, as a fraction of |q|; the larger of the two applies.

boundary_topologystr, optional-

Boundary topology already known to the caller.

boundary_reasonstr, optional-

Why that topology was, or could not be, decided.

time_sliceint, optional-

The slice index to record.

timefloat, optionals

The time of that slice to record.

Returns
contextCoreQContext-

The descriptors, with every threshold and the radial coordinate recorded.

Convention

Every q is |q|; q_sign keeps the source’s sign. Shear is d ln|q| / d ln rho in the recorded coordinate, signed, so the two surfaces of a reversed-shear pair have opposite signs. q_axis is |q| at the first sample and q_min the smallest |q|: they are equal only for a monotonic profile. A first sample more than AXIS_Q_OUTLIER_RATIO from its neighbours (the EFIT q0 artifact, #317) is reported as q_axis with axis_q_outlier set and left out of every derived field, never repaired. A rho_tor_norm that is the sqrt(psi_n) proxy (#276) is named as the poloidal radius it is. The profile turns only where |q| moves back by more than max(q_noise_atol, q_noise_rtol |q|).

Raises

  • ValueError The profiles are not 1-D and of equal length, fewer than three samples are finite, psi_n does not increase, or a threshold is not positive.
Processing steps · Input semantics · Output semantics · Applicability · Limitations · Provenance

Processing steps

  1. Take |q| (resonance is |q| = |m/n|) and record the sign the source gave it.
  2. Choose the radius (rho_tor_norm or sqrt(psi_n)) and take the shear (rho/|q|) d|q|/drho in it.
  3. Locate q_axis, q_min and its place, and read the profile’s shape from the sign changes of d|q|.
  4. Locate every rational crossing with rational_surfaces, attach its interpolated shear, pair same-m/n neighbours, and measure q_min - m/n for every requested rational.
  5. Find the low-shear and near-rational low-shear intervals for each threshold, and the pressure enclosed by each q=1 surface when a volume profile is given.

Input semantics

Profiles of one equilibrium slice on one grid; nothing is fabricated for a profile that is not given.

Output semantics

Descriptors of the equilibrium, not of a mode: no field says an instability is present.

Applicability

Machine-independent.

Limitations

Linear interpolation between samples, as rational_surfaces: a rational touched between two samples is not a crossing and appears only as tangent_candidate. Interval edges are at sample resolution. q95 is interpolated at psi_n = 0.95; q_boundary is reported only for a limited boundary, since on a separatrix it is not a finite boundary q.

Provenance

  1. Issue #1798, core q / rational / low-shear / boundary context.

low_shear_regions

Machine-independent source
low_shear_regions(rho, shear, threshold, *, psi_n=None, q=None, pressure=None)
Show source vaft/process/q_profile_context.py, lines 292–367
def low_shear_regions(rho, shear, threshold, *, psi_n=None, q=None, pressure=None) -> tuple[LowShearRegion, ...]:
    """Connected radial intervals where ``|s| < threshold``.

    Parameters
    ----------
    rho : array_like
        Radial coordinate, increasing; the one the shear was taken in [-].
    shear : array_like
        Magnetic shear on ``rho`` [-].
    threshold : float
        The ``|s|`` bound, always explicit: no value of it is a stability boundary [-].
    psi_n : array_like, optional
        Normalized poloidal flux on the same grid, for the ``psi_n`` edges [-].
    q : array_like, optional
        Safety factor on the same grid, for the q range and q=1 containment [-].
    pressure : array_like, optional
        Pressure on the same grid, for the drive-context descriptors [Pa].

    Returns
    -------
    regions : tuple of LowShearRegion
        Every interval, innermost first, at sample resolution [-].

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

    Limitations
    -----------
    Intervals end at the last sample inside, without interpolating the
    threshold crossing, so a width is resolved to the grid spacing. An interval
    is closed only by a sample outside it: a non-finite shear sample breaks it.
    ``contains_q_min`` compares against the global ``|q|`` minimum on the grid.
    """
    if not threshold > 0:
        raise ValueError(f"threshold must be positive, not {threshold!r}")
    rho = np.asarray(rho, dtype=float).ravel()
    shear = np.asarray(shear, dtype=float).ravel()
    if rho.shape != shear.shape:
        raise ValueError(f"rho and shear differ in length: {rho.size} vs {shear.size}")
    psi = rho if psi_n is None else np.asarray(psi_n, dtype=float).ravel()
    q_abs = None if q is None else np.abs(np.asarray(q, dtype=float).ravel())
    p = None if pressure is None else np.asarray(pressure, dtype=float).ravel()
    inside = np.isfinite(shear) & (np.abs(shear) < threshold)
    i_min = None if q_abs is None or not np.isfinite(q_abs).any() else int(np.nanargmin(q_abs))
    regions = []
    for i, j in _interval_edges(rho, inside):
        sl = slice(i, j + 1)
        q_lo = q_hi = math.nan
        contains_q1 = False
        if q_abs is not None:
            q_lo, q_hi = float(np.nanmin(q_abs[sl])), float(np.nanmax(q_abs[sl]))
            contains_q1 = bool(q_lo <= 1.0 <= q_hi)
        pressure_fields: dict[str, Optional[float]] = {}
        if p is not None and np.isfinite(p[sl]).all():
            pressure_fields["pressure_drop"] = float(p[i] - p[j])
            if j > i:
                gradient = np.gradient(p[sl], rho[sl])
                pressure_fields["mean_abs_pressure_gradient"] = float(np.mean(np.abs(gradient)))
                pressure_fields["max_abs_pressure_gradient"] = float(np.max(np.abs(gradient)))
        regions.append(LowShearRegion(
            threshold=float(threshold),
            rho_start=float(rho[i]),
            rho_end=float(rho[j]),
            psi_n_start=float(psi[i]),
            psi_n_end=float(psi[j]),
            contains_axis=bool(i == 0),
            contains_q_min=bool(i_min is not None and i <= i_min <= j),
            contains_q1_surface=contains_q1,
            q_low=q_lo,
            q_high=q_hi,
            mean_shear=float(np.mean(shear[sl])),
            max_abs_shear=float(np.max(np.abs(shear[sl]))),
            **pressure_fields,
        ))
    return tuple(regions)

Connected radial intervals where |s| < threshold.

NameTypeUnitDescription
rhoarray_like-

Radial coordinate, increasing; the one the shear was taken in.

sheararray_like-

Magnetic shear on rho.

thresholdfloat-

The |s| bound, always explicit: no value of it is a stability boundary.

psi_narray_like, optional-

Normalized poloidal flux on the same grid, for the psi_n edges.

qarray_like, optional-

Safety factor on the same grid, for the q range and q=1 containment.

pressurearray_like, optionalPa

Pressure on the same grid, for the drive-context descriptors.

Returns
regionstuple of LowShearRegion-

Every interval, innermost first, at sample resolution.

Applicability · Limitations

Applicability

Machine-independent.

Limitations

Intervals end at the last sample inside, without interpolating the threshold crossing, so a width is resolved to the grid spacing. An interval is closed only by a sample outside it: a non-finite shear sample breaks it. contains_q_min compares against the global |q| minimum on the grid.

results matching ""

    No results matching ""