Coverage for python/gsfit/database_readers/st40_mdsplus/setup_plasma.py: 0%
61 statements
« prev ^ index » next coverage.py v7.15.0, created at 2026-07-07 13:12 +0000
« prev ^ index » next coverage.py v7.15.0, created at 2026-07-07 13:12 +0000
1import typing
2from typing import TYPE_CHECKING
4import gsfit_rs
5import numpy as np
6import numpy.typing as npt
7from gsfit_rs import Plasma
8from st40_database import GetData
10if TYPE_CHECKING:
11 from . import DatabaseReader
14def setup_plasma(
15 self: "DatabaseReader",
16 pulseNo: int,
17 settings: dict[str, typing.Any],
18) -> Plasma:
19 """
20 This method initialises the Rust `Plasma` class.
22 :param pulseNo: Pulse number, used to read from the database
23 :param settings: Dictionary containing the JSON settings read from the `settings` directory
25 **This method is specific to ST40's experimental MDSplus database.**
27 See `python/gsfit/database_readers/interface.py` for more details on how a new database_reader should be implemented.
28 """
30 # Initial plasma conditions
31 initial_ip = settings["GSFIT_code_settings.json"]["initial_guess"]["ip"]
32 initial_cur_r = settings["GSFIT_code_settings.json"]["initial_guess"]["r_cur"]
33 initial_cur_z = settings["GSFIT_code_settings.json"]["initial_guess"]["z_cur"]
35 # Set the source functions types
36 p_prime_source_function: gsfit_rs.EfitPolynomial | gsfit_rs.TensionedCubicBSpline
37 ff_prime_source_function: gsfit_rs.EfitPolynomial | gsfit_rs.TensionedCubicBSpline
39 if settings["source_function_p_prime.json"]["method"] == "efit_polynomial":
40 n_dof = settings["source_function_p_prime.json"]["efit_polynomial"]["n_dof"]
41 regularisations = np.array(settings["source_function_p_prime.json"]["efit_polynomial"]["regularizations"])
42 # If `regularisations` is [[]] in the json file, will be interpreted by numpy as having size (1, 0).
43 # Which would be interpreted as (n_regularisations, n_dof). So it would cause an error
44 if regularisations.shape == (1, 0):
45 regularisations = np.zeros((0, n_dof), dtype=np.float64)
46 p_prime_source_function = gsfit_rs.EfitPolynomial(n_dof, regularisations)
47 elif settings["source_function_p_prime.json"]["method"] == "tensioned_cubic_b_spline":
48 regularisations = np.array(settings["source_function_p_prime.json"]["tensioned_cubic_b_spline"]["regularizations"])
49 # If `regularisations` is [[]] in the json file, will be interpreted by numpy as having size (1, 0).
50 # Which would be interpreted as (n_regularisations, n_dof). So it would cause an error
51 interior_knots = np.array(settings["source_function_p_prime.json"]["tensioned_cubic_b_spline"]["interior_knots"])
52 n_dof = len(interior_knots) + 4
53 if regularisations.shape == (1, 0):
54 regularisations = np.zeros((0, n_dof), dtype=np.float64)
55 interval_tensions = np.array(settings["source_function_p_prime.json"]["tensioned_cubic_b_spline"]["interval_tensions"])
56 p_prime_source_function = gsfit_rs.TensionedCubicBSpline(regularisations, interior_knots, interval_tensions)
57 else:
58 raise ValueError(f"Unknown method for p_prime source function: {settings['source_function_p_prime.json']['method']}")
60 if settings["source_function_ff_prime.json"]["method"] == "efit_polynomial":
61 n_dof = settings["source_function_ff_prime.json"]["efit_polynomial"]["n_dof"]
62 regularisations = np.array(settings["source_function_ff_prime.json"]["efit_polynomial"]["regularizations"])
63 # If `regularisations` is [[]] in the json file, will be interpreted by numpy as having size (1, 0).
64 # Which would be interpreted as (n_regularisations, n_dof). So it would cause an error
65 if regularisations.shape == (1, 0):
66 regularisations = np.zeros((0, n_dof), dtype=np.float64)
67 ff_prime_source_function = gsfit_rs.EfitPolynomial(n_dof, regularisations)
68 elif settings["source_function_ff_prime.json"]["method"] == "tensioned_cubic_b_spline":
69 regularisations = np.array(settings["source_function_ff_prime.json"]["tensioned_cubic_b_spline"]["regularizations"])
70 # If `regularisations` is [[]] in the json file, will be interpreted by numpy as having size (1, 0).
71 # Which would be interpreted as (n_regularisations, n_dof). So it would cause an error
72 interior_knots = np.array(settings["source_function_ff_prime.json"]["tensioned_cubic_b_spline"]["interior_knots"])
73 n_dof = len(interior_knots) + 4
74 if regularisations.shape == (1, 0):
75 regularisations = np.zeros((0, n_dof), dtype=np.float64)
76 interval_tensions = np.array(settings["source_function_ff_prime.json"]["tensioned_cubic_b_spline"]["interval_tensions"])
77 ff_prime_source_function = gsfit_rs.TensionedCubicBSpline(regularisations, interior_knots, interval_tensions)
78 else:
79 raise ValueError(f"Unknown method for ff_prime source function: {settings['source_function_ff_prime.json']['method']}")
81 # Grid size and shape
82 n_r = settings["GSFIT_code_settings.json"]["grid"]["n_r"]
83 n_z = settings["GSFIT_code_settings.json"]["grid"]["n_z"]
84 r_min = settings["GSFIT_code_settings.json"]["grid"]["r_min"]
85 r_max = settings["GSFIT_code_settings.json"]["grid"]["r_max"]
86 z_min = settings["GSFIT_code_settings.json"]["grid"]["z_min"]
87 z_max = settings["GSFIT_code_settings.json"]["grid"]["z_max"]
89 # Normalised poloidal flux grid
90 n_psi_n = settings["GSFIT_code_settings.json"]["n_psi_n"]
91 psi_n = np.linspace(0.0, 1.0, n_psi_n).astype(np.float64)
93 # Limiter
94 elmag_run_name = settings["GSFIT_code_settings.json"]["database_reader"]["st40_mdsplus"]["workflow"]["elmag"]["run_name"]
95 elmag = GetData(pulseNo, f"ELMAG#{elmag_run_name}", is_fail_quiet=False)
96 limit_pts_r = typing.cast(npt.NDArray[np.float64], elmag.get("LIMITER.LIMIT_PTS.R"))
97 limit_pts_z = typing.cast(npt.NDArray[np.float64], elmag.get("LIMITER.LIMIT_PTS.Z"))
99 # Vacuum vessel where the plasma is allowed to be
100 vessel_r = limit_pts_r
101 vessel_z = limit_pts_z
103 # Add lower MC tiles
104 limit_pts_r = np.append(limit_pts_r, 0.7103)
105 limit_pts_z = np.append(limit_pts_z, -0.3131)
106 # Add upper MC tiles
107 limit_pts_r = np.append(limit_pts_r, 0.7103)
108 limit_pts_z = np.append(limit_pts_z, 0.3031)
110 # Initialise the Plasma Rust class
111 plasma = Plasma(
112 n_r,
113 n_z,
114 r_min,
115 r_max,
116 z_min,
117 z_max,
118 psi_n, # BUXTON: perhaps better to send in `n_psi_n`
119 limit_pts_r,
120 limit_pts_z,
121 vessel_r,
122 vessel_z,
123 p_prime_source_function,
124 ff_prime_source_function,
125 initial_ip,
126 initial_cur_r,
127 initial_cur_z,
128 )
130 return plasma