fuse29 — Mamba-2 pedestal predictor for DIII-D

A 29-input, 6-layer Mamba-2 state-space model that predicts nine pedestal quantities at ρ_tor = 0.85 from DIII-D actuator settings, at 20 Hz, with a strictly causal O(1)-per-tick inference path suitable for real-time control.

Packaged as two ONNX graphs with normalisation baked in: raw physical units in, physical units out.

Parameters 11,254,425
Architecture Mamba-2 (SSD), 6 layers, d_model 512, d_state 128
Inputs 29 actuator channels, physical units
Outputs 9 heads, physical units
Cadence 20 Hz (50 ms)
Precision float32
ONNX opset 17
Step latency ~2.9 ms/tick, CPU, batch 1
License MIT

Intended use

Predicting pedestal density, temperature, rotation, heights and locations from the actuator request, inside FUSE or an equivalent DIII-D control or analysis pipeline. The step graph is designed for the 50 ms control cycle; the sequence graph is for offline scoring and replay.

Not intended for other machines, other radial locations, or as a safety-critical interlock. It has no uncertainty estimate and no out-of-distribution detector.

Quickstart

pip install numpy onnxruntime
from fuse29.runtime import Fuse29Predictor

predictor = Fuse29Predictor.from_pretrained("SCS-Lab/FUSE29-Pedestal-model")   # loads seed 0
state = predictor.init_state()

for actuators in shot:                     # (29,) float32, raw physical units
    out, state = predictor.step(actuators, state)
    if out.is_hmode:
        print(out.ne, out.te_ped, out.neped_prmtan)

Or straight from onnxruntime, with no Python package — the full contract is about fifteen lines and is written out in docs/ONNX.md.

Files

Per seed (s0/s7/):

File
fuse29_step.onnx one 50 ms tick, carries state, no length limit
fuse29_seq.onnx whole shot at a fixed 256 ticks
model_config.json I/O contract: names, order, units, sources, shapes
norms.json the statistics baked into the graphs
actuator_ranges.json training-split distribution, for checking your units
provenance.json source checkpoint SHA-256, library versions, artefact hashes

Plus manifest.json at the root. Seed 0 is the champion and the default.

Inputs

29 DIII-D actuator channels in raw physical units: beam power (MW) and torque, ECH power, the eighteen shaping F-coil currents (A), both E-coil currents (A), five gas valve flows (Torr·L/s), and the toroidal field (T). Order is load-bearing; see docs/IO_CONTRACT.md.

pohm, ip and ipspr15v are deliberately excluded — they are plasma responses, not commands, and a model predicting the response must not be handed it.

Outputs

# Head Units
0 ne 10¹⁹ m⁻³
1 te_ped keV
2 ti_ped keV
3 t_rot_ped krad/s
4 neped_prmtan * 10¹⁹ m⁻³
5 teped_prmtan * keV
6 rho_sym * ρ_tor
7 ne_top_loc * ρ_tor
8 hmode probability

* H-mode only. See the limitations below.

Performance

Seed 0, scored with the exported ONNX graph on 4087 held-out shots. Median of per-shot RMSE:

Head Median per-shot RMSE Units
ne 0.3057 10¹⁹ m⁻³
te_ped 0.0605 keV
ti_ped 0.1065 keV
t_rot_ped 4.1497 krad/s
neped_prmtan * 0.3950 10¹⁹ m⁻³
teped_prmtan * 0.0783 keV
rho_sym * 0.0113 ρ_tor
ne_top_loc * 0.0134 ρ_tor
hmode 0.9443 accuracy, 0.9476 F1

ONNX-vs-PyTorch parity is within 2.5e-05 of a head's training standard deviation across all eight seeds and both graphs. Full protocol: docs/VALIDATION.md.

Training

~40 900 DIII-D shots, 20 Hz, labels as trailing-bin means with empty bins masked rather than filled. Stratified random 80/10/10 split (seed 20260829). AdamW, lr 2e-4, cosine schedule, 25 epochs, batch 128. Checkpoint selected on lowest total validation loss across all nine heads.

Eight seeds are published; they differ only in weight initialisation and data ordering. Full recipe in docs/TRAINING.md.

Limitations

  • Four heads are undefined in L-mode. neped_prmtan, teped_prmtan, rho_sym and ne_top_loc were trained only on H-mode ticks. The graph emits them unconditionally anyway. You must gate on the model's own hmode output, which is ~94% accurate with errors concentrated at L–H transitions. See docs/GATING.md.
  • Beam power is a live input in this package. The predecessor (fuse29_s*) could not see pinj because a corrupted shot set the divisor to 194 MW. These weights were retrained against winsorised actuator statistics; a half-range pinj swing now moves ne by 0.79. Isolated sweeps are not a real power scan — other actuators stay at recorded values. See docs/LIMITATIONS.md.
  • Accuracy measures interpolation. The split is random, so validation shots come from the same campaigns as training shots. A chronological split scores roughly 1.5–2× worse. Expect degradation outside the training distribution, with no built-in warning.
  • No uncertainty. Seed spread measures optimisation variance, not predictive uncertainty, and says nothing about errors all eight seeds share.
  • Units have no guard rail. pinj is MW, not W. A unit error produces confident nonsense rather than an exception; run predictor.check_units(shot) once during integration.
  • Fixed 50 ms cadence, all 29 channels required every tick, no missing-channel handling, no dropped-tick recovery.
  • Sequence graph is fixed at 256 ticks. Use the step graph for anything longer.
  • float32 only; no quantised variants are published or validated.
  • DIII-D only, ρ_tor = 0.85 only.

Full discussion in docs/LIMITATIONS.md.

Downloads last month

-

Downloads are not tracked for this model. How to track
Inference Providers NEW
This model isn't deployed by any Inference Provider. 🙋 Ask for provider support