Skip to content

GKX 2.2.0

Choose a tag to compare

@rogeriojorge rogeriojorge released this 20 Sep 22:03
· 947 commits to main since this release
eeb3481

GKX 2.2.0

A minor release. Nothing is removed since 2.1.0. Two shipped defaults change, both to fix measured errors, and several routes that could return a wrong answer silently now either report or refuse.

Defaults that change a run

  • Linear resolution fallback is now (Nl, Nm) = (12, 24), not (24, 12) (#262). On the shipped Cyclone deck the old fallback sat 4.4% below the tracked golden growth rate; the new one is +0.4%, at identical Nl·Nm and identical state size. Higher resolution was not bought: 384 and 576 degrees of freedom both land further out than 288.
  • A deck that sets no time step now gets rk4 with the CFL controller, not rk2 at a fixed step (#262). The defaulted fixed step was 7.8× the stable one and overflowed for rk2 and rk4, so the method and the step policy move together. Decks that set their own step are untouched, and a test enforces that. Cost at matched accuracy: 11072 right-hand-side evaluations against 15612, 29.1% fewer.
  • KrylovConfig.power_iters is 40, not 200 (#262): five times fewer propagator applies, identical outcome. The power route never certifies at either value, so the number is a cost, not an accuracy setting.

Correctness

  • Float64 runs stayed float32 (#257). The runtime assembled its initial state in complex64 and handed it over unwidened, so a run launched with JAX_ENABLE_X64=true — which the shipped Cyclone deck's own header instructs — ran in float32 and applied the float32 certification gate. Certified residual on that deck: 1.76e-6 against a 1.19e-4 tolerance, now 4.04e-15 against 1e-9. The float32 default is unchanged and verified to seven significant figures against the float64 pair.
  • Supplied states and restarts are projected onto the linked-chain cover (#247, #253). Rows outside the chains are decoupled, but the nonlinear bracket dealiases only its output, so they aliased back onto live rows: a broadband restart moved one right-hand side by 2.4e-2 and an 8-step run's heat flux by 335%. Now zero. Free energy on the linked pilot had been inflated 115×.
  • kperp2_max was computed from the stored row count in two places (#258), halving the perpendicular cutoff and inflating every hyperdiffusion rate by 4**p. The restart block length and the seeded initial band had the same defect.
  • An even grid's Nyquist row took weight 2 on a half axis (#254). It is stored once with no conjugate twin, so the weight is 1. The ky weight rule now has one owner instead of four copies.
  • The shift-invert inner solve seeded itself with M⁻¹b (#261). Under right preconditioning that vector is already the first Krylov direction, so the guess could only start the solve behind zero, and with a weak preconditioner it did. The route went from rejected at outer residual 0.995 to certified at 3.25e-07, matching the control's growth rate to eight significant figures.
  • gkx.prepare and the runtime nonlinear route now compile one graph (#249). All 12 gate cases are bitwise identical in both precisions, where every one differed before. Peak memory over eight chunked calls: 1200 MB → 826 MB.

Added

  • pr3-cm structured preconditioner (#261), with an exact block-Thomas plus Sherman–Morrison solve of the z-local block — verified exact (off-tridiagonal entries identically zero, rank-one ratio 6.0e-15, applies agreeing to 7.4e-16), with factors 2.60× smaller. A structural guard refuses rather than approximates where the z-locality does not hold, which it does for zonal rows under adiabatic electrons.
  • Solver status reaches the routes it previously missed (#263): the IMEX diagnostics and sheared routes carry implicit-solve statistics, and saved *.summary.json files now carry all nine status fields, where none existed on disk before. Graphs that do not ask for statistics compile byte-identically.
  • ky ≥ 0 state layout, opt-in (#248, #258, #259): build_spectral_grid(..., ky_layout="half") stores only the non-negative-ky rows, with the reality condition holding by construction. Bitwise identical to the full layout across 58 right-hand-side outputs and 65 trajectory outputs in both precisions. It is not the default yet.

Evidence

  • The collisionless Cyclone ITG mode at kyρ=0.55 has no Laguerre-converged growth rate up to Nl=48 (#252). Twelve certified eigenpairs show one slowly converging branch, not a mode change, with a cutoff pile-up that sits at the same fraction of the grid at every resolution. The next step is a declared velocity-space sink, not more resolution.
  • Inner-solve cost (#255, #261): the shipped shift-invert route is apply-bound, not iteration-bound — its iteration counts are 2.4–4.0× below the adaptive control while costing 1.68–2.27× more. adaptive remains the default eigen route.
  • Shared linked-chain transforms (#250, #259): FFT launches per right-hand side fall 23 → 13. On corrected metrics the half layout writes 63% fewer bytes for one right-hand side and 72–73% fewer for a full step.
  • README and methods documentation (#256): a feature summary linking each claim to its evidence, and a methods-and-decisions page with four figures regenerated from tracked data by a committed script.

Installing

pip install gkx==2.2.0