From 4483583dddf291e6c324399511fbbccfd582e908 Mon Sep 17 00:00:00 2001 From: Jonathan Shimwell Date: Fri, 18 Jul 2025 08:46:13 +0200 Subject: [PATCH] automatically finding appropriate dimension when making regular mesh from domain (#3468) --- openmc/mesh.py | 19 +++++++++++++++--- tests/unit_tests/test_mesh_from_domain.py | 24 +++++++++++++++++++++++ 2 files changed, 40 insertions(+), 3 deletions(-) diff --git a/openmc/mesh.py b/openmc/mesh.py index 56fe2bd1c..339702884 100644 --- a/openmc/mesh.py +++ b/openmc/mesh.py @@ -1094,7 +1094,7 @@ class RegularMesh(StructuredMesh): def from_domain( cls, domain: HasBoundingBox, - dimension: Sequence[int] = (10, 10, 10), + dimension: Sequence[int] | int = 1000, mesh_id: int | None = None, name: str = '' ): @@ -1106,8 +1106,11 @@ class RegularMesh(StructuredMesh): 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 - dimension : Iterable of int - The number of mesh cells in each direction (x, y, z). + 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 + will will be divided into that many mesh cells with roughly equal + lengths in each direction (cubes). mesh_id : int Unique identifier for the mesh name : str @@ -1125,6 +1128,16 @@ class RegularMesh(StructuredMesh): mesh = cls(mesh_id=mesh_id, name=name) mesh.lower_left = domain.bounding_box[0] mesh.upper_right = domain.bounding_box[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_size = ideal_cube_volume ** (1 / 3) + dimension = [ + max(1, int(round(side / ideal_cube_size))) + for side in domain.bounding_box.width + ] mesh.dimension = dimension return mesh diff --git a/tests/unit_tests/test_mesh_from_domain.py b/tests/unit_tests/test_mesh_from_domain.py index 0e3858913..5b1173126 100644 --- a/tests/unit_tests/test_mesh_from_domain.py +++ b/tests/unit_tests/test_mesh_from_domain.py @@ -147,3 +147,27 @@ def test_reg_mesh_from_geometry(): def test_error_from_unsupported_object(): with pytest.raises(TypeError): openmc.RegularMesh.from_domain("vacuum energy") + + +def test_regularmesh_from_domain_error_from_small_dimensions(): + surface = openmc.Sphere(r=20) + cell = openmc.Cell(region=-surface) + with pytest.raises( + ValueError, match='Unable to set "dimension" to "-2" since it is less than "1"' + ): + openmc.RegularMesh.from_domain(domain=cell, dimension=-2) + + +def test_dimensions_from_domain_dimensions_from_int(): + region = openmc.model.RectangularParallelepiped( + xmin=-100, + xmax=150, + ymin=-50, + ymax=200, + zmin=300, + zmax=400, + boundary_type="vacuum", + ) + cell = openmc.Cell(region=-region) + mesh = openmc.RegularMesh.from_domain(domain=cell, dimension=1000) + assert mesh.dimension == (14, 14, 5)