Optimization Sweep Results¶
This page collects the generated optimization sweep artifacts used by the README and the main optimization guide. The full regeneration target covers QA, QH, QP, and QI targets; checked-in artifacts are explicitly labeled when they are only partial snapshots:
QA: the reference omnigenity NFP=2 QA deck, aspect ratio target 5, signed mean iota target 0.42, and quasi-axisymmetry.
QH: the bundled NFP=4 warm start, aspect ratio target 5, quasi-helical symmetry, and a smooth
abs(mean_iota) >= 0.41lower bound.QP: aspect ratio target 5, quasi-poloidal symmetry, and a smooth
abs(mean_iota) >= 0.41lower bound, using the common minimal-seed workflow in the README examples.QI: aspect ratio target 5 in the full common-minimal regeneration target, a differentiable smooth Boozer-space quasi-isodynamic residual evaluated through
booz_xform_jax, maximum mirror-ratio penalty, maximum-LCFS-elongation penalty, and a smoothabs(mean_iota) >= 0.41lower bound.LgradBis available as an optional commented term in the example script but is not active by default. The historical compact best-row panel used the bundledinput.nfp2_QIomnigenity seed; the active public QI workflow now starts from minimal, circular-torus-like inputs and keeps any reference-family proposal explicit. The production CLI can optionally use a same-mode QP preseed; the current best gated QI row starts the constrained QI refinement directly from the seed with--qi-qp-preseed off.
Publication structure¶
The split between README and docs is deliberate:
README.mdshows the current reviewed NFP coverage compactly with figures only: the aspect-5,max_mode=5common-minimal QA/QH/QP GPU state panel plus the case-gated QI NFP=1/2/3/4 state panel. Numeric rows live below. The README does not claim missing uniform aspect-5 common-minimal QI rows.This page is the intended publication home for complete sweeps. A complete publication should represent every CPU/GPU, continuation/direct, ESS on/off, QI preseed/no-preseed,
max_mode=1..5reviewed row through downloadable CSV/JSON summaries plus generated objective-history panels, initial/final state atlases, and wall-time summary tables. Treat archivedmax_mode<=3snapshots as historical until matching aspect-5 rows and figures are present.Additional QI case coverage belongs here rather than in the README. Legacy far-seed rows remain useful diagnostics, but public QI optimization entry points now start from the minimal-seed NFP family.
Current README NFP Snapshot¶
The README figures correspond to the rows below. QA/QH/QP rows are current
common-minimal-seed GPU runs with continuation, ESS, and max_mode=5. The
QI panel is a reviewed, case-gated NFP snapshot: it keeps the user-facing input
deck visible and marks deterministic reference-family proposals explicitly
instead of claiming that every QI NFP row is already solved from one uniform
common-minimal policy.
Target |
NFP |
Evidence |
Backend |
Policy |
max_mode |
ESS |
Final J |
QI legacy |
Mirror |
Aspect |
Iota |
Wall time |
|---|---|---|---|---|---|---|---|---|---|---|---|---|
QA |
2 |
common minimal seed |
GPU |
continuation |
5 |
yes |
1.09e-04 |
5.000 |
0.4200 |
25.3 min |
||
QA |
3 |
common minimal seed |
GPU |
continuation |
5 |
yes |
4.21e-03 |
5.004 |
0.4201 |
17.3 min |
||
QH |
3 |
common minimal seed |
GPU |
continuation |
5 |
yes |
9.14e-04 |
5.000 |
-1.0474 |
17.4 min |
||
QH |
4 |
common minimal seed |
GPU |
continuation |
5 |
yes |
2.08e-03 |
5.000 |
-1.6951 |
24.6 min |
||
QP |
2 |
common minimal seed |
GPU |
continuation |
5 |
yes |
2.34e-02 |
5.001 |
-0.4177 |
16.7 min |
||
QP |
3 |
common minimal seed |
GPU |
continuation |
5 |
yes |
9.80e-02 |
5.024 |
-0.4144 |
14.7 min |
||
QI |
1 |
case-gated staged QI |
CPU |
staged |
case |
case |
1.56e-02 |
7.75e-04 |
0.242 |
9.999 |
0.5369 |
15.8 min |
QI |
2 |
case-gated staged QI |
CPU |
staged |
case |
case |
1.61e-02 |
5.25e-04 |
0.240 |
6.006 |
-0.5994 |
28.7 min |
QI |
3 |
case-gated staged QI |
CPU |
staged |
case |
case |
9.33e-02 |
1.01e-03 |
0.304 |
3.541 |
-1.0401 |
4.6 min |
QI |
4 |
case-gated staged QI |
CPU |
staged |
case |
case |
2.52e-02 |
2.54e-04 |
0.287 |
6.011 |
-1.2930 |
0.4 min |
Every published full-sweep result should provide these assets in the sweep
output tree or as GitHub release assets. Only compact, reviewed,
documentation-critical artifacts should be copied into docs/_static/figures:
qs_ess_summary_all.csvandqs_ess_summary_all.jsonwith all row diagnostics, including wall time, backend/device metadata, success/crash status, active policy, and output provenance.Objective history over all stages:
objective_panel_all_policies.png/.pdf, CPU/GPU policy subsets, LASYM variants when present, and the legacyobjective_panelaliases.Initial/final 3D and initial/final VMEC-angle LCFS
|B|atlases:initial_final_state_atlas_*.png/.pdf. Legacyfinal_state_atlas_*.png/.pdfaliases are compatibility copies only. The full-sweep atlas renderer uses VMECtheta/zetagrids fromvmecplot2_bmag_grid; do not describe these as Boozer-space atlases. Boozer-space line contours are limited to the compact README and dedicated QI case panels generated throughbooz_xform_jax.Wall-time and status table figures:
summary_tables_*.png/.pdfplus the CSV/JSON downloads above.Optional full report composites:
publication_panel_full.png/.pdfand LASYM variants.
The checked-in source tree currently contains the historical compact best-row
panels, the QI case-coverage snapshot, the minimal-seed showcase
objective/state panels, the constrained-QI status panel, and compact CSV/JSON
summary files.
qs_ess_summary_all.csv is a heterogeneous partial/archive snapshot: archived
CPU README QA/QH/QP rows plus one failed/partial constrained-QI status row,
older GPU/LASYM rows with incomplete target metadata, and no checked-in
max_mode>=4 rows. qi_constrained_summary.csv currently contains one CPU
max_mode=3 continuation status row. It does not currently contain the full
objective-history panels, initial/final state atlases, summary-table images, or
publication-panel composites.
Those assets must be regenerated locally, attached to a release, or compacted
and explicitly reviewed before claiming a complete full-sweep docs publication.
Individual Examples¶
Each standalone example keeps all user controls as top-level Python variables:
PYTHONPATH=. python examples/optimization/QA_optimization.py
PYTHONPATH=. python examples/optimization/QH_optimization.py
PYTHONPATH=. python examples/optimization/QP_optimization.py
PYTHONPATH=. python examples/optimization/QI_optimization.py
The QP script is quasisymmetry with HELICITY_M = 0. The QI script is a
different objective: it builds Boozer spectra with booz_xform_jax, improves
the smooth QI residual, and then adds mirror-ratio and LCFS-elongation
penalties. A commented LgradB block is included for users who want that
extra regularization term. The extra terms are imported from
vmec_jax.optimization_workflow and assembled explicitly in the script, so
users can change weights or add terms such as magnetic-well depth by appending
another residual block in the same section. QI examples use
booz_xform_jax, which is installed by the plain vmec-jax package and by
python -m pip install . from a source checkout.
Sweep Reproduction¶
Run the CPU production sweep:
PYTHONPATH=. JAX_PLATFORMS=cpu python examples/optimization/generate_qs_ess_sweep.py --backend-label cpu --solver-device cpu --policy continuation --problems qa,qh,qp,qi --modes 1,2,3,4,5 --ess both --qi-qp-preseed off --max-nfev 70 --continuation-nfev 25 --inner-max-iter 180 --inner-ftol 1e-9 --trial-max-iter 180 --trial-ftol 1e-9 --rerun
PYTHONPATH=. JAX_PLATFORMS=cpu python examples/optimization/generate_qs_ess_sweep.py --backend-label cpu --solver-device cpu --policy direct --problems qa,qh,qp,qi --modes 1,2,3,4,5 --ess both --qi-qp-preseed off --max-nfev 70 --continuation-nfev 25 --inner-max-iter 180 --inner-ftol 1e-9 --trial-max-iter 180 --trial-ftol 1e-9 --rerun
PYTHONPATH=. python examples/optimization/render_qs_ess_publication_panel.py
These commands describe the complete regeneration target, not the contents of
the checked-in snapshot. Do not cite a full max_mode>=4 CPU/GPU matrix until
the corresponding CSV/JSON rows and publication figures are present under
docs/_static/figures.
The historical compact figure renderer filters QI rows against the same
aspect-5 target as QA/QH/QP. The standalone QI_optimization.py
case-coverage lanes may still use case-specific aspect targets when mirror
ratio or far-seed basin capture is the experiment; those rows are documented
separately and are not mixed into the README figure snapshot.
The constrained QI study has one extra axis: whether the QI solve starts from a
same-mode QP preseed. The production CLI default is --qi-qp-preseed off;
regenerate the focused preseed/no-preseed matrix with:
PYTHONPATH=. JAX_PLATFORMS=cpu python examples/optimization/generate_qs_ess_sweep.py --backend-label cpu --solver-device cpu --policy continuation --problems qi --modes 1,2,3,4,5 --ess both --qi-qp-preseed both --max-nfev 70 --continuation-nfev 25 --inner-max-iter 180 --inner-ftol 1e-9 --trial-max-iter 180 --trial-ftol 1e-9 --rerun
PYTHONPATH=. JAX_PLATFORMS=cpu python examples/optimization/generate_qs_ess_sweep.py --backend-label cpu --solver-device cpu --policy direct --problems qi --modes 1,2,3,4,5 --ess both --qi-qp-preseed both --max-nfev 70 --continuation-nfev 25 --inner-max-iter 180 --inner-ftol 1e-9 --trial-max-iter 180 --trial-ftol 1e-9 --rerun
PYTHONPATH=. python examples/optimization/render_qi_constrained_sweep.py
The checked-in constrained-QI snapshot is not that full matrix; it currently
contains only a single CPU continuation max_mode=3 status row without a
same-mode QP preseed.
Seed-robust QI is a larger validation matrix than the tracked constrained-QI
snapshot and the checked-in NFP coverage panel. The constrained-QI matrix
artifacts use the bundled NFP=2 QI seed and optional same-mode QP preseed; the
separate README/docs NFP 1-4 panel uses case-gated source decks and
case-specific targets. Before documenting QI as robust to arbitrary starts,
run the constrained objective from QI, QP, QH, QA, and a simple
non-omnigenous boundary seed, then inspect both numerical gates and Boozer
|B| contour plots. Until those rows are generated and curated, treat the
full multi-seed matrix as deferred validation rather than a required
reproduction command.
Use the bounded seed preflight to choose and document starting points before launching that matrix:
PYTHONPATH=. python examples/optimization/audit_qi_seed_suitability.py --quick --csv results/qi_seed_audit.csv
PYTHONPATH=. python examples/optimization/audit_qi_seed_suitability.py --quick --smooth-qi-max 5e-3 --legacy-qi-max 2e-3 --csv results/qi_seed3127_audit.csv
The preflight ranks seeds by smooth-plus-legacy QI score and leaves mirror,
elongation, aspect, and iota gates as explicit columns. The second command
shows the relaxed smooth-gate convention used by the far-seed
qi_stel_seed_3127 optimization case. This is deliberate:
for QI robustness work, a seed that is already QI-like but violates mirror or
aspect slightly is usually more informative than a non-QI seed that satisfies
the engineering constraints.
To review the tiny QI-prefine probes before executing them:
PYTHONPATH=. python examples/optimization/audit_qi_seed_suitability.py --quick --prefine-probes plan --prefine-manifest results/qi_seed_audit/prefine_manifest.json --prefine-output-dir results/qi_seed_audit/prefine_probes
The dry-run manifest is the intended bridge between seed audit and full
seed-robust QI sweeps. It is bounded by design and should be inspected before
switching to --prefine-probes run.
The docs NFP=4 QI coverage lane starts from examples/data/input.minimal_seed_nfp4
with only RBC(0,0), RBC(0,1), and ZBS(0,1) in the source input,
then applies a same-NFP finite-beta QI reference-family preconditioner before
bounded local cleanup. Treat the NFP=4 QH-warm and finite-beta QI variants as
stress fixtures unless their independent diagnostics.json records a reviewed
smooth/legacy QI and mirror-ratio gate pass; run them through
QI_optimization.py with explicit --input-file, --reference-input,
and --output-dir overrides rather than legacy environment variables.
Run the GPU production sweep on a machine with a working JAX GPU install:
PYTHONPATH=. JAX_PLATFORM_NAME=gpu python examples/optimization/generate_qs_ess_sweep.py --backend-label gpu --solver-device gpu --policy continuation --problems qa,qh,qp,qi --modes 1,2,3,4,5 --ess both --qi-qp-preseed off --max-nfev 70 --continuation-nfev 25 --inner-max-iter 180 --inner-ftol 1e-9 --trial-max-iter 180 --trial-ftol 1e-9 --rerun
PYTHONPATH=. JAX_PLATFORM_NAME=gpu python examples/optimization/generate_qs_ess_sweep.py --backend-label gpu --solver-device gpu --policy direct --problems qa,qh,qp,qi --modes 1,2,3,4,5 --ess both --qi-qp-preseed off --max-nfev 70 --continuation-nfev 25 --inner-max-iter 180 --inner-ftol 1e-9 --trial-max-iter 180 --trial-ftol 1e-9 --rerun
PYTHONPATH=. python examples/optimization/render_qs_ess_publication_panel.py
Render the historical compact best-row panels from the best stellarator-symmetric rows:
PYTHONPATH=. python examples/optimization/render_readme_best_optimizations.py
The default per-case timeout is 1800 seconds. The current README science
configs use NFP=4 for QH, aspect target 5 for QA/QH/QP/QI, signed iota
0.42 for QA, and high-priority abs(mean_iota) >= 0.41 constraints for
QH/QP/QI.
They use inner_max_iter = trial_max_iter = 120 and
ftol = trial_ftol = 1e-9; GPU production sweeps cap those values at 180
if a future problem config requests a larger replay budget. Add
--diagnostic-budgets only for bounded quick-look GPU diagnostics, and use
--case-timeout-s 0 only for unbounded local diagnostics.
On timeout, the sweep driver terminates the worker process group as well as
direct children, so stale descendant solver or GPU processes should not survive
after a recorded timeout row.
Before each long QI stage, the runner writes a pending
stage_checkpoint.json beside the case output. After a stage solve returns,
it writes a pre-diagnostic checkpoint, materializes root-level
input.initial and input.final files from the selected exact accepted
point, and then writes the exact-diagnostic promotion checkpoint. Timeout and
worker-failure rows are annotated from the latest checkpoint when possible,
preserving the last accepted objective, aspect, iota, QI, mirror, elongation,
wall time, and stage label in case_result.json and the CSV summaries. Treat
these checkpoint-derived rows as partial diagnostics; publication and README
promotion still require the independent physics gates and reviewed Boozer
contour plots.
Run the non-stellarator-symmetric sweep by adding
--stellarator-asymmetric. This sets LASYM = T in memory, includes
RBS and ZBC boundary degrees of freedom, seeds initially-zero
asymmetric modes with 1e-7, and writes separate outputs under the
asymmetric backend subdirectory.
PYTHONPATH=. JAX_PLATFORMS=cpu python examples/optimization/generate_qs_ess_sweep.py --backend-label cpu --solver-device cpu --policy continuation --problems qa,qh,qp,qi --modes 1,2,3,4,5 --ess both --qi-qp-preseed off --stellarator-asymmetric --max-nfev 70 --continuation-nfev 25 --inner-max-iter 180 --inner-ftol 1e-9 --trial-max-iter 180 --trial-ftol 1e-9 --rerun
PYTHONPATH=. JAX_PLATFORMS=cpu python examples/optimization/generate_qs_ess_sweep.py --backend-label cpu --solver-device cpu --policy direct --problems qa,qh,qp,qi --modes 1,2,3,4,5 --ess both --qi-qp-preseed off --stellarator-asymmetric --max-nfev 70 --continuation-nfev 25 --inner-max-iter 180 --inner-ftol 1e-9 --trial-max-iter 180 --trial-ftol 1e-9 --rerun
PYTHONPATH=. JAX_PLATFORM_NAME=gpu python examples/optimization/generate_qs_ess_sweep.py --backend-label gpu --solver-device gpu --policy continuation --problems qa,qh,qp,qi --modes 1,2,3,4,5 --ess both --qi-qp-preseed off --stellarator-asymmetric --max-nfev 70 --continuation-nfev 25 --inner-max-iter 180 --inner-ftol 1e-9 --trial-max-iter 180 --trial-ftol 1e-9 --rerun
PYTHONPATH=. JAX_PLATFORM_NAME=gpu python examples/optimization/generate_qs_ess_sweep.py --backend-label gpu --solver-device gpu --policy direct --problems qa,qh,qp,qi --modes 1,2,3,4,5 --ess both --qi-qp-preseed off --stellarator-asymmetric --max-nfev 70 --continuation-nfev 25 --inner-max-iter 180 --inner-ftol 1e-9 --trial-max-iter 180 --trial-ftol 1e-9 --rerun
PYTHONPATH=. python examples/optimization/render_qs_ess_publication_panel.py
For NVIDIA-only JAX installations, JAX_PLATFORMS=cuda is also valid. Do
not use JAX_PLATFORMS=gpu: some JAX versions interpret that as both CUDA
and ROCm and fail if ROCm is not installed.
Historical Compact Best Rows¶
The four compact readme_best_optimization_*.png panels below are retained
as historical aspect-6/mode-3 comparison artifacts. The active README no
longer uses them as the primary optimization evidence; it uses the refreshed
common-minimal QA/QH/QP state panel and the reviewed QI NFP case panel.
When replacing these historical panels, select rows from the reviewed matrix
and filter against the common aspect-5 target. The selected QI row should be
chosen with the legacy branch diagnostic, mirror-ratio, elongation, iota, and
aspect-ratio gates used as promotion evidence rather than as exact equality
constraints; small numerical slack is expected when independent Boozer
diagnostics are recomputed after the optimization. The archived source table
is available as
readme_best_optimizations.csv.
QI_optimization Input Coverage¶
The dedicated QI docs renderer is a lightweight snapshot renderer for
case-gated QI lanes; it does not rerun optimization jobs. The current rows are
the NFP=1 QI seed deck, the NFP=2 target-helicity seed deck, the NFP=3
seed-3127 deck, and the NFP=4 minimal-seed lane. This figure is separate from
the deferred
common-minimal-seed stress matrix and should not be read as evidence that one
common simple seed optimizes successfully for every NFP. The renderer reads
the existing QI_optimization.py outputs, records the final smooth QI
metric, legacy QI metric, mirror ratio, elongation, iota, aspect, and CPU wall
time, and draws source-initial and final Boozer |B| line contours only
after the initial WOUT boundary matches the paired input deck. These are
archived mixed-target case checks, not current aspect-5 README best-row
promotions: NFP=1 uses target aspect 10, the NFP=2 target-helicity lane uses
target aspect 6, the seed-3127 NFP=3 lane uses target aspect 4, and the NFP=4
row uses the minimal seed plus a same-NFP finite-beta QI reference-family
proposal. Regenerate all rows with the current uniform aspect-5 policy before
using this figure as current README promotion evidence.
Finite-beta NFP=4 remains a separate stress fixture.
The NFP=3 seed-3127 row uses
examples/data/wout_QI_stel_seed_3127.nc as the raw initial artifact. The
renderer validates it against examples/data/input.QI_stel_seed_3127 under
the direct VMEC input convention or VMEC’s equivalent canonical phase
convention, and fails if neither boundary map matches; there is no
known-artifact exception bypass.
For lanes with a reference-family preconditioner, the plotted initial panel is
still the raw/source input WOUT and the plotted final panel is the accepted
audited WOUT; preconditioner scan points are provenance for basin capture, not
the final acceptance diagnostic.
To refresh the exact rows used by this panel, run the source optimizations with
explicit command-line overrides before rendering. The example below regenerates
the current uniform aspect-5 minimal-seed policy for NFP=1/2/3/4. Named
far-seed cases such as qi_stel_seed_3127 remain explicit diagnostics. If
any raw artifact is replaced during a refresh, the replacement must pass the
renderer boundary match before the panel is published.
for nfp in 1 2 3 4; do
PYTHONPATH=. JAX_PLATFORMS=cpu python examples/optimization/QI_optimization.py \
--input-file examples/data/input.minimal_seed_nfp${nfp} \
--output-dir results/qi_opt/ess/minimal_nfp${nfp}_qi \
--target-aspect 5 --target-abs-iota-min 0.41 \
--max-mode 5 --max-nfev 70 --continuation-nfev 20 \
--inner-max-iter 450 --inner-ftol 1e-9 \
--trial-max-iter 450 --trial-ftol 1e-9 \
--ess-alpha 1.2 --use-ess --use-mode-continuation \
--stage-mode-policy lower
done
PYTHONPATH=. python examples/optimization/render_qi_readme_cases.py
The optimization commands above create candidate result directories under
results/. After reviewing diagnostics and plots, replace the corresponding
docs/_static/qi_readme_cases/<case>/ bundle before rendering; the renderer
does not read ignored local result directories.
Input |
Output/provenance |
Final J |
Smooth QI |
Legacy QI |
Mirror |
Elong. |
Aspect |
Iota |
CPU min |
Status |
|---|---|---|---|---|---|---|---|---|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Source table snapshot:
readme_qi_optimization_cases.csv.
In that generated CSV, validation_status=case-gated records
case-specific QI gate status from the renderer and should not be read as
aspect-5 README best-row promotion evidence or global seed-robustness
evidence; the NFP=4 row is case-gated by the minimal-seed plus same-NFP
reference-family path. The NFP=3 raw initial artifact is now checked by the
renderer instead of accepted through a case-specific exception.
Regenerate these lightweight artifacts with:
PYTHONPATH=. python examples/optimization/render_qi_readme_cases.py
This renderer intentionally consumes the curated
docs/_static/qi_readme_cases bundle instead of ignored local
results/ directories. Large WOUT files in that bundle are ignored by git
and must be fetched as release assets or regenerated before rerendering from a
clean clone. Raw per-stage history.json files are kept in git for
auditing non-monotone or stalled optimizer stages; the public panel plots
normalized best-so-far traces for readability.
The bundled preconditioner summaries are also scrubbed to scalar scan metrics
and selected-lambda flags so the tracked release artifacts do not point at
local scratch directories from the run host.
The staged objective panel concatenates every recorded history file used by the selected case-specific result. It plots the best-so-far value in each stage, normalized to that stage’s first objective, with dashed separators marking objective-definition or weight changes. For the seed-3127 lane, the inset is a boundary-reference interpolation scan, not an optimizer trajectory.
Minimal-Seed Showcase Snapshot¶
The minimal-seed showcase is a bounded stress/reproduction lane for the common three-coefficient input family, not a README table. The checked-in assets are:
minimal_seed_showcase_objective_panel.pngminimal_seed_showcase_state_panel.png
The summary CSV is provenance-aware: initial_input records the raw
user-facing minimal seed and initial_wout is populated when the state panel
was refreshed from the same result root,
stage_seed_kind and stage_seed_input identify any target-helicity or
reference-family preseed used by the optimizer, and final_wout identifies
the promoted final output. This prevents a continuation or staged-QI
input.initial file from being silently displayed as the raw seed.
Those checked-in assets currently document the minimal-seed showcase snapshot as follows:
Case |
Problem |
NFP |
Status |
Completion |
Release interpretation |
|---|---|---|---|---|---|
|
QA |
2 |
|
success |
Current aspect-5, |
|
QA |
3 |
|
success |
Current aspect-5, |
|
QH |
3 |
|
success |
Current aspect-5, |
|
QH |
4 |
|
success |
Current aspect-5, |
|
QP |
2 |
|
success |
Current aspect-5, |
|
QP |
3 |
|
success |
Current aspect-5, |
Current non-stale common-minimal QI outputs for minimal_nfp1_qi,
minimal_nfp2_qi, minimal_nfp3_qi, and minimal_nfp4_qi are not
present in the checked-in summary. Do not infer a successful QI
minimal-seed reproduction from the older qi_circular_nfp1 partial row or
from the separate QI NFP coverage panel above. The NFP coverage panel uses
reviewed case-gated QI inputs and, for NFP=4, a minimal seed plus a same-NFP
finite-beta QI reference-family basin-capture step; it is not the same artifact
as the common-minimal showcase.
Regenerate the current aspect-5 common-minimal showcase with:
PYTHONPATH=. JAX_PLATFORMS=cuda python3 examples/optimization/generate_minimal_seed_showcase.py \
--cases qa_nfp2,qa_nfp3,qh_nfp3,qh_nfp4,qp_nfp2,qp_nfp3,qi_nfp1,qi_nfp2,qi_nfp3,qi_nfp4 \
--backend-label gpu --solver-device gpu --worker-jax-platforms cuda \
--policy continuation --max-mode 5 --ess on \
--max-nfev 70 --continuation-nfev 20 \
--inner-max-iter 550 --inner-ftol 1e-10 \
--trial-max-iter 550 --trial-ftol 1e-10 \
--ess-alpha 1.2 --case-timeout-s 7200 --rerun
PYTHONPATH=. python examples/optimization/render_minimal_seed_showcase.py --publication-matrix
For bounded smoke rendering of a partial run, use --cases and
--skip-missing so the renderer validates the selected case but does not
warn about the rest of the production matrix:
PYTHONPATH=. python examples/optimization/render_minimal_seed_showcase.py \
--output-root /path/to/minimal_seed_showcase \
--figure-dir /path/to/figures \
--cases qi_nfp1 --skip-missing
Use cpu for the three CUDA/GPU flags for a slower local CPU-only
reproduction. Keep --rerun for release reproduction. Without it, successful
showcase_case.json rows may be reused from an older local run; the renderer
skips known-stale rows by default and --include-stale should be used only
for debugging. The renderer writes both a compact objective-history panel and,
when the required WOUT artifacts are available, a state panel with the raw
user-facing seed LCFS, final LCFS, initial Boozer |B| line contours, final
Boozer |B| line contours, and the full best-so-far objective history.
Rows without non-stale initial/final WOUT provenance are omitted from that
state panel instead of being silently replaced by stale artifacts.
Objective Histories¶
When regenerated, the all-policy panel contains every available backend/policy
row. Solid curves met the optimizer success criterion; dashed curves are
stopped, failed, or budgeted lanes. The summary tables distinguish
max_nfev stops from bounded per-case timeouts and GPU-memory failures. Curves
are split by objective stage and plotted as best-so-far values within that
stage, so QP preseed and full constrained QI refinement are not treated as one
continuous scalar objective. Vertical dotted lines mark continuation stage
boundaries.
Constrained QI Matrix¶
The constrained QI renderer can compare CPU and available GPU rows for
max_mode = 1..5, ESS on/off, continuation/direct, and QP-preseed on/off
using the public NFP=2 minimal seed. The checked-in constrained snapshot is
partial: it contains one CPU continuation max_mode=3 status row and no GPU,
direct, or QP-preseed constrained-QI rows. Rerun the commands above to
populate the full CPU/GPU/direct/asymmetric matrix under the current objective
policy. For each requested max_mode, deterministic target-helicity hints
are added when needed and the input boundary is projected onto
max(abs(m), abs(n)) <= max_mode before the stage is built.
The QI objective is intentionally not ranked by scalar objective alone: rows
are also evaluated by the legacy branch-squash/stretch/shuffle diagnostic,
raw smooth QI residual, maximum mirror ratio, maximum LCFS elongation,
abs(mean_iota) >= 0.41, and the active aspect target. The default smooth QI
objective includes shuffle_profile_weight = 1.0 so the optimizer follows
the same ranking as the legacy diagnostic on the seed and reference
omnigenity cases. Rows that stop at max_nfev but have valid VMEC solves
and satisfy the physics gates are kept as valid stopped rows.
The checked-in target-6 constrained-QI artifact is an archived partial status
snapshot, not the promoted QI result. At the moment it contains the bounded
partial continuation row annotated from stage_checkpoint.json before full
QI diagnostics were available. It is a status artifact and must not be
promoted as current aspect-5 evidence. The README best QI row should be
replaced only after the full constrained CPU/GPU matrix is rerun and passes the
same QI, mirror, elongation, iota, and aspect gates.
Downloadable constrained-QI summaries:
The checked-in archived README QI row is the CPU qi_default standalone
QI_optimization.py lane, max_mode=3, ESS row without a same-mode QP
preseed: legacy-ranked QI diagnostic 4.31e-4, smooth QI diagnostic
1.32e-3, maximum mirror ratio 0.272 for a target 0.30, maximum
elongation 6.90 for a target 8.2, aspect ratio 6.002, mean iota
-0.5690, and total wall time 10.9 min. It is not current aspect-5
promotion evidence. Best-row selection uses
vmec_jax.qi_promotion_score: raw-fallback legacy diagnostics are rejected,
rows above the loose 2e-2 QI promotion ceiling cannot win solely by having
good mirror/elongation, and engineering-clean rows are preferred over lower-QI
rows only when they remain QI-like.
The constrained matrix is a bundled-QI-seeded lane, not evidence that the
optimizer is seed-robust across unrelated QA/QH/QP/simple starts.
Non-stellarator-symmetric LASYM runs use the same script with
--stellarator-asymmetric. The current LASYM artifacts are intentionally
published as partial bounded-time lanes. Timeout and OOM rows are kept because
they document the current cost envelope of the asymmetric exact/replay path.
The checked-in summary snapshot has 23 CPU LASYM rows and 36 GPU LASYM rows.
The objective-history figures are generated artifacts and are not part of the
current checked-in snapshot. Regenerate them with
PYTHONPATH=. python examples/optimization/render_qs_ess_publication_panel.py
after producing or fetching the sweep results. For a complete docs
publication, keep bulky reviewed outputs in the local result tree or attach
them to a GitHub release; promote only compact documentation-critical assets to
docs/_static/figures and keep the CSV/JSON summaries in sync. The renderer
writes:
objective_panel_all_policies.png/.pdfobjective_panel_cpu_policies.png/.pdfobjective_panel_gpu_policies.png/.pdfobjective_panel_asymmetric_all_policies.png/.pdflegacy aliases
objective_panel.png/.pdf
Initial/Final State Atlases¶
The initial/final state atlases show the initial and final LCFS plus line
contours of |B| on the LCFS in VMEC theta/zeta coordinates.
Each 3-D panel has its own colorbar because the aspect-ratio constraint changes
the absolute |B| range. These are not Boozer-coordinate atlases; the full
sweep renderer gets the contour grid from vmecplot2_bmag_grid.
Partial LASYM atlases are rendered separately. Missing or failed lanes are
shown as placeholders, while successful lanes include one colorbar per 3-D
surface and one colorbar per LCFS |B| contour panel.
When generated, atlas filenames include:
initial_final_state_atlas_continuation.png/.pdfinitial_final_state_atlas_direct.png/.pdfinitial_final_state_atlas_cpu_continuation.png/.pdfinitial_final_state_atlas_cpu_direct.png/.pdfinitial_final_state_atlas_gpu_continuation.png/.pdfinitial_final_state_atlas_gpu_direct.png/.pdfinitial_final_state_atlas_asymmetric_*legacy alias
geometry_atlas.png/.pdf
No initial_final_state_atlas_*.png/.pdf files are currently checked in.
Summary Tables¶
The summary-table image is intended for reports and presentations and must include wall-time/status fields for full-sweep publication. The CSV and JSON are better for analysis scripts and remain the source of truth.
Downloadable summaries:
Generated summary-table figures include summary_tables_all_policies,
summary_tables_cpu_policies, summary_tables_gpu_policies,
summary_tables_asymmetric_all_policies, and legacy alias
summary_table.
Publication Panel¶
The full panel combines objective histories, initial/final state atlases, and summary tables. It is large by design and should be used for review, not as the only README figure.
Generated full-panel filenames include publication_panel_full.png/.pdf,
legacy alias publication_panel.png/.pdf, and
publication_panel_asymmetric_full.png/.pdf for the partial LASYM lanes.
Finite-beta Stage-One Examples¶
The finite-beta examples mirror the VMEC-only stage-one reference workflow from
the separate single_stage_optimization_finite_beta scripts without SIMSOPT
or coils:
PYTHONPATH=. python examples/optimization/qa_optimization_finite_beta.py
PYTHONPATH=. python examples/optimization/qh_optimization_finite_beta.py
PYTHONPATH=. python examples/optimization/qi_optimization_finite_beta.py
The input decks are bundled as:
examples/data/input.nfp2_QA_finite_betaexamples/data/input.nfp4_QH_finite_betaexamples/data/input.nfp4_QI_finite_beta
Each script builds the optimization problem explicitly: load the VMEC input,
construct FiniteBetaTargets, define the global residuals for aspect ratio,
iota lower/mean/upper bounds, volume-averaged field proxy, and total beta, then
append the field-quality residual. QA/QH use quasisymmetry residuals and QI
uses the smooth Boozer-space QI residual. The small shared helper only keeps
the stage bookkeeping, structured stage/final summaries, and artifact writing
consistent. After the direct FixedBoundaryExactOptimizer calls complete,
stage1_result.stage_summaries and stage1_result.final_summary expose
JSON-friendly diagnostics such as objective, aspect, iota, function counts,
termination status, method, device, and wall time. The scripts save
input.initial, input.final, wout_initial.nc, wout_final.nc, and
history.json for each run.
The pressure/current-profile setup follows the SIMSOPT finite-beta bootstrap
workflow. At the top of each script, BETA_PERCENT defines a standard
profile bundle through vj.standard_finite_beta_profiles:
ne = ne0 * [1, 0, 0, 0, 0, -0.99],
Te = Te0 * [1, -0.99], ni=ne, Ti=Te, Zeff=1, and
pressure_pa = e * (ne*Te + ni*Ti). vj.with_pressure_profile writes
the pressure into the VMEC deck, while the Redl bootstrap-current residual
uses the same density/temperature coefficients. This is the recommended path
for tokamak, QA, QH, QP, QI, and LP-QA finite-beta runs because it avoids
handwritten pressure scales that can drift away from the bootstrap-current
profile.
These examples deliberately remain one layer lower than
least_squares_solve. The ordinary QA/QH/QP/QI scripts are the recommended
objective-tuple API examples; finite-beta stage one keeps direct
FixedBoundaryExactOptimizer calls visible so users can see the custom
finite-pressure/current residual closures, stage-local profile data, and
optional bootstrap-current residual wiring.
All finite-beta controls are plain variables at the top of the scripts. For
QI, QI_MBOZ, QI_NBOZ, QI_NPHI, QI_NALPHA, and
QI_N_BOUNCE control the Boozer/QI residual grid. MAX_MIRROR_RATIO and
MAX_ELONGATION control the two engineering penalties. The default QI grid
is small enough for first-run diagnostics; increase it for final
research-quality QI runs. QI_OPTIONS.phimin controls the start of the
one-field-period well interval; keep 0.0 for the bundled NFP=2 seed, or set
np.pi / nfp when auditing a reference field whose first well starts there.
Redl bootstrap-current mismatch is now available as vj.RedlBootstrapMismatch.
The implementation ports the SIMSOPT/Redl et al. bootstrap algebra and uses a
differentiable VMEC-state geometry approximation with fixed trapped-fraction
quadrature on nearest full-mesh surfaces. Mercier DMerc is also available
as vj.DMerc, a smooth lower-bound objective backed by the differentiable
mercier_terms_from_state path for stellarator-symmetric and LASYM
equilibria. VMEC/JXBFORCE profile accessors vj.JDotB, vj.BDotB and
vj.BDotGradV are also available for finite-beta targeting or
regularization, together with state-derived vj.ToroidalCurrent and
vj.ToroidalCurrentGradient current-profile objectives. Advanced vector
targeting is available through vj.BVector for Cartesian magnetic field on a
single radial surface and vj.JVector for flattened VMEC-coordinate
(J^theta, J^zeta) current-density components. The JAX
mercier_gpp_from_realspace_geometry,
mercier_surface_integrals_from_realspace, and
mercier_terms_from_profile_integrals helpers now cover the VMEC-style
geometry channel, surface reductions, and algebraic
DMerc = DShear + DCurr + DWell + DGeod step once real-space field channels
are available. mercier_realspace_geometry_channels_from_state,
mercier_bsubs_half_mesh_from_geometry,
mercier_zeta_half_mesh_from_realspace_geometry,
mercier_bsubs_full_mesh_from_half_mesh,
mercier_bsubs_derivatives_lasym_false, and
mercier_bdotk_from_covariant_derivatives also port state synthesis of the
even/odd geometry channels, half-mesh toroidal geometry, radial covariant field
assembly, jxbforce full-mesh averaging, stellarator-symmetric derivative
reconstruction, LASYM derivative reconstruction, itheta/izeta/bdotk,
jdotb/bdotb/bdotgradv profile blocks, and torcur/ip current-profile
blocks. The RUN_FULL=1 finite-beta test suite compares this state-level
path against the existing VMEC/wout Mercier/JXBFORCE implementation on the
bundled finite-beta QI input. The next finite-beta validation lane is comparing
the new Redl residual against SIMSOPT’s Boozer-geometry and VMEC-geometry Redl
paths on converged finite-beta equilibria.