Skip to main content

GSFit: Equilibrium reconstruction

Project description

GSFit: Grad-Shafranov Fit

The 3-Clause BSD License Python 3.11|3.12|3.13 Rust Ruff Checked with mypy

GSFit is a modern tokamak equilibrium reconstruction tool for post-shot experimental analysis and scientific interpretation. Developed by Tokamak Energy Ltd. for use on ST40, the worlds highest field spherical tokamak.

The Grad-Shafranov equation is the is equilibrium solution to the ideal, single fluid, MHD equations, assuming axysymmetry. The Grad-Shafranov equation has two free degrees of freedom, often referred to as the source functions: the pressure gradient p_prime and ff_prime where f gives rise to the the poloidal plasma current. GSFit uses diagnostics, most importantly the magnetics, to symultaneiously solve the non-linear Grad-Shafranov equation while optimising the p_prime and ff_prime degrees of freedom to minimise the difference between the experimental "measured" values and the "calculated" values. More details about the algorithms used can be found in the excellent paper J.-M. Moret, et. al., "Tokamak equilibrium reconstruction code LIUQE and its real time implementation", Fusion Eng. Design, 91, 2015.

GSFit's numerical solver is written in Rust for speed and robustness, and the user interface / set-up is written in Python for it's convenience.

The goal of GSFit is high accuracy, not performance; when something can be calculated accurately, it should be calculated accurately regardless of computational cost.

GSFit uses the COCOS 13 coordinate system, as described in O. Sauter and S. Y Medvedev, "Tokamak Coordinate Conventions: COCOS", Comput. Phys. Commun. 184, 2013. Where in summary, flux is measured in weber, and the poloidal angle increase counterclockwise, starting from the outboard mid-plane.

Why Rust and Python?

Rust is a compiled, high-performance language, nearly as fast as C and Fortran. It includes modern tooling such as a package manager and centralised registry (cargo and crates.io), autoformatting (rustfmt), and has testing built into the language. Rust enforces strict ownership rules, making programs extremely memory efficient without requiring any extra effort. These rules also eliminate entire classes of memory issues. Additionally, Rust has zero-cost abstractions, allowing "implementations", whcih are similar to classes in object-oriented programming, to be used without any performance penalty. For more information the official Rust book gives a complet introduction to the language with examples.

Python is ubiquitous within the fusion industry. Using Python allows easy integration into existing workflows, for example in examples/example_02_mastu_with_synthetic_data_from_freegsnke.ipynb, we reconstruct an equilibrium using synthetic "measured" data produced by the open source forward Grad-Shafranov solver FreeGSNKE.

1. Instiallation and environment

1.1 Python environment

Presently, GSFit can be run on Python 3.11, 3.12 and 3.13 (see the banner at the top of this page).

When installing from PyPi, see section 1.2, you can use the system Python, but it is best practice to use a virtual environment.

There are three main virtual environment providers: uv, conda, and virtualenv.

uv is both an environment and package manager and is the recomended option. This is because uv can create an environment with any version of Python, the instillation is done within the user's home directory, and uv has been specifically designed for speed. This makes it simple and quick to test against multiple Python versions.

# Install the `uv` environment and package manager
python -m pip install uv

# Creating and activating a virtual environment, called `venv_gsfit`
python -m uv venv venv_gsfit --python=3.13
source venv_gsfit/bin/activate

1.2 Installing from PyPi

GSFit is available on the PyPi package registry as a pre-compiled binary. The binary is compiled using the "manylinux2014" standard, which typically can be run on any Linux machine newer than 2014.

All of the packages GSFit depends on are listed in the pyproject.toml. These are divided into essential packages which are always required for any run and optional packages which can be installed for different purposes. An example of optional packages are machine specific database readers.

# Install GSFit from the PyPi package registry, with only the essential packages
uv pip install gsfit
# or install GSFit with the "developer" packages, such as `pytest` and `mypy`
uv pip install gsfit[dev]
# or install GSFit with reading/writing to/from ST40's experimental database
# (this will only work within Tokamak Energy's network)
uv pip install --reinstall .[with_st40_mdsplus]
# or any combination
uv pip install --reinstall .[dev,with_st40_mdsplus]

1.3 Compiling and installin from source code

While GSFit can be installed into the system Python from PyPi, when compiling from source code a virtual environment is required.

The Rust compiler is easily installed using rustup.

GSFIt also requires OpenBLAS to perform various LAPACK routines, such as least squares minimisation and eignevalue/eigenvector calculations.

# Install the Rust compiler (only needs to be done once)
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh

# Clone a copy of GSFit from GitHub
git clone git@github.com:tokamak-energy/gsfit.git
cd gsfit

# Load OpenBLAS (gsfit is statically linked so this is only required when compiling)
module avail
module load OpenBLAS

# Install GSFit
uv pip install --reinstall .

1.4 IDE

VS Code is the recomended IDE for GSFit.

A particularly useful extension is rust-analyser, which "is a part of a larger rls-2.0 effort to create excellent IDE support for Rust."

The PyO3 crate requires Python>=3.7. On machines where the python3 command links to an unsupported Python version, you can change the following file: ~/.vscode-server/data/Machine/settings.json to point to your desired Python's "standard library files". Which will be similar to:

{
    "rust-analyzer.server.extraEnv": {
        "PYO3_CROSS_LIB_DIR": "/home/<user.name>/.local/share/uv/python/cpython-3.13.2-linux-x86_64-gnu/lib"
    }
}

and Python's "standard library files" directory can be found by:

python -c "import sysconfig; print(sysconfig.get_config_var('LIBDIR'))"

2. GSFit program layout and flow

2.1 Initialisation

GSFit's solver and numerics are programmed in Rust, with the initialisation done within Python.

The communication between Python and Rust is handled by the PyO3 crate. From the Python side the integration is seemless, and a general user would not know if a fuction / class is written in Python or Rust. In a similar way a user interacting with numpy does not know if they are calling Python, C or Fortran.

GSFit has the following implementations (which are similar to classes):

  • coils for the PF and TF coils. This object contains the geometry; measured values; and reconstructed values
  • passives for the toroidally conducting strucutres, such as the vacuum vessel and passive plates. passives also contains the degrees of freedom allowed for the passive conductors
  • plasma contains a $(R, Z)$ grid and the reconstructed equilibrium
  • bp_probes contains the Mrinov coils: geometry; measured values; which sensors to use in the reconstruction and their weights; and the reconstructed values
  • flux_loops the toroidal flux loops. Note the units are in weber.
  • rogowski_coils measuring toroidal currents
  • isoflux contains two time-dependent $(R, Z)$ coordinates which have equal poloidal flux
  • isoflux_boundary contains a time-dependent $(R, Z)$ coordinate which has the same poloidal flux as the plasma boundary. This can be used if we have measurements of where the strike point is, for example if there is an IR camera

All of these implementations are initialised from Python. As a result, all of the database access is contained within Python, and any pre-processing such as filtering or smoothing experimental data can also be done within Python.

Below is a reproduction of examples/example_01_st40_with_experimental_data.py.

# Note, this example will only run inside Tokamak Energy's network

from gsfit import Gsfit

# Construct the GSFit object
gsfit_controller = Gsfit(
    pulseNo=12050,
    run_name="TEST01",
    run_description="Test run",
    write_to_mds=True,
    settings_path="default"
)

# Run (solve the inverse Grad-Shafranov equation, and if requested write to database)
gsfit_controller.run()

To improve reliability and tracability the number of arguments needed to initialise the gsfit_controller object is deliberately kept to a minimum. The settings_path="default" argument tells GSFit to use the settings (JSON files) from this directory python/gsfit/settings/default/. By storing all of the settings needed to run GSFit in JSON files allows changes to be tracked through Git.

2.2 Adding a new experimental device or coupling to a new forward Grad-Shafranov code

The information needed to run GSFit comes from two sources:

  1. python/gsfit/settings/: Contains parameters in JSON files, such as:
    • the maximum number of iterations,
    • which magnetic sensors to use in the reconstruction,
    • the degrees of freedom given to p_prime and ff_prime,
    • and which database_reader to use.
  2. python/gsfit/database_readers/: Connects to machine specific databases to read experimental results in, such as:
    • geometry and current in poloidal field coils
    • measured signals from magnetic sensors
    • isoflux constraints

These two sources of information are combined to initialise the Rust objects needed to run GSFit (as described in section 2.1).

Writing to the database is done through python/gsfit/database_writers, in a similar format to database_readers.

Included are the settings and readers for ST40's experimental data, and synthetic data produced by FreeGS and FreeGSNKE simulations. We welcome and are happy to inclue configurations for other devices.

2.3 Where are the Green's tables stored?

We can classify objects as either "current sources" or "sensors".

  • coils, passives, and plasma are "current sources".
  • bp_probes, flux_loops, rogowski_coils, isoflux, and plasma are "sensors".

Note, plasma is both a current source and a sensor, this is because it contains the plasma current and the 2D (R, Z) grid where we want to take measurement on.

Principles about where data should be:

  • "sensors" contain the Greens tables.
  • "current sources" contain the currents.

the sensors and currens are linked by names, every magnetic probe and PF coil must have a unique name.

2.4 Decision on coils vs PSU's

On many tokamaks, including ST40, several PF coils are connected to a single PSU. For ST40 we have the BVLT and BVLB PF coils, both connected to the BVL PSU.

Several equilibrium reconstruction codes treat the PSU current as a measurement with an associated degree of freedom. To allow for this degree of freedom we would need to tell GSFit which PF coil is connected to which PSU. This is quite burdensom and to keep GSFit simple to initialise, we have decided to only consider "coils". The work-around, if you want to have the PSU currents as a degree of freedom, is to combine all of the PF coils connected to a single power supply into a single coil. On ST40 we could create a PF coil called BVL_combined which contains both BVLT and BVLB.

3. Planned future development

  • Pressure constrained.
  • Spline p_prime and ff_prime
  • Interfacing to and from IMAS & OMAS.
  • More kinetic sensors, such as MSE, polarimeters, and interferometers.

4. Citing GSFit

We intend on publishing a paper on GSFit. While GSFit is unpublished please cite it as "P. F. Buxton, GSFit, https://github.com/tokamak-energy/gsfit, 2025"

Please use the GSFit nomenclature, not GS-Fit, GSFIT, or g/s fit.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

gsfit-0.0.0.tar.gz (180.8 kB view details)

Uploaded Source

Built Distributions

If you're not sure about the file name format, learn more about wheel file names.

gsfit-0.0.0-cp313-cp313-win_amd64.whl (6.4 MB view details)

Uploaded CPython 3.13Windows x86-64

gsfit-0.0.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (2.5 MB view details)

Uploaded CPython 3.13manylinux: glibc 2.17+ x86-64

gsfit-0.0.0-cp313-cp313-macosx_11_0_arm64.whl (1.2 MB view details)

Uploaded CPython 3.13macOS 11.0+ ARM64

gsfit-0.0.0-cp312-cp312-win_amd64.whl (6.4 MB view details)

Uploaded CPython 3.12Windows x86-64

gsfit-0.0.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (2.5 MB view details)

Uploaded CPython 3.12manylinux: glibc 2.17+ x86-64

gsfit-0.0.0-cp312-cp312-macosx_11_0_arm64.whl (1.2 MB view details)

Uploaded CPython 3.12macOS 11.0+ ARM64

gsfit-0.0.0-cp311-cp311-win_amd64.whl (6.4 MB view details)

Uploaded CPython 3.11Windows x86-64

gsfit-0.0.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (2.5 MB view details)

Uploaded CPython 3.11manylinux: glibc 2.17+ x86-64

gsfit-0.0.0-cp311-cp311-macosx_11_0_arm64.whl (1.2 MB view details)

Uploaded CPython 3.11macOS 11.0+ ARM64

File details

Details for the file gsfit-0.0.0.tar.gz.

File metadata

  • Download URL: gsfit-0.0.0.tar.gz
  • Upload date:
  • Size: 180.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: maturin/1.9.0

File hashes

Hashes for gsfit-0.0.0.tar.gz
Algorithm Hash digest
SHA256 da14f3a5145b04065b22fd4afdab58da160c481abde922f9c8db816c25b7fece
MD5 cd6182b9124f5cc546179ea2fd061a55
BLAKE2b-256 e19434fca7a39557817ed1788b83bb0390b94972af199bd116e4f8fa42e3fc2d

See more details on using hashes here.

File details

Details for the file gsfit-0.0.0-cp313-cp313-win_amd64.whl.

File metadata

  • Download URL: gsfit-0.0.0-cp313-cp313-win_amd64.whl
  • Upload date:
  • Size: 6.4 MB
  • Tags: CPython 3.13, Windows x86-64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: maturin/1.9.4

File hashes

Hashes for gsfit-0.0.0-cp313-cp313-win_amd64.whl
Algorithm Hash digest
SHA256 8bf5906896276771b1a149666110b8e231362238dece3a28b9b1d2bcfd4c6145
MD5 dca5974345086ae12bbc31caf34a4845
BLAKE2b-256 32dbf4b78747d5fc904341f1d8fc22a9c1255381ecedb2874210bee49f724c1d

See more details on using hashes here.

File details

Details for the file gsfit-0.0.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for gsfit-0.0.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 69fd110c80c30da53a10abce7cf1fb7c53b01bd80f24a02afad845e4426b55b6
MD5 8002eb9abb4c5bb9a8e3be09967bc46a
BLAKE2b-256 b261aa84c9630a47c9905a1c1c5e79615361edc7d46c0c9988da439482ce93e0

See more details on using hashes here.

File details

Details for the file gsfit-0.0.0-cp313-cp313-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for gsfit-0.0.0-cp313-cp313-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 c8c985636433342e59797a1168f7e4e74296186a5bb6d1505ec7649828bc870a
MD5 10e0e61f99166e0e1ce800cc73afc9b5
BLAKE2b-256 be1f4f45c7778d77f3f89b1e303b8e79ac599cae0b35a313e67fbf1cdf1588d0

See more details on using hashes here.

File details

Details for the file gsfit-0.0.0-cp312-cp312-win_amd64.whl.

File metadata

  • Download URL: gsfit-0.0.0-cp312-cp312-win_amd64.whl
  • Upload date:
  • Size: 6.4 MB
  • Tags: CPython 3.12, Windows x86-64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: maturin/1.9.4

File hashes

Hashes for gsfit-0.0.0-cp312-cp312-win_amd64.whl
Algorithm Hash digest
SHA256 5afe6696b4faeffeff62f112cfe590784754814c63622db9640c107b506b7fd8
MD5 4edff533376fcf9140c03d9db3ff8a3e
BLAKE2b-256 0f35f3d3a89df247ae6a080082048f84e6858d799708d624ea35421c32c7f670

See more details on using hashes here.

File details

Details for the file gsfit-0.0.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for gsfit-0.0.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 4a27f8eb9cad5d732647082cb7b968461ddaf084e53a4e2b63504792216a129a
MD5 188bf5f915340959ef87883d552376eb
BLAKE2b-256 49d70dfb669743a39e773935dc2b73c8297246ea47253357d5ea6af8c091653a

See more details on using hashes here.

File details

Details for the file gsfit-0.0.0-cp312-cp312-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for gsfit-0.0.0-cp312-cp312-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 a505453d326378543c5b11824c9a4e7f83fc65d154c2444b7d04dc9268322b10
MD5 b5c4dccb66318ff50978b7ccb9561af4
BLAKE2b-256 ef91ca3e043f1408a97cbb3b49c864afc2cd602069768ccabec44fabb508f137

See more details on using hashes here.

File details

Details for the file gsfit-0.0.0-cp311-cp311-win_amd64.whl.

File metadata

  • Download URL: gsfit-0.0.0-cp311-cp311-win_amd64.whl
  • Upload date:
  • Size: 6.4 MB
  • Tags: CPython 3.11, Windows x86-64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: maturin/1.9.4

File hashes

Hashes for gsfit-0.0.0-cp311-cp311-win_amd64.whl
Algorithm Hash digest
SHA256 95698ab4c3b63ee1ce5c25140325642252330cb883da8285fb2779cfd8acbe0a
MD5 8df13a6f965157ddfb20c1942e2b5f7c
BLAKE2b-256 48cc61146ab8eb3606208aeffab9c2c0ca7f7db7d01e68e7d5b890a2a311fb60

See more details on using hashes here.

File details

Details for the file gsfit-0.0.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for gsfit-0.0.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 bb4ab5ed5b647f71766a11edf167ebe9d43ff26bc282e6d56ce1579ebd9f4ef9
MD5 e03f9200e7a4e6c93b94e1b2d9b86b94
BLAKE2b-256 e279f487b9198b0938e1bdb6c33ef2f5dcd4198f74a52d232f48a32f3cf88d06

See more details on using hashes here.

File details

Details for the file gsfit-0.0.0-cp311-cp311-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for gsfit-0.0.0-cp311-cp311-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 f9871237ad1a6648f4f705a9ba99ce041e38765c4f5128674e190b6e9396ace5
MD5 84d062be69a50b35cfc93ad9ee5f36c0
BLAKE2b-256 ab5b339ee1e21292ef647a137d14f0355823a0ac5a0acc775056ed52adad12d1

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page