Process reference: resistive_zeff

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

Overview

Infers one scalar Zeff_resistive over a time window: the effective charge a stated parallel-conductivity model needs to reproduce the plasma resistance observed through Romero’s transformer balance (issue #1214). It is a model-inferred quantity, not the composition value sum n_i Z_i^2 / n_e; it absorbs every error in T_e, the equilibrium, the boundary voltage, the conductivity model and any non-inductive current, and is named and stored so that nobody mistakes it for a measurement. Nothing here writes core_profiles.zeff.

The chain, and where each step’s state changes::

boundary flux psi_B, I_p, li_3 per slice          [RomeroBoundaryFlux]
-> smoothed in time, differentiated               [Smoothing]
-> V_B, V_I, V_R = V_B - V_I, R_p = V_R/(I_p - I_ni)  [ObservedResistance]
flux-surface state: T_e, n_e, <J.B>, <B^2>, V(psi) [FluxSurfaceState]
-> sigma_par(Z) -> P_Ohm(Z) -> R_p^model(Z)        [ModelResistance]
-> bounded scalar fit of V_R^model(Z) to V_R^obs   [ResistiveZeffInference]
SymbolMeaningUnit
psi_Bboundary poloidal flux, full flux in Romero's signWb
V_Bboundary loop voltage, -d psi_B / dtV
V_Iinductive voltage, L_i dI_p/dt + I_p/2 dL_i/dtV
V_Rresistive voltage, V_B - V_I = R_p (I_p - I_ni)V
L_idimensional internal inductance, mu0 R0 li_3 / 2H
<J.B>flux-surface average of J.BA T m^-2
<B^2>flux-surface average of B^2 (IMAS gm5)T^2
sigma_parparallel electrical conductivityS m^-1

Romero’s voltage convention, full webers. Every voltage is V = -d psi/dt on the full flux, so a positive V_B sustains a positive I_p (issue #781). This is not the Ejima convention of vaft.formula.equilibrium.loop_voltage_from_total_flux (+2 pi d psi/dt on a per-radian flux, #354): the observed path accepts a RomeroBoundaryFlux only, which carries its convention tag, and refuses anything else rather than guess which one an array is in.

Ohmic power, not j_tor. The model resistance is the flux-surface Ohmic dissipation over the current squared, R_p = int <E.B><J.B>/<B^2> dV / I_p^2 with <E.B> = (<J.B> - <J_bs.B>) / sigma_par. V_R I_p is the same dissipation in Romero’s balance, so the two sides are one definition. The parallel current is never replaced by j_tor – they differ at VEST aspect ratio (#1214 Sec. 7.2).

One scalar, not a profile. A single global resistance constrains a single amplitude; the inferred Z_eff is held constant across radius and across the inference window (#1214 Sec. 10). The forward model accepts a prescribed profile Z_eff(psi) – one from an impurity model, say (#1566) – to project it onto the resistance; it is never fitted.

Plasma current from the reconstruction. I_p in R_p = V_R/I_p and in the flux-surface state is the equilibrium’s global_quantities.ip, not the Rogowski: the current that normalises <J.B> and the one that divides V_R are then the same number (#1514). On Tier A they differ from the Rogowski by 5-10 %.

Functions

infer_resistive_zeffBounded scalar Z_eff that makes the model resistive voltage match the observed one.
model_resistancePlasma resistance a conductivity model predicts from the flux-surface Ohmic power. Convention
observed_resistanceResistive voltage and plasma resistance from Romero’s transformer balance. Convention
parallel_conductivityParallel electrical conductivity on every surface of a flux-surface state. Convention
per_slice_resistive_zeffZ_eff solved at each state on its own: a diagnostic of the window estimate.
resistive_zeff_sensitivityNominal resistive Z_eff and how far each input moves it.
smooth_local_polynomialLocal least-squares polynomial smoothing on a non-uniform time axis.

infer_resistive_zeff

Machine-independent source
infer_resistive_zeff(observed, states, *, model, ln_lambda, bounds, weights, time_tolerance_s=5e-05, scan_points=41)

Bounded scalar Z_eff that makes the model resistive voltage match the observed one.

NameTypeUnitDescription
observedObservedResistanceany

Observed V_R history from observed_resistance.

statessequence of FluxSurfaceStateany

Flux-surface states at times inside observed.time.

modelstr or callableany

Conductivity model, as in parallel_conductivity.

ln_lambdafloat or str-

Coulomb logarithm, as in parallel_conductivity.

boundstuple of float-

(Z_min, Z_max), explicit; the solution is never clipped.

weightsstr or sequence of float-

"uniform" or one weight per state; required.

time_tolerance_sfloat, optionals

Largest gap between a state and its observed sample.

scan_pointsint, optional-

Log-spaced Z samples used to test monotonicity first.

Returns
—ResistiveZeffInferenceany

The #1214 Sec. 11 result: estimate (zeff, uncertainty, bounds, objective, status), observed and predicted voltages, quality and provenance.

Raises

  • ValueError No state, bounds that are not 1 <= Z_min < Z_max, weights of the wrong length, or a state with no observed sample at its time [-].
Processing steps · Defaults · Applicability · Limitations · Provenance

Processing steps

  1. Match each state to the observed sample at its time.
  2. Keep every matched sample, counting those flagged R_p_nonpositive (dropping them would bias Z upward); a non-positive mean V_R gives not_identifiable.
  3. Scan R_p^model(Z) over the bounds; a non-monotonic response gives non_monotonic without a fit.
  4. Minimise J(Z) = sum w (V_R^obs - R_p^model(Z) (I_p - I_ni))^2 with a bounded scalar search.
  5. Uncertainty from the curvature of J and the residual scatter (None with one sample); a minimum within 0.1 % of the range from a bound gives bound_hit. The scan only brackets the search: its smallest J sitting at an end point says nothing by itself, since a clean plasma (Z_eff ~ 1.0-1.03) minimises inside the first scan interval without touching the bound.

Defaults

time_tolerance_s 50 us is a numerical convenience below the 1e-4 s rounding of the Lane K state key (#1454); scan_points 41 is a numerical convenience.

Applicability

Machine-independent.

Limitations

One amplitude only: Z_eff is constant across radius and time (#1214 Sec. 10). The uncertainty is statistical; the systematic part comes from resistive_zeff_sensitivity.

Provenance

  1. #1214 Secs. 9-11.

model_resistance

Machine-independentConvention-sensitive source
model_resistance(state, z_eff, *, model, ln_lambda)

Plasma resistance a conductivity model predicts from the flux-surface Ohmic power.

NameTypeUnitDescription
stateFluxSurfaceStateany

One slice: profiles, <J.B>, <B^2>, enclosed volume and the optional bootstrap <J_bs.B>.

z_efffloat or array_like-

Effective charge, constant or a profile on state.psi_norm, as in parallel_conductivity. A profile is a forward input only: infer_resistive_zeff still fits one scalar (#1214 Sec. 10).

modelstr or callableany

Conductivity model, as in parallel_conductivity.

ln_lambdafloat or str-

Coulomb logarithm, as in parallel_conductivity.

Returns
—ModelResistanceany

R_p = P_Ohm / I_p^2 [Ohm], with the conductivity profile and the model, ln Lambda and bootstrap labels it came from.

Convention

V_R I_p = P_Ohm is the resistive term of Romero’s Poynting balance, so this R_p is the same quantity observed_resistance closes for. <E.J> ~ <E.B><J.B>/<B^2> treats J_par/B as a flux function; the parallel current is used, never j_tor (#1214 Sec. 7.2).

Raises

  • ValueError Propagated from parallel_conductivity [-].
Processing steps · Applicability · Limitations · Provenance

Processing steps

  1. sigma_par(psi) from parallel_conductivity.
  2. <E.B> = (<J.B> - <J_bs.B>) / sigma_par – <J_bs.B> is zero when the state carries none.
  3. P_Ohm = int <E.B><J.B>/<B^2> dV by the trapezoid rule on the enclosed volume.
  4. R_p = P_Ohm / I_p^2.

Applicability

Machine-independent.

Limitations

<E.J> ~ <E.B><J.B>/<B^2> is exact only when J_par/B is a flux function; the poloidal variation of the Pfirsch-Schlueter current is dropped, which at VEST aspect ratio is part of the model-form uncertainty rather than a resolved term. Steady state is not assumed: the current profile is the equilibrium’s own, and only its parallel resistivity is modelled.

Provenance

  1. S. P. Hirshman and D. J. Sigmar, Nucl. Fusion 21 (1981) 1079 – the flux-surface parallel Ohm’s law.
  2. #1214 Sec. 7.

observed_resistance

Machine-independentConvention-sensitive source
observed_resistance(flux, *, I_ni, smoothing)

Resistive voltage and plasma resistance from Romero’s transformer balance.

Smooths the plasma current, the boundary flux and the internal inductance, evaluates vaft.process.equilibrium.romero_flux_balance on them, and reports V_R = V_B - V_I and R_p = V_R / (I_p - I_ni) sample by sample with the assumptions that produced them.

NameTypeUnitDescription
fluxRomeroBoundaryFluxany

Boundary flux, current and li_3 in Romero’s convention; nothing else is accepted.

I_nifloat or array_likeA

Non-inductively driven current. Required: 0 asserts a purely Ohmic discharge and is recorded as such, never assumed.

smoothingSmoothingany

How the series are smoothed before differentiation; required.

Returns
—ObservedResistanceany

V_B, V_I, V_R [V], R_p [Ohm], the derivatives, inductive_fraction = |V_I| / |V_B| and per-sample flags (R_p_nonpositive, V_B_nonpositive), plus the provenance of the flux convention, li definition, smoothing and current-source assumption.

Convention

Romero’s: full-weber flux, V = -dpsi/dt; a positive V_B drives a positive I_p and an Ohmic R_p is positive. The Ejima loop voltage of vaft.formula.equilibrium.loop_voltage_from_total_flux differs by sign and, on a per-radian flux, by 2 pi (#354), which is why only a tagged RomeroBoundaryFlux gets in.

Raises

  • TypeError flux is not a RomeroBoundaryFlux: a bare loop-voltage array carries no convention and is refused [-].
  • ValueError I_ni does not broadcast to the time axis, or vaft.process.equilibrium.romero_flux_balance rejects the series [-].
Processing steps · Defaults · Applicability · Limitations · Provenance

Processing steps

  1. Smooth I_p, psi_B and L_i with smoothing.
  2. psi_C = psi_B + L_i I_p (Romero eqs. 35-36) and run the balance with R_p = 0 so that its V_R is unused.
  3. V_R = V_B - V_I; R_p = V_R / (I_p - I_ni).
  4. Flag samples whose V_B or R_p is not positive.

Defaults

None. I_ni and smoothing have no default: an assumed value for either moves R_p and must be the caller’s stated choice.

Applicability

Machine-independent. Closed-flux phase only, as the balance it calls.

Limitations

R_p is a closure: it absorbs every error in V_B, L_i and I_ni. dL_i/dt from reconstructed li_3 is the noisiest term; where inductive_fraction is large the resistance is a small difference of large numbers and should not be fitted.

Provenance

  1. J. A. Romero and JET-EFDA contributors, Nucl. Fusion 50 (2010) 115002, eqs. (23)-(27), (35)-(40).
  2. #1214 Sec. 5 (observed path) and Sec. 4 (convention).

parallel_conductivity

Machine-independentConvention-sensitive source
parallel_conductivity(state, z_eff, *, model, ln_lambda)

Parallel electrical conductivity on every surface of a flux-surface state.

NameTypeUnitDescription
stateFluxSurfaceStateany

Electron profiles and geometry on a flux grid.

z_efffloat or array_like-

Effective charge: one value for a constant charge, or a profile with one value per surface of state.psi_norm (#1566); at least 1 everywhere.

modelstr or callableany

"spitzer_nrl" (1/eta_par of the NRL Formulary, linear in Z), "sauter_spitzer" (Sauter’s Spitzer with N(Z)), "sauter" or "redl" (the neoclassical corrections), or a callable model(state, z_eff, ln_lambda_profile) -> sigma – the seam a NEO conductivity table plugs into without an API change.

ln_lambdafloat or str-

Coulomb logarithm: a number, or "sauter" for Sauter’s electron ln Lambda_e(n_e, T_e) on every surface.

Returns
—np.ndarrayS/m

sigma_par on state.psi_norm.

Convention

Parallel, not perpendicular: spitzer_nrl is 1/eta_par with the NRL coefficient 5.2e-5 Ohm m eV^1.5 (#1188). The neoclassical models use the circular trapped fraction from epsilon = (R_out - R_in)/(R_out + R_in) unless the state carries its own, and R = (R_out + R_in)/2 in nu_e* – as vaft.omas.neoclassical.compute_conductivity does.

Raises

  • ValueError z_eff below 1, a profile whose length is not the state’s, an unknown model name, or a non-positive ln_lambda [-].
Applicability · Limitations · Provenance

Applicability

Machine-independent.

Limitations

spitzer_nrl and sauter_spitzer differ by tens of percent at Z > 1 (linear Z against Z N(Z)); the model name is part of the result. The axis surface has epsilon = 0 and no trapped particles.

Provenance

  1. O. Sauter, C. Angioni and Y. R. Lin-Liu, Phys. Plasmas 6 (1999) 2834; 9 (2002) 5140 (erratum).
  2. A. Redl et al., Phys. Plasmas 28 (2021) 022502.
  3. NRL Plasma Formulary (2019), p. 29.

per_slice_resistive_zeff

Machine-independent source
per_slice_resistive_zeff(observed, states, *, model, ln_lambda, bounds, time_tolerance_s=5e-05)
Show source vaft/process/resistive_zeff.py, lines 1120–1190
def per_slice_resistive_zeff(
    observed: ObservedResistance,
    states: Sequence[FluxSurfaceState],
    *,
    model: Union[str, Callable],
    ln_lambda: Union[float, str],
    bounds: tuple,
    time_tolerance_s: float = 5e-5,
) -> dict:
    """Z_eff solved at each state on its own: a diagnostic of the window estimate.

    Parameters
    ----------
    observed : ObservedResistance
        Observed ``V_R`` history from :func:`observed_resistance` [any].
    states : sequence of FluxSurfaceState
        Flux-surface states inside ``observed.time`` [any].
    model : str or callable
        Conductivity model, as in :func:`parallel_conductivity` [any].
    ln_lambda : float or str
        Coulomb logarithm, as in :func:`parallel_conductivity` [-].
    bounds : tuple of float
        ``(Z_min, Z_max)`` [-].
    time_tolerance_s : float, optional
        Largest gap between a state and its observed sample [s].

    Returns
    -------
    dict
        ``time`` [s], ``zeff`` (NaN where a slice has no estimate) [-] and
        ``status`` per state, ordered in time [any].

    Raises
    ------
    ValueError
        Propagated from :func:`infer_resistive_zeff` [-].

    Processing steps
    ----------------
    1. Order the states in time.
    2. Run :func:`infer_resistive_zeff` on each state alone.
    3. Keep the value only for ``ok`` and ``bound_hit``; ``bound_hit`` keeps
       its bound value so the reader sees where it stuck.

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

    Limitations
    -----------
    Not the estimate: #1214 Sec. 9 fits one scalar over a window, because one
    sample carries the full noise of a differentiated ``V_R`` and no residual
    to judge it by.  These values show whether that scalar hides a trend, and
    are labelled as a diagnostic wherever they are drawn.

    Provenance
    ----------
    .. [issue] #1214 Secs. 9-10.
    """
    ordered = sorted(states, key=lambda s: s.time)
    times, values, statuses = [], [], []
    for state in ordered:
        result = infer_resistive_zeff(
            observed, [state], model=model, ln_lambda=ln_lambda, bounds=bounds,
            weights="uniform", time_tolerance_s=time_tolerance_s,
        )
        times.append(float(state.time))
        statuses.append(result.status)
        values.append(result.zeff if result.zeff is not None else np.nan)
    return {"time": np.asarray(times), "zeff": np.asarray(values, dtype=float),
            "status": tuple(statuses)}

Z_eff solved at each state on its own: a diagnostic of the window estimate.

NameTypeUnitDescription
observedObservedResistanceany

Observed V_R history from observed_resistance.

statessequence of FluxSurfaceStateany

Flux-surface states inside observed.time.

modelstr or callableany

Conductivity model, as in parallel_conductivity.

ln_lambdafloat or str-

Coulomb logarithm, as in parallel_conductivity.

boundstuple of float-

(Z_min, Z_max).

time_tolerance_sfloat, optionals

Largest gap between a state and its observed sample.

Returns
—dictany

time [s], zeff (NaN where a slice has no estimate) [-] and status per state, ordered in time.

Raises

  • ValueError Propagated from infer_resistive_zeff [-].
Processing steps · Applicability · Limitations · Provenance

Processing steps

  1. Order the states in time.
  2. Run infer_resistive_zeff on each state alone.
  3. Keep the value only for ok and bound_hit; bound_hit keeps its bound value so the reader sees where it stuck.

Applicability

Machine-independent.

Limitations

Not the estimate: #1214 Sec. 9 fits one scalar over a window, because one sample carries the full noise of a differentiated V_R and no residual to judge it by. These values show whether that scalar hides a trend, and are labelled as a diagnostic wherever they are drawn.

Provenance

  1. #1214 Secs. 9-10.

resistive_zeff_sensitivity

Machine-independent source
resistive_zeff_sensitivity(flux, states, *, I_ni, smoothing, model, ln_lambda, bounds, weights, relative_perturbation=0.1, smoothing_factors=(0.5, 2.0), models=('spitzer_nrl', 'sauter', 'redl'), time_tolerance_s=5e-05)

Nominal resistive Z_eff and how far each input moves it.

NameTypeUnitDescription
fluxRomeroBoundaryFluxany

Boundary flux history.

statessequence of FluxSurfaceStateany

Flux-surface states in the window.

I_nifloat or array_likeA

Non-inductive current, as in observed_resistance.

smoothingSmoothingany

Nominal smoothing.

modelstr or callableany

Nominal conductivity model.

ln_lambdafloat or str-

Coulomb logarithm.

boundstuple of float-

(Z_min, Z_max).

weightsstr or sequence of float-

As in infer_resistive_zeff.

relative_perturbationfloat, optional-

Fractional change applied to T_e, n_e and li_3, each way.

smoothing_factorstuple of float, optional-

Multipliers of the smoothing window.

modelstuple of str, optional-

Alternative conductivity models compared with the nominal one.

time_tolerance_sfloat, optionals

As in infer_resistive_zeff.

Returns
—tupleany

(nominal, table): the nominal ResistiveZeffInference, with its sensitivity filled with the largest shift per input, and a list of rows {"input", "setting", "zeff", "delta", "status"}

Raises

  • ValueError Propagated from infer_resistive_zeff [-].
Processing steps · Defaults · Applicability · Limitations · Provenance

Processing steps

  1. Nominal inference.
  2. Re-infer with T_e, n_e and li_3 scaled by 1 +/- relative_perturbation.
  3. Re-infer with the smoothing window scaled by each factor.
  4. Re-infer with each alternative conductivity model, and without the bootstrap current if the states carry one.
  5. delta = Z - Z_nominal; the largest absolute delta per input goes into nominal.sensitivity.

Defaults

relative_perturbation 0.1 and smoothing_factors (0.5, 2) are numerical-convenience probes of local sensitivity, not uncertainty estimates of VEST diagnostics; models is the conventional Spitzer/Sauter/Redl ladder of #1214 Sec. 3.

Applicability

Machine-independent.

Limitations

One-at-a-time perturbations; no correlation between inputs. NEO enters only as a callable model the caller supplies.

Provenance

  1. #1214 Sec. 12 and Phase F.

smooth_local_polynomial

Machine-independent source
smooth_local_polynomial(time, values, *, window_s, order)
Show source vaft/process/resistive_zeff.py, lines 431–503
def smooth_local_polynomial(time, values, *, window_s: float, order: int) -> np.ndarray:
    """Local least-squares polynomial smoothing on a non-uniform time axis.

    A Savitzky-Golay filter written for unevenly spaced samples: at each
    sample a polynomial of ``order`` is fitted by least squares to every
    sample within ``window_s / 2`` of it, and its value there is returned.
    EFIT slices arrive at about 1 ms with gaps, which the uniform-grid filter
    cannot take.

    Parameters
    ----------
    time : array_like
        Sample times, strictly increasing [s].
    values : array_like
        The sampled quantity, same length as ``time`` [any].
    window_s : float
        Full width of the fitting window [s].
    order : int
        Polynomial order; at least ``order + 2`` samples must fall in every
        window [-].

    Returns
    -------
    np.ndarray
        Smoothed values on ``time`` [any].

    Raises
    ------
    ValueError
        Lengths differ, time does not strictly increase, or a window holds
        fewer than ``order + 2`` samples -- a fit with no redundancy is an
        interpolation, not a smoothing, and is refused [-].

    Processing steps
    ----------------
    1. For each sample, select the samples with ``|t - t_i| <= window_s/2``.
    2. Fit a polynomial of ``order`` in ``t - t_i`` by least squares.
    3. Return its constant term.

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

    Limitations
    -----------
    The window shrinks to one side at the ends of the record, where the fit
    extrapolates and is least reliable; cut a margin of ``window_s / 2`` off
    the inference window if the end samples matter.

    Provenance
    ----------
    .. [1] A. Savitzky and M. J. E. Golay, Anal. Chem. 36 (1964) 1627 --
           the uniform-grid special case.
    """
    t = np.asarray(time, dtype=float)
    x = np.asarray(values, dtype=float)
    if t.shape != x.shape or t.ndim != 1:
        raise ValueError("time and values must be one-dimensional and the same length")
    if np.any(np.diff(t) <= 0.0):
        raise ValueError("time must strictly increase")
    order = int(order)
    half = 0.5 * float(window_s)
    out = np.empty_like(x)
    for i, centre in enumerate(t):
        mask = np.abs(t - centre) <= half + 1e-12
        if mask.sum() < order + 2:
            raise ValueError(
                f"{mask.sum()} samples within {window_s:g} s of t = {centre:.4f} s; "
                f"order {order} needs at least {order + 2} -- widen the window"
            )
        coeffs = np.polynomial.polynomial.polyfit(t[mask] - centre, x[mask], order)
        out[i] = coeffs[0]
    return out

Local least-squares polynomial smoothing on a non-uniform time axis.

A Savitzky-Golay filter written for unevenly spaced samples: at each sample a polynomial of order is fitted by least squares to every sample within window_s / 2 of it, and its value there is returned. EFIT slices arrive at about 1 ms with gaps, which the uniform-grid filter cannot take.

NameTypeUnitDescription
timearray_likes

Sample times, strictly increasing.

valuesarray_likeany

The sampled quantity, same length as time.

window_sfloats

Full width of the fitting window.

orderint-

Polynomial order; at least order + 2 samples must fall in every window.

Returns
—np.ndarrayany

Smoothed values on time.

Raises

  • ValueError Lengths differ, time does not strictly increase, or a window holds fewer than order + 2 samples – a fit with no redundancy is an interpolation, not a smoothing, and is refused [-].
Processing steps · Applicability · Limitations · Provenance

Processing steps

  1. For each sample, select the samples with |t - t_i| <= window_s/2.
  2. Fit a polynomial of order in t - t_i by least squares.
  3. Return its constant term.

Applicability

Machine-independent.

Limitations

The window shrinks to one side at the ends of the record, where the fit extrapolates and is least reliable; cut a margin of window_s / 2 off the inference window if the end samples matter.

Provenance

  1. A. Savitzky and M. J. E. Golay, Anal. Chem. 36 (1964) 1627 – the uniform-grid special case.

results matching ""

    No results matching ""