Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
63 changes: 38 additions & 25 deletions openmc/mesh.py
Original file line number Diff line number Diff line change
Expand Up @@ -1179,7 +1179,7 @@ def from_rect_lattice(
@classmethod
def from_domain(
cls,
domain: HasBoundingBox,
domain: HasBoundingBox | BoundingBox,
dimension: Sequence[int] | int = 1000,
mesh_id: int | None = None,
name: str = ''
Expand All @@ -1188,10 +1188,12 @@ def from_domain(

Parameters
----------
domain : HasBoundingBox
domain : HasBoundingBox | openmc.BoundingBox
The object passed in will be used as a template for this mesh. The
bounding box of the property of the object passed will be used to
set the lower_left and upper_right and of the mesh instance
set the lower_left and upper_right and of the mesh instance.
Alternatively, a :class:`openmc.BoundingBox` can be passed
directly.
dimension : Iterable of int | int
The number of mesh cells in total or number of mesh cells in each
direction (x, y, z). If a single integer is provided, the domain
Expand All @@ -1208,21 +1210,26 @@ def from_domain(
RegularMesh instance

"""
if not hasattr(domain, 'bounding_box'):
raise TypeError("Domain must have a bounding_box property")
if isinstance(domain, BoundingBox):
bb = domain
elif hasattr(domain, 'bounding_box'):
bb = domain.bounding_box
else:
raise TypeError("Domain must be a BoundingBox or have a "
"bounding_box property")

mesh = cls(mesh_id=mesh_id, name=name)
mesh.lower_left = domain.bounding_box[0]
mesh.upper_right = domain.bounding_box[1]
mesh.lower_left = bb[0]
mesh.upper_right = bb[1]
if isinstance(dimension, int):
cv.check_greater_than("dimension", dimension, 1, equality=True)
# If a single integer is provided, divide the domain into that many
# mesh cells with roughly equal lengths in each direction
ideal_cube_volume = domain.bounding_box.volume / dimension
ideal_cube_volume = bb.volume / dimension
ideal_cube_size = ideal_cube_volume ** (1 / 3)
dimension = [
max(1, int(round(side / ideal_cube_size)))
for side in domain.bounding_box.width
for side in bb.width
]
mesh.dimension = dimension

Expand Down Expand Up @@ -1887,7 +1894,7 @@ def from_hdf5(cls, group: h5py.Group, mesh_id: int, name: str):
@classmethod
def from_domain(
cls,
domain: HasBoundingBox,
domain: HasBoundingBox | BoundingBox,
dimension: Sequence[int] = (10, 10, 10),
mesh_id: int | None = None,
phi_grid_bounds: Sequence[float] = (0.0, 2*pi),
Expand All @@ -1898,10 +1905,11 @@ def from_domain(

Parameters
----------
domain : HasBoundingBox
domain : HasBoundingBox | openmc.BoundingBox
The object passed in will be used as a template for this mesh. The
bounding box of the property of the object passed will be used to
set the r_grid, z_grid ranges.
set the r_grid, z_grid ranges. Alternatively, a
:class:`openmc.BoundingBox` can be passed directly.
dimension : Iterable of int
The number of equally spaced mesh cells in each direction (r_grid,
phi_grid, z_grid)
Expand All @@ -1922,11 +1930,13 @@ def from_domain(
CylindricalMesh instance

"""
if not hasattr(domain, 'bounding_box'):
raise TypeError("Domain must have a bounding_box property")

# loaded once to avoid recalculating bounding box
cached_bb = domain.bounding_box
if isinstance(domain, BoundingBox):
cached_bb = domain
elif hasattr(domain, 'bounding_box'):
cached_bb = domain.bounding_box
else:
raise TypeError("Domain must be a BoundingBox or have a "
"bounding_box property")

if enclose_domain:
outer_radius = 0.5 * np.linalg.norm(cached_bb.width[:2])
Expand Down Expand Up @@ -2269,7 +2279,7 @@ def from_hdf5(cls, group: h5py.Group, mesh_id: int, name: str):
@classmethod
def from_domain(
cls,
domain: HasBoundingBox,
domain: HasBoundingBox | BoundingBox,
dimension: Sequence[int] = (10, 10, 10),
mesh_id: int | None = None,
phi_grid_bounds: Sequence[float] = (0.0, 2*pi),
Expand All @@ -2281,10 +2291,11 @@ def from_domain(

Parameters
----------
domain : HasBoundingBox
domain : HasBoundingBox | openmc.BoundingBox
The object passed in will be used as a template for this mesh. The
bounding box of the property of the object passed will be used to
set the r_grid, phi_grid, and theta_grid ranges.
set the r_grid, phi_grid, and theta_grid ranges. Alternatively, a
:class:`openmc.BoundingBox` can be passed directly.
dimension : Iterable of int
The number of equally spaced mesh cells in each direction (r_grid,
phi_grid, theta_grid). Spacing is in angular space (radians) for
Expand All @@ -2309,11 +2320,13 @@ def from_domain(
SphericalMesh instance

"""
if not hasattr(domain, 'bounding_box'):
raise TypeError("Domain must have a bounding_box property")

# loaded once to avoid recalculating bounding box
cached_bb = domain.bounding_box
if isinstance(domain, BoundingBox):
cached_bb = domain
elif hasattr(domain, 'bounding_box'):
cached_bb = domain.bounding_box
else:
raise TypeError("Domain must be a BoundingBox or have a "
"bounding_box property")

if enclose_domain:
outer_radius = 0.5 * np.linalg.norm(cached_bb.width)
Expand Down
11 changes: 11 additions & 0 deletions tests/unit_tests/test_mesh_from_domain.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,17 @@ def test_reg_mesh_from_cell():
assert np.array_equal(mesh.upper_right, cell.bounding_box[1])


def test_reg_mesh_from_bounding_box():
"""Tests a RegularMesh can be made from a BoundingBox directly."""
bb = openmc.BoundingBox([-8, -7, -5], [12, 13, 15])

mesh = openmc.RegularMesh.from_domain(domain=bb, dimension=[7, 11, 13])
assert isinstance(mesh, openmc.RegularMesh)
assert np.array_equal(mesh.dimension, (7, 11, 13))
assert np.array_equal(mesh.lower_left, bb[0])
assert np.array_equal(mesh.upper_right, bb[1])


def test_cylindrical_mesh_from_cell():
"""Tests a CylindricalMesh can be made from a Cell and the specified
dimensions are propagated through."""
Expand Down
Loading