Applications and Examples¶
NEO_JAX is designed both as a production solver for Boozer-coordinate transport analysis and as a building block for optimization, design-space exploration, and differentiable workflows.
Example scripts¶
The repository ships executable examples in examples/:
Script |
Purpose |
|---|---|
|
Computes \(\epsilon_{\mathrm{eff}}^{3/2}\) on an NCSX fixture and plots the radial profile. |
|
Demonstrates forward-mode differentiation with respect to a simple geometric scalar. |
|
Uses autodiff on a toy magnetic-field scaling problem. |
|
Combines effective ripple with aspect-ratio objectives in a warm-start optimization setting. |
|
Runs the in-memory VMEC→Boozer→NEO workflow without intermediate files. |
Typical research uses¶
NEO_JAX is well suited to:
radial scans of \(\epsilon_{\mathrm{eff}}^{3/2}\) on a fixed equilibrium
design comparisons across Boozer or VMEC equilibria
sensitivity analysis of ripple to geometry or current-profile changes
gradient-based optimization where a differentiable approximation is useful
automated studies in which the Python API is more convenient than text-file orchestration
solver benchmarking across CPU, GPU, JIT, and Fourier-evaluation modes
Example: radial survey from a Boozer file¶
from neo_jax import NeoConfig, run_neo
config = NeoConfig(
surfaces=[0.1, 0.2, 0.4, 0.6, 0.8],
theta_n=96,
phi_n=96,
npart=64,
multra=2,
)
results = run_neo("boozmn.nc", config=config)
for s, eps in zip(results.s, results.epsilon_effective):
print(f"s={s:.3f} eps_eff^(3/2)={eps:.6e}")
Example: in-memory pipeline¶
from neo_jax import NeoConfig, run_vmec_boozer_neo
config = NeoConfig(surfaces=[0.3, 0.5, 0.7], theta_n=64, phi_n=64)
results = run_vmec_boozer_neo(
"input.vmec",
vmec_kwargs=dict(max_iter=1, use_initial_guess=True, vmec_project=False),
booz_kwargs=dict(mboz=12, nboz=12),
neo_config=config,
)
Optimization and autodiff¶
The main autodiff use cases in the repository are deliberately simple and transparent:
changing a scalar geometry parameter and differentiating the resulting \(\epsilon_{\mathrm{eff}}^{3/2}\)
reusing a prebuilt JAX solver inside an outer optimization loop
studying tradeoffs between ripple and secondary geometric objectives
For repeated solves, prefer neo_jax.build_vmec_boozer_neo_jax() so the
static geometry setup is compiled once and reused:
from neo_jax import NeoConfig, build_vmec_boozer_neo_jax
solve = build_vmec_boozer_neo_jax(
run,
booz_kwargs=dict(mboz=10, nboz=10),
neo_config=NeoConfig(surfaces=[0.5]),
jit=True,
)
outputs = solve(run.state)
Comparison workflows¶
NEO_JAX also supports direct comparison against existing output decks and reference cases when that is scientifically useful. Those comparisons are documented in Validation and Testing and CI; they are intended as evidence for correctness, not as the primary framing of the code.