End-to-end differentiable JAX implementation of VMEC2000 for fixed and free-boundary equilibria.
Project description
vmec-jax
End-to-end differentiable JAX implementation of VMEC2000 for fixed-boundary and free-boundary ideal-MHD equilibria.
Showcase (single-grid)
All figures below use the same single-grid run settings: NS_ARRAY=151, NITER_ARRAY=5000, FTOL_ARRAY=1e-14, NSTEP=500.
ITERModel cross-section (VMEC2000 vs vmec_jax) |
LandremanPaul2021_QA_lowres cross-section (VMEC2000 vs vmec_jax) |
ITERModel iota (VMEC2000 vs vmec_jax) |
LandremanPaul2021_QA_lowres iota (VMEC2000 vs vmec_jax) |
Cold vs warm runtime: the cold bar includes XLA JIT compilation on the first call (one-time cost per process); the warm bar is the steady-state solve time for all subsequent calls in the same process, with the compiled kernels already in-memory. VMEC2000 is a pre-compiled Fortran binary and therefore has no compilation overhead — it is always effectively "cold". The warm vmec_jax time is the fair comparison for repeated solves (e.g., in an optimization loop). Starting from v0.2, vmec_jax automatically caches compiled XLA kernels to disk (~/.cache/vmec_jax/jax_cache), so that cold runs in a fresh process on the same machine after the first invocation benefit from the on-disk cache and approach warm-run speed.
More visuals (single-grid)
ITERModel 3D LCFS (VMEC2000 vs vmec_jax) |
LandremanPaul2021_QA_lowres 3D LCFS (VMEC2000 vs vmec_jax) |
ITERModel |B| on LCFS (VMEC2000 vs vmec_jax) |
LandremanPaul2021_QA_lowres |B| on LCFS (VMEC2000 vs vmec_jax) |
What it is
- 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.
Quickstart
Install 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 --suite
If you want a release-style non-editable install instead, use:
python -m pip install .
If you want the bundled reference outputs and mgrid files, fetch the assets once:
python tools/fetch_assets.py
Lightweight clone (keeps full history, downloads blobs lazily):
git clone --filter=blob:none https://github.com/uwplasma/vmec_jax
Note: 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_tokamak
Sanity check (verifies the console script is wired to the right interpreter):
vmec_jax --help
If 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_tokamak
For 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 --json
Run tests:
pytest -q
Full test suite (requires netCDF assets):
python tools/fetch_assets.py
RUN_FULL=1 pytest -q
Advanced optimization examples live in examples/optimization/. They are
intended as deeper workflow templates rather than README quickstarts, so use
the fixed-boundary driver example above as the validated copy/paste entry point
and then adapt the optimization scripts for your target objective. The simplest
starting point is:
python examples/optimization/target_iota_aspect_volume.py --opt-steps 2
That example keeps the boundary parameterization small (max |m|,|n| <= 1),
targets equilibrium volume, aspect ratio, and mean iota, and defaults to the
bundled current-driven cth_like_fixed_bdy case so the iota channel is active.
Performance vs parity
- 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
VMEC++ notes
The current runtime benchmark compares vmec_jax against VMEC2000. VMEC++ is not included in this benchmark.
When VMEC++ is available, it can be added to the runtime plot via --cpu-summary entries with backend=vmecpp. Some inputs are not supported or do not converge under the same single-grid settings:
VMEC++ unsupported inputs (lasym=True):
LandremanSenguptaPlunk_section5p3_low_resbasic_non_stellsym_pressurecth_like_free_bdy_lasym_smallup_down_asymmetric_tokamak
VMEC++ known non-convergence 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
CLI output and NSTEP
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=0
Quiet 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
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file vmec_jax-0.0.1.tar.gz.
File metadata
- Download URL: vmec_jax-0.0.1.tar.gz
- Upload date:
- Size: 465.2 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
0c40869f17a767dd55cfa87131d3f0ebe6daf39a0fcf435d50660fdb68436514
|
|
| MD5 |
fc70f01f0a4f64fd58c067e140433645
|
|
| BLAKE2b-256 |
3e9fb9d41f4bfedfd8d0c9c2eab0317a1fd189ebe48e962ce978b90c1d14e7cf
|
Provenance
The following attestation bundles were made for vmec_jax-0.0.1.tar.gz:
Publisher:
publish-pypi.yml on uwplasma/vmec_jax
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
vmec_jax-0.0.1.tar.gz -
Subject digest:
0c40869f17a767dd55cfa87131d3f0ebe6daf39a0fcf435d50660fdb68436514 - Sigstore transparency entry: 1334421097
- Sigstore integration time:
-
Permalink:
uwplasma/vmec_jax@531aa4073ee1ad3afdde0ea46c5abe929abfb8e1 -
Branch / Tag:
refs/tags/v0.0.1 - Owner: https://github.com/uwplasma
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish-pypi.yml@531aa4073ee1ad3afdde0ea46c5abe929abfb8e1 -
Trigger Event:
release
-
Statement type:
File details
Details for the file vmec_jax-0.0.1-py3-none-any.whl.
File metadata
- Download URL: vmec_jax-0.0.1-py3-none-any.whl
- Upload date:
- Size: 423.1 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
a6a947c60c5d7673d5d18b52f1010be314a66239dbed1becfa6dd27dbbe2ca5a
|
|
| MD5 |
e1053e6bdf13a78b320170bd2601a532
|
|
| BLAKE2b-256 |
57fdc363e95bff33c743aa7ef5a36e2afafd1c716e48cb53d9a1e5882fb80467
|
Provenance
The following attestation bundles were made for vmec_jax-0.0.1-py3-none-any.whl:
Publisher:
publish-pypi.yml on uwplasma/vmec_jax
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
vmec_jax-0.0.1-py3-none-any.whl -
Subject digest:
a6a947c60c5d7673d5d18b52f1010be314a66239dbed1becfa6dd27dbbe2ca5a - Sigstore transparency entry: 1334421166
- Sigstore integration time:
-
Permalink:
uwplasma/vmec_jax@531aa4073ee1ad3afdde0ea46c5abe929abfb8e1 -
Branch / Tag:
refs/tags/v0.0.1 - Owner: https://github.com/uwplasma
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish-pypi.yml@531aa4073ee1ad3afdde0ea46c5abe929abfb8e1 -
Trigger Event:
release
-
Statement type: