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 world's highest field spherical tokamak.

The Grad-Shafranov equation is the equilibrium solution to the ideal, single-fluid, MHD equations, assuming axisymmetry. 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 poloidal plasma current. GSFit uses diagnostics, most importantly the magnetics, to simultaneously 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 its 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 increases 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", which are similar to classes in object-oriented programming, to be used without any performance penalty. For more information, the official Rust book gives a complete 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. Installation and environment

1.1 Python environment

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 recommended option. This is because uv can create an environment with any version of Python, the installation 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 for Linux, macOS, and Windows. For Linux the "manylinux2014" standard is used, 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 from the PyPI package registry, 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
uv pip install gsfit.[with_st40_mdsplus]  # (this will only work within Tokamak Energy's network)
# or any combination
uv pip install gsfit.[dev,with_st40_mdsplus]

1.3 Compiling and installing from source code on Linux

# 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 .
# or install with the "developer" packages, such as `pytest` and `mypy`
uv pip install --reinstall .[dev]

1.4 Compiling and installing from source code on macOS

# 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

# Install OpenBLAS (gsfit is statically linked so this is only required when compiling)
brew install openblas

# Install GSFit
uv pip install --reinstall .
# or install with the "developer" packages, such as `pytest` and `mypy`
uv pip install --reinstall .[dev]

1.5 Compiling and installing from source code on Windows

On Windows, OpenBLAS can be installed using vcpkg:

# Install `vcpkg` (Windows package manager)
git clone https://github.com/Microsoft/vcpkg.git C:\Users\<user.name>\github\vcpkg
cd C:\Users\<user.name>\github\vcpkg
.\bootstrap-vcpkg.bat
# Install `vcpkg` for all users, into "C:/vcpkg/...", and make `vcpkg` command available in `PATH`
.\vcpkg\vcpkg integrate install

# Install OpenBLAS/LAPACK with static linking
vcpkg install openblas:x64-windows-static-md
vcpkg install lapack-reference:x64-windows-static-md

# Download and install Rust compiler
# run rustup-init.exe from https://www.rust-lang.org/tools/install

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

# Copy OpenBLAS and LAPACk *.dll library files
# Since Python 3.8+, *.dll library files are not found using the `PATH` environment variable. Instead, they are only found from:
#   1. The directory containing the .pyd file (what we will be doing)
#   2. System directories
#   3. Directories explicitly added with `os.add_dll_directory("path_to_dlls")`
Copy-Item "C:/vcpkg/installed/x64-windows-static-md/bin/*.dll" -Destination "python/gsfit_rs/" -ErrorAction Stop

# Install GSFit
uv pip install --reinstall .
# or install with the "developer" packages, such as `pytest` and `mypy`
uv pip install --reinstall .[dev]

1.6 IDE

VS Code is the recommended IDE for GSFit.

A particularly useful extension is rust-analyzer, 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 seamless, and a general user would not know if a function / 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 structures, 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 Mirnov 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 traceability, 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 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 include 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 measurements on.

Principles about where data should be:

  • "sensors" contain the Green's tables.
  • "current sources" contain the currents.

The sensors and currents are linked by names; every magnetic probe and PF coil must have a unique name.

2.4 Decision on coils vs PSUs

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 burdensome 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. Advanced building

GSFit is intended to be a Python library, where the Rust code is called from Python (Python is not called from within Rust). The advantage of this is that the Rust binary does not need to link agains libpython-dev which is not always installed on all machines.

However, for testing, where the Rust code is run as it's own executable, not from within Python, we must link to Python!

4. 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.

5. 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.4.tar.gz (407.2 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.4-cp313-cp313-win_amd64.whl (7.1 MB view details)

Uploaded CPython 3.13Windows x86-64

gsfit-0.0.4-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (2.8 MB view details)

Uploaded CPython 3.13manylinux: glibc 2.17+ x86-64

gsfit-0.0.4-cp313-cp313-macosx_11_0_arm64.whl (1.5 MB view details)

Uploaded CPython 3.13macOS 11.0+ ARM64

gsfit-0.0.4-cp312-cp312-win_amd64.whl (7.1 MB view details)

Uploaded CPython 3.12Windows x86-64

gsfit-0.0.4-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (2.8 MB view details)

Uploaded CPython 3.12manylinux: glibc 2.17+ x86-64

gsfit-0.0.4-cp312-cp312-macosx_11_0_arm64.whl (1.5 MB view details)

Uploaded CPython 3.12macOS 11.0+ ARM64

gsfit-0.0.4-cp311-cp311-win_amd64.whl (7.1 MB view details)

Uploaded CPython 3.11Windows x86-64

gsfit-0.0.4-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (2.8 MB view details)

Uploaded CPython 3.11manylinux: glibc 2.17+ x86-64

gsfit-0.0.4-cp311-cp311-macosx_11_0_arm64.whl (1.5 MB view details)

Uploaded CPython 3.11macOS 11.0+ ARM64

File details

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

File metadata

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

File hashes

Hashes for gsfit-0.0.4.tar.gz
Algorithm Hash digest
SHA256 be224393034bd340fdc0484dba73d4942769fcfafa4e5585605b7c4c90547c35
MD5 6bddc1a8f15594ab1adfcb333d4dc56a
BLAKE2b-256 cd402efc0fa4393f176da9bf63c2ece5facc03a809049eec2ace4a680471e513

See more details on using hashes here.

File details

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

File metadata

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

File hashes

Hashes for gsfit-0.0.4-cp313-cp313-win_amd64.whl
Algorithm Hash digest
SHA256 5d672f24c131c841fabe0db39eb40deedc532f90556f6e84ac351972bb63c388
MD5 48c58591999c5d1d2a95e6458a8bbc1d
BLAKE2b-256 9489c08cffb525e6268d5c19110cdb5cdd565e7e54fcde6beb0d022ea9ab56c6

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for gsfit-0.0.4-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 552c7c598903d6fe1ece7bb50ed804d0b4bc665f600fb0afaf4e76c4b82706fc
MD5 298c542958f6a9e521068bb243e4bfa4
BLAKE2b-256 eb109e1776db45a46dbf5f30ca5bca262b43fea306f6dc0c2dc745aa38c42657

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for gsfit-0.0.4-cp313-cp313-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 1dbdc62bb6a858eb4eb809ea37c07e9e540c5ccb24ec1c5c893501744ab695ad
MD5 eb89f4b55cab381f14cb91d935cef88f
BLAKE2b-256 0f353083641f4e13a2aed63c54ac2244ca84a06d1c9df7b639cd7c08ee0859d8

See more details on using hashes here.

File details

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

File metadata

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

File hashes

Hashes for gsfit-0.0.4-cp312-cp312-win_amd64.whl
Algorithm Hash digest
SHA256 f3827916bab34ce369ff84af85d4d4a25956cfa8e8d09a5bb7c301f431d6aa97
MD5 4fcdd24d5697c8680b9c4e591e4e5c38
BLAKE2b-256 bef215fd85cf239f044556f62510446476932cae6e9cded6bd200daf6e04b12c

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for gsfit-0.0.4-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 29a2f57b78d6f74d7e472199381260e04505f7f288411318ef73fa0cbed50966
MD5 df58d56891eabc97e596c4008f8fa878
BLAKE2b-256 4089b10212ecff2c6ee68ef3541f8d47f7e6240a94f00146fcfc80f33d2daa60

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for gsfit-0.0.4-cp312-cp312-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 048cfdd5ea6c8af55f2888387d7ccfab24078d6490573174a475cbc6195b351e
MD5 dd52b028688fe35503efd4d7c144aca6
BLAKE2b-256 e2bd4f63e158ff612b4029d8898b002dfd4aacd64df49eb93d0729cd6f3408f1

See more details on using hashes here.

File details

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

File metadata

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

File hashes

Hashes for gsfit-0.0.4-cp311-cp311-win_amd64.whl
Algorithm Hash digest
SHA256 6916bd25c1b2d4e60af63f39cc6facb6b4075b7fb1d2e38bd19da592aceda617
MD5 269b8fecfd2b74db3c0461df950fc95b
BLAKE2b-256 ec3a4205f650f6908ea7d858dd0659228b658a62330eb02e5ca1fa88351ccf9d

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for gsfit-0.0.4-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 02b841dc85ecea0f5a066d209583f3f8207311a06d8cfe9ed04455274901975c
MD5 86d055b4a7324b237fe3863e3ce467d3
BLAKE2b-256 0e20cb1da72e29330807fc034827903c138484e31fcdf4277536a4dbebdef4ef

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for gsfit-0.0.4-cp311-cp311-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 39fb008ad63ff080d86af78caceafc05548b41d1a2a4e3d66ce04e6881720e99
MD5 bf8d94f021871e3b8ae26af1c9e6bf89
BLAKE2b-256 c948b5810a4e65dcffe1ad1b9ea23fa2733ebc764172a46b10e825c872ea5c4b

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