Repository navigation
Expand file tree
/
Copy pathevidence_ledger.toml
More file actions
451 lines (417 loc) · 30.6 KB
/
Copy pathevidence_ledger.toml
File metadata and controls
451 lines (417 loc) · 30.6 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
# GKX evidence ledger
#
# One [[row]] per public number or claim. `tests/release/test_release_gates.py`
# checks that every artifact and generator exists, that every row is
# well formed, and that each README number recomputes from its artifact.
#
# Contract (plan.md sections 3.1-3.2):
# reference_rank 1 analytic
# 2 published numbers
# 3 reference-code goldens shipped in the reference code's tree
# 4 open published dataset
# 5 self-run comparator
# tier 0 push, <60 s 1 push, bitwise on stored outputs
# 2 nightly physics 3 campaign, GPU
# status open | passing | failing | provisional | superseded
#
# A claim cites the highest-ranked reference available. A self-run reference is
# labeled rank 5 and is never described as published.
#
# Linked-boundary GX references additionally record reference_index_count =
# Nz*Nl*Nm and reference_clamp_binds. GX launches dampEnds_linked with
# dG_all.z = min(65535, Nz*Nl*Nm) but, unlike linkedCopyBackAll and
# linkedAccumulateBackAll, that kernel has no grid-stride loop over z, so when
# the count exceeds 65535 the highest Hermite moments receive no end damping.
# See tools/comparison/fixtures/gx_goldens/README.md for the derivation.
#
# Every linear row (id starting "L-lin-") additionally declares the
# velocity-space regularization its deck applies, as a list drawn from
# none | hermite-kz-hypercollision | hermite-const-hypercollision
# | laguerre-hypercollision | isotropic-hypercollision
# | conserving-collisions | dougherty-lb-collisions
# and, when that list contains no ell-space channel and the deck is
# collisionless, a velocity_limit of
# truncation-limited | extrapolated | unmeasured
# with velocity_limit_evidence naming where it was measured. plan.md 0.5:
# a collisionless row reports the nu -> 0 extrapolation, not a single
# regularized number, and "none" commits the row to being reported as
# resolution-limited rather than converged.
schema_version = 1
updated = "2026-10-20"
# ---------------------------------------------------------------- README parity
[[row]]
id = "L-lin-kaw"
claim = "README linear parity table, KAW"
readme_label = "KAW"
observable = "100*max|gkx-ref|/max|ref| over the tracked scan, gamma and omega"
artifact = "docs/_static/kaw_exact_growth_dump.csv"
columns = { gamma_ref = "gamma_ref", gamma_gkx = "gamma_gkx", omega_ref = "omega_ref", omega_gkx = "omega_gkx" }
generator = "retired@df2953026 scripts/artifacts/build_linear_validation_artifacts.py"
reference = "analytic kinetic-Alfven-wave dispersion; GX benchmarks/linear/KAW golden retained as a cross-check"
reference_rank = 1
velocity_regularization = ["none"]
velocity_limit = "unmeasured"
velocity_limit_evidence = "analytic KAW roots; the generator runs with hypercollisions = 0.0 and no collisions, and no Laguerre ladder has been run for this case"
tier = 2
status = "passing"
[[row]]
id = "L-lin-etg"
claim = "README linear parity table, ETG"
readme_label = "ETG"
observable = "100*max|gkx-ref|/max|ref| over the tracked scan, gamma and omega"
artifact = "docs/_static/etg_mismatch_table.csv"
columns = { gamma_ref = "gamma_ref", gamma_gkx = "gamma_gkx", omega_ref = "omega_ref", omega_gkx = "omega_gkx" }
generator = "retired@df2953026 scripts/benchmarks/linear_benchmark.py etg"
reference = "GX ETG comparison scan generated by this campaign"
reference_rank = 5
velocity_regularization = ["none"]
velocity_limit = "unmeasured"
velocity_limit_evidence = "self-run GX ETG comparison scan; no Laguerre ladder has been run for this case"
tier = 2
status = "passing"
# Both stellarator scans share a provenance gap found on 2026-09-08: the
# decisive parameters live in unrecorded environment variables
# (W7X_IMPORTED_ARGS, HSX_IMPORTED_ARGS) that carry the GX reference, and the
# two manifests name different configs. The W7-X CSV matches the parity config
# (dky = 0.1, y0 = 10); the HSX CSV matches the runtime config (dky = 1/21,
# y0 = 21). Recording those variable values is what closes both rows.
[[row]]
id = "L-lin-w7x"
claim = "README linear parity table, W7-X"
readme_label = "W7-X"
observable = "100*max|gkx-ref|/max|ref| over the tracked scan, gamma and omega"
artifact = "docs/_static/w7x_linear_t2_scan.csv"
columns = { gamma_ref = "gamma_ref_last", gamma_gkx = "gamma_last", omega_ref = "omega_ref_last", omega_gkx = "omega_last" }
generator = "retired@df2953026 scripts/comparison/build_gx_parity_matrix.py"
reference = "GX benchmarks/linear/ITG_w7x, run by this campaign; upstream ships the deck and eik but no *_correct.out.nc"
reference_rank = 5
reference_index_count = 32768 # Nz 256 * Nl 8 * Nm 16
reference_clamp_binds = false
velocity_regularization = ["hermite-kz-hypercollision"]
velocity_limit = "unmeasured"
velocity_limit_evidence = "collisionless GX-parity deck (nu = 0, hypercollisions_kz = 1, hypercollisions_const = 0); no Laguerre channel and no ladder for this case"
tier = 2
status = "passing"
[[row]]
id = "L-lin-hsx"
claim = "README linear parity table, HSX"
readme_label = "HSX"
observable = "100*max|gkx-ref|/max|ref| over the tracked scan, gamma and omega"
artifact = "docs/_static/hsx_linear_t2_scan.csv"
columns = { gamma_ref = "gamma_ref_last", gamma_gkx = "gamma_last", omega_ref = "omega_ref_last", omega_gkx = "omega_last" }
generator = "retired@df2953026 tools/benchmark_refresh_manifest.toml job 'imported-linear-hsx' -> scripts/comparison/compare_gx_imported_linear.py"
reference = "GX output supplied through the unrecorded HSX_IMPORTED_ARGS environment variable"
reference_rank = 5
velocity_regularization = ["hermite-kz-hypercollision"]
velocity_limit = "unmeasured"
velocity_limit_evidence = "collisionless GX-parity deck; no Laguerre channel and no ladder for this case"
tier = 2
status = "provisional"
notes = "provenance corrected 2026-09-08. The generator is NOT tools/comparison/fixtures/parity/hsx_itg.toml, which the GX parity manifest names: that config declares y0=10, Nl=8, Nm=16 while the CSV is spaced dky=1/21 (y0=21) and the real pipeline uses runtime_hsx_nonlinear_vmec_geometry.toml at y0=21, Nl=4, Nm=8. The equilibrium is Nuhrenberg-Zille 1988 QHS, regenerable from the tracked examples/vmec/input.NuhrenbergZille_1988_QHS, and is not literally HSX despite the label. What is still unrecorded is the value of HSX_IMPORTED_ARGS, which carries the GX reference; the same gap applies to the W7-X row. Row stays provisional until that is recorded, not because the scan cannot be rebuilt."
[[row]]
id = "L-lin-cyclone-miller"
claim = "README linear parity table, Cyclone Miller"
readme_label = "Cyclone Miller"
observable = "100*max|gkx-ref|/max|ref| over the tracked scan, gamma and omega"
artifact = "docs/_static/cyclone_miller_linear_mismatch.csv"
columns = { gamma_ref = "gamma_gx", gamma_gkx = "gamma", omega_ref = "omega_gx", omega_gkx = "omega" }
generator = "retired@df2953026 scripts/comparison/build_gx_parity_matrix.py"
reference = "GX benchmarks/linear/ITG_cyclone/itg_miller_adiabatic_electrons_correct.out.nc"
reference_rank = 3
reference_sha256 = "96947cfcf118548ca4b4543d79f91cef4a26ab4ceac733b90f0719247b586fc5"
reference_index_count = 73728 # Nz 96 * Nl 16 * Nm 48
reference_clamp_binds = true
velocity_regularization = ["hermite-kz-hypercollision"]
velocity_limit = "unmeasured"
velocity_limit_evidence = "collisionless GX-parity deck; the s-alpha sibling is truncation-limited at ky=.55, but no Miller ladder has been run"
tier = 2
status = "provisional"
notes = "reference applies no end damping to Hermite m>=42 of 48 (11.11% of index space); the published 5.51%/1.25% disagreement cannot be attributed to GKX until the reference is regenerated with a repaired build"
[[row]]
id = "L-lin-cyclone-salpha"
claim = "README linear parity table, Cyclone ITG"
readme_label = "Cyclone ITG"
observable = "100*max|gkx-ref|/max|ref| over the tracked scan, gamma and omega"
artifact = "docs/_static/cyclone_mismatch_table.csv"
columns = { gamma_ref = "gamma_ref", gamma_gkx = "gamma_gkx", omega_ref = "omega_ref", omega_gkx = "omega_gkx" }
generator = "retired@df2953026 scripts/comparison/build_gx_parity_matrix.py"
reference = "GX benchmarks/linear/ITG_cyclone/itg_salpha_adiabatic_electrons_correct.out.nc"
reference_rank = 3
reference_sha256 = "4887335d61b79495a39dd222d795c22c1a285aee6044eee8d0f5655da2da083e"
reference_index_count = 73728
reference_clamp_binds = true
velocity_regularization = ["hermite-kz-hypercollision"]
velocity_limit = "truncation-limited"
velocity_limit_evidence = "plan/log.md Q16 (#252): at ky=.55, Nm96, collisionless certified eigenpairs give gamma .03301/.02485/.01835 at Nl 24/32/48 with a Laguerre cutoff pile-up that relocates to 0.79-0.85 of each new Nl, so this unsunk row's growth rate is a truncation value, not a converged one"
tier = 2
status = "provisional"
notes = "same clamp as L-lin-cyclone-miller; the published 6.83%/1.59% disagreement is not yet attributable"
[[row]]
id = "L-lin-kbm"
claim = "README linear parity table, KBM"
readme_label = "KBM"
observable = "100*max|gkx-ref|/max|ref| over the tracked scan, gamma and omega"
artifact = "docs/_static/kbm_mismatch_table.csv"
columns = { gamma_ref = "gamma_ref", gamma_gkx = "gamma_gkx", omega_ref = "omega_ref", omega_gkx = "omega_gkx" }
generator = "retired@df2953026 scripts/comparison/build_gx_parity_matrix.py"
reference = "GX benchmarks/linear/KBM/kbm_miller_correct.out.nc"
reference_rank = 3
reference_sha256 = "3d3096f51da012a062364816cfd4919037fc183e98c41034f29027d4beed2ba8"
reference_index_count = 73728
reference_clamp_binds = true
velocity_regularization = ["hermite-kz-hypercollision"]
velocity_limit = "unmeasured"
velocity_limit_evidence = "collisionless GX-parity deck; no Laguerre channel and no ladder for this case"
tier = 2
status = "provisional"
notes = "the largest published disagreement (20.0%/11.1%); the reference omits end damping on its top Hermite moments and also omits delta B_parallel, so it is a reduced-EM two-field comparison (plan.md EM2)"
# ------------------------------------------------------------- figure artifacts
[[row]]
id = "F-landau-damping"
claim = "Landau damping against the exact roots of 1 + T_i/T_e + zeta Z(zeta) = 0"
observable = "relative error of the extrapolated GKX root against the exact root"
artifact = "docs/_static/landau_damping_validation.png"
generator = "retired@df2953026 scripts/artifacts/build_landau_damping_figure.py"
reference = "analytic plasma dispersion function roots"
reference_rank = 1
tier = 2
status = "passing"
[[row]]
id = "F-collision-verification"
claim = "collision operator coefficients, invariants and projections in an eight-moment basis"
observable = "conservation, self-adjointness and published-coefficient residuals"
artifact = "docs/_static/collision_operator_verification.json"
generator = "retired@df2953026 scripts/artifacts/build_linear_validation_artifacts.py collision-verification"
reference = "Frei, Ernst & Ricci (2022) Appendix C closed forms"
reference_rank = 2
tier = 2
status = "passing"
notes = "offline operator algebra, not runtime transport; the finite-k Coulomb tables remain research-only (plan.md Phase 6)"
[[row]]
id = "F-nonlinear-autodiff"
claim = "checkpointed nonlinear window derivative against centered finite differences, and its memory"
observable = "AD/FD relative agreement versus window length; measured temporary state"
artifact = "docs/_static/nonlinear_autodiff_validation.png"
generator = "retired@df2953026 scripts/artifacts/build_nonlinear_autodiff_figure.py"
reference = "centered finite differences on the same detached state and discrete map"
reference_rank = 1
tier = 3
status = "passing"
notes = "agreement 1e-11 at 512 steps and 2.7e-9 at 1024, degrading by 2048 as trajectories separate; this bounds the useful gradient horizon (plan.md Phase 4)"
[[row]]
id = "F-runtime-memory"
claim = "README performance figure: cold wall time and peak memory across tracked cases"
observable = "cold wall time and peak resident set size per case and backend"
artifact = "docs/_static/runtime_memory_benchmark.png"
companion = "docs/_static/runtime_memory_results_ship_refresh.csv"
generator = "retired@df2953026 scripts/artifacts/build_runtime_memory_figure.py"
reference = "self-measured on named hardware; not a cross-code speed claim"
reference_rank = 5
tier = 3
status = "passing"
[[row]]
id = "F-saturation-policy"
claim = "the stopping policy replayed on three tracked runs, each stopped by a different gate"
observable = "stop time as a fraction of t_max, and the binding gate"
artifact = "docs/_static/saturation_examples.png"
generator = "retired@df2953026 scripts/artifacts/build_saturation_figure.py"
reference = "replay of tracked runs under the shipped policy"
reference_rank = 5
tier = 2
status = "provisional"
notes = "plan.md 2.1 replaces this heuristic policy with the pre-registered protocol in plan.md 3.4; this row is superseded once L-stat-calibration exists"
[[row]]
id = "F-qa-transport"
claim = "QA shape optimization through turbulence: initial and candidate equilibria, and matched heat-flux traces"
observable = "heat-flux reduction across nominal pairs with its conditional interval"
artifact = "docs/_static/qa_transport_reduction.svg"
companion = "docs/_static/qa_transport_summary.csv"
generator = "retired@df2953026 scripts/artifacts/build_qa_transport_figures.py"
reference = "matched paired GKX runs; no external reference"
reference_rank = 5
tier = 3
status = "provisional"
notes = "Historical traces predate the periodic hypercollision correction and require regeneration; they are not evidence for the current operator. Nominal 12.26% reduction is NOT statistically resolved: 4 of 48 nominal traces fail the published final-drift test. Promotion requires plan.md 4.7"
[[row]]
id = "F-qa-equilibria"
claim = "initial and candidate QA boundaries and Boozer contours"
observable = "boundary shape, aspect ratio, mean iota and QA residual"
artifact = "docs/_static/qa_transport_equilibria.png"
generator = "retired@df2953026 scripts/artifacts/build_qa_transport_figures.py"
reference = "VMEX equilibria solved for this campaign"
reference_rank = 5
tier = 3
status = "passing"
[[row]]
id = "A-zonal-residual"
claim = "README Analytic benchmarks: zonal residual against Xiao-Catto within 2.4% on circular cases"
observable = "fitted phi_inf / Xiao-Catto closed form"
artifact = "docs/_static/analytic_benchmarks.json"
generator = "retired@df2953026 scripts/artifacts/build_analytic_benchmarks.py zonal"
reference = "Rosenbluth & Hinton PRL 80 724 (1998); Xiao & Catto PoP 13 082307 (2006)"
reference_rank = 1
tier = 1
status = "passing"
[[row]]
id = "A-gam"
claim = "README Analytic benchmarks: GAM frequency within 3.5% of the Sugama-Watanabe root"
observable = "fitted omega_G and gamma_G / root of SW Eq. (2.7) at the run's k_x"
artifact = "docs/_static/analytic_benchmarks.json"
generator = "retired@df2953026 scripts/artifacts/build_analytic_benchmarks.py zonal"
reference = "Sugama & Watanabe JPP 72 825 (2006)"
reference_rank = 1
tier = 1
status = "provisional"
notes = "Damping is off by 11-25% against the root, not the 15% of the specification; gated at 30%. Open question: Hermite recurrence at Nm 128 versus physics that SW Eq. (2.7) omits."
[[row]]
id = "A-kbm-pkj"
claim = "README Analytic benchmarks: Cyclone KBM onset 1.04% against GENE 1.14%"
observable = "zero of the linear gamma(beta) fit through the three lowest unstable betas, ky 0.2"
artifact = "docs/_static/analytic_benchmarks.json"
generator = "retired@df2953026 scripts/artifacts/build_analytic_benchmarks.py pkj"
reference = "Pueschel, Kammerer & Jenko PoP 15 102310 (2008)"
reference_rank = 2
tier = 1
status = "provisional"
notes = "8% below GENE, which misses the 3% specification (gated at 10%). Nm 16 and nperiod 3; Nm 32 gives 1.07%. Closing it needs an nperiod and Nm ladder and the subdominant-branch eigen route."
[[row]]
id = "A-kbm-strong-drive"
claim = "README Analytic benchmarks: strongly driven KBM omega_r / (omega_*pi/2) = 1.06-1.10 (s-alpha)"
observable = "omega / (ky (fprim + tprim)/2) at beta 1.5%, R/L_T 35 and 15"
artifact = "docs/_static/analytic_benchmarks.json"
generator = "retired@df2953026 scripts/artifacts/build_analytic_benchmarks.py az"
reference = "Tang, Connor & Hastie NF 20 1439 (1980); Aleynikova & Zocco PoP 24 092106 (2017)"
reference_rank = 1
tier = 1
status = "provisional"
notes = "s-alpha sets omega_kappa = omega_gradB, so this is not AZ's equation; 5% missed, gated at 12%. Closing it needs an s-alpha option with a beta-prime drift split."
[[row]]
id = "X-cyclone-repaired-gx"
claim = "Cyclone ITG adiabatic, s-alpha and Miller: certified GKX eigenpairs against the clamp-repaired GX goldens and converged GS2/gyaradax"
observable = "relative gamma difference per ky, GKX Nl16/Nm48 certified Krylov eigenpair vs GX rerun with the dampEnds_linked grid-stride fix (s-alpha ky .15/.20/.30/.40, Miller .15/.30/.40/.55) and vs GS2 r3/r4 (Miller .15/.30/.40/.55, s-alpha .30) and gyaradax g2 (s-alpha .30)"
artifact = "docs/_static/cross_code_linear_points.csv"
generator = "retired@4564828bf plan/research/2026-10-06-val-ke/scripts/assemble.py"
reference = "GX 3865a537 + dampEnds_linked grid-stride loop (self-run, sha256 96a53403...); GS2 8.2.1; gyaradax 8d9dc2d2"
reference_rank = 5
tier = 3
status = "passing"
notes = "GKX vs repaired GX: <= 0.30% at 7 of 8 points, +1.45% at Miller ky .15. GKX vs GS2: <= 0.3% at Miller .30/.40, +0.65% at Miller .55, +1.0% at s-alpha .30, +2.4% at Miller .15; gyaradax s-alpha .30 is 1.1% below GKX. The repaired build reproduces the shipped adiabatic goldens to 0.06% above ky 0.1, so the clamp is immaterial for these two cases; the L-lin-cyclone-* rows still cite the time-fitted parity tables. The csv also holds a stella v1.0 r1 scan in GX units (gamma and omega times sqrt 2, ky over sqrt 2); stella is 1.37-1.49x above GKX in gamma at ky .25-.71, an open stella-side disagreement, and is not a reference."
[[row]]
id = "X-ke-miller"
claim = "Cyclone Miller with kinetic electrons (m_e/m_i 2.7e-4, beta 1e-5, A_par), linear: GKX certified eigenpairs against repaired GX and GS2"
observable = "relative gamma and omega difference at ky .30 and .50, GKX Nl16/Nm48 with damp_ends_rate 160.6 (GX's 0.1/dt at its settled dt 6.228e-4)"
artifact = "docs/_static/cross_code_linear_points.csv"
generator = "retired@4564828bf plan/research/2026-10-06-val-ke/scripts/assemble.py"
reference = "GX 3865a537 + dampEnds_linked grid-stride loop (self-run, t = 40); GS2 8.2.1 rung e3 (ntheta 48, nperiod 3, negrid 16, ngauss 8)"
reference_rank = 5
tier = 3
status = "provisional"
notes = "ky .30: GKX 0.23128/0.23603 vs GX 0.23209/0.23651 (-0.35%/-0.20%) and GS2 0.23484/0.2210 (-1.5%); Nl8/Nm24 gives 0.23115 (0.06% from Nl16/Nm48). ky .50: 0.25479/0.46698 vs GX 0.25410/0.46771 (+0.27%/-0.16%) and GS2 0.25354 (+0.5%). Only two ky are measured; ky .10 is unsettled in both GX (t = 40) and GS2 e3. Before this row the Krylov route damped the linked ends at damp_ends_amp instead of amp/dt and gave 0.3579 at ky .30 (+54%)."
[[row]]
id = "X-tem-dj2005"
claim = "Collisionless TEM, Dannert & Jenko PoP 12 072309 (2005) nominal case, linear: GKX against GS2 at matched physics"
observable = "relative gamma and omega difference at ky rho_s 0.3 along a GKX (Nl, Nm) ladder with the banded eigensolver; GKX (8, 32) scan ky rho_s 0.2-0.6 against GS2; end-damping rate and parallel-domain scans"
artifact = "docs/_static/cross_code_linear_points.csv"
generator = "retired@gkx-plan plan/research/2026-10-19-val-linear/scripts/csvrows.py"
reference = "GS2 8.2.1 rungs t1 (ntheta 32, nperiod 2, negrid 12, ngauss 6) and t2 (ntheta 48, nperiod 3, negrid 16, ngauss 8); deck tools/comparison/fixtures/parity/tem_dannert_jenko_2005.toml"
reference_rank = 5
tier = 3
status = "open"
notes = "nu_ee 0.01 (Dougherty) against GS2 default operator (vnewk 0.00707, ions at the physical ratio; GS2 t1/t2 0.7618/0.7674 in GKX units): GKX banded, shift near the mode, Nl 8, Nm 32/64/96 gamma 0.639/0.734/0.779 (-16.8%/-4.4%/+1.5% of t2), omega -1.238/-1.280/-1.288 (-4.7%/-1.5%/-0.9%). Nl 16 banded was killed at Nm 64 (62 GB host); the time route at the deck dt exceeds the CFL bound and diverges; the Landau tables overflowed at (16,128) (fixed in GKX PR 392). Collisionless: GS2 is converged (t1 -> t2 <= 2.5% over the scan; beta_e x2 moves ky .3 by +0.5%): gamma 0.8694, omega -1.2723 (v_ti/R) at ky rho_s 0.3. GKX banded eigenpairs (nperiod 2, damp_ends_rate 100) at Nl 8 rise with Nm: 16 0.490, 24 0.611, 32 0.673, 48 0.744, 64 0.773, 96 0.825 (-5.1%); omega at Nm 96 -1.2849 (+1.0%). Not converged in Nm. In Nl at Nm 24 the growth rate is not monotone (Nl 4, 6, 8, 10, 12: 0.480, 0.623, 0.611, 0.513, 0.552): the Hermite |kz| hypercollision has no Laguerre sink. The result also depends on the end absorber and parallel domain: (Nl, Nm) = (8, 24) gives 0.871 at damp_ends_rate 5, 0.668 at 20, 0.611 at 100, 0.607 at 400; at (4, 16) the spread between rates 5 and 100 falls from 0.29 at nperiod 2 to 0.07 at nperiod 5. ky scan at (8, 32) over GS2: 0.68, 0.77, 0.84, 0.88, 0.93 of GS2 gamma at ky rho_s 0.2-0.6. The automatic shift of the banded route lands on a damped fast oscillator for this deck and the route falls back to adaptive (1493 s against 39 s with a shift near the mode). A Laguerre-only sink (hypercollisions_const 1, nu_hyper_m_const 0, nu_hyper_l 0.03, Nm 24) makes the Nl sequence 4, 6, 8, 10 monotone (0.493, 0.507, 0.554, 0.567) and nu 0.01 flat to 2% from Nl 6, at a growth rate below the sink-free one; it was not tested above Nm 24. (12, 32) and (16, 48) were killed by the out-of-memory killer on the shared host. The paper publishes this case in figures only, so GS2 is the reference."
[[row]]
id = "X-mu-grid-convergence"
claim = "Nodal magnetic-moment grid (opt-in, linear) against the Laguerre expansion: Cyclone ITG at ky 0.3 and 0.4 with adiabatic electrons, and the Dannert-Jenko TEM"
observable = "gamma against the node count 4-16 and the Laguerre count 8-24 (Cyclone, Nm 32) and 4-16 (TEM, Nm 24), banded eigensolver, with wall time and peak memory"
artifact = "docs/numerics.rst"
generator = "retired@gkx-plan plan/research/2026-10-25-mu-grid/scripts/mu2.py"
reference = "converged GKX Laguerre ladder (Nl 24); GX v2 nodal runs (nmu 8: Cyclone 0.0934 and 0.0795, TEM 0.564) as a cross-check"
reference_rank = 5
tier = 3
status = "open"
notes = "Cyclone, Nm 32, vperp_max 4: 8 nodes are within 1.4% (ky 0.3) and 0.5% (ky 0.4) of the converged Laguerre rate, where Laguerre needs Nl 16 and 24 (5.4x and 12x the wall time, 2.7x and 4x the memory). 16 nodes at ky 0.4 are 4% below the 12-node value. TEM (Nm 24, still Nm-limited against GS2 0.869): nodal 0.514, 0.561, 0.547, 0.548 at 4, 8, 12, 16 nodes against Laguerre 0.480, 0.611, 0.552, 0.565, at equal or up to 2x the cost per node. Linear only; Dougherty collisions on nodes in weak form (landau and Laguerre-index hypercollisions are refused). KBM, Miller KE, W7-X ITG and collisional TEM ladders are in docs/numerics.rst. Timings are one shared 4-thread CPU."
[[row]]
id = "X-kbm-beta-gs2"
claim = "Miller CBC kinetic ballooning, ky 0.3, beta 0.005-0.020, A_par and A_par+B_par, linear: GKX against GS2"
observable = "relative gamma and omega difference at four beta, GKX (8, 24) and (8, 32) nperiod 2 and (8, 24) nperiod 3 against GS2 e4v"
artifact = "docs/_static/cross_code_linear_points.csv"
generator = "retired@gkx-plan plan/research/2026-10-19-val-linear/scripts/csvrows.py"
reference = "GS2 8.2.1 rung e4v (ntheta 48, nperiod 3, negrid 24, ngauss 12, bishop 4, betaprim 0); e3 agrees within 0.3%"
reference_rank = 5
tier = 3
status = "open"
notes = "A_par, (8, 24) nperiod 2, gamma/omega against GS2: beta .005 -2.4%/+10.8%, .010 -8.2%/+8.8%, .015 +7.3%/+7.8%, .020 +6.1%/+4.7%. A_par+B_par: -2.6%/+11.0%, -10.1%/+9.5%, +6.4%/+6.6%, +5.4%/+4.0%. Nm 32 moves gamma by up to 4 points and omega by up to 3 points. nperiod 3 at beta .015 gives gamma +16.5%, omega +1.7%; at beta .005 -3.0%/+11.7%. The end-damping rate is not a factor: the timestep-free default and 200 agree to 7e-6 in gamma. The signs and size of the gamma differences follow the earlier GX-GS2 KBM gap (GS2 below GX) and are not attributed. Only ky 0.3, one geometry, one velocity resolution family."
[[row]]
id = "X-w7x-itg-gx"
claim = "W7-X standard configuration ITG, adiabatic electrons, s = 0.64, 6 poloidal turns, linear: GKX against repaired GX"
observable = "relative gamma and omega difference over ky 0.8-2.4 at Nl 8, Nm 16 with GX's damp_ends rate 0.1/dt = 17"
artifact = "docs/_static/cross_code_linear_points.csv"
generator = "retired@gkx-plan plan/research/2026-10-19-val-linear/scripts/csvrows.py"
reference = "GX 3865a537 + dampEnds_linked grid-stride loop, deck benchmarks/linear/ITG_w7x, self-run to t = 200"
reference_rank = 5
tier = 3
status = "provisional"
notes = "GKX eigenpairs agree with GX to 3e-4 relative in gamma and omega at ky 1.1-2.4 (nine points). At ky 0.9-1.0 the eigensolver returns a different certified pair than GX's fit: ky 1.0 gamma +0.1% but omega 0.2645 against 0.1489; ky 0.9 gamma 0.1630 against 0.1493. GKX's time route reproduces GX at ky 1.0 (0.17475/0.1489) and is unsettled at 0.9 (0.1300/0.1162). The extra pair is a bulk mode, not an end-layer one: 2e-6 of |state|^2 lies in the outer 12.5% of the line, and damp_ends_rate 17 to 40 moves no Ritz value by more than 1e-4. At ky 1.0 three certified pairs lie within 2e-4 in gamma, among them GX's (0.17473, 0.1489); GX's fit and the time route follow the one a Gaussian density start excites, the eigensolver returns the fastest. Velocity resolution is not the cause (ky 1.6 gamma 0.2430-0.2456 for Nl 4-12 at Nm 16 and (8, 24), (8, 32)). stella with the same field line (nfield_periods = 6 nfp/iota, geometry checked against the GX eik file) is converged in its own grids but its growth-rate curve differs from GX and GKX, so it is not used as a reference. GX is unsettled below ky 0.8. One velocity resolution (the GX deck's) and one equilibrium; the Gonzalez-Jerez et al. 2022 decks were not obtainable."
[[row]]
id = "X-hsx-itg-gx"
claim = "HSX QHS vacuum ITG, adiabatic electrons, s = 0.64, 4 poloidal turns, linear: GKX against repaired GX"
observable = "relative gamma and omega difference over ky 0.3-1.5 at Nl 8, Nm 16 with GX's damp_ends rate 0.1/dt = 9.9"
artifact = "docs/_static/cross_code_linear_points.csv"
generator = "retired@gkx-plan plan/research/2026-10-19-val-linear/scripts/csvrows.py"
reference = "GX 3865a537 + dampEnds_linked grid-stride loop, W7-X deck with the HSX QHS vacuum VMEC (ns 201) and npol 4, self-run to t = 200"
reference_rank = 5
tier = 3
status = "provisional"
notes = "GKX eigenpairs agree with GX to 3e-4 relative in gamma and omega at ky 0.5-1.5 (seven points); at ky 0.3 gamma is -0.5% and omega unsettled in GX (0.012 against 0.066). The GX geometry script failed on this equilibrium (an array with an extra axis in the interpolation) and the eik file was generated with the same script after squeezing the arrays; GKX imports that geometry. The equilibrium is the cutstudy HSX QHS vacuum wout, not the Nuhrenberg-Zille example of the L-lin-hsx row. One velocity resolution."
[[row]]
id = "N-cyclone-gx-table1"
claim = "nonlinear Cyclone ITG heat flux, adiabatic electrons, a/LT 2.49, 192x64x24 (4,8), against GX"
observable = "Q_i/Q_GB, Sokal-IAT standard error, agreement within two combined errors"
artifact = "docs/validation.rst"
generator = "retired@gkx-plan plan/research/2026-10-20-nonlinear-stats/nonlinear_statistics.py"
reference = "GX paper Table 1 (doi:10.1017/S0022377824000631) 7.2 +- 0.8; repaired GX self-run 6.66 +- 0.25"
reference_rank = 2
tier = 3
status = "passing"
[[row]]
id = "N-dimits-scan"
claim = "Dimits shift in nonlinear Cyclone ITG (GX paper Sec. 6.1.2 deck): not reproduced at (4, 8) by GKX or repaired GX; both move toward it at (8, 16)"
observable = "Q_i/Q_GB at a/LT 1.5, t = 1000: GKX 1.20 +- 0.04 (4,8), 0.77 +- 0.15 (8,16); repaired GX 1.37 +- 0.12, 0.61 +- 0.22; paper about 0.3 (Fig. 4b)"
artifact = "docs/validation.rst"
generator = "retired@gkx-plan plan/research/2026-10-25-paper-exact/scripts/ns.py"
reference = "Dimits et al., Phys. Plasmas 7, 969 (2000); GX paper Sec. 6.1.2 and Fig. 4b"
reference_rank = 2
tier = 3
status = "open"
notes = "Deck of the paper's App. G.3 (Nx 192, Ny 64, Nz 24, nu_ii 0.01 Dougherty, hypercollisions p = Nm/2, D_hyper 0.05 n 4, RK3, init 1e-5, one seed). Zonal fraction late: GKX 0.86/0.76, GX 0.79/0.87. The (4,8) GKX window is not stationary (halves differ). With nu_ii = 0 both decay to a zonal-dominated state (gkx-plan 2026-10-20-nonlinear-stats). The paper's initial condition and averaging window are not stated. Records in gkx-plan plan/research/2026-10-25-paper-exact."
[[row]]
id = "N-cyclone-gx-fig4b"
claim = "nonlinear Cyclone ITG heat-flux scan in a/LT, adiabatic electrons, GKX against GX paper Fig. 4b and Table 1"
observable = "Q_i/Q_GB at (4,8): a/LT 2.0 3.43 +- 0.13, 2.49 7.08 +- 0.12, 3.0 11.6 +- 0.2; (8,16) 2.49 7.39 +- 0.19"
artifact = "docs/validation.rst"
generator = "retired@gkx-plan plan/research/2026-10-25-paper-exact/scripts/ns.py"
reference = "GX paper Fig. 4b (read off, about 10%): 3.6, 7.2, 12; Table 1: 7.2 +- 0.8 (4,8), 7.3 +- 0.9 (8,16); repaired GX self-run 7.07 +- 0.23 (4,8) and 7.49 +- 0.21 (8,16)"
reference_rank = 2
tier = 3
status = "passing"
[[row]]
id = "N-cyclone-ke-table2"
claim = "nonlinear Cyclone with kinetic electrons (GX Table 2, Q_i 23.6, Q_e 7.3 at (4,16), t = 600): not run"
observable = "GKX 2.7.0 defaults at 192x64x24 advance 0.079 a/v_ti in 17 s on a shared RTX A4000, about 36 h for t = 600"
artifact = "docs/validation.rst"
generator = "retired@gkx-plan plan/research/2026-10-25-paper-exact/scripts/ns.py"
reference = "GX paper Table 2 (doi:10.1017/S0022377824000631)"
reference_rank = 2
tier = 3
status = "open"
notes = "Cost only; no heat-flux statistic exists. Needs an exclusive GPU for about a day or a cheaper stepper for the electron streaming."
[[row]]
id = "X-w7x-itg-paper"
claim = "W7-X high-mirror bean tube ITG (Gonzalez-Jerez 2022 test 1), adiabatic electrons, linear: GKX against the paper's curves and repaired GX"
observable = "a gamma/v_th, a omega/v_th at k_y rho_i 2.1 (v_th = sqrt(2T/m)): GKX 0.1750, 0.2628; repaired GX 0.1750, 0.2628; paper 0.172, 0.27 (Fig. 5, read off)"
artifact = "docs/validation.rst"
generator = "retired@gkx-plan plan/research/2026-10-25-paper-exact/scripts/w7x.py"
reference = "Gonzalez-Jerez et al., JPP 88, 905880310 (2022) Fig. 5 and appendix INDATA (VMEC rebuilt: a 0.4944 m, R0 5.485 m, beta 3.0%, iota 0.910 at s 0.64); GX 3865a537 + dampEnds repair self-run"
reference_rank = 2
tier = 3
status = "passing"
notes = "GKX (Nl,Nm) = (4,8) 0.1776, (8,16) 0.1750, (16,32) 0.1754; 1, 3, 6 poloidal turns agree to 3e-4 at k_y rho_i 2.1. Against GX at 7 k_y (0.7-3.0, one turn): within 0.5%. Against the paper curve at k_y rho_i 1.0, 1.3, 2.3, 3.0, 4.0 (6 turns below 1.3): 0.087/0.116/0.176/0.159/0.140 against 0.085/0.113/0.175/0.157/0.134, read off a figure to about 0.003. The paper's curve is collisionless; the decks here have nu = 0. At k_y rho_i < 1.3 GX's time fit lands on another branch than the eigenpair. Zonal flow (npol 3) and the triangular tube were not run."