Process reference: gyrokinetics
Generated from the docstrings of vaft.process.gyrokinetics:
17 public functions. Each entry is what
vaft.process.describe("gyrokinetics.<name>") prints.
All process categories
Overview
Turns the potential of a nonlinear gyrokinetic run into the two intensities the
reduced model of vaft.formula.turbulence speaks about, characterises the
cycles they go through, and fits the two-variable Lotka–Volterra model to them.
Every routine takes plain NumPy arrays, so any code that writes
$\phi_{k_x,k_y}(t)$ can be analysed; nothing here runs, steers or reads a
solver.
The chain::
phi(kx, ky, t)
-> zonal_turbulence_intensity : N(t) = sum_{ky!=0} |phi|^2, E(t) = sum_{ky=0} |phi|^2
-> zonal_shear_proxy : sum kx^2 |phi_{kx,0}|^2, sum kx^4 |phi_{kx,0}|^2
(N, E, optional transport)
-> predator_prey_cycle_metrics : peaks, periods, peak lag, correlation lag
-> fit_predator_prey_model : gamma_eff, c1, c2, gamma_Z by trajectory fit
The output is a consistency test, not a mechanism claim. A good fit says the traces are compatible with predator–prey dynamics under the stated intensity definitions. It does not establish Dimits-shift physics, and a poor fit does not rule zonal flows out: tertiary instability, profile evolution and noise also make traces bursty.
| Symbol | Meaning | Unit |
|---|---|---|
| phi | fluctuating electrostatic potential, Fourier components | solver units |
| N, E | turbulence (k_y != 0) and zonal (k_y = 0) potential intensity | phi^2 |
| gamma_eff, gamma_Z | effective growth and zonal damping rates | 1/time |
| c1, c2 | suppression and drive couplings | [1/(time E)], [1/(time N)] |
Intensities are proxies. Unweighted $\sum|\phi|^2$ is a
potential-intensity proxy, not an energy; a fit’s $c_1, c_2$ are
meaningful only together with the definition of $N$ and $E$, which
every result records (PredatorPreyFit.normalization). Rescaling
$N\to aN$, $E\to bE$ maps $c_1\to c_1/b$,
$c_2\to c_2/a$; the rates are unchanged.
Time is the caller’s. Any consistent unit (s, $a/c_s$); every returned rate or lag is in that unit.
Positive lag = zonal flow after turbulence, for both the peak lag and the cross-correlation lag.
Functions
assess_comparison | Assess signatures grouped by display/state/model/qualification. |
field_transport_contributions | Signed field totals and fractions; cancellation is explicit, never clipped. |
fit_predator_prey_model | Fit the two-variable Lotka–Volterra model to turbulence and zonal-flow traces. Convention |
local_result_signature | Non-mutating IMAS signature with explicit missing physical/provenance evidence. |
predator_prey_cycle_metrics | Cycle observables of a turbulence / zonal-flow pair: periods, peak lag, correlation lag. Convention |
prepare_diagnostic_traces | Prepare causal, gap-broken traces; renderers never interpolate or reduce. |
radial_correlation_from_spectrum | Cosine autocorrelation 1/e crossing and integral scale; unresolved is a bound. |
rebin_contributions | Conserve signed flux using piecewise-uniform density within audited bins. |
reconstruct_field | Reconstruct CGYRO’s half-sum Re phi exp(+ikxx-iky*y). |
reduce_time_series | Time-weighted window reduction with explicit coverage and independent evidence. |
saturated_intensity | TGLF moment intensity = QL intensity weight * saturated phi intensity. |
select_time | Nearest finite time and evidence; no implicit scientific tolerance. |
spectral_integral | Integrate signed bin contributions or densities with explicit bin edges. |
time_window_average | Average aligned scalar or multi-channel histories with the shared gap policy. |
zonal_fraction | I_Z/(I_Z+I_T); all-zero intensity is undefined, not zero. |
zonal_shear_proxy | Spectral proxies for the zonal-flow energy and the zonal shear. Convention |
zonal_turbulence_intensity | Split fluctuation intensity into its zonal ($k_y = 0$) and non-zonal parts. Convention |
No function matches.
assess_comparison
Machine-independent
source
assess_comparison(left, right, *, intent='exploratory_overlay', controlled=(), rtol=0.001)
Assess signatures grouped by display/state/model/qualification.
| Name | Type | Unit | Description |
|---|---|---|---|
left | mapping | - | Left result evidence grouped by display/state/model/qualification. |
right | mapping | - | Right result evidence with the same axis/key vocabulary. |
intent | str, optional | - | Matched baseline, controlled sensitivity or exploratory overlay. |
controlled | sequence of str, optional | - | Explicit controlled changes named axis.key; display mismatches cannot be controlled. |
rtol | float, optional | - | Relative numerical tolerance for compatible scalar/array evidence. |
| Returns | |||
| — | ComparisonAssessment | - | Independent per-axis status, reasons and supporting evidence. |
Applicability · Notes · Provenance
Applicability
Machine-independent. Requires the declared physical definitions, source identity and units. Matching display conventions alone does not establish physical equivalence or convergence.
Notes
Assess signatures grouped by display/state/model/qualification.
Each axis is a mapping of named evidence. Missing keys/None are unverified. Controlled variations must be named ‘axis.key’, never inferred from intent.
Provenance
- #2030 four-axis comparison and time-selection contract; #2028 diagnostic ownership.
field_transport_contributions
Machine-independent
source
field_transport_contributions(values, *, axis=0, cancellation_rtol=1e-08)
Show source vaft/process/gyrokinetics.py, lines 987–1028
def field_transport_contributions(values, *, axis=0, cancellation_rtol=1e-8):
"""Signed field totals and fractions; cancellation is explicit, never clipped.
Parameters
----------
values : array-like
Signed spectral contributions or aligned time samples [quantity].
axis : int, optional
Axis containing spectral bins or additive field contributions [-].
cancellation_rtol : float, optional
Numerical threshold for total versus absolute summed magnitude [-].
Returns
-------
dict
Signed total, unbounded signed fractions and cancellation mask [quantity; fractions -].
Applicability
-------------
Machine-independent. Requires the declared spectral convention, retained axes and units.
These are numerical reductions of solver data, not independent evidence of physical validity.
Notes
-----
Signed field totals and fractions; cancellation is explicit, never clipped.
Provenance
----------
.. [1] Canonical mathematical definition in #2028; uses the retained-source and weighting contract of #2025.
"""
values = np.asarray(values, float)
total = np.sum(values, axis=axis)
magnitude = np.sum(np.abs(values), axis=axis)
cancelled = np.abs(total) <= cancellation_rtol * magnitude
good = np.isfinite(total) & (total != 0) & ~cancelled
fractions = np.divide(values, np.expand_dims(np.where(good, total, np.nan), axis))
return {
"total": total,
"fractions": fractions,
"cancellation": cancelled,
"definition": "signed contribution / signed total",
}Signed field totals and fractions; cancellation is explicit, never clipped.
| Name | Type | Unit | Description |
|---|---|---|---|
values | array-like | quantity | Signed spectral contributions or aligned time samples. |
axis | int, optional | - | Axis containing spectral bins or additive field contributions. |
cancellation_rtol | float, optional | - | Numerical threshold for total versus absolute summed magnitude. |
| Returns | |||
| — | dict | quantity; fractions - | Signed total, unbounded signed fractions and cancellation mask. |
Applicability · Notes · Provenance
Applicability
Machine-independent. Requires the declared spectral convention, retained axes and units. These are numerical reductions of solver data, not independent evidence of physical validity.
Notes
Signed field totals and fractions; cancellation is explicit, never clipped.
Provenance
- Canonical mathematical definition in #2028; uses the retained-source and weighting contract of #2025.
fit_predator_prey_model
Machine-independentConvention-sensitive
source
fit_predator_prey_model(time, turbulence, zonal, *, method='trajectory', initial_parameters=None, normalization=None, window=None, fit_initial_state=True, min_r2=0.5)
Fit the two-variable Lotka–Volterra model to turbulence and zonal-flow traces.
Finds $\gamma_\mathrm{eff}, c_1, c_2, \gamma_Z$ (and, by default, the
initial state) whose trajectory of
vaft.formula.turbulence.predator_prey_rhs best matches the data.
| Name | Type | Unit | Description |
|---|---|---|---|
time | array-like | time | Strictly increasing sample times. |
turbulence | array-like | N | Turbulence intensity $N(t)$, positive. |
zonal | array-like | E | Zonal-flow intensity $E(t)$, positive. |
method | {"trajectory"}, optional | - | Only the trajectory fit is implemented. |
initial_parameters | sequence of 4 floats, optional | 1/time, 1/(time E), 1/(time N), 1/time | Starting $(\gamma_\mathrm{eff}, c_1, c_2, \gamma_Z)$; by default a per-capita regression, or the fixed-point guess when that gives a non-positive coefficient. |
normalization | mapping, optional | - | How $N$, $E$ and time were constructed; stored with the result (keys in |
window | (float, float), optional | time | Fit only samples with |
fit_initial_state | bool, optional | - | Fit $N(t_0), E(t_0)$ as well instead of taking the first samples. |
min_r2 | float, optional | - | Coefficient of determination each trace must reach for |
| Returns | |||
| — | PredatorPreyFit | rates 1/time; c1 1/(time E); c2 1/(time N); RMS and R^2 - | The four coefficients, the model traces on the data times, the RMS misfit of each trace divided by its mean ( |
Convention
$c_1, c_2$ carry the units of $1/E$, $1/N$ and are comparable across fits
only when normalization matches; the rates are normalisation-free.
Raises
ValueErrorMismatched or non-finite traces, non-positive intensities, fewer than four samples in the window, non-increasing time, an unknown method, or non-positive initial parameters.
Processing steps · Defaults · Assumptions · Applicability · Limitations · Provenance
Processing steps
- Restrict to
window; take $(N, E)$ at its first sample as the initial state guess. - Start from
initial_parameters, else the per-capita regression of $\dot N/N = \gamma_\mathrm{eff} - c_1E$, $\dot E/E = c_2N - \gamma_Z$, else the fixed-point guess. - Integrate
vaft.formula.turbulence.predator_prey_rhsfrom the initial state and sample it at the data times. - Minimise the residual $\ln N_\mathrm{model} - \ln N$ and $\ln E_\mathrm{model} - \ln E$ over log-coefficients (positivity by construction) with a bounded least-squares solver.
- Report the model traces, $R^2$ and the mean-normalised RMS per trace;
successneeds the optimiser to converge and $R^2 \ge$min_r2on both traces.
Defaults
The trajectory method is the conventional choice (#1820 Sec. 9): it uses no
numerical derivative. Log residuals are a numerical convenience for traces
spanning decades. fit_initial_state=True is a numerical convenience:
a noisy first sample otherwise biases the whole orbit. min_r2=0.5 is
a conventional threshold: the model must explain at least half of each
trace’s variance.
Assumptions
The traces follow one closed orbit of the classical model over the window; bursts of changing amplitude (orbits with different invariant) are fitted by a single compromise orbit.
Applicability
Machine-independent.
Limitations
A local optimum is possible; success reflects the optimiser and the
$R^2$ threshold, not a global search. Irregular bursty traces fit
poorly by construction, and that misfit is the information.
Provenance
- S. Kobayashi, O. D. Gurcan and P. H. Diamond, Phys. Plasmas 22 (2015) 090702.
- #1820 Sec. 9 and 10.
local_result_signature
Machine-independent
source
local_result_signature(obj)
Non-mutating IMAS signature with explicit missing physical/provenance evidence.
| Name | Type | Unit | Description |
|---|---|---|---|
obj | object | - | IMAS/OMAS entry supporting the shared non-mutating dotted-path accessor. |
| Returns | |||
| — | dict | - | Display, physical-state, model and qualification evidence with unknowns kept as None. |
Applicability · Notes · Provenance
Applicability
Machine-independent. Requires the declared physical definitions, source identity and units. Matching display conventions alone does not establish physical equivalence or convergence.
Notes
Non-mutating IMAS signature with explicit missing physical/provenance evidence.
Provenance
- #2030 four-axis comparison and time-selection contract; #2028 diagnostic ownership.
predator_prey_cycle_metrics
Machine-independentConvention-sensitive
source
predator_prey_cycle_metrics(time, turbulence, zonal, *, transport=None, min_cycles=2, prominence=0.2, scale='log')
Cycle observables of a turbulence / zonal-flow pair: periods, peak lag, correlation lag.
| Name | Type | Unit | Description |
|---|---|---|---|
time | array-like | time | Strictly increasing sample times. |
turbulence | array-like | N | Turbulence intensity $N(t)$. |
zonal | array-like | E | Zonal-flow intensity $E(t)$. |
transport | array-like, optional | flux | A transport trace on the same times (a flux); summarised per cycle, never used in place of $N$. |
min_cycles | int, optional | - | Complete turbulence cycles needed for |
prominence | float, optional | - | Peak prominence as a fraction of each trace’s range. |
scale | {"log", "linear"}, optional | - | Detect peaks and correlate on $\ln N, \ln E$ or on $N, E$. |
| Returns | |||
| — | PredatorPreyCycleMetrics | times and lags in the unit of ``time`` | Peak times of both traces, cycle periods (turbulence peak to peak) and their mean and spread, the per-cycle peak response lag (first zonal peak after each turbulence peak and before the next) with mean and spread, the cross-correlation curve and the lag of its maximum, |
Convention
Lags are positive when the zonal flow follows the turbulence. Peak lag and
cross-correlation lag are different estimators and are returned
separately; for a small-amplitude Lotka–Volterra orbit both equal $T/4$
(vaft.formula.turbulence.predator_prey_response_lag).
Raises
ValueErrorMismatched or non-finite traces, non-increasing time, fewer than four samples, ormin_cycles < 1.
Processing steps · Defaults · Applicability · Limitations · Provenance
Processing steps
- Take $\ln N, \ln E$ (
scale="log") or $N, E$; find peaks of each with a prominence ofprominencetimes that trace’s range. - Periods are the spacings of successive $N$ peaks;
n_cyclescounts them. - For each $N$ peak, the first $E$ peak before the next $N$ peak gives the peak response lag.
- On a uniform resampling of both traces (median spacing), standardise and
cross-correlate; the lag of the maximum within $\pm$ half a mean period
(a quarter of the record without cycles) is
correlation_lag. - Qualify: at least
min_cyclescycles, a following zonal peak for every turbulence peak but at most one (the last may have none), and a positive mean peak lag.
Defaults
min_cycles=2 is the conventional minimum for a period estimate with a
spread; prominence=0.2 is a numerical convenience that ignores
sub-burst wiggles and should be lowered for weak, regular oscillations.
scale="log" is a numerical convenience for bursty gyrokinetic traces
that span decades, where a linear-range prominence sees only the largest
burst; peak times do not depend on the scale, only which peaks pass.
Applicability
Machine-independent.
Limitations
Irregular bursts give a period distribution, not a period; the spread is reported, not hidden. Peaks closer than the sampling interval are not resolved.
Provenance
- M. Leconte, A. Masson and L. Qi, Phys. Plasmas 29 (2022) 022302.
- #1820 Sec. 8.
prepare_diagnostic_traces
Machine-independent
source
prepare_diagnostic_traces(diagnostics, frame_times)
Show source vaft/process/gyrokinetic_comparison.py, lines 239–310
def prepare_diagnostic_traces(diagnostics, frame_times):
"""Prepare causal, gap-broken traces; renderers never interpolate or reduce.
Parameters
----------
diagnostics : mapping
Labelled traces with time, values, unit and optional maximum gap [declared trace units].
frame_times : array-like
Simulation timestamps of the selected field frames [trace time units].
Returns
-------
dict
Causal per-frame traces, broken gaps and fixed display limits [input trace units].
Applicability
-------------
Machine-independent. Requires the declared physical definitions, source identity and units.
Matching display conventions alone does not establish physical equivalence or convergence.
Notes
-----
Prepare causal, gap-broken traces; renderers never interpolate or reduce.
Provenance
----------
.. [issue] #2030 four-axis comparison and time-selection contract; #2028 diagnostic ownership.
"""
frame_times = np.asarray(frame_times, float)
if frame_times.ndim != 1 or not np.isfinite(frame_times).all():
raise ValueError("frame times must be finite and one-dimensional")
result = {}
for label, trace in diagnostics.items():
t = np.asarray(trace["time"], float)
y = np.asarray(trace["values"], float)
if (
t.ndim != 1
or y.shape != t.shape
or not len(t)
or not np.isfinite(t).all()
or np.any(np.diff(t) <= 0)
):
raise ValueError(f"invalid diagnostic trace {label}")
gap = trace.get(
"max_gap", 3 * float(np.median(np.diff(t))) if len(t) > 1 else np.inf
)
gap = float(gap)
if np.isnan(gap) or gap <= 0:
raise ValueError("diagnostic max_gap must be positive and not NaN")
frames = []
for instant in frame_times:
n = int(np.searchsorted(t, instant, side="right"))
x = t[:n]
v = y[:n].copy()
# Insert separators; retain the first observed sample after each gap.
if n > 1:
breaks = np.flatnonzero(np.diff(x) > gap) + 1
x = np.insert(x, breaks, np.nan)
v = np.insert(v, breaks, np.nan)
frames.append((x, v))
finite = y[np.isfinite(y)]
low, high = (
(float(finite.min()), float(finite.max())) if finite.size else (0.0, 1.0)
)
pad = max((high - low) * 0.05, abs(high) * 0.01, 1e-12)
result[label] = {
"frames": frames,
"limits": (low - pad, high + pad),
"unit": trace.get("unit", "unspecified"),
"max_gap": gap,
}
return resultPrepare causal, gap-broken traces; renderers never interpolate or reduce.
| Name | Type | Unit | Description |
|---|---|---|---|
diagnostics | mapping | declared trace units | Labelled traces with time, values, unit and optional maximum gap. |
frame_times | array-like | trace time units | Simulation timestamps of the selected field frames. |
| Returns | |||
| — | dict | input trace units | Causal per-frame traces, broken gaps and fixed display limits. |
Applicability · Notes · Provenance
Applicability
Machine-independent. Requires the declared physical definitions, source identity and units. Matching display conventions alone does not establish physical equivalence or convergence.
Notes
Prepare causal, gap-broken traces; renderers never interpolate or reduce.
Provenance
- #2030 four-axis comparison and time-selection contract; #2028 diagnostic ownership.
radial_correlation_from_spectrum
Machine-independent
source
radial_correlation_from_spectrum(kx, spectrum, *, box_length, samples=513)
Show source vaft/process/gyrokinetics.py, lines 1210–1276
def radial_correlation_from_spectrum(kx, spectrum, *, box_length, samples=513):
"""Cosine autocorrelation 1/e crossing and integral scale; unresolved is a bound.
Parameters
----------
kx : array-like
Radial Fourier wavenumbers [inverse perpendicular length].
spectrum : array-like
Nonnegative radial power spectrum on kx [intensity].
box_length : float
Positive periodic radial box extent [perpendicular length].
samples : int, optional
Number of separation samples across half the box; default 513 [-].
Returns
-------
dict
1/e crossing, lower bound if unresolved, and first-zero integral scale [perpendicular length].
Applicability
-------------
Machine-independent. Requires the declared spectral convention, retained axes and units.
These are numerical reductions of solver data, not independent evidence of physical validity.
Notes
-----
Cosine autocorrelation 1/e crossing and integral scale; unresolved is a bound.
Array-only counterpart of the CGYRO locality reader, with its existing
half-box search and first-zero integral definition preserved.
Provenance
----------
.. [1] Existing CGYRO locality algorithm (#1354/#1484), spectrum-based cosine autocorrelation; #2028.
"""
kx, power = np.asarray(kx, float), np.asarray(spectrum, float)
length = float(box_length)
if (
kx.ndim != 1
or power.shape != kx.shape
or not np.isfinite(kx).all()
or not np.isfinite(power).all()
or np.any(power < 0)
or not np.isfinite(length)
or length <= 0
or samples < 2
):
raise ValueError("finite kx/nonnegative spectrum and positive box required")
if not np.any(power > 0):
return {"reason": "zero turbulent amplitude in the window"}
dx = np.linspace(0, 0.5 * length, samples)
correlation = (power[None, :] * np.cos(np.outer(dx, kx))).sum(axis=1)
correlation /= correlation[0]
below = np.flatnonzero(correlation <= np.exp(-1.0))
crossing = None
if below.size:
j = int(below[0])
x0, x1, c0, c1 = dx[j - 1], dx[j], correlation[j - 1], correlation[j]
crossing = float(x0 + (np.exp(-1.0) - c0) * (x1 - x0) / (c1 - c0))
zero = np.flatnonzero(correlation <= 0)
stop = int(zero[0]) if zero.size else dx.size
integrate = getattr(np, "trapezoid", None) or np.trapz
return {
"l_corr": crossing,
"l_corr_lower_bound": None if crossing is not None else 0.5 * length,
"l_integral": float(integrate(correlation[:stop], dx[:stop])),
}Cosine autocorrelation 1/e crossing and integral scale; unresolved is a bound.
| Name | Type | Unit | Description |
|---|---|---|---|
kx | array-like | inverse perpendicular length | Radial Fourier wavenumbers. |
spectrum | array-like | intensity | Nonnegative radial power spectrum on kx. |
box_length | float | perpendicular length | Positive periodic radial box extent. |
samples | int, optional | - | Number of separation samples across half the box; default 513. |
| Returns | |||
| — | dict | perpendicular length | 1/e crossing, lower bound if unresolved, and first-zero integral scale. |
Applicability · Notes · Provenance
Applicability
Machine-independent. Requires the declared spectral convention, retained axes and units. These are numerical reductions of solver data, not independent evidence of physical validity.
Notes
Cosine autocorrelation 1/e crossing and integral scale; unresolved is a bound.
Array-only counterpart of the CGYRO locality reader, with its existing half-box search and first-zero integral definition preserved.
Provenance
- Existing CGYRO locality algorithm (#1354/#1484), spectrum-based cosine autocorrelation; #2028.
rebin_contributions
Machine-independent
source
rebin_contributions(values, edges, new_edges)
Show source vaft/process/gyrokinetics.py, lines 936–984
def rebin_contributions(values, edges, new_edges):
"""Conserve signed flux using piecewise-uniform density within audited bins.
Parameters
----------
values : array-like
Signed spectral contributions or aligned time samples [quantity].
edges : array-like, optional
Audited increasing spectral bin edges [wavenumber].
new_edges : array-like
Destination bin edges spanning exactly the source interval [wavenumber].
Returns
-------
numpy.ndarray
Conservative destination-bin contributions under piecewise-uniform density [quantity].
Applicability
-------------
Machine-independent. Requires the declared spectral convention, retained axes and units.
These are numerical reductions of solver data, not independent evidence of physical validity.
Notes
-----
Conserve signed flux using piecewise-uniform density within audited bins.
The destination must cover exactly the same interval; no extrapolation.
Provenance
----------
.. [1] Canonical mathematical definition in #2028; uses the retained-source and weighting contract of #2025.
"""
values, edges, new = map(lambda x: np.asarray(x, float), (values, edges, new_edges))
if (
values.shape[-1] + 1 != len(edges)
or len(new) < 2
or not np.isfinite(edges).all()
or not np.isfinite(new).all()
or np.any(np.diff(edges) <= 0)
or np.any(np.diff(new) <= 0)
or not np.allclose([edges[0], edges[-1]], [new[0], new[-1]], rtol=0, atol=1e-12)
):
raise ValueError("audited increasing edges with identical coverage required")
overlap = np.maximum(
0,
np.minimum(new[1:, None], edges[None, 1:])
- np.maximum(new[:-1, None], edges[None, :-1]),
)
return (values / np.diff(edges)) @ overlap.TConserve signed flux using piecewise-uniform density within audited bins.
| Name | Type | Unit | Description |
|---|---|---|---|
values | array-like | quantity | Signed spectral contributions or aligned time samples. |
edges | array-like, optional | wavenumber | Audited increasing spectral bin edges. |
new_edges | array-like | wavenumber | Destination bin edges spanning exactly the source interval. |
| Returns | |||
| — | numpy.ndarray | quantity | Conservative destination-bin contributions under piecewise-uniform density. |
Applicability · Notes · Provenance
Applicability
Machine-independent. Requires the declared spectral convention, retained axes and units. These are numerical reductions of solver data, not independent evidence of physical validity.
Notes
Conserve signed flux using piecewise-uniform density within audited bins.
The destination must cover exactly the same interval; no extrapolation.
Provenance
- Canonical mathematical definition in #2028; uses the retained-source and weighting contract of #2025.
reconstruct_field
Machine-independent
source
reconstruct_field(coefficients, kx, ky, *, length_x, component='total', nx=None, ny=None)
Reconstruct CGYRO’s half-sum Re phi exp(+ikxx-iky*y).
| Name | Type | Unit | Description |
|---|---|---|---|
coefficients | array-like | native potential | Complex Fourier coefficients (kx, ky), excluding native special slots. |
kx | array-like | inverse perpendicular length | Radial Fourier wavenumbers. |
ky | array-like | inverse perpendicular length | Binormal wavenumbers, including zero. |
length_x | float | perpendicular length | Positive periodic radial box length. |
component | str | - | Total, zonal (ky=0), or nonzonal field selection. |
nx | int, optional | - | Radial sample count; default resolves retained Fourier harmonics. |
ny | int, optional | - | Binormal sample count; default resolves retained Fourier harmonics. |
| Returns | |||
| — | SpatialField | native potential | Periodic coordinates, real potential and explicit half-sum convention. |
Applicability · Notes · Provenance
Applicability
Machine-independent. Requires the declared spectral convention, retained axes and units. These are numerical reductions of solver data, not independent evidence of physical validity.
Notes
Reconstruct CGYRO’s half-sum Re phi exp(+ikxx-iky*y).
Matches pygacode b493397 plot_fluct.maptoreal, including half weight for ky=0. The caller must remove CGYRO’s special first radial slot. This is a saved-theta local plane, not a global or full 3D field.
Provenance
- GACODE b493397 pygacode/cgyro/plot_fluct.py, maptoreal and maptoreal_fft; #2019.
reduce_time_series
Machine-independent
source
reduce_time_series(time, values, *, window, blocks=4, max_gap=None, time_unit='a/c_s')
Time-weighted window reduction with explicit coverage and independent evidence.
| Name | Type | Unit | Description |
|---|---|---|---|
time | array-like | time_unit | Finite strictly increasing simulation times. |
values | array-like | quantity | Signed spectral contributions or aligned time samples. |
window | tuple of float | time_unit | Selected closed integration interval; no extrapolation. |
blocks | int, optional | - | Equal-duration blocks; at least two observed samples per block. |
max_gap | float, optional | time_unit | Largest integrated interval; default three median sample spacings. |
time_unit | str, optional | - | Time-coordinate unit recorded with the result; default a/c_s. |
| Returns | |||
| — | dict | quantity; time_unit | Mean, coverage, block evidence, drift and independent qualifications. |
Applicability · Notes · Provenance
Applicability
Machine-independent. Requires the declared spectral convention, retained axes and units. These are numerical reductions of solver data, not independent evidence of physical validity.
Notes
Time-weighted window reduction with explicit coverage and independent evidence.
Integrates linear segments only between finite adjacent observed samples. Without an explicit max_gap, gaps above 3*median cadence are excluded. No extrapolation or interpolation across missing samples. Blocks tile time, and their standard error is conditional on independence, never a confidence interval.
Provenance
- Existing nonlinear workflow batch-means implementation (#1484/#1820); piecewise-linear quadrature with explicit gaps; #2028.
saturated_intensity
Machine-independent
source
saturated_intensity(ql_weights, potential_intensity)
Show source vaft/process/gyrokinetics.py, lines 1173–1207
def saturated_intensity(ql_weights, potential_intensity):
"""TGLF moment intensity = QL intensity weight * saturated phi intensity.
Parameters
----------
ql_weights : array-like
Native TGLF quasilinear moment weights (species, ky, mode, moment) [native weight].
potential_intensity : array-like
Saturated potential intensity (ky, mode) [native phi squared].
Returns
-------
numpy.ndarray
Saturated moment intensity on the original four axes [native moment intensity].
Applicability
-------------
Machine-independent. Requires the declared spectral convention, retained axes and units.
These are numerical reductions of solver data, not independent evidence of physical validity.
Notes
-----
TGLF moment intensity = QL intensity weight * saturated phi intensity.
Weights: (species, ky, mode, moment); phi: (ky, mode). This is not a
transport-flux reconstruction: transport also needs its audited quadrature.
Provenance
----------
.. [1] GACODE b493397 tglf_inout.f90 field/intensity writers; native SAT0/SAT2 fixture identities; #2025/#2028.
"""
q, p = np.asarray(ql_weights, float), np.asarray(potential_intensity, float)
if q.ndim != 4 or p.shape != q.shape[1:3]:
raise ValueError("QL weights and saturated phi intensity axes disagree")
return q * p[None, :, :, None]TGLF moment intensity = QL intensity weight * saturated phi intensity.
| Name | Type | Unit | Description |
|---|---|---|---|
ql_weights | array-like | native weight | Native TGLF quasilinear moment weights (species, ky, mode, moment). |
potential_intensity | array-like | native phi squared | Saturated potential intensity (ky, mode). |
| Returns | |||
| — | numpy.ndarray | native moment intensity | Saturated moment intensity on the original four axes. |
Applicability · Notes · Provenance
Applicability
Machine-independent. Requires the declared spectral convention, retained axes and units. These are numerical reductions of solver data, not independent evidence of physical validity.
Notes
TGLF moment intensity = QL intensity weight * saturated phi intensity.
Weights: (species, ky, mode, moment); phi: (ky, mode). This is not a transport-flux reconstruction: transport also needs its audited quadrature.
Provenance
- GACODE b493397 tglf_inout.f90 field/intensity writers; native SAT0/SAT2 fixture identities; #2025/#2028.
select_time
Machine-independent
source
select_time(times, requested=None, *, tolerance=None)
Show source vaft/process/gyrokinetic_comparison.py, lines 169–236
def select_time(times, requested=None, *, tolerance=None):
"""Nearest finite time and evidence; no implicit scientific tolerance.
Parameters
----------
times : array-like
Stored finite, distinct experimental timestamps [s].
requested : float, optional
Requested experimental time, or first stored time when omitted [s].
tolerance : float, optional
Explicit maximum time mismatch; absence leaves scientific alignment unverified [s].
Returns
-------
dict
Stored index, requested/selected time, difference and alignment status [s; index -].
Applicability
-------------
Machine-independent. Requires the declared physical definitions, source identity and units.
Matching display conventions alone does not establish physical equivalence or convergence.
Notes
-----
Nearest finite time and evidence; no implicit scientific tolerance.
Provenance
----------
.. [issue] #2030 four-axis comparison and time-selection contract; #2028 diagnostic ownership.
"""
t = np.asarray(times, float)
if (
t.ndim != 1
or not len(t)
or not np.isfinite(t).all()
or len(np.unique(t)) != len(t)
):
raise ValueError("unavailable or ambiguous time stamps")
if tolerance is not None and (not np.isfinite(tolerance) or tolerance < 0):
raise ValueError("time tolerance must be finite and nonnegative")
target = float(t[0] if requested is None else requested)
if not np.isfinite(target):
raise ValueError("requested time must be finite")
distances = np.abs(t - target)
i = int(np.argmin(distances))
delta = float(t[i] - target)
if (
np.count_nonzero(
np.isclose(
distances,
distances[i],
rtol=0,
atol=4 * np.finfo(float).eps * max(1, abs(target)),
)
)
> 1
):
raise ValueError("ambiguous equidistant time slices")
if tolerance is not None and abs(delta) > tolerance:
raise ValueError("selected experimental time outside tolerance")
return {
"index": i,
"requested_time": target,
"selected_time": float(t[i]),
"delta_time": delta,
"tolerance": tolerance,
"status": "matched" if tolerance is not None else "unverified",
}Nearest finite time and evidence; no implicit scientific tolerance.
| Name | Type | Unit | Description |
|---|---|---|---|
times | array-like | s | Stored finite, distinct experimental timestamps. |
requested | float, optional | s | Requested experimental time, or first stored time when omitted. |
tolerance | float, optional | s | Explicit maximum time mismatch; absence leaves scientific alignment unverified. |
| Returns | |||
| — | dict | s; index - | Stored index, requested/selected time, difference and alignment status. |
Applicability · Notes · Provenance
Applicability
Machine-independent. Requires the declared physical definitions, source identity and units. Matching display conventions alone does not establish physical equivalence or convergence.
Notes
Nearest finite time and evidence; no implicit scientific tolerance.
Provenance
- #2030 four-axis comparison and time-selection contract; #2028 diagnostic ownership.
spectral_integral
Machine-independent
source
spectral_integral(values, *, representation='contribution', edges=None, axis=-1)
Show source vaft/process/gyrokinetics.py, lines 887–933
def spectral_integral(values, *, representation="contribution", edges=None, axis=-1):
"""Integrate signed bin contributions or densities with explicit bin edges.
Parameters
----------
values : array-like
Signed spectral contributions or aligned time samples [quantity].
representation : str
Contribution means bin-integrated values; density requires edges [-].
edges : array-like, optional
Audited increasing spectral bin edges [wavenumber].
axis : int, optional
Axis containing spectral bins or additive field contributions [-].
Returns
-------
numpy.ndarray
Signed integral with the selected spectral axis removed [quantity].
Applicability
-------------
Machine-independent. Requires the declared spectral convention, retained axes and units.
These are numerical reductions of solver data, not independent evidence of physical validity.
Notes
-----
Integrate signed bin contributions or densities with explicit bin edges.
Provenance
----------
.. [1] Canonical mathematical definition in #2028; uses the retained-source and weighting contract of #2025.
"""
values = np.asarray(values, float)
if representation == "contribution":
return np.sum(values, axis=axis)
if representation != "density" or edges is None:
raise ValueError("density requires audited bin edges")
edges = np.asarray(edges, float)
if (
edges.size != values.shape[axis] + 1
or not np.isfinite(edges).all()
or np.any(np.diff(edges) <= 0)
):
raise ValueError("increasing finite edges must bracket every bin")
shape = [1] * values.ndim
shape[axis] = len(edges) - 1
return np.sum(values * np.diff(edges).reshape(shape), axis=axis)Integrate signed bin contributions or densities with explicit bin edges.
| Name | Type | Unit | Description |
|---|---|---|---|
values | array-like | quantity | Signed spectral contributions or aligned time samples. |
representation | str | - | Contribution means bin-integrated values; density requires edges. |
edges | array-like, optional | wavenumber | Audited increasing spectral bin edges. |
axis | int, optional | - | Axis containing spectral bins or additive field contributions. |
| Returns | |||
| — | numpy.ndarray | quantity | Signed integral with the selected spectral axis removed. |
Applicability · Notes · Provenance
Applicability
Machine-independent. Requires the declared spectral convention, retained axes and units. These are numerical reductions of solver data, not independent evidence of physical validity.
Notes
Integrate signed bin contributions or densities with explicit bin edges.
Provenance
- Canonical mathematical definition in #2028; uses the retained-source and weighting contract of #2025.
time_window_average
Machine-independent
source
time_window_average(time, values, *, window, max_gap=None)
Show source vaft/process/gyrokinetics.py, lines 1279–1314
def time_window_average(time, values, *, window, max_gap=None):
"""Average aligned scalar or multi-channel histories with the shared gap policy.
Parameters
----------
time : array-like
Strictly increasing sample times [time].
values : array-like
Histories with time on the final axis [quantity].
window : tuple of float
Selected integration bounds in the input time unit [time].
max_gap : float, optional
Largest integrated interval; default three median sample spacings [time].
Returns
-------
numpy.ndarray
Means with the time axis removed; unavailable integrals are NaN [quantity].
Applicability
-------------
Machine-independent. Uses observed adjacent samples only, with the same
no-extrapolation and missing-interval policy as reduce_time_series.
Provenance
----------
.. [1] Shared piecewise-linear reduction contract in #2028.
"""
t, y = np.asarray(time, float), np.asarray(values, float)
if y.ndim < 1 or y.shape[-1] != t.size:
raise ValueError("histories must end in the simulation time axis")
means = [
reduce_time_series(t, row, window=window, max_gap=max_gap, blocks=2)["mean"]
for row in y.reshape(-1, len(t))
]
return np.asarray([np.nan if v is None else v for v in means]).reshape(y.shape[:-1])Average aligned scalar or multi-channel histories with the shared gap policy.
| Name | Type | Unit | Description |
|---|---|---|---|
time | array-like | time | Strictly increasing sample times. |
values | array-like | quantity | Histories with time on the final axis. |
window | tuple of float | time | Selected integration bounds in the input time unit. |
max_gap | float, optional | time | Largest integrated interval; default three median sample spacings. |
| Returns | |||
| — | numpy.ndarray | quantity | Means with the time axis removed; unavailable integrals are NaN. |
Applicability · Provenance
Applicability
Machine-independent. Uses observed adjacent samples only, with the same no-extrapolation and missing-interval policy as reduce_time_series.
Provenance
- Shared piecewise-linear reduction contract in #2028.
zonal_fraction
Machine-independent
source
zonal_fraction(phi, ky, *, weights=None, ky_tolerance=1e-12, weighting=None)
Show source vaft/process/gyrokinetics.py, lines 847–884
def zonal_fraction(phi, ky, *, weights=None, ky_tolerance=1e-12, weighting=None):
"""I_Z/(I_Z+I_T); all-zero intensity is undefined, not zero.
Parameters
----------
phi : array-like
Complex potential coefficients (kx, ky, time) [native potential].
ky : array-like
Binormal wavenumbers, including zero [inverse perpendicular length].
weights : array-like, optional
Nonnegative intensity weights broadcast over kx and ky [-].
ky_tolerance : float, optional
Numerical threshold identifying the zero binormal wavenumber [ky unit].
weighting : str, optional
Explicit interpretation of the supplied intensity weights [-].
Returns
-------
numpy.ndarray
Zonal fraction at each time; all-zero intensity is NaN [-].
Applicability
-------------
Machine-independent. Requires the declared spectral convention, retained axes and units.
These are numerical reductions of solver data, not independent evidence of physical validity.
Notes
-----
I_Z/(I_Z+I_T); all-zero intensity is undefined, not zero.
Provenance
----------
.. [1] Canonical mathematical definition in #2028; uses the retained-source and weighting contract of #2025.
"""
result = zonal_turbulence_intensity(
phi, ky, weights=weights, ky_tolerance=ky_tolerance, weighting=weighting
)
return result.fractionI_Z/(I_Z+I_T); all-zero intensity is undefined, not zero.
| Name | Type | Unit | Description |
|---|---|---|---|
phi | array-like | native potential | Complex potential coefficients (kx, ky, time). |
ky | array-like | inverse perpendicular length | Binormal wavenumbers, including zero. |
weights | array-like, optional | - | Nonnegative intensity weights broadcast over kx and ky. |
ky_tolerance | float, optional | ky unit | Numerical threshold identifying the zero binormal wavenumber. |
weighting | str, optional | - | Explicit interpretation of the supplied intensity weights. |
| Returns | |||
| — | numpy.ndarray | - | Zonal fraction at each time; all-zero intensity is NaN. |
Applicability · Notes · Provenance
Applicability
Machine-independent. Requires the declared spectral convention, retained axes and units. These are numerical reductions of solver data, not independent evidence of physical validity.
Notes
I_Z/(I_Z+I_T); all-zero intensity is undefined, not zero.
Provenance
- Canonical mathematical definition in #2028; uses the retained-source and weighting contract of #2025.
zonal_shear_proxy
Machine-independentConvention-sensitive
source
zonal_shear_proxy(phi, kx, ky, *, ky_tolerance=1e-12)
Show source vaft/process/gyrokinetics.py, lines 274–333
def zonal_shear_proxy(phi, kx, ky, *, ky_tolerance=1e-12):
r"""Spectral proxies for the zonal-flow energy and the zonal shear.
$E_Z \propto \sum_{k_x} k_x^2|\phi_{k_x,0}|^2$ and
$S_Z^2 \propto \sum_{k_x} k_x^4|\phi_{k_x,0}|^2$, from
$v_{E,Z} \propto k_x\phi_Z$ and $\partial_x v_{E,Z} \propto k_x^2\phi_Z$.
Parameters
----------
phi : array-like
Potential Fourier components, shape ``(n_kx, n_ky, n_time)`` [solver units].
kx : array-like
Radial wavenumber of each ``kx`` row, length ``n_kx`` [1/length].
ky : array-like
Binormal wavenumber of each ``ky`` column, length ``n_ky`` [1/length].
ky_tolerance : float, optional
Largest ``|ky|`` counted as zonal [1/length].
Returns
-------
ZonalShearProxy
``flow`` and ``shear`` per time sample and the ``normalization`` label
[kx^2 phi^2, kx^4 phi^2].
Raises
------
ValueError
Shapes do not match, inputs are not finite, or no zonal ``ky`` exists.
Defaults
--------
``ky_tolerance=1e-12`` is a numerical convenience (solvers store the zonal
wavenumber as exact zero).
Convention
----------
Spectral proxies in the units of $\phi$ and $k_x$: physical flow energy
and shearing rate need the solver's potential and perpendicular-length
normalisation and geometric factors, which this routine does not apply.
Applicability
-------------
Machine-independent.
Provenance
----------
.. [1] P. H. Diamond, S.-I. Itoh, K. Itoh and T. S. Hahm,
Plasma Phys. Control. Fusion 47 (2005) R35.
.. [issue] #1820 Sec. 7.
"""
cube = _spectral_cube(phi)
zonal_mask, _ = _ky_masks(ky, cube.shape[1], ky_tolerance)
k = np.asarray(kx, dtype=float).ravel()
if k.size != cube.shape[0] or not np.all(np.isfinite(k)):
raise ValueError(f"kx must be finite with {cube.shape[0]} entries")
power = (np.abs(cube[:, zonal_mask]) ** 2).sum(axis=1) # (n_kx, n_time)
flow = (k[:, None] ** 2 * power).sum(axis=0)
shear = (k[:, None] ** 4 * power).sum(axis=0)
return ZonalShearProxy(flow=flow, shear=shear,
normalization="spectral proxy: sum kx^p |phi_{kx,0}|^2 in solver units")Spectral proxies for the zonal-flow energy and the zonal shear.
$E_Z \propto \sum_{k_x} k_x^2|\phi_{k_x,0}|^2$ and $S_Z^2 \propto \sum_{k_x} k_x^4|\phi_{k_x,0}|^2$, from $v_{E,Z} \propto k_x\phi_Z$ and $\partial_x v_{E,Z} \propto k_x^2\phi_Z$.
| Name | Type | Unit | Description |
|---|---|---|---|
phi | array-like | solver units | Potential Fourier components, shape |
kx | array-like | 1/length | Radial wavenumber of each |
ky | array-like | 1/length | Binormal wavenumber of each |
ky_tolerance | float, optional | 1/length | Largest |
| Returns | |||
| — | ZonalShearProxy | kx^2 phi^2, kx^4 phi^2 |
|
Convention
Spectral proxies in the units of $\phi$ and $k_x$: physical flow energy and shearing rate need the solver’s potential and perpendicular-length normalisation and geometric factors, which this routine does not apply.
Raises
ValueErrorShapes do not match, inputs are not finite, or no zonalkyexists.
Defaults · Applicability · Provenance
Defaults
ky_tolerance=1e-12 is a numerical convenience (solvers store the zonal
wavenumber as exact zero).
Applicability
Machine-independent.
Provenance
- P. H. Diamond, S.-I. Itoh, K. Itoh and T. S. Hahm, Plasma Phys. Control. Fusion 47 (2005) R35.
- #1820 Sec. 7.
zonal_turbulence_intensity
Machine-independentConvention-sensitive
source
zonal_turbulence_intensity(phi, ky, *, weights=None, ky_tolerance=1e-12, weighting=None)
Show source vaft/process/gyrokinetics.py, lines 200–271
def zonal_turbulence_intensity(phi, ky, *, weights=None, ky_tolerance=1e-12, weighting=None):
r"""Split fluctuation intensity into its zonal ($k_y = 0$) and non-zonal parts.
$I_\mathrm{turb}(t) = \sum_{k_x, k_y\ne0} w\,|\phi_{k_x,k_y}(t)|^2$,
$I_\mathrm{zonal}(t) = \sum_{k_x} w\,|\phi_{k_x,0}(t)|^2$ and
$R_{ZT} = I_\mathrm{zonal}/I_\mathrm{turb}$.
Parameters
----------
phi : array-like
Potential Fourier components, shape ``(n_kx, n_ky, n_time)``, real or
complex; average or select any poloidal coordinate beforehand [solver units].
ky : array-like
Binormal wavenumber of each ``ky`` column; the zonal column is the one
with ``|ky| <= ky_tolerance`` [1/length].
weights : array-like, optional
Spectral weight broadcastable to ``(n_kx, n_ky)``; ``None`` for 1 [caller units].
ky_tolerance : float, optional
Largest ``|ky|`` counted as zonal [1/length].
weighting : str, optional
Name of the weighting, recorded in the result [-].
Returns
-------
ZonalTurbulenceIntensity
``turbulence``, ``zonal`` and ``ratio`` per time sample (``ratio`` is
NaN where the turbulence intensity is zero) and the ``weighting`` label
[weight * phi^2; ratio -].
Raises
------
ValueError
``phi`` is not 3-D or not finite, ``ky`` does not match its ky axis, no
``ky`` is zonal within the tolerance, or a weight is negative.
Defaults
--------
``ky_tolerance=1e-12`` is a numerical convenience: solvers store the zonal
wavenumber as exact zero. Unit weights (``weights=None``) are the
conventional potential-intensity proxy.
Convention
----------
Unweighted $|\phi|^2$ is a potential-intensity proxy, labelled as such; it
becomes an energy only with the metric weights the caller supplies (e.g.
$k_\perp^2$ for an $E\times B$ kinetic-energy proxy). Solvers that store
only $k_y \ge 0$ count each non-zonal mode once.
Applicability
-------------
Machine-independent.
Provenance
----------
.. [1] S. Kobayashi, O. D. Gurcan and P. H. Diamond, Phys. Plasmas 22 (2015) 090702.
.. [issue] #1820 Sec. 6.
"""
cube = _spectral_cube(phi)
zonal_mask, turb_mask = _ky_masks(ky, cube.shape[1], ky_tolerance)
power = np.abs(cube) ** 2
if weights is not None:
w = np.asarray(weights, dtype=float)
if not np.all(np.isfinite(w)) or np.any(w < 0):
raise ValueError("weights must be finite and non-negative")
power = power * np.broadcast_to(w, cube.shape[:2])[..., None]
turbulence = power[:, turb_mask].sum(axis=(0, 1))
zonal = power[:, zonal_mask].sum(axis=(0, 1))
with np.errstate(divide="ignore", invalid="ignore"):
ratio = np.where(turbulence > 0, zonal / np.where(turbulence > 0, turbulence, 1.0), np.nan)
label = weighting or ("unweighted |phi|^2 (potential-intensity proxy)" if weights is None
else "caller-weighted |phi|^2")
return ZonalTurbulenceIntensity(turbulence=turbulence, zonal=zonal, ratio=ratio, weighting=label)Split fluctuation intensity into its zonal ($k_y = 0$) and non-zonal parts.
$I_\mathrm{turb}(t) = \sum_{k_x, k_y\ne0} w\,|\phi_{k_x,k_y}(t)|^2$, $I_\mathrm{zonal}(t) = \sum_{k_x} w\,|\phi_{k_x,0}(t)|^2$ and $R_{ZT} = I_\mathrm{zonal}/I_\mathrm{turb}$.
| Name | Type | Unit | Description |
|---|---|---|---|
phi | array-like | solver units | Potential Fourier components, shape |
ky | array-like | 1/length | Binormal wavenumber of each |
weights | array-like, optional | caller units | Spectral weight broadcastable to |
ky_tolerance | float, optional | 1/length | Largest |
weighting | str, optional | - | Name of the weighting, recorded in the result. |
| Returns | |||
| — | ZonalTurbulenceIntensity | weight * phi^2; ratio - |
|
Convention
Unweighted $|\phi|^2$ is a potential-intensity proxy, labelled as such; it becomes an energy only with the metric weights the caller supplies (e.g. $k_\perp^2$ for an $E\times B$ kinetic-energy proxy). Solvers that store only $k_y \ge 0$ count each non-zonal mode once.
Raises
ValueErrorphiis not 3-D or not finite,kydoes not match its ky axis, nokyis zonal within the tolerance, or a weight is negative.
Defaults · Applicability · Provenance
Defaults
ky_tolerance=1e-12 is a numerical convenience: solvers store the zonal
wavenumber as exact zero. Unit weights (weights=None) are the
conventional potential-intensity proxy.
Applicability
Machine-independent.
Provenance
- S. Kobayashi, O. D. Gurcan and P. H. Diamond, Phys. Plasmas 22 (2015) 090702.
- #1820 Sec. 6.