----------------------------------------------------
| ██╗██╗ ██╗ ██╗ █████╗ ██████╗ |
| ██║██║ ██║ ██║██╔══██╗██╔══██╗ |
| ██║██║ ██║ ██║███████║██║ ██║ |
| ██║██║ ██║ ██║██╔══██║██║ ██║ |
| ██║██████╗██████╗██║██║ ██║██████╔╝ |
| ╚═╝╚═════╝╚═════╝╚═╝╚═╝ ╚═╝╚═════╝ |
| ILlinois Lagrangian Ion Advection and Deposition |
----------------------------------------------------
ILLIAD ( ILlinois Lagrangian Ion Advection and Deposition) is a Python modeling framework for reconstructing three-dimensional magnetic and electrostatic fields and simulating trace impurity-ion transport through the scrape-off layer (SOL).
The code was developed for lithium evaporation experiments in the HIDRA stellarator at the University of Illinois Urbana-Champaign. ILLIAD connects reconstructed HIDRA fields to kinetic particle tracing so wall-deposition patterns can be compared with magnetic topology, background-plasma models, and lithium ion dynamics.
The current source tree identifies as version 1.1.0; this does not by itself
indicate that a Git tag or package release has been published. Version 1.0.0
established the supported command names and JSON configuration interface
documented in docs/PUBLIC_API.md. Version 1.1.0 adds
package-native SOL density and potential construction, regularization, and a
bounded-memory unified connection-length workflow. See
CHANGELOG.md for the release summary.
- Reconstruct HIDRA vacuum magnetic fields from coil geometry with Biot-Savart integration and fitted field corrections.
- Trace field lines, generate Poincare sections, identify the last closed flux surface (LCFS), and diagnose low-order island chains from measured rotational transform.
- Integrate toroidal flux and interpolate normalized interior profiles with independent 2-D or periodically wrapped local 3-D RBF fits.
- Trace open SOL field lines on CPU or CUDA with the PyTorch-backed
SOLTracer, retaining compact plane-sorted crossing data, and regularize saved crossings onto the package-standard scalar-field mesh. - Generate a Cartesian electric field from either a newly interpolated flux profile or an existing regular scalar field.
- Advance lithium ions with a Boris-Buneman full-orbit pusher, optional ion-neutral and ion-ion collisions, wall termination, trace capture, and deposition diagnostics.
-
illiad/cli/: adapters behind the installed commands. -
illiad/sol/: official SOL tracing, regularization, profile, and shared LCFS analyses. -
illiad/flux/: flux calculation, interpolation, and gradient analyses. -
illiad/mesh/: NumPy-backedMeshand PyTorch-backedTorchMeshclasses. -
illiad/: Poincare, Boris, collision, particle, IO, and plotting code. -
run*.py: thin source-checkout launchers for installed command modules. -
misc_scripts/: source-only research and plotting scripts. They are not installed and are not public API. -
input_files/*.example.json: tracked configuration templates. -
input_files/: tracked reference inputs plus ignored local JSON overrides and generated scientific data. -
output/: generated logs, arrays, and plots. -
fastplotlib_tests/: standalone interactive trace viewers.
Release artifact contents are summarized in
docs/RELEASE_CONTENTS.md.
ILLIAD requires Python 3.11. Current development uses NumPy 2.3.1, SciPy 1.16.0, Matplotlib 3.10.3, pandas 2.3.1, tqdm 4.67.1, PyTorch 2.7.1, Pillow, and torchrbf. Production-size SOL and ion tracing are intended for a CUDA-capable GPU, although supported analyses can fall back to CPU.
From a source checkout:
python3 -m venv .venv
source .venv/bin/activate
pip install torch==2.7.1 --index-url https://download.pytorch.org/whl/cu126
pip install -e .Replace cu126 with the appropriate PyTorch build for the local system.
Optional fitting, viewer, and export dependencies are available as extras:
pip install -e ".[fitting,viewer,export]"Ten active workflow commands use JSON inputs:
illiad-fieldsolver --inputs input_files/fieldsolver_inputs.example.json
illiad-poincare --inputs input_files/poincare_inputs.example.json
illiad-flux-calc --inputs input_files/flux_calc_inputs.example.json
illiad-flux-grad --inputs input_files/flux_grad_inputs.example.json
illiad-sol-trace --inputs input_files/sol_trace_inputs.example.json
illiad-sol-regularize --inputs input_files/sol_regularize_inputs.example.json
illiad-sol-connection-length trace_regularize --inputs input_files/sol_connection_length_inputs.example.json
illiad-sol-density --inputs input_files/sol_density_inputs.example.json
illiad-sol-potential --inputs input_files/sol_potential_inputs.example.json
illiad-boris --inputs input_files/boris_inputs.example.jsonThe tracked templates may be passed directly to their commands, although
analyses still require their documented upstream field or run data. Before
customizing a template, copy it to the same directory without .example:
cp input_files/poincare_inputs.example.json input_files/poincare_inputs.json
illiad-poincare --inputs input_files/poincare_inputs.jsonWorking *.json files are ignored by Git. This keeps run-specific settings
out of commits without hiding the release templates.
Each active command also accepts the JSON path positionally:
illiad-poincare input_files/poincare_inputs.jsonSupply either the positional path or --inputs, but not both.
All relative inputs and the output/ tree are resolved from the process
working directory. The preferred Python imports include:
from illiad.io import IOHandler
from illiad.mesh import Mesh, TorchMesh
from illiad.flux import FluxCalculator, FluxInterpolator, FluxGradientor
from illiad.sol import SOLDensity, SOLPotential, SOLRegularizer, SOLTracerSee docs/PUBLIC_API.md for command and configuration
contracts and docs/PUBLIC_NAMESPACE.md for
public imports.
Start from input_files/poincare_inputs.example.json and copy it before
changing run-specific values:
illiad-poincare --inputs input_files/poincare_inputs.example.jsonThe command saves Poincare planes, wall intersections, plots, and a log under
output/<OUTPUT_DIR>/. Downstream analyses read the selected LCFS.
Configure ANLYS_DIR, ANLYS_SUBDIR, LCFS_INDEX, and sampling in
input_files/flux_calc_inputs.example.json or an ignored working copy:
illiad-flux-calc --inputs input_files/flux_calc_inputs.example.jsonIsland detection measures rotational transform from ordered Poincare
crossings, compares it with low-order rational values whose denominator is no
larger than MAX_SUBSETS, and splits matched chains with strided subsets.
ISLAND_ALGORITHM and HIST_BINS remain accepted legacy inputs but no longer
select the active detector.
illiad-flux-grad --inputs input_files/flux_grad_inputs.example.jsonWith RUN_INTERPOLATOR set to true, FLUX_INTERPOLATION_MODE selects
independent 2d fits or a periodically wrapped local 3d fit. The
interpolator writes a float64 nField_<OUTPUT_FILE_NAME>.npy, and the gradient
stage writes Efield_<OUTPUT_FILE_NAME>.npy using periodic centered angular
derivatives in radians.
To generate an electric field from an existing regular scalar field, set
RUN_INTERPOLATOR to false and set INPUT_FIELD_NAME to a path relative to
output/<ANLYS_DIR>/data/.
Configure the magnetic field, LCFS, seed grid, integration, device, and plots
in input_files/sol_trace_inputs.example.json or an ignored working copy:
illiad-sol-trace --inputs input_files/sol_trace_inputs.example.jsonSOLTracer samples exterior seed points, traces both field directions until
the wall or configured length limit, and captures crossings at regular
toroidal planes. The trace path continuously appends packed records under
raw_crossings/, publishes its manifest only after a successful trace, and
retains plane_phi_deg.npy, fieldline_connection_length_m.npy, seed,
directional, and wall-hit metadata. The reader also remains compatible with
the earlier monolithic NumPy representation.
Regularize those saved crossings onto the flux-compatible
(phi, theta, rho) mesh with:
illiad-sol-regularize --inputs input_files/sol_regularize_inputs.example.jsonSOLRegularizer reads each toroidal plane through a bounded chunk interface,
averages finite positive samples at their nearest regular-grid nodes, and
fills unsampled exterior cells in seam-free poloidal (x, z) coordinates.
It writes connection_length_field_m.npy and its coordinate arrays for the
density and potential stages.
The unified command exposes retention through its mode rather than through separate output-product flags:
illiad-sol-connection-length trace --inputs input_files/sol_connection_length_inputs.example.json
illiad-sol-connection-length regularize --inputs input_files/sol_connection_length_inputs.example.json
illiad-sol-connection-length trace_regularize --inputs input_files/sol_connection_length_inputs.example.jsontrace_regularize traces both directions for each bounded field-line batch,
temporarily spools only regular-cell and field-line IDs, and folds that batch
into fixed-size sufficient statistics as soon as its connection lengths are
known. It retains the regular field and compact trace metadata, but no raw
crossing dataset. regularize never removes its externally supplied raw
trace input.
Build the density and normalized electrostatic-potential fields from the linear interior profile, the regular SOL connection-length field, and saved Poincare surfaces:
illiad-sol-density --inputs input_files/sol_density_inputs.example.json
illiad-sol-potential --inputs input_files/sol_potential_inputs.example.jsonSOLDensity and SOLPotential preserve the float64
(phi, theta, rho) scalar-field and coordinate-file contract used by
FluxGradientor. Both models anchor at the LCFS, bridge the unsampled
LCFS-to-SOL interval, integrate the connection-length-dependent attenuation
to the wall, and can produce contour and midplane diagnostics.
Their official defaults consume DEFAULT/data/SOLTrace_RegularGrid together
with DEFAULT/data/LCFS19/nField_LCFS19alpha1p0.npy. Before constructing any
planes, both analyses verify the complete regular-grid convention, every
selected Poincare LCFS plane, the vessel boundary, and any propagated trace
geometry metadata. Unless explicitly configured, L_PARALLEL_0_M comes from
the SOL trace-length metadata when available and otherwise falls back to the
Poincare spin count for legacy artifacts.
Point input_files/boris_inputs.example.json or an ignored working copy at the
prepared density and electric fields:
illiad-boris --inputs input_files/boris_inputs.example.jsonIon-neutral collisions accept viscous_drag, langevin, or null. Ion-ion
collisions accept linear_fp, fokker_planck, or null. Enabled operators
are applied as half-steps around the Boris push.
Particles are stored emitter-major. Initial speeds follow the configured
Maxwellian model, and launch directions are cosine-weighted over a hemisphere
about the local electric-field direction, with the outward geometric LCFS
normal as fallback. Every run writes E0_Dist.png and V0_Dist.png before
transport.
Analyses use a common layout:
output/<run>/logs/: merged inputs and run logs.output/<run>/data/: Poincare, flux, field, particle, and impact arrays.output/<run>/plots/: topology, field, initialization, trajectory, and deposition figures.
Runs that reuse directory and subdirectory names may overwrite earlier products. Retain the input JSON, package version, dependency environment, and provenance for separately distributed scientific inputs with each result.
ILLIAD is licensed under the GNU General Public License, version 3.0 only
(GPL-3.0-only). See LICENSE for the full terms.