Vignesh Gopakumar
  • Home
  • Research
  • Talks
  • Blog

On this page

  • Purpose
  • Conventions common to all four
  • Mapping tables
  • Correctness
    • What the round trip cannot see
  • Post-mortem: flux radius on export (K-007, fixed)
  • Changelog

IMAS adapters

Modified

September 30, 2026

Purpose

IMAS is the fusion community’s standard data model; an IDS is one record type in it. The Tokamak Toolkit speaks IMAS at every boundary and nowhere else: data comes in and goes out as IDSs, and inside it is converted to the state objects of core state. Adapters are the only place any unit or coordinate conversion happens. Versions: IMAS-Python 2.1.0, Data Dictionary 4.1.1.

The payoff came at M1: FreeGSNKE writes its equilibrium as an IDS, which these adapters already read, so joining two independently written codes needed no hand-made mapping (entry 6).

Conventions common to all four

  • Homogeneous time, one time slice per IDS.
  • Uncertainty: where a state object carries an ensemble spread (std), it is written to the node’s _error_upper and _error_lower as a symmetric error bar, and read back from there.
  • IDSs pass the Data Dictionary’s own validate().

Mapping tables

equilibrium (time slice 0, profiles_1d, plus globals). With \(\rho_{t,b}\) the toroidal-flux radius at the boundary:

IDS node state field conversion
rho_tor_norm grid.rho none
rho_tor – \(\rho\,\rho_{t,b}\)
psi psi none (COCOS 11 in both)
q q none
dvolume_drho_tor vprime \(V' = (\partial V/\partial\rho_t)\,\rho_{t,b}\)
gm3 g1 \(G = \texttt{gm3} / \rho_{t,b}^2\)
volume, area volume, area none
global_quantities.ip ip none
boundary.minor_radius a_minor none
vacuum_toroidal_field.r0, .b0 r0, b0 none

On import, \(\rho_{t,b}\) is read from the IDS as rho_tor[-1] / rho_tor_norm[-1]. On export it is the equilibrium’s own rho_tor_b (the minor radius only for the circular case); until 30 Sep 2026 it was wrongly taken to be a_minor (see the post-mortem below).

core_profiles (profiles_1d[0]): grid.rho_tor_norm ← cell centres; electron temperature and density ← te, ne; one ion species, deuterium, with temperature ti and density ne (quasi-neutral, single species at this stage).

core_transport (one model entry, identifier index 25, “unspecified”): face grid written to grid_d, grid_v and grid_flux; electrons.energy.d ← chi_e; total_ion_energy.d ← chi_i; electrons.particles.d ← d_e; electrons.particles.v ← v_e; spreads as error bars.

core_sources (one source entry holding the summed sources, identifier index 1, “total”): electrons.energy ← q_e; total_ion_energy ← q_i; electrons.particles ← s_n; spreads as error bars.

Reading a grid back: IDSs store only cell centres, so faces are rebuilt as midpoints between centres plus \(\rho = 0\) and \(\rho = 1\) at the ends.

Correctness

The round trip state → IDS → state preserves values and coordinates to 10−14C-024 for all four IDSs, with and without uncertainties, including through a netCDF file (tests/unit/test_adapters_roundtrip.py). TORAX output exported through these adapters passes validate() (tests/regression/test_torax_backend.py::test_ids_export_validates).

What the round trip cannot see

A round trip checks that export and import are inverses. It cannot check that the exported numbers mean what IMAS says they mean: if both directions share a wrong assumption, the round trip passes. That is the case for one assumption, below. The complementary check, comparing an exported node against the source code’s own value of the same quantity, is what would catch it.

Post-mortem: flux radius on export (K-007, fixed)

Found 2026-09-30 while writing this page; fixed the same day.

What was written. The export wrote rho_tor, dvolume_drho_tor and gm3 using a_minor in place of \(\rho_{t,b}\).

What is correct. The two radii coincide only for circular geometry. For ITER they differ by a factor of 1.37C-030, for MAST-U by a factor of 1.52C-021. The exported rho_tor was therefore too small by that factor, dvolume_drho_tor too large by it, and gm3 too small by its square.

What the bug looked like from inside. Every existing check passed, and each for a good reason. The round trip passed because it re-derived \(\rho_{t,b}\) from the same wrong rho_tor it had just written, so the error cancelled — a ruler measuring itself. rho_tor_norm, \(V'\) and \(G\) inside the simulation were right, so no conservation, physics or gradient test could see it. Import was right too, since the equilibrium-code path reads the IDS’s own rho_tor. The only consumer that would have noticed is a different code reading our IMAS output, and there isn’t one yet.

The check that caught it. Not a test: writing down the mapping table for this page, next to the definition of \(\rho_{t,b}\), while entry 6 was explaining that the two radii differ on a spherical tokamak. The same confusion had been found in the physics one page earlier and was still sitting in the adapter.

Fix. Equilibrium now carries rho_tor_b (None means the circular case, where it equals a_minor). The analytic equilibrium sets it to the minor radius, the transport-code backend to that code’s own boundary flux radius, and the equilibrium-code backend to the value derived from toroidal flux.

So it cannot recur. test_equilibrium_export_uses_toroidal_flux_radius exports an equilibrium whose two radii deliberately differ and asserts the boundary rho_tor, the separately reported minor_radius, and a lossless round trip of \(V'\), \(G\) and volume. A round trip cannot detect an error made the same way in both directions (see above), so two further tests make the independent comparison: the exported boundary rho_tor against TORAX’s own reported flux radius (ITER hybrid), and against FreeGSNKE’s own value (MAST-U). Both agree to 10−12C-033 (test_equilibrium_export_matches_torax_flux_radius, test_equilibrium_export_matches_source_flux_radius).

Blast radius. None published: the bug was found and fixed before this page went live, and no claim depended on the exported nodes.

Changelog

  • 2026-09-30: first published version; K-007 found, fixed and pinned by a regression test (entry 7).

© Copyright 2026 Vignesh Gopakumar

 
 
Code and first draft by Claude (Anthropic), working to a brief by Vignesh Gopakumar, who reviewed and approved this page. How this is built · Tokamak Toolkit home