Skip to content

Commit aca999d

Browse files
get indeces for rectilinear meshes
1 parent 4bda85f commit aca999d

2 files changed

Lines changed: 72 additions & 4 deletions

File tree

openmc/mesh.py

Lines changed: 39 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1688,10 +1688,45 @@ def to_xml_element(self):
16881688

16891689
return element
16901690

1691-
def get_indices_at_coords(self, coords: Sequence[float]) -> tuple:
1692-
raise NotImplementedError(
1693-
"get_indices_at_coords is not yet implemented for RectilinearMesh"
1694-
)
1691+
def get_indices_at_coords(self, coords: Sequence[float]) -> tuple[int, int, int]:
1692+
"""Find the mesh cell indices containing the specified coordinates.
1693+
1694+
Parameters
1695+
----------
1696+
coords : Sequence[float]
1697+
Cartesian coordinates of the point as (x, y, z).
1698+
1699+
Returns
1700+
-------
1701+
tuple[int, int, int]
1702+
Mesh indices (ix, iy, iz).
1703+
1704+
Raises
1705+
------
1706+
ValueError
1707+
If coords does not contain exactly 3 values, or if a coordinate is
1708+
outside the mesh grid boundaries.
1709+
"""
1710+
if len(coords) != 3:
1711+
raise ValueError(
1712+
f"coords must contain exactly 3 values for a rectilinear mesh, "
1713+
f"got {len(coords)}"
1714+
)
1715+
1716+
grids = (self.x_grid, self.y_grid, self.z_grid)
1717+
indices = []
1718+
1719+
for grid, value in zip(grids, coords):
1720+
if value < grid[0] or value > grid[-1]:
1721+
raise ValueError(
1722+
f"Coordinate value {value} is outside the mesh grid boundaries: "
1723+
f"[{grid[0]}, {grid[-1]}]"
1724+
)
1725+
1726+
idx = np.searchsorted(grid, value, side="right") - 1
1727+
indices.append(int(min(idx, len(grid) - 2)))
1728+
1729+
return tuple(indices)
16951730

16961731

16971732
class CylindricalMesh(StructuredMesh):

tests/unit_tests/test_mesh.py

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -994,3 +994,36 @@ def test_regular_mesh_get_indices_at_coords():
994994
assert isinstance(result_1d, tuple)
995995
assert len(result_1d) == 1
996996
assert result_1d == (5,)
997+
998+
def test_rectilinear_mesh_get_indices_at_coords():
999+
"""Test get_indices_at_coords method for RectilinearMesh"""
1000+
# Create a 3x2x2 rectilinear mesh with non-uniform spacing
1001+
mesh = openmc.RectilinearMesh()
1002+
mesh.x_grid = [0., 1., 5., 10.]
1003+
mesh.y_grid = [-10., -5., 0.]
1004+
mesh.z_grid = [-100., 0., 100.]
1005+
1006+
# Test lower-left corner maps to first voxel (0, 0, 0)
1007+
assert mesh.get_indices_at_coords([0.0, -10., -100.]) == (0, 0, 0)
1008+
1009+
# Test centroid of first voxel
1010+
assert mesh.get_indices_at_coords([0.5, -7.5, -50.]) == (0, 0, 0)
1011+
1012+
# Test centroid of last voxel maps correctly
1013+
assert mesh.get_indices_at_coords([7.5, -2.5, 50.]) == (2, 1, 1)
1014+
1015+
# Test upper_right corner maps to last voxel
1016+
assert mesh.get_indices_at_coords([10., 0., 100.]) == (2, 1, 1)
1017+
1018+
# Test a middle voxel
1019+
assert mesh.get_indices_at_coords([2., -5., 0.]) == (1, 1, 1)
1020+
1021+
# Test coordinates outside mesh bounds raise ValueError
1022+
with pytest.raises(ValueError):
1023+
mesh.get_indices_at_coords([-0.5, 0.5, 0.5])
1024+
with pytest.raises(ValueError):
1025+
mesh.get_indices_at_coords([1.5, 0.5, 0.5])
1026+
with pytest.raises(ValueError):
1027+
mesh.get_indices_at_coords([0.5, -0.5, 110.])
1028+
with pytest.raises(ValueError):
1029+
mesh.get_indices_at_coords([0.5, -20., 110.])

0 commit comments

Comments
 (0)