Process reference: zeff_projection
Generated from the docstrings of vaft.process.zeff_projection:
6 public functions. Each entry is what
vaft.process.describe("zeff_projection.<name>") prints.
All process categories
Overview
The composition model (#1565) gives a local profile Z_eff(rho); the
Romero transformer balance (#1214, Lane Z) gives one scalar Z_eff^res,
the constant a conductivity model needs to reproduce the observed plasma
resistance. They are different quantities and are compared only through an
explicit forward projection (issue #1566): the scalar that makes the same
conductivity model, on the same flux-surface states, produce the same
resistance – or, over a window, the same resistive voltage under the same
objective – as the profile does.
The chain::
Z_eff(psi_N) on a FluxSurfaceState [composition, #1565]
-> sigma_par(psi_N; Z_eff(psi_N)) [Lane Z's model, surface by surface]
-> R_p^profile = P_Ohm / I_p^2 [vaft.process.resistive_zeff.model_resistance]
-> Z* with R_p^model(Z*) = R_p^profile [one slice: a bounded root]
-> or argmin_Z sum w (V_R^profile - V_R^model(Z))^2 over a window
[vaft.process.resistive_zeff.infer_resistive_zeff]
Nothing here writes core_profiles.zeff: the projection is a model-space
scalar, never a profile. A flat profile built from a resistive scalar needs
the explicit assumption of flat_profile_from_resistive.
| Symbol | Meaning | Unit |
|---|---|---|
| Z_eff(psi_N) | effective-charge profile on the state's surfaces | - |
| R_p | plasma resistance, P_Ohm / I_p^2 | Ohm |
| Z_eff^res,equiv | constant Z_eff giving the profile's R_p (or V_R(t)) | - |
| Z_eff^res,obs | Lane Z's scalar inferred from the observed V_R | - |
Same model, same states, same objective. The profile’s conductivity is
Lane Z’s vaft.process.resistive_zeff.parallel_conductivity
evaluated surface by surface at that surface’s Z_eff, so the profile and the
scalar differ only in Z_eff; the window scalar is Lane Z’s own
vaft.process.resistive_zeff.infer_resistive_zeff fed the profile’s
predicted voltage, so the projection is defined in the observable space the
experimental scalar lives in.
Functions
flat_profile_from_resistive | A flat Z_eff profile from a resistive scalar – only under the stated flat assumption. Convention |
profile_conductivity_model | A conductivity-model callable that evaluates Lane Z’s model at a radially varying Z_eff. Convention |
project_window_to_resistive_scalar | The window scalar Lane Z’s estimator would infer if the profile were the truth. Convention |
project_zeff_profile_to_resistive_scalar | The constant Z_eff whose model resistance equals that of a Z_eff profile, on one slice. Convention |
spitzer_resistive_equivalent_zeff | Analytic resistive equivalent of a Z_eff profile under Spitzer (NRL) resistivity. Convention |
zeff_profile_for_state | The atomic-data Z_eff profile on a flux-surface state’s own surfaces. Convention |
No function matches.
flat_profile_from_resistive
Machine-independentConvention-sensitive
source
flat_profile_from_resistive(zeff_resistive, state, *, assumption)
Show source vaft/process/zeff_projection.py, lines 427–467
def flat_profile_from_resistive(zeff_resistive: float, state: Any, *, assumption: str) -> np.ndarray:
"""A flat Z_eff profile from a resistive scalar -- only under the stated flat assumption.
Parameters
----------
zeff_resistive : float
A resistive scalar (Lane Z), at least 1 [-].
state : FluxSurfaceState
The surfaces to put it on [any].
assumption : str
Must be ``"flat"``: the caller states the modelling assumption [-].
Returns
-------
np.ndarray
``Z_eff(psi_N) = zeff_resistive`` on every surface [-].
Raises
------
ValueError
Any assumption other than ``"flat"``, or a scalar below 1.
Convention
----------
#1566 Sec. 6: a modelling assumption, never a measurement or an
inference of the profile; nothing here writes it to ``core_profiles``.
Applicability
-------------
Machine-independent.
Provenance
----------
.. [issue] #1566 Sec. 6.
"""
if assumption != "flat":
raise ValueError("a profile from a resistive scalar needs assumption='flat', stated explicitly")
value = float(zeff_resistive)
if not value >= 1.0:
raise ValueError(f"zeff_resistive must be at least 1, got {zeff_resistive!r}")
return np.full(np.shape(state.psi_norm), value)A flat Z_eff profile from a resistive scalar – only under the stated flat assumption.
| Name | Type | Unit | Description |
|---|---|---|---|
zeff_resistive | float | - | A resistive scalar (Lane Z), at least 1. |
state | FluxSurfaceState | any | The surfaces to put it on. |
assumption | str | - | Must be |
| Returns | |||
| — | np.ndarray | - |
|
Convention
#1566 Sec. 6: a modelling assumption, never a measurement or an
inference of the profile; nothing here writes it to core_profiles.
Raises
ValueErrorAny assumption other than"flat", or a scalar below 1.
Applicability · Provenance
Applicability
Machine-independent.
Provenance
- #1566 Sec. 6.
profile_conductivity_model
Machine-independentConvention-sensitive
source
profile_conductivity_model(zeff_profile, *, base_model='redl', ln_lambda='sauter')
Show source vaft/process/zeff_projection.py, lines 105–175
def profile_conductivity_model(
zeff_profile: Any,
*,
base_model: str = "redl",
ln_lambda: Union[float, str] = "sauter",
) -> Callable:
"""A conductivity-model callable that evaluates Lane Z's model at a radially varying Z_eff.
Parameters
----------
zeff_profile : array-like
Z_eff on the state's ``psi_norm`` surfaces, at least 1 [-].
base_model : str, optional
One of :data:`vaft.process.resistive_zeff.CONDUCTIVITY_MODELS` [-].
ln_lambda : float or str, optional
Coulomb logarithm as :func:`~vaft.process.resistive_zeff.parallel_conductivity`
takes it [-].
Returns
-------
callable
``model(state, z, lnl) -> sigma(psi_N)`` for
:func:`~vaft.process.resistive_zeff.model_resistance`; the scalar
``z`` it is handed is ignored [any].
Raises
------
ValueError
At call time: a profile that does not match the state's surfaces, or
that is non-finite or below 1.
Convention
----------
Surface ``i`` gets ``parallel_conductivity(state, Z_eff[i])[i]``: the
unmodified scalar model, so a flat profile reproduces it exactly and no
kernel is copied. ``model_resistance`` records ``z_eff = 1`` for this
route; the profile is the record of what was used. The ``ln_lambda`` it
is built with must be the one ``model_resistance`` is called with; a
mismatch is refused, not silently overridden.
Applicability
-------------
Machine-independent.
Provenance
----------
.. [issue] #1566 Sec. 3 (the Redl/Sauter projection through Lane Z's
conductivity models), #1214 (the models), #1486 (Lane Z).
"""
from vaft.process.resistive_zeff import _ln_lambda_profile, parallel_conductivity
profile = np.asarray(zeff_profile, dtype=float)
def model(state, _z, lnl):
z = _profile(state, profile)
own, _ = _ln_lambda_profile(state, ln_lambda)
if not np.allclose(np.asarray(lnl, dtype=float), own, rtol=1e-12, atol=0.0):
raise ValueError(
"model_resistance was given a different ln_lambda from the one this profile model was "
f"built with ({ln_lambda!r}); build it with the same ln_lambda"
)
sigma = np.empty(z.shape)
for value in np.unique(z):
at = z == value
sigma[at] = parallel_conductivity(state, float(value), model=base_model, ln_lambda=ln_lambda)[at]
return sigma
model.zeff_profile = profile
model.base_model = base_model
model.__name__ = f"profile_{base_model}"
return modelA conductivity-model callable that evaluates Lane Z’s model at a radially varying Z_eff.
| Name | Type | Unit | Description |
|---|---|---|---|
zeff_profile | array-like | - | Z_eff on the state’s |
base_model | str, optional | - | One of |
ln_lambda | float or str, optional | - | Coulomb logarithm as |
| Returns | |||
| — | callable | any |
|
Convention
Surface i gets parallel_conductivity(state, Z_eff[i])[i]: the
unmodified scalar model, so a flat profile reproduces it exactly and no
kernel is copied. model_resistance records z_eff = 1 for this
route; the profile is the record of what was used. The ln_lambda it
is built with must be the one model_resistance is called with; a
mismatch is refused, not silently overridden.
Raises
ValueErrorAt call time: a profile that does not match the state’s surfaces, or that is non-finite or below 1.
Applicability · Provenance
Applicability
Machine-independent.
Provenance
- #1566 Sec. 3 (the Redl/Sauter projection through Lane Z’s conductivity models), #1214 (the models), #1486 (Lane Z).
project_window_to_resistive_scalar
Machine-independentConvention-sensitive
source
project_window_to_resistive_scalar(states, zeff_profiles, *, model='redl', ln_lambda='sauter', bounds=(1.0, 10.0), weights='uniform', profile_source='caller')
The window scalar Lane Z’s estimator would infer if the profile were the truth.
| Name | Type | Unit | Description |
|---|---|---|---|
states | sequence of FluxSurfaceState | any | The window’s slices. |
zeff_profiles | sequence of array-like | - | One Z_eff profile per state, on its surfaces. |
model | str, optional | - | Conductivity model. |
ln_lambda | float or str, optional | - | Coulomb logarithm. |
bounds | tuple of float, optional | - | Search interval. |
weights | str or sequence of float, optional | - | As |
profile_source | str, optional | - | Where the profiles came from. |
| Returns | |||
| — | ResistiveZeffProjection | any | The scalar, the per-slice resistances of the profile and of the scalar, the window and Lane Z’s status. |
Convention
#1566 Sec. 7: a spatio-temporal model-equivalent scalar, comparable with
Z_eff^res,obs because the objective is literally the same function.
The drive is |I_p|: R_p is a dissipation and does not depend on
the current’s sign convention. Near Z_eff = 1 the estimator reports
bound_hit (a ~0.3 % bias at the lower bound), exactly as it does for
the observed scalar.
Raises
ValueErrorUnequal numbers of states and profiles, two states at one time, or a profile off its state’s surfaces.
Processing steps · Applicability · Provenance
Processing steps
- Per slice,
R_p^profile(t)as inproject_zeff_profile_to_resistive_scalar. - An
ObservedResistancewhoseV_R = R_p^profile (I_p - I_ni)withI_ni = 0– the profile’s voltage, as if observed. - Lane Z’s
infer_resistive_zeffon it: the same objectivesum w (V_R - R_p^model(Z) I_p)^2and bounds as the experimental scalar.
Applicability
Machine-independent.
Provenance
- #1566 Sec. 7, #1214 Sec. 10.
project_zeff_profile_to_resistive_scalar
Machine-independentConvention-sensitive
source
project_zeff_profile_to_resistive_scalar(state, zeff_profile, *, model='redl', ln_lambda='sauter', bounds=(1.0, 10.0), profile_source='caller')
The constant Z_eff whose model resistance equals that of a Z_eff profile, on one slice.
| Name | Type | Unit | Description |
|---|---|---|---|
state | FluxSurfaceState | any | One slice. |
zeff_profile | array-like | - | Z_eff on the state’s |
model | str, optional | - | Conductivity model, as Lane Z names them. |
ln_lambda | float or str, optional | - | Coulomb logarithm. |
bounds | tuple of float, optional | - | Search interval for the scalar. |
profile_source | str, optional | - | Where the profile came from, for provenance. |
| Returns | |||
| — | ResistiveZeffProjection | any | The scalar, both resistances, the bracket and status. |
Convention
The projection is defined in resistance space with the same states and model on both sides (#1566 Sec. 1); a flat profile returns its own value.
Raises
ValueErrorA profile off the state’s surfaces, or no root insidebounds(the profile’s resistance is outside what a constant Z_eff inboundscan give).
Processing steps · Applicability · Provenance
Processing steps
R_p^profilefrommodel_resistancewithprofile_conductivity_model.- A bounded root of
R_p^model(Z) - R_p^profile(brentq).
Applicability
Machine-independent.
Provenance
- #1566 Sec. 1 and 3.
spitzer_resistive_equivalent_zeff
Machine-independentConvention-sensitive
source
spitzer_resistive_equivalent_zeff(state, zeff_profile, *, ln_lambda='sauter')
Show source vaft/process/zeff_projection.py, lines 178–232
def spitzer_resistive_equivalent_zeff(state: Any, zeff_profile: Any, *, ln_lambda: Union[float, str] = "sauter") -> float:
"""Analytic resistive equivalent of a Z_eff profile under Spitzer (NRL) resistivity.
Parameters
----------
state : FluxSurfaceState
One slice (``bootstrap = none``) [any].
zeff_profile : array-like
Z_eff on the state's ``psi_norm`` surfaces [-].
ln_lambda : float or str, optional
Coulomb logarithm [-].
Returns
-------
float
``int Z w dV / int w dV`` with ``w = eta(Z=1) <J.B>^2/<B^2>``, the
Ohmic-dissipation weight [-].
Raises
------
ValueError
A profile off the state's surfaces, a state carrying a bootstrap
current (the weight is then not linear in Z), or a zero weight.
Convention
----------
NRL Spitzer resistivity is linear in Z_eff, so ``P_Ohm`` is a weighted
integral of Z_eff and the equivalent scalar is that weighted mean -- the
weight is the dissipation ``eta_1 j^2``, not the volume or the density.
Integrated with the same trapezoid rule on the enclosed volume as
:func:`~vaft.process.resistive_zeff.model_resistance`.
Applicability
-------------
Machine-independent.
Provenance
----------
.. [issue] #1566 Sec. 2 (the Spitzer reference projection).
"""
from scipy.integrate import trapezoid
from vaft.process.resistive_zeff import parallel_conductivity
if getattr(state, "j_bootstrap_dot_b", None) is not None:
raise ValueError("the analytic Spitzer projection needs a state without bootstrap current")
z = _profile(state, zeff_profile)
sigma_1 = parallel_conductivity(state, 1.0, model="spitzer_nrl", ln_lambda=ln_lambda)
jb = np.asarray(state.j_dot_b, dtype=float)
weight = jb**2 / np.asarray(state.b2_average, dtype=float) / sigma_1
volume = np.asarray(state.volume, dtype=float)
denominator = trapezoid(weight, volume)
if not denominator > 0.0:
raise ValueError("the dissipation weight integrates to zero")
return float(trapezoid(weight * z, volume) / denominator)Analytic resistive equivalent of a Z_eff profile under Spitzer (NRL) resistivity.
| Name | Type | Unit | Description |
|---|---|---|---|
state | FluxSurfaceState | any | One slice ( |
zeff_profile | array-like | - | Z_eff on the state’s |
ln_lambda | float or str, optional | - | Coulomb logarithm. |
| Returns | |||
| — | float | - |
|
Convention
NRL Spitzer resistivity is linear in Z_eff, so P_Ohm is a weighted
integral of Z_eff and the equivalent scalar is that weighted mean – the
weight is the dissipation eta_1 j^2, not the volume or the density.
Integrated with the same trapezoid rule on the enclosed volume as
vaft.process.resistive_zeff.model_resistance.
Raises
ValueErrorA profile off the state’s surfaces, a state carrying a bootstrap current (the weight is then not linear in Z), or a zero weight.
Applicability · Provenance
Applicability
Machine-independent.
Provenance
- #1566 Sec. 2 (the Spitzer reference projection).
zeff_profile_for_state
Machine-independentConvention-sensitive
source
zeff_profile_for_state(state, elemental_weights, **options)
Show source vaft/process/zeff_projection.py, lines 470–512
def zeff_profile_for_state(state: Any, elemental_weights: Mapping[str, float], **options: Any):
"""The atomic-data Z_eff profile on a flux-surface state's own surfaces.
Parameters
----------
state : FluxSurfaceState
One slice; its ``T_e``, ``n_e`` and enclosed volume are used [any].
elemental_weights : mapping
Relative elemental densities, e.g. ``{"C": 1, "O": 1}``; further
keyword arguments go to
:func:`vaft.process.impurity.resolve_radial_composition`
(``normalization``, ``target_zeff``, ``ionization``, ``plasma_age_s``,
``projection``/``resistive_target``, ``tables``...) [-].
Returns
-------
RadialImpurityComposition
On ``psi_norm``, with ``dV`` from the state's volume [any].
Raises
------
ValueError
As ``resolve_radial_composition``.
Convention
----------
The profile is built from the very T_e and n_e the conductivity model
uses, so composition and resistance share one state.
Applicability
-------------
Machine-independent.
Provenance
----------
.. [issue] #1566 Sec. 5 (connect #1565 profiles to #1214).
"""
from vaft.process.impurity import resolve_radial_composition
volume = np.asarray(state.volume, dtype=float)
edges = np.concatenate(([volume[0]], 0.5 * (volume[1:] + volume[:-1]), [volume[-1]]))
return resolve_radial_composition(state.T_e, state.n_e, state.psi_norm, elemental_weights,
volume_weights=np.diff(edges), time=float(state.time), **options)The atomic-data Z_eff profile on a flux-surface state’s own surfaces.
| Name | Type | Unit | Description |
|---|---|---|---|
state | FluxSurfaceState | any | One slice; its |
elemental_weights | mapping | - | Relative elemental densities, e.g. |
| Returns | |||
| — | RadialImpurityComposition | any | On |
Convention
The profile is built from the very T_e and n_e the conductivity model uses, so composition and resistance share one state.
Raises
ValueErrorAsresolve_radial_composition.
Applicability · Provenance
Applicability
Machine-independent.
Provenance
- #1566 Sec. 5 (connect #1565 profiles to #1214).