33from abc import ABC , abstractmethod
44from collections .abc import Iterable , Sequence , Mapping
55from functools import wraps
6- from math import pi , sqrt , atan2
6+ import math
77from numbers import Integral , Real
88from pathlib import Path
99from typing import Protocol
1010
1111import h5py
1212import lxml .etree as ET
1313import numpy as np
14- from pathlib import Path
1514
1615import openmc
1716import openmc .checkvalue as cv
1817from openmc .checkvalue import PathLike
19- from openmc .utility_funcs import change_directory
2018from .bounding_box import BoundingBox
2119from ._xml import get_elem_list , get_text
2220from .mixin import IDManagerMixin
@@ -291,7 +289,7 @@ def from_hdf5(cls, group: h5py.Group):
291289 """
292290 mesh_type = 'regular' if 'type' not in group .keys () else group ['type' ][()].decode ()
293291 mesh_id = int (group .name .split ('/' )[- 1 ].lstrip ('mesh ' ))
294- mesh_name = '' if not 'name' in group else group ['name' ][()].decode ()
292+ mesh_name = '' if 'name' not in group else group ['name' ][()].decode ()
295293
296294 if mesh_type == 'regular' :
297295 return RegularMesh .from_hdf5 (group , mesh_id , mesh_name )
@@ -1903,7 +1901,7 @@ def __init__(
19031901 self ,
19041902 r_grid : Sequence [float ],
19051903 z_grid : Sequence [float ],
1906- phi_grid : Sequence [float ] = (0 , 2 * pi ),
1904+ phi_grid : Sequence [float ] = (0 , 2 * math . pi ),
19071905 origin : Sequence [float ] = (0. , 0. , 0. ),
19081906 mesh_id : int | None = None ,
19091907 name : str = '' ,
@@ -1960,7 +1958,7 @@ def phi_grid(self, grid):
19601958 cv .check_length ('mesh phi_grid' , grid , 2 )
19611959 cv .check_increasing ('mesh phi_grid' , grid )
19621960 grid = np .asarray (grid , dtype = float )
1963- if np .any ((grid < 0.0 ) | (grid > 2 * pi )):
1961+ if np .any ((grid < 0.0 ) | (grid > 2 * math . pi )):
19641962 raise ValueError ("phi_grid values must be in [0, 2π]." )
19651963 self ._phi_grid = grid
19661964
@@ -2028,9 +2026,9 @@ def __repr__(self):
20282026 return string
20292027
20302028 def get_indices_at_coords (
2031- self ,
2032- coords : Sequence [float ]
2033- ) -> tuple [int , int , int ]:
2029+ self ,
2030+ coords : Sequence [float ]
2031+ ) -> tuple [int , int , int ]:
20342032 """Finds the index of the mesh element at the specified coordinates.
20352033
20362034 .. versionadded:: 0.15.0
@@ -2046,7 +2044,7 @@ def get_indices_at_coords(
20462044 The r, phi, z indices
20472045
20482046 """
2049- r_value_from_origin = sqrt (( coords [0 ]- self .origin [0 ]) ** 2 + ( coords [1 ]- self .origin [1 ]) ** 2 )
2047+ r_value_from_origin = math . hypot ( coords [0 ]- self .origin [0 ], coords [1 ]- self .origin [1 ])
20502048
20512049 if r_value_from_origin < self .r_grid [0 ] or r_value_from_origin > self .r_grid [- 1 ]:
20522050 raise ValueError (
@@ -2070,13 +2068,13 @@ def get_indices_at_coords(
20702068 delta_x = coords [0 ] - self .origin [0 ]
20712069 delta_y = coords [1 ] - self .origin [1 ]
20722070 # atan2 returns values in -pi to +pi range
2073- phi_value = atan2 (delta_y , delta_x )
2071+ phi_value = math . atan2 (delta_y , delta_x )
20742072 if delta_x < 0 and delta_y < 0 :
20752073 # returned phi_value anticlockwise and negative
2076- phi_value += 2 * pi
2074+ phi_value += 2 * math . pi
20772075 if delta_x > 0 and delta_y < 0 :
20782076 # returned phi_value anticlockwise and negative
2079- phi_value += 2 * pi
2077+ phi_value += 2 * math . pi
20802078
20812079 phi_grid_values = np .array (self .phi_grid )
20822080
@@ -2111,7 +2109,7 @@ def from_bounding_box(
21112109 dimension : Sequence [int ] = (10 , 10 , 10 ),
21122110 mesh_id : int | None = None ,
21132111 name : str = '' ,
2114- phi_grid_bounds : Sequence [float ] = (0.0 , 2 * pi ),
2112+ phi_grid_bounds : Sequence [float ] = (0.0 , 2 * math . pi ),
21152113 enclose_domain : bool = False ,
21162114 ) -> CylindricalMesh :
21172115 """Create CylindricalMesh from a bounding box.
@@ -2339,8 +2337,8 @@ class SphericalMesh(StructuredMesh):
23392337 def __init__ (
23402338 self ,
23412339 r_grid : Sequence [float ],
2342- phi_grid : Sequence [float ] = (0 , 2 * pi ),
2343- theta_grid : Sequence [float ] = (0 , pi ),
2340+ phi_grid : Sequence [float ] = (0 , 2 * math . pi ),
2341+ theta_grid : Sequence [float ] = (0 , math . pi ),
23442342 origin : Sequence [float ] = (0. , 0. , 0. ),
23452343 mesh_id : int | None = None ,
23462344 name : str = '' ,
@@ -2397,7 +2395,7 @@ def theta_grid(self, grid):
23972395 cv .check_length ('mesh theta_grid' , grid , 2 )
23982396 cv .check_increasing ('mesh theta_grid' , grid )
23992397 grid = np .asarray (grid , dtype = float )
2400- if np .any ((grid < 0.0 ) | (grid > pi )):
2398+ if np .any ((grid < 0.0 ) | (grid > math . pi )):
24012399 raise ValueError ("theta_grid values must be in [0, π]." )
24022400 self ._theta_grid = grid
24032401
@@ -2411,7 +2409,7 @@ def phi_grid(self, grid):
24112409 cv .check_length ('mesh phi_grid' , grid , 2 )
24122410 cv .check_increasing ('mesh phi_grid' , grid )
24132411 grid = np .asarray (grid , dtype = float )
2414- if np .any ((grid < 0.0 ) | (grid > 2 * pi )):
2412+ if np .any ((grid < 0.0 ) | (grid > 2 * math . pi )):
24152413 raise ValueError ("phi_grid values must be in [0, 2π]." )
24162414 self ._phi_grid = grid
24172415
@@ -2483,8 +2481,8 @@ def from_bounding_box(
24832481 dimension : Sequence [int ] = (10 , 10 , 10 ),
24842482 mesh_id : int | None = None ,
24852483 name : str = '' ,
2486- phi_grid_bounds : Sequence [float ] = (0.0 , 2 * pi ),
2487- theta_grid_bounds : Sequence [float ] = (0.0 , pi ),
2484+ phi_grid_bounds : Sequence [float ] = (0.0 , 2 * math . pi ),
2485+ theta_grid_bounds : Sequence [float ] = (0.0 , math . pi ),
24882486 enclose_domain : bool = False ,
24892487 ) -> SphericalMesh :
24902488 """Create SphericalMesh from a bounding box.
@@ -2645,10 +2643,82 @@ def _convert_to_cartesian(arr, origin: Sequence[float]):
26452643 arr [..., 2 ] = z + origin [2 ]
26462644 return arr
26472645
2648- def get_indices_at_coords (self , coords : Sequence [float ]) -> tuple :
2649- raise NotImplementedError (
2650- "get_indices_at_coords is not yet implemented for SphericalMesh"
2651- )
2646+ def get_indices_at_coords (
2647+ self ,
2648+ coords : Sequence [float ]
2649+ ) -> tuple [int , int , int ]:
2650+ """Find the mesh cell indices containing the specified coordinates.
2651+
2652+ .. versionadded:: 0.15.4
2653+
2654+ Parameters
2655+ ----------
2656+ coords : Sequence[float]
2657+ Cartesian coordinates of the point as (x, y, z).
2658+
2659+ Returns
2660+ -------
2661+ tuple[int, int, int]
2662+ The r, theta, phi indices.
2663+
2664+ Raises
2665+ ------
2666+ ValueError
2667+ If the coordinates fall outside the mesh grid boundaries.
2668+
2669+ """
2670+ dx = coords [0 ] - self .origin [0 ]
2671+ dy = coords [1 ] - self .origin [1 ]
2672+ dz = coords [2 ] - self .origin [2 ]
2673+
2674+ r_value = math .hypot (dx , dy , dz )
2675+
2676+ if r_value < self .r_grid [0 ] or r_value > self .r_grid [- 1 ]:
2677+ raise ValueError (
2678+ f'The r value { r_value } computed from the specified '
2679+ f'coordinates is outside the r grid range '
2680+ f'[{ self .r_grid [0 ]} , { self .r_grid [- 1 ]} ].'
2681+ )
2682+
2683+ r_index = int (min (
2684+ np .searchsorted (self .r_grid , r_value , side = 'right' ) - 1 ,
2685+ len (self .r_grid ) - 2
2686+ ))
2687+
2688+ if r_value == 0.0 :
2689+ theta_value = 0.0
2690+ phi_value = 0.0
2691+ else :
2692+ theta_value = math .acos (dz / r_value )
2693+ phi_value = math .atan2 (dy , dx )
2694+ if phi_value < 0 :
2695+ phi_value += 2 * math .pi
2696+
2697+ if theta_value < self .theta_grid [0 ] or theta_value > self .theta_grid [- 1 ]:
2698+ raise ValueError (
2699+ f'The theta value { theta_value } computed from the specified '
2700+ f'coordinates is outside the theta grid range '
2701+ f'[{ self .theta_grid [0 ]} , { self .theta_grid [- 1 ]} ].'
2702+ )
2703+
2704+ theta_index = int (min (
2705+ np .searchsorted (self .theta_grid , theta_value , side = 'right' ) - 1 ,
2706+ len (self .theta_grid ) - 2
2707+ ))
2708+
2709+ if phi_value < self .phi_grid [0 ] or phi_value > self .phi_grid [- 1 ]:
2710+ raise ValueError (
2711+ f'The phi value { phi_value } computed from the specified '
2712+ f'coordinates is outside the phi grid range '
2713+ f'[{ self .phi_grid [0 ]} , { self .phi_grid [- 1 ]} ].'
2714+ )
2715+
2716+ phi_index = int (min (
2717+ np .searchsorted (self .phi_grid , phi_value , side = 'right' ) - 1 ,
2718+ len (self .phi_grid ) - 2
2719+ ))
2720+
2721+ return (r_index , theta_index , phi_index )
26522722
26532723
26542724def require_statepoint_data (func ):
0 commit comments