Normalization

This section documents the normalization conventions used in SPECTRAX-GK and the calibration parameters that scale drift/drive terms for benchmark comparisons.

Canonical normalization contract

SPECTRAX-GK now centralizes benchmark-family normalization values in spectraxgk.normalization via spectraxgk.normalization.NormalizationContract. This is the single source of truth for case defaults:

Canonical per-case normalization contracts

Case key

rho_star

omega_d_scale

omega_star_scale

diagnostic_norm_default

cyclone

1.0

1.0

1.0

none

etg

1.0

0.4

0.8

none

kinetic (kinetic_itg alias)

1.0

1.0

1.0

none

tem

1.0

1.0

1.0

none

kbm

1.0

1.0

0.8

none

These contracts are consumed by benchmark constants for backward compatibility (CYCLONE_OMEGA_D_SCALE, etc.), so existing scripts keep working while all new calibration updates flow through one module.

Dimensionless units

We evolve a dimensionless gyrokinetic system normalized to ion thermal quantities. The parallel streaming term uses the normalized thermal velocity \(v_{th}\) and the flux-tube coordinate \(z\) (theta-like). The perpendicular wave numbers are normalized by the ion gyro-radius \(\rho_i\), while the distribution function and potential use the standard gyrokinetic scaling:

\[\tilde{\phi} = \frac{e \phi}{T_i}, \qquad \tilde{\omega} = \frac{\omega}{v_{th}/R_0}.\]

For the Cyclone base case we take the reference length \(L_{ref}=a\) so that the input gradients are expressed as \(a/L_T\) and \(a/L_n\). With \(R_0 = R/a\), this means \(R/L_T = (R_0)\,(a/L_T)\) and similarly for \(R/L_n\).

Kinetic species conventions

SPECTRAX-GK supports multi-species kinetic systems. Species-dependent arrays carry the charge, mass, density, temperature, and gradient inputs:

  • charge_sign: \(Z_s\) (e.g., \(+1\) for ions, \(-1\) for electrons).

  • temp / mass / density: normalized to the reference species.

  • tz: \(Z_s / T_s\) coupling used in the field terms.

  • R_over_LTi / R_over_Ln: normalized gradients for each species.

For adiabatic closures, tau_e provides the ratio between the kinetic species temperature and the Boltzmann species temperature.

Field-aligned grid parameters

For the Cyclone base case we use a field-aligned grid with:

\[y_0 = 20,\qquad n_\theta = 32,\qquad n_{period} = 2.\]

In SPECTRAX-GK these map to GridConfig(y0=20, ntheta=32, nperiod=2), which sets:

\[L_y = 2 \pi y_0,\qquad z \in [-\pi Z_p, \pi Z_p),\qquad Z_p = 2 n_{period} - 1.\]

The reduced scan tables and regression tests use Nx=1, Ny=24, Nz=96 on this grid to match the discrete ky set used in the reference CSV.

Spectral grids

SPECTRAX-GK’s explicit benchmark integrator uses the compressed Fourier conventions required by the tracked reference data. The perpendicular wave numbers are defined as

\[k_x = \frac{n_x}{x_0}, \qquad k_y = \frac{n_y}{y_0},\]

with x0 = Lx / (2π) and y0 = Ly / (2π). The parallel wave number is

\[k_z = \frac{n_z}{Z_p},\]

where \(Z_p\) sets the field-line length (\(z \in [-\pi Z_p, \pi Z_p)\)), and \(k_z\) is defined without the gradpar factor. These definitions are implemented by spectraxgk.grids.build_spectral_grid and are consistent with GX’s kInit kernel.

The midplane index used by the reference growth-rate diagnostic corresponds to z_index = Nz//2 + 1, matching the audited benchmark kernel logic when Nz > 1.

Perpendicular normalization

The reference diagnostic contract defines the perpendicular metric as \(k_\perp^2/B^2\) before applying the Laguerre gyroaverage. To match that convention in SPECTRAX-GK:

  • kperp2_bmag = True (include the \(B^{-2}\) factor in \(k_\perp^2\))

  • bessel_bmag_power = 0 (no extra \(B\) scaling inside the Bessel argument)

The Cyclone base case defaults follow this benchmark setting, and the compare_gx_rhs_terms.py comparison tool assumes the same normalization.

Sign conventions

The growth-rate fitting in spectraxgk.analysis.fit_growth_rate() assumes

\[s(t) \sim \exp((\gamma - i \omega)\, t),\]

so:

  • gamma > 0 indicates instability.

  • omega is obtained from the negative phase slope.

This is consistent across time-integration and Krylov post-processing paths. For scan tables and figures, values are reported in the same sign convention as the solver output unless an explicit diagnostic normalization is requested.

Normalization parameters

The linear operator exposes three normalization parameters that influence the drift/drive terms:

  • rho_star: scales \(k_x\) and \(k_y\) in the drift and drive terms.

  • omega_d_scale: scales curvature/grad-\(B\)/mirror couplings.

  • omega_star_scale: scales the diamagnetic drive.

In code, rho_star multiplies the Fourier grids inside spectraxgk.linear.build_linear_cache(), while omega_d_scale and omega_star_scale enter directly in spectraxgk.linear.linear_rhs_cached().

Diagnostic normalization mode

Benchmark runners expose diagnostic_norm and route it through spectraxgk.normalization.apply_diagnostic_normalization:

  • none: return raw solver (gamma, omega).

  • gx / rho_star: multiply reported (gamma, omega) by rho_star.

This affects reporting only; it does not alter the RHS/operator.

The unified runtime schema defaults to diagnostic_norm = "gx" so that out-of-the-box reports match the tracked benchmark normalization. Set diagnostic_norm = "none" in the TOML or runtime config to recover raw solver outputs.

Diagnostic scaling

The reference diagnostics apply fixed factors in a few places that depend on the storage convention (e.g. real-FFT nyquist handling or per-unit-time damping). The runtime schema therefore exposes light-weight diagnostic scale factors:

  • flux_scale: multiplicative factor applied to the reported heat/particle fluxes (default 1.0 for the tracked comparison convention).

  • wphi_scale: multiplicative factor applied to Wphi (default 1.0; the Cyclone nonlinear comparison config uses 1.155).

These are reporting-only knobs; they do not alter the RHS/operator. They are intended to document exact comparison settings used for benchmark plots.

The reference end-damping defaults are damp_ends_amp = 0.1 and damp_ends_widthfrac = 0.125. The damping kernel interprets damp_ends_amp directly as a rate; the runtime no longer rescales it by the timestep.

Defaults (model parameters):

  • rho_star = 1.0 (model default)

  • omega_d_scale = 1.0 (model default)

  • omega_star_scale = 1.0 (model default)

These parameters are surfaced in the regression tables so that future normalization refinements can be tracked in a reproducible way.

Programmatic usage

from spectraxgk.normalization import get_normalization_contract

contract = get_normalization_contract("etg")
# contract.omega_d_scale == 0.4
# contract.omega_star_scale == 0.8