Skip to content

VMEX 0.7.0

Choose a tag to compare

@rogeriojorge rogeriojorge released this 24 Aug 18:47
b365672

Complete VMEC2000 profile coverage, a fast-ion confinement proxy, alpha-particle tracing, and a correctness fix to every implicit gradient.

  • sum_atan in particular is available for PCURR_TYPE and PIOTA_TYPE -- VMEC2000 offers it for those two and not for pressure, and VMEX matches that. It prescribes I(s) rather than I'(s), so the current lane needs no quadrature. Measured against live xvmec2000 on li383_low_res: iotaf 2.8e-14 and jcurv 1.2e-14 on the current lane, iotaf 1.2e-16 on the iota lane. (#158)
  • VMEX implements every profile parameterization VMEC2000 offers: ten for PMASS_TYPE, seven for PIOTA_TYPE, seventeen for PCURR_TYPE. The seven that were missing are sum_atan, two_power_gs, two_Lorentz, rational, nice_quadratic, and the three sum_cossq_* current forms; the last are analytic piecewise integrals of windowed cos-squared waves. All were checked against literal transcriptions of profile_functions.f and functions.f -- exact for six of the seven, 7.4e-17 for two_Lorentz -- and four of them additionally end to end against live xvmec2000. A profile type outside VMEC2000's set now raises rather than falling through to a default, and docs/reference/input-file.rst lists the accepted strings, which it previously did not for the current and iota profiles. (#158, #159)
  • Implicit gradients are anchored at a refined fixed point. ftol gates a sum of squares, so a solve VMEX calls converged stops with residual of order sqrt(ftol); where dF/dz has a small singular value that is a real state displacement, and the adjoint was linearizing about the wrong point. Refining before linearizing moved the LASYM RBS(1,1) Mercier channel from 4.2e-3 to 5.3e-7 and every symmetric channel with it, taking the shared gate from 2.0e-3 to 2.0e-5. Two channels had been over the gate, not one. Costs 14 to 26 percent on the forward solve, gated on the measured residual. (#148)
  • Gamma_c, the Nemov fast-ion confinement proxy, is available as a differentiable objective, on the bounce kernel of Unalmis et al. and anchored to the literature ordering against the independent effective-ripple lane. (#141)
  • Alpha-particle tracing: trace_alphas and vmex --trace, on released ESSOS. (#138, #146)
  • VMEX no longer crashes on macOS with jaxlib < 0.10. The persistent compilation cache deserialization overflowed the stack and raised SIGILL; it is disabled there, with the guard verified firing. This retroactively explains why the NCSX free-boundary work needed the cache disabled by hand and why one adjoint certificate failed only under pytest -n 2. (#142)
  • Boozer input tables gain traceable gmnc, bsupumnc, bsupvmnc and bsubsmns for guiding-centre coupling. (#137)
  • A second free-boundary geometry family, NCSX c09r00, with its mgrid shipped as a fetched asset rather than a tracked blob. (#140)
  • The performance reference reports the numbers its own benchmark artifacts contain. Seven of nine figures in the free-boundary paragraph were wrong and they understated VMEX: the multigrid warm solve is 1.31x of Fortran, not the 2.1x claimed, and a FSQR parity defect described there does not exist in the data. The FFT synthesis claim is split, because the artifact shows it reduces peak memory but not wall time. (#150)
  • The gyrokinetic bridge handed GKX an R/L gradient where its operator consumes a/L. GKX's defaults tprim = 2.49, fprim = 0.8 are the Cyclone base case R/L_T = 6.9, R/L_n = 2.2 divided by that case's R/a = 2.77; VMEX set the deprecated R_over_LTi instead, so every turbulence evaluation ran at a drive R/a times too strong. The drive is now divided by the equilibrium's own aspect ratio, and a nominally subcritical case that reported a growth rate of 2.2e-2 reports 8.9e-15. (#153)
  • Twelve of the fourteen primary pull-request test lanes were invoked by no CI job, which left 36 modules and 256 tests outside continuous integration. They now run, in four sharded jobs, and a guard test fails if a declared lane is ever orphaned again. Two real defects were hiding there: the drive units above, and a compile-count measurement that had been reading zero because importing VMEX raises the JAX logger to ERROR. (#153)
  • The free-boundary gradient is certified factor by factor rather than against a finite difference of two cold re-solves, which could not separate an FD floor from an adjoint error. Each factor now has its own gate, and the forward-adjoint duality closes within one root. That measurement identified what actually limits the lane: two entries into the solve land on roots 4.7e-4 apart, which moves the gradient by 1.9e-3, while the adjoint of either root is exact to 3.5e-12. (#154)
  • The turbulence extra carries GKX's own jax >= 0.10.1 floor, so the lane no longer installs into an environment where it fails at call time. (#149)
  • Documentation figures are stored as lossless WebP, and the QI finite-beta self-consistent bootstrap optimization ships as an example. (#143, #136)
  • two_power_gs skips a Gaussian peak whose amplitude is zero. An unset peak slot has a zero width, and functions.f evaluates exp(-((x - 0)/0)**2) for it, which is 0/0 at the axis: VMEC2000 returns NaN there for any deck that fills fewer than six peaks, which is the ordinary way to use one or two. This is the one deliberate departure from profile_functions.f in the profiles module, and Fortran applies the same guard itself in 'sum_cossq_s_free'. Every peak that is actually set is bit-identical to VMEC. (#161)

Upgrade notes:

  • Turbulence growth rates and every proxy derived from them change. r_over_lt and r_over_ln are R/L and are now divided by the equilibrium's aspect ratio before reaching GKX; they were previously passed through as if they were a/L, so the drive was R/a times too strong. Pass params_linear to supply a/L directly.
  • Gradients through the implicit lane change. They were linearized about an under-converged state before; the new values are the correct ones, and objectives whose adjoint passes through a small singular direction move most.
  • Profile types outside VMEC2000's set raise a NotImplementedError naming the supported set rather than falling through to a default.
  • On macOS with jaxlib < 0.10 the persistent compilation cache is now off. Cold compiles are slower there; upgrade jaxlib to get it back.

Verification: the full non-full suite passes locally, 1178 tests. The sum_atan parity rows against live xvmec2000 require --run-vmec2000 and a built xvmec2000 and are not part of the hosted matrix.