Operators And Terms
This page states the operator GKX integrates, term by term, and ties each term to its runtime controls and source files. For TOML syntax and every supported key, see Input Files and Executable.
State And Coupled Variable
For each species \(s\), GKX evolves Laguerre-Hermite moments \(G^{(s)}_{\ell m}(k_x,k_y,z,t)\). The field-coupled variable used by the linear operator is
with \(J_\ell^B = J_\ell + J_{\ell-1}\).
On the explicit-time reference-compatible path, streaming acts on the field-coupled streamed variable built from the same field terms before the Hermite ladder is taken.
Source mapping:
src/gkx/operators/linear/params.py(LinearParams)src/gkx/terms/fields.pysrc/gkx/terms/assembly.py
Implemented Linear Operator
The assembled RHS is
Every term has a multiplicative weight of the same name in TermConfig and
RuntimeTermsConfig. All default to 1 except hyperdiffusion and
nonlinear, which default to 0.
Gyroaverage And Bessel Factors
The Laguerre gyroaverage coefficients are
Nonlinear electromagnetic terms also use \(J_0(\alpha)\) and \(J_1(\alpha)\) on the quadrature grid.
Source mapping:
src/gkx/core_velocity.pysrc/gkx/terms/nonlinear.py
Streaming
The Hermite ladder streaming term is
where \(X\) is either \(H\) or the benchmark-compatible streamed variable, depending on the solver path.
Controls:
LinearParams.kpar_scaleRuntimeTermsConfig.streamingboundary/link metadata from the geometry/grid
The parallel FFT uses the signed frequencies of NumPy’s DFT convention. For a chain of \(N\) points separated by \(\Delta z\),
Opposite Nyquist signs give the same sampled wave \((-1)^j\) but opposite
first derivatives. Match this convention before comparing another code’s RHS;
filtering a mode is not a substitute for spatial convergence. Linked chains
must use the total chain length and preserve their gather/scatter ordering.
test_fft_highest_modes_and_ad_contract checks analytic derivatives, JVPs
and real-parameter pullbacks on odd/even periodic and reordered linked chains.
The linked-map tests independently check signed frequencies and exact topology.
These are discrete-operator contracts, not turbulent-transport benchmarks.
Mirror
The mirror term uses \(b'(z)\) and couples both Laguerre and Hermite indices:
Curvature And Grad-B
The drift terms are
Controls:
LinearParams.omega_d_scaleRuntimeTermsConfig.curvatureRuntimeTermsConfig.gradb
Diamagnetic Drive
The diamagnetic drive acts through density and temperature-gradient couplings in the low Hermite moments. It drives:
m=0through density and perpendicular-energy combinations,m=2through temperature-gradient coupling,m=1andm=3for electromagneticA_parallelterms when enabled.
Controls:
LinearParams.omega_star_scaleLinearParams.fprimLinearParams.tprimRuntimeTermsConfig.diamagnetic
Collisions
GKX ships six collision models. The collision_operator key in the
[time] section of a TOML input selects one, and
gkx.operators.linear.collision_tables.collision_operator_from_config()
builds the same operator from Python:
|
Model |
Reference |
|---|---|---|
|
Linearized Landau (Fokker-Planck), drift-kinetic limit, any |
built in, described below |
|
Conserving diagonal Lenard-Bernstein/Dougherty relaxation |
built in, described below |
|
Drift-kinetic Sugama, conservative by construction |
Frei, Ernst & Ricci (2022), Eqs. (C6a)–(C6f) |
|
Improved Sugama, corrected Pfirsch-Schlüter friction |
Sugama et al. (2019); Frei, Ernst & Ricci (2022) |
|
Alias of |
shipped data kept as a regression reference |
|
Gyrokinetic Coulomb retaining finite \(k_\perp\) |
Frei, Ball, Hoffmann, Jorge, Ricci & Stenger (2021), Eqs. (3.47)–(3.50) |
landau, none and lenard_bernstein are applied inside the linear
RHS from the cache, so every solver path (fixed-step, CFL-controlled, Krylov,
IMEX, nonlinear) uses them; Hermite-sharded runs refuse landau.
none and lenard_bernstein keep the built-in diagonal term described in
this section. The three moment operators replace that term with a dense
Hermite-Laguerre matrix. The solver switches the diagonal contribution off
exactly when a moment operator is active, so collisions are never counted twice.
Two constraints follow from the tabulated coefficients. The run’s basis must
be a shipped table’s (Nl, Nm) = (J+1, P+1): (2, 4) for the eight-moment
tables, or (3, 6) for the 18-moment finite-Larmor table. Matching Nl*Nm
is not enough: the tables are Hermite-major, so the transposed (4, 2) would
pair every coefficient with the wrong moment, and it is refused. The operators
run on the fixed-step cached integrator. The sharded, Krylov eigenvalue, and
CFL-controlled explicit_time paths raise rather than silently substituting
the diagonal term. The Coulomb tables are generated at unit mass and temperature ratio, so a
multispecies request is refused rather than extrapolated.
Linearized Landau operator (default)
The default is the linearized Landau operator about Maxwellians,
\(C_{ab}[f_a,f_b]=C(f_a,F_b)+C(F_a,f_b)\), in its drift-kinetic
(\(k_\perp\to0\)) limit, applied to the non-adiabatic response H.
With \(x=v/v_{ta}\), \(v_{ta}=\sqrt{2T_a/m_a}\), the test part is the
Rosenbluth diffusion
with \(G\) the Chandrasekhar function and \(H_b\), \(\mathsf D_b=\nabla\nabla G_b\) the Rosenbluth potentials of \(F_b\). The field part is
with \(H_b\), \(G_b\) the potentials of the perturbation \(f_b\)
(Helander & Sigmar 2002, ch. 3). The operator is rotationally invariant, so in
the Legendre-Sonine basis \(x^lL_k^{(l+1/2)}(x^2)P_l(\xi)\) it is block
diagonal in \(l\) and each block is a pair of radial integrals. GKX
evaluates them by composite Gauss quadrature once per run, for the run’s
(Nl, Nm) and species mass and temperature ratios, and maps them to the
Hermite-Laguerre box with an exact orthogonal transform
(gkx.operators.linear.collisions.linearized_landau_pair_matrices()). The
result is a dense matrix per species pair; one RHS applies it as a moment-space
matrix product.
What is verified (tests/validation/physics_gates/test_collision_physics.py):
density, parallel momentum and energy are exact null vectors (
1e-13), the like-species matrix is symmetric negative semidefinite with exactly three zero eigenvalues (H-theorem);it equals the multiprecision Coulomb tables of Frei et al. (2021, 2022) to
1e-12at(Nl, Nm) = (2, 4)and(3, 6), once their collision frequency (twice GKX’s) is accounted for;its test part equals the Sugama test part at equal temperatures for \(m_a/m_b = 1,\ 1/1836,\ 1836\);
electron-ion momentum and energy exchange cancel exactly, also at \(T_e/T_i=3\);
the Spitzer-Harm ratio \(\gamma_E(Z)\) is within 0.5% of Spitzer & Harm (1953) for \(Z=1,2,4,16\);
the application is differentiable in
nu(and in density and charge).
Frequency convention. nu is each species’ self-collision frequency in GKX
units, \(\nu=\sqrt2\,\mathtt{vnewk}^{\rm GS2}\), and
\(\nu_{ab}=\nu_a n_bZ_b^2/(n_aZ_a^2)\). Inter-species conservation is
exact when the species rates are mutually consistent,
\(\nu_a\propto n_aZ_a^4/(m_a^{1/2}T_a^{3/2})\). At unequal temperatures the
operator still conserves but is not self-adjoint; the thermal equilibration
\(C(F_a,F_b)\) is dropped, as in all delta-f codes.
Default and cost. landau is the default both in the runtime and in
LinearParams (collision_model); the
matrices are built only when some nu is nonzero. The runtime applies the
factors \(T B T^{\mathsf T}\) directly: \(T\) is block diagonal in the
degree \(p+2j\) and \(B\) in \(l\), which at
\((N_l,N_m)=(16,48)\) is 4.1x fewer flops than the dense product. On an
idle A4000, Cyclone grid \(16\times8\times32\), the whole linear RHS at
\((16,48)\) costs 1.6x the Dougherty RHS in float32 (one and two species)
and 1.9x (one species) and 2.3x (two species) in float64; at \((8,24)\),
1.4-1.7x (plan/research/2026-10-15-collisions/results/rhs_collision_share_gpu.txt).
Benchmarks against other codes (results/xcode_collisional.txt,
results/zonal_collisional.txt):
Cyclone ITG with adiabatic electrons, \(k_y=0.3\), \(\nu_i\) from 0 to 0.1: within 1.1% of GS2’s model operator at \((N_l,N_m)=(12,48)\), including GS2’s slight collisional destabilisation. The Dougherty kernel goes the other way, and is 21% low at \(\nu_i=0.1\).
Cyclone with kinetic electrons (\(m_e/m_i=2.7\times10^{-4}\)), \(\nu_i\) from 0 to 0.1 with consistent \(\nu_e\): within 1.2-4.8% of GS2 at \((8,24)\). Dougherty is 11% low at \(\nu_i=0.03\).
Collisional decay of the Rosenbluth-Hinton residual (s-alpha, \(q=1.4\), \(\epsilon=0.18\)): the residual levels are within 6% of Xiao, Catto & Molvig (2007), but the decay rate is 21-27% slower. That formula drops energy diffusion, and its \(\nu_{ii}\) convention was not checked against the paper, so the rate is not used as a gate. The Dougherty kernel does not damp this residual at all.
Not included: finite-\(k_\perp\) (gyroaveraging) terms, which
coulomb_finite_kperp carries for one species at fixed tabulated
resolutions. The matrix depends on mass and temperature ratios through a
host-side build, so it is not differentiated with respect to them.
Collision frequency
The tabulated matrices carry only the dimensionless pair scaling
\(\nu_{ab} = n_b / (\sqrt{m_a}\,T_a^{3/2})\). The common collisionality
prefactor comes from the species nu, so every model sits on the same
collisionality axis as the built-in Lenard-Bernstein term.
Warning
Three mutually incompatible normalizations of the collision frequency appear in this literature. Writing \(\nu = C\,n q^4 \ln\Lambda / (m^{1/2} T^{3/2})\), Sugama (2009, 2019) uses \(C = 4.4429\), Frei et al. (2021) and Frei, Ernst & Ricci (2022) use \(C = 2.3633\), and Frei, Hoffmann & Ricci (2022) use \(C = 0.7523\). Any comparison against a published figure must fix the convention first; it is the most common source of apparent agreement.
Baseline Lenard-Bernstein model
The built-in collisional model is a Lenard-Bernstein-style diagonal damping plus conservation-restoring low-order moment corrections. The base damping is
where lb_lam is the cached Hermite/Laguerre collision eigenvalue,
\(\Lambda_{\ell m} = \nu_\ell\,\ell + \nu_m\,m\) with
nu_laguerre (default 2) and nu_hermite (default 1). The code then
reconstructs the low moments
and a temperature-like correction \(\bar{T}\) from m=0 and m=2, and
adds them back only into the m=0,1,2 channels.
This is a conserving Lenard–Bernstein/Dougherty-like model, not a complete linearized gyrokinetic Landau operator. Its low-order field-particle correction matters: the operator cannot be represented by a diagonal damping array alone.
At \(k_\perp\rho=0\) the model conserves each species’ density, parallel momentum and temperature-like moments; a five-step gate checks this from populated high moments, in serial and decomposed integration. At finite \(k_\perp\rho\) the guiding-centre moments are not locally conserved. Collisions are local in real space, so the gyrocentre change is nonlocal. This is the physics of the published model, not a residual to tune away. A direct finite-\(b\) gate checks every term of equations (3.38)–(3.42) of Frei et al. (2021), including parallel/perpendicular flow and temperature restoration.
Structural verification of the moment operators
Every shipped matrix is asserted against the published closed forms, not only against internal consistency. All twelve Appendix-C coefficients of Frei, Ernst & Ricci (2022) (six Coulomb, six Sugama) reproduce, for example
GKX stores the opposite Laguerre sign convention to the paper, so a published entry maps onto the stored one through \((-1)^{j+j'}\). That flips exactly the couplings between different Laguerre parities and leaves same-parity entries alone, so the comparison checks the convention as well as the values.
tests/validation/physics_gates/test_collision_physics.py gates the
properties a linearized collision operator must satisfy. The offline
verification artifact docs/_static/collision_operator_verification.json
records the measured values against its thresholds:
Property |
Measured |
Gate |
|---|---|---|
Density, parallel-momentum, energy conservation |
\(5.6\times10^{-17}\) |
\(5\times10^{-12}\) |
H-theorem (largest eigenvalue of the symmetrized operator) |
\(9.0\times10^{-18}\) |
\(10^{-12}\) |
Onsager self-adjointness |
\(8.3\times10^{-17}\) |
\(5\times10^{-12}\) |
Published Appendix-C coefficients |
\(1.1\times10^{-16}\) |
\(5\times10^{-12}\) |
Finite-Larmor gyrocenter-diffusion order at small \(b\) |
\(B^{1.94}\)–\(B^{2.00}\) |
\(B^{1.7}\)–\(B^{2.3}\) |
The invariants are the left null vectors of the moment matrix, since the production of a moment functional \(v\) is \(v^{T} C N\). With the Hermite-major index \(p(J+1)+j\) they are \(e_0\) (density), \(e_2\) (parallel momentum), and \(e_1 + e_4/\sqrt{2}\) (energy), the last read off the exact null space rather than assumed. At \(b=0\) the finite-Larmor tables reduce to the drift-kinetic Coulomb operator.
The finite-Larmor operator acts on gyrocenter moments. Gyroaveraging modifies their conservation and plain self-adjointness, so the test is the ordering: both defects must vanish at \(b=0\) and enter at first order in \(b = B^2/2\). A kernel assembled at the wrong order would show \(B^{1}\) or \(B^{4}\) instead. The finite-\(b\) density row is classical gyro-diffusion, not a conservation failure. Equation (3.35) of Frei et al. (2021) maps a gyrocenter distribution to particle moments; it does not invert the gyrophase average of equation (3.5), so local particle-space conservation cannot be inferred by applying that map to the gyroaveraged collision matrix.
Tabulated resolutions
Finite-Larmor tables ship at 8 and 18 Hermite-Laguerre moments. They are
generated in 60-digit arithmetic on a 14-point Bessel-argument grid
\(B = k_\perp v_{\mathrm{th}}/\Omega \in [0, 4]\) and stored as
checksummed float64. The runtime interpolates at \(B=\sqrt{2b}\) from the
cached \(b\), so one table covers every perpendicular wavenumber, and it
selects the table matching the run’s Nl*Nm automatically, then requires
the run’s (Nl, Nm) to be that table’s (J+1, P+1).
Cost and the resolution ceiling
The finite-Larmor operator interpolates its tables at every grid point, so the
compiler sees a distinct moment matrix per \((k_y, k_x, z)\). That storage
grows as \(n^2\) in the moment count \(n\) while the state grows as
\(n\). On a 16x8x32 grid the compiled linear RHS needs 5.9x the temporary
storage of the built-in diagonal operator at 8 moments and 12.1x at 18. The
cost gates in test_collision_physics.py bound these ratios at 12x and 24x,
and bound the growth between the two resolutions by the \(n^2\) ratio.
Extrapolating the per-point matrices to a 32x64x32 grid gives:
moments |
per-point matrix storage |
note |
|---|---|---|
8 |
0.07 GB |
shipped |
18 |
0.34 GB |
shipped |
128 |
17 GB |
linear Cyclone ITG convergence resolution; exceeds a 16 GB card |
512 |
275 GB |
converged resolution in the published study |
The published convergence resolutions are therefore not reachable in this form, and resolution should be scanned rather than assumed. Generate a further table resolution with:
python scripts/artifacts/build_finite_wavelength_coulomb_data.py \
--hermite 7 --laguerre 3 --digits 60 --workers 24 --check
Python collision protocol
A collision model receives a post-field CollisionContext (distribution,
hamiltonian, fields, cache, parameters; see
src/gkx/operators/collision.py), so finite-Larmor models can distinguish the
evolved distribution \(G\) from the Hamiltonian response \(H\). It
implements
apply(context), the complete unit-weight RHS, including low-rank or dense field-particle terms; and optionallySplitCollisionOperator.split_step(context, dt), an exact or implicit finite-time update. The runtime does not route this method.
Pass the model to linear_rhs_cached or nonlinear_rhs_cached with
collision_operator=. The callback must return a JAX array with the state
shape. GKX removes the built-in collision contribution before adding
terms.collisions * operator.apply(...); hypercollisions stay independent:
class CollisionModel:
def apply(self, context):
return collision_rhs(
context.distribution,
context.hamiltonian,
context.cache,
context.parameters,
)
rhs, fields = nonlinear_rhs_cached(
state, cache, parameters, terms,
collision_operator=CollisionModel(),
)
The callback runs after the field solve and is traced by JAX, so its array
operations stay differentiable. context.fields carries phi, apar,
and bpar; context.hamiltonian follows the same enabled-field policy as
the gyrokinetic RHS.
The [time] collision_split policy splits only diagonal hypercollisions. The
conserving collision term stays in the Runge–Kutta RHS, with its
field-particle corrections; the chain IMEX steps (imex-ars3, imex-ark3)
advance the Landau operator by a local backward-Euler sub-step instead
(collision_scheme = "implicit") when the explicit collision bound would
bind, which removes \(\nu_e\) from the step-size bound (Resolution, Step and Solver Guidance).
Diagnostics in src/gkx/operators/linear/dissipation.py:
collision_invariant_ratesreturns the discrete long-wavelength density, parallel-momentum, and thermal-energy rates of a state-shaped contribution.collision_quadratic_rateevaluates \(\operatorname{Re}\langle H,C[H]\rangle\) with optional species/spatial weights.multispecies_collision_invariant_ratesreturns each species’ particle rate and the weighted sums\[\dot P_\parallel = \sum_s n_s\sqrt{m_s T_s}\,\dot N_s^{10}, \qquad \dot E = \sum_s n_s T_s \left(\sqrt{2}\,\dot N_s^{20}+2\dot N_s^{01}\right),\]which must all vanish for a species-coupled model.
Research operators (Python only)
The following are exported from gkx.operators.linear (or the module named)
for verification and model development. None of them has a TOML selector.
API |
What it is |
|---|---|
|
The like-species six-gyromoment Sugama matrix of Appendix C, Eqs. (C6a)–(C6f); zero outside the six-moment projection. |
|
Checksummed package-data tables and their JAX application, including per-species and ordered target/source pair tables interpolated in \(k_\perp\) on device. |
|
Multispecies drift-kinetic original and improved Sugama on the
eight-mode space (Appendix C, Eqs. (C4)–(C5) and (101)–(102)), with
directed frequency \(\nu_{ab}\propto n_b/(\sqrt{m_a}T_a^{3/2})\).
This is what the |
|
Finite-wavelength operators that interpolate generated test, field and polarization tables at \(B_a=\sqrt{2b_a}\). The equal-species forms refuse multispecies input. |
|
The driven parallel-current problem \(C N_e + s_E = 0\) of Frei,
Ernst & Ricci (2022), Eq. (81), solved with |
|
\(K_n(B) = e^{-B^2/4}(B^2/4)^n/n!\) and the equation-(2.12) prefactor of Frei et al. (2021). |
|
The pairwise primitive moments of the improved multispecies Dougherty model (Francisquez et al., Eqs. (2.11)–(2.12)). This is a full-\(f\) reference; it must not be inserted into the linearized field-particle restoration. |
The high-precision coefficient algebra (Coulomb speed integrals, basis
transforms, Laguerre products and the equation (3.48)–(3.50) contractions)
lives in the offline generator scripts/artifacts/build_linear_validation_artifacts.py (retired; Retired generators),
not in the package. The runtime only interpolates validated tables and applies
matrices, which is the same split as the GYACOMO/COSOlver pair.
References: Frei et al. (2021), Frei, Ernst & Ricci (2022), Abel et al. (2008) (the conservation, null-space, adjointness and H-theorem requirements), Jorge, Ricci & Loureiro (2017) and Jorge, Frei & Ricci (2019) (the basis transforms), and the improved multispecies Dougherty derivation.
Collision validation evidence
Offline Coulomb-operator closure. Panel (a) shows Bessel–Laguerre
convergence of a finite-\(b\) polarization coefficient to a 24-term
reference, Bessel convergence of an assembled 4-by-4 collision block, and
the independent spherical/radial hierarchy convergence of that block;
panel (b) compares five generated coefficients with independent
80-by-80 Gauss–Hermite/Laguerre velocity projection; panel (c) shows five
dissipative modes and the three density, parallel-momentum, and thermal-
energy null modes, while its inset verifies leading \(O(b^2)\) classical
gyro-diffusion away from the drift-kinetic limit; panel (d) shows the
complete retained drift-kinetic moment block. The machine-readable gate is
collision_operator_verification.json.
Regenerate with
python scripts/artifacts/build_linear_validation_artifacts.py collision-verification (retired; Retired generators).
The largest direct-projection relative error is \(3.1\times10^{-13}\). At
\(b=0.8\) the assembled block changes by \(4.50\times10^{-7}\) between
Bessel orders four and six, at the \((p_{\max},j_{\max})=(8,4)\) spherical
cutoff, which is within \(8.68\times10^{-7}\) of the \((9,4)\)
reference. The smaller cutoff \((3,1)\) differs from that reference by 29%
and is rejected.
Driven parallel current. The collision-response subcommand (retired;
Retired generators) built
docs/_static/collision_response_convergence.json from equations
(3.53)–(3.56). With \(\widehat E=eE/(m_ev_{Te}\nu_{ee})\), the plotted
response \((u_e/v_{Te})/\widehat E\) is
\(\sigma_\parallel/[n_e e^2/(m_e\nu_{ee})]\). At \((P,J)=(20,5)\) the
largest current change from \((15,5)\) is \(1.66\times10^{-4}\) over
\(Z=1,2,5,10,100\), and the invariant, self-adjointness, spectrum and
driven-solve residuals pass a \(2\times10^{-12}\) gate. Original Sugama
gives 11.29% less current than Coulomb at \(Z=1\) and 0.61% less at
\(Z=100\); improved Sugama stays within 0.307% of Coulomb at every scanned
charge. The \(Z=100\) Coulomb point is 7.453% from the Spitzer high-charge
limit \(64/[3\,2^{3/2}\pi Z]\), inside the 8% gate. This validates the
unmagnetized equal-temperature conductivity problem, not finite-\(b\)
collisional transport.
Collisional zonal response. docs/_static/collision_finite_wavelength_zonal_response.json
reproduces the Figure 12–14 protocol of Frei, Ernst & Ricci (2022) at
P24/J10 through \(t\nu=30\). The late responses are:
\(k_x\rho_i\) |
original Sugama |
improved Sugama |
Coulomb |
|---|---|---|---|
0.1 |
0.00242 |
0.00255 |
0.00288 |
0.2 |
\(9.66\times10^{-5}\) |
\(1.15\times10^{-4}\) |
\(1.92\times10^{-4}\) |
Improved Sugama tracks Coulomb more closely than the original model in the early window at both wavenumbers.
Short-wavelength ITG boundary. On a Cyclone-like s-\(\alpha\) probe,
raising the
drift-kinetic collision weight damps the growth rate at
\(k_y\rho\simeq0.63\) but excites the short-wave branch at
\(k_y\rho\simeq0.94\), the behaviour expected when collisional FLR terms are
omitted. test_drift_kinetic_collision_model_is_blocked_for_short_wave_itg
requires both observations. Only a converged finite-\(b\) operator can
close that lane.
Controls:
[time] collision_operatorRuntimePhysicsConfig.collisionsRuntimeTermsConfig.collisionsRuntimeSpeciesConfig.nuRuntimeCollisionConfig.nu_hermiteRuntimeCollisionConfig.nu_laguerre
For two kinetic species, the explicit species-parallel integrator evaluates
the complete built-in collision contribution locally on each device after the
shared field reduction; nonzero, unequal ion/electron rates are
identity-gated against serial evolution. The direct species-sharded RHS helper
is collision-free, so use integrate_linear(...,
parallel=RuntimeParallelConfig(strategy="velocity", axis="species",
num_devices=2)) for the collisional route. The same route is gated for
Hermite/Laguerre hypercollisions with nonzero nu_hyper_l/nu_hyper_m.
Electromagnetic species decomposition sums the local field moments over the
species axis and reduces them across devices, so phi, apar and bpar
are the serial fields; mixed species–Hermite meshes are not covered.
Hypercollisions
GKX implements an isotropic branch, a constant-coefficient Hermite/Laguerre branch, and a \(|k_z|\)-scaled Hermite branch:
Controls, and the branch each one reaches:
|
Branch |
Notes |
|---|---|---|
|
isotropic |
always applied; defaults |
|
constant only |
the Laguerre channel. The \(|k_z|\) kernel has no \(\ell\)
index, so this knob needs |
|
constant only |
mixed channel, same restriction |
|
both |
the Hermite channel; the constant branch reuses it unless
|
|
constant only |
per-branch Hermite rate. |
|
branch switches |
see the defaults below |
The defaults differ between a TOML run and a hand-built LinearParams:
Setting |
TOML runtime ( |
Python |
|---|---|---|
|
|
|
|
|
|
|
|
|
RuntimePhysicsConfig.hypercollisionsandRuntimeTermsConfig.hypercollisionsgate the whole operator.
Declared velocity-space regularization
Because nu_hyper_l is branch-bound, a deck that set it under the runtime
defaults would have run with no Laguerre sink. That is an error:
RuntimeCollisionConfig refuses a nonzero nu_hyper_l or
nu_hyper_lm while hypercollisions_const = 0.0, and names the two ways
to fix it. Cross-section case validation also refuses those channels when
RuntimePhysicsConfig.hypercollisions or
RuntimeTermsConfig.hypercollisions disables the whole operator. A declared
regularization either acts or the run stops; it is never silently discarded.
This matters beyond configuration hygiene. For the Cyclone s-\(\alpha\)
adiabatic-electron ITG mode at \(k_y \rho_i = 0.55\), certified eigenpairs
show that the collisionless growth rate is not converged in Laguerre
resolution: the eigenvector carries a cutoff pile-up that relocates to
0.79–0.85 of every new Nl instead of resolving, and the only ladder that
converges is the one with enough velocity-space dissipation to remove it. A
collisionless growth rate at such a point is a truncation value, not a
converged number.
Contract. Every collisionless linear row published from GKX declares the
velocity-space regularization it used, and reports the
\(\nu \to 0\) (or \(\nu_{hyper} \to 0\)) extrapolation rather than a
single regularized number. none is a legal declaration and the common one
for reference-code parity rows, whose decks must reproduce the reference
exactly; it commits the row to being reported as resolution-limited, not as a
converged growth rate. The declaration is a required field of every linear row
of tools/evidence_ledger.toml and is checked by
tests/release/test_release_gates.py.
Hyperdiffusion And End Damping
The perpendicular hyperdiffusion term is
masked by the dealias region. \(k_{\perp,\max}^2\) is the dealiased corner
of the full grid: when a linear run selects a subset of ky rows, the parent
grid’s \(|k_y|\) at row (Ny - 1) // 3 is carried as
SpectralGrid.ky_cut and used in place of the missing row. D_hyper defaults to 0 and the
hyperdiffusion term weight to 0, so it is off unless a deck enables it.
The field-line end damping is \(\mathcal{R}_{end} = -w_{end}\,\nu_{end}\,d(z)\,H\),
where \(d(z)\) is a smooth profile over the last damp_ends_widthfrac
(default 0.125) of the chain at each end, and zero on a periodic boundary.
The zonal row carries no end damping. \(\nu_{end}\) is one timestep-free
rate on every route; its default and how to check sensitivity are in
Parallel boundary and end damping.
Controls:
RuntimeTermsConfig.hyperdiffusionRuntimeCollisionConfig.D_hyperRuntimeCollisionConfig.p_hyper_kperp[time] damp_ends_rateRuntimeCollisionConfig.damp_ends_widthfrac
Nonlinear \(E \\times B\) And Flutter
The nonlinear bracket is evaluated pseudospectrally:
The electrostatic nonlinear term is
and the electromagnetic flutter contribution couples adjacent Hermite moments:
Controls:
TimeConfig.compressed_real_fft(defaulttrue)TimeConfig.laguerre_nonlinear_mode(default"grid")TimeConfig.nonlinear_dealias(defaulttrue, the 2/3 rule)RuntimeTermsConfig.nonlinear
Source Mapping
linear term kernels:
src/gkx/terms/linear_terms.pyandsrc/gkx/operators/linear/collision models:
src/gkx/operators/linear/collisions.py,src/gkx/operators/linear/collision_tables.py,src/gkx/operators/linear/collision_tables.pynonlinear term kernels:
src/gkx/terms/nonlinear.pyandsrc/gkx/operators/nonlinear/assembly:
src/gkx/terms/assembly.pylow-level parameter container:
src/gkx/operators/linear/params.pyruntime parameter surface:
src/gkx/config.py
Parameter Surface
The primary parameter groups are:
RuntimePhysicsConfigRuntimeCollisionConfigRuntimeNormalizationConfigRuntimeTermsConfigLinearParams
For TOML syntax and all supported keys, see Input Files and Executable.