Gyrokinetic Transport — Three-Path Architecture¶
scpn-control implements all three gyrokinetic transport paths in a single codebase. No competing code (TORAX, FUSE, DREAM, FreeGS) has this combination.
Architecture Overview¶
┌─────────────────────────────┐
│ integrated_transport_solver │
│ transport_model = ? │
└──────────┬──────────────────┘
│
┌────────────────┼────────────────┐
│ │ │
"gyro_bohm" "external_gk" "gyrokinetic"
(fast fallback) (Path A) (analytic QL)
│
┌──────────┴──────────┐
│ GKSolverBase ABC │
└──────────┬──────────┘
┌────────┬───────┼───────┬────────┐
TGLF GENE GS2 CGYRO QuaLiKiz
Path B (native): gk_eigenvalue → gk_quasilinear → GKOutput
Path C (hybrid): surrogate → OOD check → GK spot-check → correction
Path A: External GK Code Coupling¶
Five first-principles gyrokinetic codes interfaced via subprocess:
| Solver | Module | Input Format | Reference |
|---|---|---|---|
| TGLF | gk_tglf.py |
Fortran namelist | Staebler et al., Phys. Plasmas 14 (2007) 055909 |
| GENE | gk_gene.py |
parameters_gene namelist |
Jenko et al., Phys. Plasmas 7 (2000) 1904 |
| GS2 | gk_gs2.py |
gs2_input namelist + NetCDF |
Kotschenreuther et al., CPC 88 (1995) 128 |
| CGYRO | gk_cgyro.py |
input.cgyro |
Candy & Waltz, J. Comp. Phys. 186 (2003) 545 |
| QuaLiKiz | gk_qualikiz.py |
Python API | Bourdelle et al., Phys. Plasmas 14 (2007) 112501 |
All solvers implement the GKSolverBase abstract interface:
from scpn_control.core.gk_interface import GKSolverBase, GKLocalParams, GKOutput
class TGLFSolver(GKSolverBase):
def prepare_input(self, params: GKLocalParams) -> Path: ...
def run(self, input_path: Path, *, timeout_s: float = 30.0) -> GKOutput: ...
def is_available(self) -> bool: ...
Usage¶
from scpn_control.core.integrated_transport_solver import TransportSolver
ts = TransportSolver(config_path, transport_model="external_gk")
ts.neoclassical_params = neo_params
ts.evolve_profiles(dt=0.01, P_aux=20.0)
Falls back to gyro-Bohm if the solver binary is unavailable or returns unconverged results.
Path B: Native Linear GK Eigenvalue Solver¶
Self-contained flux-tube linear GK solver — no external binaries needed.
Physics¶
Solves the linearised electrostatic gyrokinetic equation in ballooning representation:
| Module | Physics |
|---|---|
gk_geometry.py |
Miller flux-tube parameterisation (R, Z, |
gk_species.py |
Per-species distribution, Gauss-Legendre (E, λ) grid, Sugama collision |
gk_eigenvalue.py |
Response-matrix eigenvalue problem → growth rates γ(k_y) |
gk_quasilinear.py |
Mixing-length saturation → chi_i, chi_e, D_e [m²/s] |
Usage¶
from scpn_control.core.gk_eigenvalue import solve_linear_gk
from scpn_control.core.gk_quasilinear import quasilinear_fluxes_from_spectrum
from scpn_control.core.gk_species import deuterium_ion, electron
species = [deuterium_ion(R_L_T=6.9, R_L_n=2.2), electron(R_L_T=6.9, R_L_n=2.2)]
result = solve_linear_gk(species_list=species, R0=2.78, a=1.0, B0=2.0,
q=1.4, s_hat=0.78, n_ky_ion=12, n_theta=32)
fluxes = quasilinear_fluxes_from_spectrum(result, species[0], R0=2.78, a=1.0, B0=2.0)
print(f"chi_i = {fluxes.chi_i:.4f} m²/s, dominant: {fluxes.dominant_mode}")
Known Limitations¶
- Electrostatic only — no A∥ or B∥ (no KBM, no microtearing)
- Collision operator: pitch-angle scattering only (no energy diffusion, no inter-species drag). Adequate for growth rate ordering, not for quantitative collisional damping
- Adiabatic electrons: kinetic electron path exists but not fully wired
- Resolution: default (n_E=12, n_lambda=16) gives qualitative instability detection. Quantitative γ within 20% of GENE/GS2 requires higher resolution and is not yet benchmarked
Validation¶
Cyclone Base Case (Dimits et al., Phys. Plasmas 7, 969, 2000):
- Circular geometry, R/a=2.78, q=1.4, s_hat=0.78, R/L_Ti=6.9
- Produces positive γ_max with ITG classification
- Reference data in validation/reference_data/cyclone_base/
- Not yet quantitatively benchmarked against GENE/GS2 to 20% tolerance
Path C: Hybrid Surrogate + GK Validation¶
Real-time QLKNN surrogate with automatic GK spot-check verification.
QLKNN surrogate (µs)
│
├── OOD detector → Mahalanobis + range + ensemble
│ ↓ (if OOD or scheduled)
├── GK spot-check → scheduler selects flux surfaces
│ ↓
├── Correction → multiplicative/additive/replace + EMA smoothing
│ ↓
└── Online learner → buffer → retrain → validate → accept/rollback
| Module | Role |
|---|---|
gk_ood_detector.py |
Mahalanobis distance, input range checks, ensemble disagreement |
gk_scheduler.py |
Periodic / adaptive / critical-region spot-check scheduling |
gk_corrector.py |
Error quantification + 3 correction modes + temporal EMA |
gk_online_learner.py |
Buffer-based retraining with validation holdout + rollback |
gk_verification_report.py |
Per-session stats, JSON export |
SCPN Phase Bridge¶
GK fluxes modulate the 8-layer UPDE Kuramoto coupling matrix:
| Coupling | GK Input | Physics |
|---|---|---|
| K[0,1] P0↔P1 | max(γ_ITG, γ_TEM) | Microturbulence ↔ zonal flow drive |
| K[1,4] P1↔P4 | mean(chi_e) / chi_ref | Zonal flow ↔ transport barrier suppression |
| K[3,4] P3↔P4 | chi_pedestal / chi_core | Sawtooth/ELM ↔ barrier strength |
from scpn_control.phase.gk_upde_bridge import adaptive_knm
K_adapted = adaptive_knm(K_base, gk_output, chi_i_profile=chi_i)
References¶
- Dimits et al., Phys. Plasmas 7 (2000) 969 — Cyclone Base Case
- Miller et al., Phys. Plasmas 5 (1998) 973 — Flux-tube geometry
- Sugama & Watanabe, Phys. Plasmas 13 (2006) 012501 — Collision operator
- Staebler et al., Phys. Plasmas 14 (2007) 055909 — TGLF
- Bourdelle et al., Phys. Plasmas 14 (2007) 112501 — QuaLiKiz
- van de Plassche et al., Phys. Plasmas 27 (2020) 022310 — QLKNN