End-to-end differentiable JAX implementation of VMEC2000 for fixed-boundary and free-boundary ideal-MHD equilibria.
All figures below use the same single-grid run settings: NS_ARRAY=151, NITER_ARRAY=5000, FTOL_ARRAY=1e-14, NSTEP=500.
More visuals (single-grid)
- VMEC2000-parity solver for fixed-boundary and free-boundary equilibria.
- Supports axisymmetric and non-axisymmetric configurations, with
lasym=Falseandlasym=Truefor stellarator symmetry/asymmetry and up-down symmetry/asymmetry. - Default CLI path is
vmec_jax input.name. wout_*.ncoutputs, iteration diagnostics, and manifest-based parity sweeps are built around VMEC2000-compatible workflows.- JAX-native kernels for geometry, transforms, and residual assembly.
- Differentiable optimization workflows are available through the Python API and bundled examples.
Install (editable) and run the showcase:
python -m venv .venv
source .venv/bin/activate
python -m pip install -e .
python examples/showcase_axisym_input_to_wout.py --suiteIf you want the bundled reference outputs and mgrid files, fetch the assets once:
python tools/fetch_assets.pyLightweight clone (keeps full history, downloads blobs lazily):
git clone --filter=blob:none https://github.com/uwplasma/vmec_jaxNote: the repo history was rewritten on 2026-03-16 to remove large assets from all commits. If you cloned before that date, please re-clone (or prune and reset) to get the smaller history.
CLI (VMEC2000-style executable):
vmec_jax examples/data/input.circular_tokamakSanity check (verifies the console script is wired to the right interpreter):
vmec_jax --helpIf the vmec_jax command is not found or raises ModuleNotFoundError, make sure
you installed with the same interpreter and use the module entrypoint:
python -m pip install -e .
python -m vmec_jax examples/data/input.circular_tokamakFor fixed-boundary inputs, the default CLI path now uses the optimized
controller: it tries the fast final-grid scan route first, then escalates to
staged continuation and strict parity finishing only when the input structure
and residual history require it. Pass --parity to force the conservative
VMEC2000 loop. Pass --solver-mode accelerated to request the optimized track
explicitly.
Python driver comparison (reference track vs optimized CLI-style track):
python examples/fixed_boundary_driver_tracks.py \
examples/data/input.circular_tokamak \
--quiet --jsonRun tests:
pytest -qFull test suite (requires netCDF assets):
python tools/fetch_assets.py
RUN_FULL=1 pytest -qOptimization tutorials (differentiable boundary tuning):
python examples/optimization/optimize_bmag_volume.py --case circular_tokamak --opt-steps 3
python examples/optimization/explicit_target_iota_volume.py --case circular_tokamak --opt-steps 3
python examples/optimization/implicit_target_iota_volume.py --case circular_tokamak --opt-steps 3- Default runs aim for VMEC2000-compatible behavior while selecting the fastest stable path for the input.
- Use
--parity(orperformance_mode=Falsein Python) to force the conservative VMEC2000 loop. - Use
--solver-mode acceleratedto force the optimized fixed-boundary controller explicitly.
Details, profiling guidance, and parity methodology:
docs/performance.rstdocs/validation.rsttools/diagnostics/parity_manifest.toml+tools/diagnostics/parity_sweep_manifest.py
The runtime plot includes VMEC++ (green) for context. Some inputs are not supported or do not converge under the same single-grid settings.
VMEC++ unsupported inputs in this benchmark (lasym=True):
LandremanSenguptaPlunk_section5p3_low_resbasic_non_stellsym_pressurecth_like_free_bdy_lasym_smallup_down_asymmetric_tokamak
VMEC++ failed to converge (non-zero exit) on these lasym=False cases under the same single-grid settings:
DIII-D_lasym_falseLandremanPaul2021_QA_reactorScale_lowresLandremanPaul2021_QH_reactorScale_lowresLandremanSengupta2019_section5.4_B2_A80cth_like_fixed_bdy
The VMEC-style iteration loop prints every NSTEP iterations. Larger NSTEP means fewer print callbacks and faster runs.
To disable live printing, set:
export VMEC_JAX_SCAN_PRINT=0Quiet runs (--quiet or verbose=False) default the scan path to a minimal
history mode (only fsqr/fsqz/fsql and w_history are kept) to reduce
host/device traffic. You can override this with:
export VMEC_JAX_SCAN_MINIMAL=0 # keep full scan diagnostics even when quiet- Use
vmec_jaxfor fixed-boundary and free-boundary production runs, autodiff, rapid parameter sweeps, and JAX-native optimization workflows. - Use the VMEC2000 executable as an optional parity reference or regression oracle, not as an operational requirement.









