Source code for gkx.benchmarking_shared

"""Shared benchmark reference data, normalization, and scan policies."""

from __future__ import annotations

from dataclasses import dataclass, replace
from importlib import resources

import numpy as np

from gkx.core_grid import SpectralGrid
from gkx.diagnostics.modes import ModeSelection
from gkx.diagnostics.normalization import (
    CYCLONE_NORMALIZATION,
    ETG_NORMALIZATION,
    KBM_NORMALIZATION,
    KINETIC_NORMALIZATION,
    TEM_NORMALIZATION,
)
from gkx.solvers_linear_krylov import KrylovConfig

CYCLONE_OMEGA_D_SCALE = CYCLONE_NORMALIZATION.omega_d_scale

CYCLONE_OMEGA_STAR_SCALE = CYCLONE_NORMALIZATION.omega_star_scale

CYCLONE_RHO_STAR = CYCLONE_NORMALIZATION.rho_star

ETG_OMEGA_D_SCALE = ETG_NORMALIZATION.omega_d_scale

ETG_OMEGA_STAR_SCALE = ETG_NORMALIZATION.omega_star_scale

ETG_RHO_STAR = ETG_NORMALIZATION.rho_star

KINETIC_OMEGA_D_SCALE = KINETIC_NORMALIZATION.omega_d_scale

KINETIC_OMEGA_STAR_SCALE = KINETIC_NORMALIZATION.omega_star_scale

KINETIC_RHO_STAR = KINETIC_NORMALIZATION.rho_star

TEM_OMEGA_D_SCALE = TEM_NORMALIZATION.omega_d_scale

TEM_OMEGA_STAR_SCALE = TEM_NORMALIZATION.omega_star_scale

TEM_RHO_STAR = TEM_NORMALIZATION.rho_star

KBM_OMEGA_D_SCALE = KBM_NORMALIZATION.omega_d_scale

KBM_OMEGA_STAR_SCALE = KBM_NORMALIZATION.omega_star_scale

KBM_RHO_STAR = KBM_NORMALIZATION.rho_star


REFERENCE_DAMP_ENDS_WIDTHFRAC = 1.0 / 8.0


def _midplane_index(grid: SpectralGrid) -> int:
    """Return reference midplane index for growth-rate diagnostics."""

    if grid.z.size <= 1:
        return 0
    idx = int(grid.z.size // 2 + 1)
    return min(idx, int(grid.z.size) - 1)


CYCLONE_KRYLOV_DEFAULT = KrylovConfig(
    method="shift_invert",
    krylov_dim=16,
    restarts=1,
    omega_target_factor=0.3,
    power_iters=60,
    power_dt=0.001,
    shift_maxiter=30,
    shift_restart=10,
    shift_tol=1.0e-3,
    shift_preconditioner="auto",
    omega_sign=1,
    mode_family="cyclone",
    fallback_method="propagator",
)

KINETIC_KRYLOV_DEFAULT = KrylovConfig(
    method="shift_invert",
    krylov_dim=16,
    restarts=1,
    omega_min_factor=0.05,
    omega_cap_factor=0.8,
    omega_target_factor=0.3,
    omega_sign=1,
    power_iters=60,
    power_dt=0.001,
    shift_source="target",
    shift_maxiter=40,
    shift_restart=12,
    shift_tol=5.0e-4,
    shift_preconditioner="auto",
    mode_family="cyclone",
    fallback_method="propagator",
)

KINETIC_KRYLOV_REFERENCE_ALIGNED = replace(
    KINETIC_KRYLOV_DEFAULT, shift_source="history"
)

# No generator uses this config: ledger row L-lin-etg is time-integrated. On
# benchmarks/cases/etg_linear.toml (Nl=24, Nm=8, ky=10/20/30) its raw propagator returned wrong branches
# at residual 0.98-0.99 (Q12, 2026-09-13), so it now fails closed rather than
# opting out of the certification gate.
ETG_KRYLOV_DEFAULT = KrylovConfig(
    method="propagator",
    krylov_dim=16,
    restarts=1,
    omega_min_factor=0.0,
    omega_target_factor=0.3,
    omega_cap_factor=0.6,
    omega_sign=-1,
    power_iters=80,
    power_dt=0.002,
    shift_maxiter=40,
    shift_restart=12,
    shift_tol=2.0e-3,
    mode_family="etg",
    fallback_method="arnoldi",
    continuation=True,
    continuation_selection="overlap",
)

KBM_KRYLOV_DEFAULT = KrylovConfig(
    method="shift_invert",
    krylov_dim=16,
    restarts=1,
    omega_min_factor=0.0,
    omega_cap_factor=2.0,
    omega_target_factor=1.5,
    omega_sign=1,
    power_iters=60,
    power_dt=0.005,
    shift_source="target",
    shift_maxiter=40,
    shift_restart=12,
    shift_tol=5.0e-4,
    shift_preconditioner="auto",
    shift_selection="targeted",
    mode_family="kbm",
    fallback_method="propagator",
    continuation=False,
)

TEM_KRYLOV_DEFAULT = KrylovConfig(
    method="shift_invert",
    krylov_dim=16,
    restarts=1,
    omega_min_factor=0.05,
    omega_cap_factor=0.6,
    omega_target_factor=0.25,
    omega_sign=-1,
    power_iters=60,
    power_dt=0.005,
    shift_source="target",
    shift_maxiter=40,
    shift_restart=12,
    shift_tol=5.0e-4,
    shift_preconditioner="auto",
    mode_family="tem",
    fallback_method="propagator",
)


[docs] @dataclass(frozen=True) class CycloneReference: ky: np.ndarray omega: np.ndarray gamma: np.ndarray
[docs] @dataclass(frozen=True) class CycloneScanResult: ky: np.ndarray gamma: np.ndarray omega: np.ndarray
[docs] @dataclass(frozen=True) class LinearRunResult: t: np.ndarray phi_t: np.ndarray gamma: float omega: float ky: float selection: ModeSelection gamma_t: np.ndarray | None = None omega_t: np.ndarray | None = None
[docs] @dataclass(frozen=True) class LinearScanResult: ky: np.ndarray gamma: np.ndarray omega: np.ndarray
def _load_csv_reference(filename: str) -> CycloneReference: data_path = resources.files("gkx").joinpath("data", filename) arr = np.loadtxt(str(data_path), delimiter=",", skiprows=1) ky = arr[:, 0] omega = arr[:, 1] gamma = arr[:, 2] return CycloneReference(ky=ky, omega=omega, gamma=gamma)
[docs] def load_cyclone_reference() -> CycloneReference: """Load Cyclone base case reference data (adiabatic electrons).""" return _load_csv_reference("cyclone_reference_adiabatic.csv")
[docs] def load_cyclone_reference_kinetic() -> CycloneReference: """Load Cyclone base case reference data (kinetic electrons).""" return _load_csv_reference("cyclone_reference_kinetic.csv")
[docs] def load_kbm_reference() -> CycloneReference: """Load KBM reference data (finite beta, kinetic electrons).""" return _load_csv_reference("kbm_reference.csv")
[docs] def load_etg_reference() -> CycloneReference: """Load ETG reference data for the tracked two-species ETG lane.""" return _load_csv_reference("etg_reference.csv")
[docs] def load_tem_reference() -> CycloneReference: """Load the provisional TEM reference digitized from the literature. This lane remains an extended stress case while the literature case definition is being reconstructed. """ return _load_csv_reference("tem_reference.csv")
__all__ = [ "resources", "CYCLONE_OMEGA_D_SCALE", "CYCLONE_OMEGA_STAR_SCALE", "CYCLONE_RHO_STAR", "ETG_OMEGA_D_SCALE", "ETG_OMEGA_STAR_SCALE", "ETG_RHO_STAR", "KINETIC_OMEGA_D_SCALE", "KINETIC_OMEGA_STAR_SCALE", "KINETIC_RHO_STAR", "TEM_OMEGA_D_SCALE", "TEM_OMEGA_STAR_SCALE", "TEM_RHO_STAR", "KBM_OMEGA_D_SCALE", "KBM_OMEGA_STAR_SCALE", "KBM_RHO_STAR", "REFERENCE_DAMP_ENDS_WIDTHFRAC", "_midplane_index", "CYCLONE_KRYLOV_DEFAULT", "KINETIC_KRYLOV_DEFAULT", "KINETIC_KRYLOV_REFERENCE_ALIGNED", "ETG_KRYLOV_DEFAULT", "KBM_KRYLOV_DEFAULT", "TEM_KRYLOV_DEFAULT", "CycloneReference", "CycloneScanResult", "LinearRunResult", "LinearScanResult", "_load_csv_reference", "load_cyclone_reference", "load_cyclone_reference_kinetic", "load_kbm_reference", "load_etg_reference", "load_tem_reference", ]