forge.io
Contains routines for reading-from and writing-to files.
Copyright 2025-2026 Chris Marsden
This file is part of FORGE.
FORGE is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
FORGE is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License along with FORGE. If not, see <http://www.gnu.org/licenses/>.
- forge.io.read_geqdsk(path_to_geqdsk=None)[source]
Reads data from a GEQDSK file.
Function to read data from a GEQDSK file. Makes use of the FreeQDSK package’s GEQDSK reader. Some additional fields not directly returned by FreeQDSK are derived, and some fields are ignored as they are not relevant to FORGE.
- Parameters:
path_to_geqdsk (str) – Path to the GEQDSK file to be read.
- Returns:
eq_data (dict) – Dictionary of data extracted from the GEQDSK file.
- forge.io.read_magnets(path_to_magnets=None)[source]
Reads a PF coil set from a JSON file.
Function to read data from a JSON file containing data on the PF coil set.
- Parameters:
path_to_magnets (str) – Path to the JSON file to be read.
- Returns:
magnets_data (dict) – Dictionary of data extracted from the JSON file [dict].
- forge.io.write_magnets(machine, path)[source]
Save a Machine’s coils and circuits to a JSON file.
The output format matches the magnets JSON schema used by
read_magnets(), so a saved file can be loaded back directly. Current values are read from the live coilset, reflecting any post-optimisation changes.- Parameters:
machine (forge.machine.Machine) – The machine to serialise.
path (str or Path) – Output file path.
- forge.io.write_geqdsk(eq, path_to_geqdsk)[source]
Takes a forge.equilibrium Equilibrium object and creates a GEQDSK file.
- Parameters:
eq (forge.equilibrium.Equilibrium object) – Equilibrium to be output as a GEQDSK.
path_to_geqdsk (str) – Output path for the GEQDSK file.
- forge.io.fancy_json_string(data: Any, indent: int = 2) str[source]
Serialize data to a JSON string with compact arrays and pretty dicts.
- Produces JSON where:
Dictionary entries split across new lines according to indent.
Lists/tuples/NumPy arrays kept on a single line (compact).
NumPy scalars converted to Python scalars.
Dicts that appear inside lists serialized in a compact (minified) form so the parent list remains single-line.
- Parameters:
data (Any) – The (typically dict) object to serialize.
indent (int) – Number of spaces used for indenting dictionary entries.
- Returns:
str – The formatted JSON string.
Notes
This function prefers valid JSON. NaN and ±Inf are converted to null.
Large lists will be written on a single (long) line by design.
Key order follows the insertion order of the input dict (Python 3.7+).
Examples
>>> d = { ... "meta": {"shot": 12345, "machine": "MAST-U"}, ... "channels": ["A", "B", "C"], ... "numbers": [1, 2, 3.5], ... } >>> save_json_compact_arrays(d, "out.json", indent=4) # Result (schematic): # { # "meta": { # "shot": 12345, # "machine": "MAST-U" # }, # "channels": ["A", "B", "C"], # "numbers": [1, 2, 3.5] # }
- forge.io.save_fancy_json(data: Any, out_path: str | Path, indent: int = 2) None[source]
Write data to a JSON file using
fancy_json_string()formatting.- Parameters:
data (Any) – The object to serialize (typically a dict).
out_path (str or pathlib.Path) – Destination file path.
indent (int) – Number of spaces for indenting dictionary entries.
- forge.io.save_optimiser(optimiser, path)[source]
Save an Optimiser object to a pickle file.
A shallow copy of the object is made and any unpicklable attributes (Shapely prepared geometries, threading events, callbacks) are stripped from the copy before serialisation. The original object is never modified.
- Parameters:
optimiser (forge.optimise.Optimiser) – The optimiser instance to save.
path (str or pathlib.Path) – Destination file path (typically ending in
.pkl).
See also
load_optimiserLoad an Optimiser object from a pickle file.
- forge.io.load_optimiser(path)[source]
Load an Optimiser object from a pickle file.
- Parameters:
path (str or pathlib.Path) – Path to the pickle file to be read.
- Returns:
optimiser (forge.optimise.Optimiser) – The deserialised optimiser instance.
See also
save_optimiserSave an Optimiser object to a pickle file.
- forge.io.save_strike_geometry(divertor_data, path, *, buffers=None, xpoint_regions=None)[source]
Save strike geometry definitions to a JSON file.
The file uses a region-first layout:
{ "lower_outer": { "strike": {"strike_R": [...], "strike_Z": [...]}, "buffers": [{"R": [...], "Z": [...], "distance": d}, ...], "xpoint_regions": {"R": [...], "Z": [...]}, "connection_length_multiplication_factor_zero": 2.0, "weight_connection_length": null, ... }, ... }
- Parameters:
divertor_data (dict) – Divertor data dict as returned by
build_divertor_data()or constructed manually in a script. Only the user-facing keys are written; internal keys added by the Optimiser are stripped.path (str or pathlib.Path) – Destination file path (typically ending in
.json).buffers (dict or None) – Optional buffer definitions keyed by region name.
xpoint_regions (dict or None) – Optional X-point region polygon definitions keyed by region name.
- forge.io.load_strike_geometry(path)[source]
Load strike geometry definitions from a JSON file.
- Parameters:
path (str or pathlib.Path) – Path to a JSON file previously written by
save_strike_geometry().- Returns:
divertor_data (dict) – Divertor data dict suitable for passing to
Optimiser.buffers (dict or None) – Buffer definitions, or None if the file contains none.
xpoint_regions (dict or None) – X-point region polygon definitions, or None if the file contains none.
- forge.io.save_optimisation_config(path, *, divertor_data=None, buffers=None, xpoint_regions=None, constraints=None, **optimiser_kwargs)[source]
Save a complete optimisation configuration to a JSON file.
The file captures every setting needed to reproduce an optimisation run (except the equilibrium and machine data, which must be loaded separately from their own files).
The JSON layout is:
{ "geometry": { "lower_outer": { "strike": {"strike_R": ..., "strike_Z": ...}, "buffers": [...], "xpoint_regions": {"R": [...], "Z": [...]}, <per-region settings> }, ... }, "constraints": { ... }, "optimiser": { "max_evals": 3000, "initial_temperature": 10.0, ... } }
- Parameters:
path (str or pathlib.Path) – Destination file path (typically ending in
.json).divertor_data (dict or None) – Divertor data dict (strike geometry + per-region settings).
buffers (dict or None) – Buffer definitions keyed by region name.
xpoint_regions (dict or None) – X-point region polygons keyed by region name.
constraints (dict or None) – Constraints dict with
"annealing"and"tikhonov"sections.**optimiser_kwargs – Scalar optimiser parameters (temperatures, step sizes, cost weights, feature toggles, etc.). Only recognised keys from
Optimiser.__init__are written.
- forge.io.load_optimisation_config(path)[source]
Load a complete optimisation configuration from a JSON file.
- Parameters:
path (str or pathlib.Path) – Path to a JSON file previously written by
save_optimisation_config().- Returns:
config (dict) – Dictionary with the following keys (any may be None if absent from the file):
"divertor_data"— dict suitable forOptimiser(divertor_data=...)."buffers"— dict suitable forOptimiser(buffers=...)."xpoint_regions"— dict suitable forOptimiser(xpoint_regions=...)."constraints"— dict suitable forOptimiser(constraints=...)."optimiser"— dict of scalar kwargs to unpack intoOptimiser(**cfg["optimiser"]).