Skip to content

Commit 6632990

Browse files
committed
Add slice_time and slice_index arguments to IMAS geometry loader
1 parent c90cc8b commit 6632990

File tree

3 files changed

+34
-2
lines changed

3 files changed

+34
-2
lines changed

torax/_src/geometry/imas.py

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
# limitations under the License.
1414

1515
"""Useful functions for handling of IMAS IDSs."""
16+
import logging
1617
import os
1718
from typing import Any
1819

@@ -29,6 +30,8 @@ def geometry_from_IMAS(
2930
Ip_from_parameters: bool = False,
3031
n_rho: int = 25,
3132
hires_factor: int = 4,
33+
slice_time: float | None = None,
34+
slice_index: int = 0,
3235
equilibrium_object: ids_toplevel.IDSToplevel | None = None,
3336
imas_uri: str | None = None,
3437
imas_filepath: str | None = None,
@@ -45,6 +48,9 @@ def geometry_from_IMAS(
4548
n_rho: Radial grid points (num cells)
4649
hires_factor: Grid refinement factor for poloidal flux <--> plasma current
4750
calculations.
51+
slice_time: Time of slice to load from IMAS IDS. If given, overrides
52+
slice_index.
53+
slice_index: Index of slice to load from IMAS IDS (default 0).
4854
equilibrium_object: The equilibrium IDS containing the relevant data.
4955
imas_uri: The IMAS uri containing the equilibrium data.
5056
imas_filepath: The path to the IMAS netCDF file containing the equilibrium
@@ -71,9 +77,18 @@ def geometry_from_IMAS(
7177
raise ValueError(
7278
"equilibrium_object must be a string (file path) or an IDS"
7379
)
74-
# TODO(b/431977390): Currently only the first time slice is used, extend to
80+
# TODO(b/431977390): Currently only a single time slice is used, extend to
7581
# support multiple time slices.
76-
IMAS_data = equilibrium.time_slice[0]
82+
if slice_time is not None:
83+
if slice_time in equilibrium.time:
84+
slice_index = np.nonzero(equilibrium.time == slice_time)
85+
else:
86+
slice_index = np.searchsorted(slice_time, equilibrium.time)
87+
logging.warning(
88+
f"t={slice_time} not in equilibrium.time."
89+
f"Using t={equilibrium.time[slice_index]} instead."
90+
)
91+
IMAS_data = equilibrium.time_slice[slice_index]
7792
B_0 = np.abs(IMAS_data.global_quantities.magnetic_axis.b_field_phi)
7893
R_major = np.asarray(equilibrium.vacuum_toroidal_field.r0)
7994

torax/_src/geometry/pydantic_model.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -290,6 +290,9 @@ class IMASConfig(torax_pydantic.BaseModelFrozen):
290290
the with running TORAX using the provided APIs. To use this option you
291291
must implement a custom run loop. Only one of imas_filepath, imas_uri or
292292
equilibrium_object can be set.
293+
slice_time: Time of slice to load from IMAS IDS. If given, overrides
294+
slice_index.
295+
slice_index: Index of slice to load from IMAS IDS (default 0).
293296
"""
294297

295298
geometry_type: Annotated[Literal['imas'], TIME_INVARIANT] = 'imas'
@@ -300,6 +303,8 @@ class IMASConfig(torax_pydantic.BaseModelFrozen):
300303
imas_filepath: str | None = 'ITERhybrid_COCOS17_IDS_ddv4.nc'
301304
imas_uri: str | None = None
302305
equilibrium_object: ids_toplevel.IDSToplevel | None = None
306+
slice_index: int = 0
307+
slice_time: float | None = None
303308

304309
@pydantic.model_validator(mode='after')
305310
def _validate_model(self) -> typing_extensions.Self:
@@ -318,6 +323,11 @@ def _validate_model(self) -> typing_extensions.Self:
318323
'`imas_uri` or `imas_filepath` to be a valid input. Inputs provided: '
319324
f'{specified_inputs}.'
320325
)
326+
if self.slice_time is not None and self.slice_index != 0:
327+
raise ValueError(
328+
'IMAS geometry needs exactly one of `slice_time` and `slice_index`.'
329+
f'Got: slice_time={self.slice_time}, slice_index={self.slice_index}.'
330+
)
321331
return self
322332

323333
def build_geometry(self) -> standard_geometry.StandardGeometry:

torax/_src/geometry/standard_geometry.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -942,6 +942,8 @@ def from_IMAS(
942942
Ip_from_parameters: bool,
943943
n_rho: int,
944944
hires_factor: int,
945+
slice_time: float | None = None,
946+
slice_index: int = 0,
945947
equilibrium_object: ids_toplevel.IDSToplevel | None = None,
946948
imas_uri: str | None = None,
947949
imas_filepath: str | None = None,
@@ -956,6 +958,9 @@ def from_IMAS(
956958
values in the Geometry are rescaled to match the new Ip.
957959
n_rho: Radial grid points (num cells).
958960
hires_factor: High resolution factor for calculations.
961+
slice_time: Time of slice to load from IMAS IDS. If given, overrides
962+
slice_index.
963+
slice_index: Index of slice to load from IMAS IDS (default 0).
959964
equilibrium_object: The equilibrium IDS containing the relevant data.
960965
imas_uri: The IMAS uri containing the equilibrium data.
961966
imas_filepath: The path to the IMAS netCDF file containing the equilibrium
@@ -973,6 +978,8 @@ def from_IMAS(
973978
Ip_from_parameters=Ip_from_parameters,
974979
n_rho=n_rho,
975980
hires_factor=hires_factor,
981+
slice_time=slice_time,
982+
slice_index=slice_index,
976983
)
977984
return cls(geometry_type=geometry.GeometryType.IMAS, **inputs)
978985

0 commit comments

Comments
 (0)