diff --git a/openmc/universe.py b/openmc/universe.py index 3ef9e66509..4aa1775fb1 100644 --- a/openmc/universe.py +++ b/openmc/universe.py @@ -2,7 +2,7 @@ from abc import ABC, abstractmethod from collections import OrderedDict from collections.abc import Iterable from copy import deepcopy -from numbers import Real +from numbers import Integral, Real from pathlib import Path from tempfile import TemporaryDirectory from xml.etree import ElementTree as ET @@ -678,7 +678,7 @@ class DAGMCUniverse(UniverseBase): @filename.setter def filename(self, val): - cv.check_type('DAGMC filename', val, str) + cv.check_type('DAGMC filename', val, (Path, str)) self._filename = val @property @@ -720,10 +720,10 @@ class DAGMCUniverse(UniverseBase): dagmc_element.set('auto_geom_ids', 'true') if self.auto_mat_ids: dagmc_element.set('auto_mat_ids', 'true') - dagmc_element.set('filename', self.filename) + dagmc_element.set('filename', str(self.filename)) xml_element.append(dagmc_element) - def bounding_region(self, bounded_type='box', boundary_type='vacuum'): + def bounding_region(self, bounded_type='box', boundary_type='vacuum', starting_id=10000): """Creates a either a spherical or box shaped bounding region around the DAGMC geometry. Parameters @@ -736,6 +736,10 @@ class DAGMCUniverse(UniverseBase): Boundary condition that defines the behavior for particles hitting the surface. Defaults to vacuum boundary condition. Passed into the surface construction. + starting_id : int + Starting ID of the surface(s) used in the region. For bounded_type + 'box', the next 5 IDs will also be used. Defaults to 10000 to reduce + the chance of an overlap of surface IDs with the DAGMC geometry. Returns ------- openmc.Region @@ -744,19 +748,20 @@ class DAGMCUniverse(UniverseBase): check_type('boundary type', boundary_type, str) check_value('boundary type', boundary_type, _BOUNDARY_TYPES) + check_type('starting surface id', starting_id, Integral) check_type('bounded type', bounded_type, str) check_value('bounded type', bounded_type, ('box', 'sphere')) - bounding_box = self.bounding_box + bbox = self.bounding_box if bounded_type == 'sphere': - import math - bounding_box_center = (bounding_box[0] + bounding_box[1])/2 - radius = math.dist(bounding_box[0], bounding_box[1]) + bbox_center = (bbox[0] + bbox[1])/2 + radius = np.linalg.norm(np.asarray(bbox)) bounding_surface = openmc.Sphere( - x0=bounding_box_center[0], - y0=bounding_box_center[1], - z0=bounding_box_center[2], + surface_id=starting_id, + x0=bbox_center[0], + y0=bbox_center[1], + z0=bbox_center[2], boundary_type=boundary_type, r=radius, ) @@ -765,14 +770,19 @@ class DAGMCUniverse(UniverseBase): if bounded_type == 'box': # defines plane surfaces for all six faces of the bounding box - lower_x = openmc.XPlane(bounding_box[0][0], boundary_type=boundary_type) - upper_x = openmc.XPlane(bounding_box[1][0], boundary_type=boundary_type) - lower_y = openmc.YPlane(bounding_box[0][1], boundary_type=boundary_type) - upper_y = openmc.YPlane(bounding_box[1][1], boundary_type=boundary_type) - lower_z = openmc.ZPlane(bounding_box[0][2], boundary_type=boundary_type) - upper_z = openmc.ZPlane(bounding_box[1][2], boundary_type=boundary_type) + lower_x = openmc.XPlane(bbox[0][0], surface_id=starting_id) + upper_x = openmc.XPlane(bbox[1][0], surface_id=starting_id+1) + lower_y = openmc.YPlane(bbox[0][1], surface_id=starting_id+2) + upper_y = openmc.YPlane(bbox[1][1], surface_id=starting_id+3) + lower_z = openmc.ZPlane(bbox[0][2], surface_id=starting_id+4) + upper_z = openmc.ZPlane(bbox[1][2], surface_id=starting_id+5) - return +lower_x & -upper_x & +lower_y & -upper_y & +lower_z & -upper_z + region = +lower_x & -upper_x & +lower_y & -upper_y & +lower_z & -upper_z + + for surface in region.get_surfaces().values(): + surface.boundary_type = boundary_type + + return region def bounded_universe(self, bounding_cell_id=10000, **kwargs): """Returns an openmc.Universe filled with this DAGMCUniverse and bounded @@ -783,7 +793,7 @@ class DAGMCUniverse(UniverseBase): Parameters ---------- bounding_cell_id : int - The cell ID number to use for the bounding cell, defaults to 1000 to reduce + The cell ID number to use for the bounding cell, defaults to 10000 to reduce the chance of overlapping ID numbers with the DAGMC geometry. Returns @@ -791,7 +801,6 @@ class DAGMCUniverse(UniverseBase): openmc.Universe Universe instance """ - bounding_cell = openmc.Cell(fill=self, cell_id=bounding_cell_id, region=self.bounding_region(**kwargs)) return openmc.Universe(cells=[bounding_cell]) diff --git a/tests/regression_tests/dagmc/legacy/test.py b/tests/regression_tests/dagmc/legacy/test.py index e0fccb9344..dacbc19ee0 100644 --- a/tests/regression_tests/dagmc/legacy/test.py +++ b/tests/regression_tests/dagmc/legacy/test.py @@ -1,6 +1,7 @@ import openmc import openmc.lib +from pathlib import Path import pytest from tests.testing_harness import PyAPITestHarness @@ -27,7 +28,7 @@ def model(): model.settings.dagmc = True # geometry - dag_univ = openmc.DAGMCUniverse("dagmc.h5m") + dag_univ = openmc.DAGMCUniverse(Path("dagmc.h5m")) model.geometry = openmc.Geometry(dag_univ) # tally diff --git a/tests/regression_tests/dagmc/universes/inputs_true.dat b/tests/regression_tests/dagmc/universes/inputs_true.dat index 2165a78b6c..ea6ad519bb 100644 --- a/tests/regression_tests/dagmc/universes/inputs_true.dat +++ b/tests/regression_tests/dagmc/universes/inputs_true.dat @@ -1,6 +1,6 @@ - + 24.0 24.0 @@ -10,12 +10,12 @@ 9 9 9 9 - - - - - - + + + + + + diff --git a/tests/regression_tests/dagmc/universes/test.py b/tests/regression_tests/dagmc/universes/test.py index f2eb3882f2..47897ad568 100644 --- a/tests/regression_tests/dagmc/universes/test.py +++ b/tests/regression_tests/dagmc/universes/test.py @@ -53,25 +53,6 @@ class DAGMCUniverseTest(PyAPITestHarness): # assigns the bound_dag_geometry to the model to test the type checks in model.Geometry setter model.Geometry = bound_pincell_geometry - # checks that the bounding box is calculated correctly - bounding_box = pincell_univ.bounding_box - assert bounding_box[0].tolist() == [-25., -25., -25.] - assert bounding_box[1].tolist() == [25., 25., 25.] - - # checks that the bounding region is six surfaces each with a vacuum boundary type - b_region = pincell_univ.bounding_region(bounded_type='box', boundary_type='vacuum') - assert isinstance(b_region, openmc.Region) - assert len(b_region.get_surfaces()) == 6 - for surface in list(b_region.get_surfaces().values()): - assert surface.boundary_type == 'vacuum' - - # checks that the bounding region is a single surface with a reflective boundary type - b_region = pincell_univ.bounding_region(bounded_type='sphere', boundary_type='reflective') - assert isinstance(b_region, openmc.Region) - assert len(b_region.get_surfaces()) == 1 - for surface in list(b_region.get_surfaces().values()): - assert surface.boundary_type == 'reflective' - # create a 2 x 2 lattice using the DAGMC pincell pitch = np.asarray((24.0, 24.0)) lattice = openmc.RectLattice() diff --git a/tests/unit_tests/dagmc/test_bounds.py b/tests/unit_tests/dagmc/test_bounds.py new file mode 100644 index 0000000000..dbca3ca253 --- /dev/null +++ b/tests/unit_tests/dagmc/test_bounds.py @@ -0,0 +1,73 @@ +import openmc +import pytest +from pathlib import Path + + +def test_bounding_box(request): + """Checks that the DAGMCUniverse.bounding_box returns the correct values""" + + u = openmc.DAGMCUniverse(Path(request.fspath).parent / "dagmc.h5m") + + ll, ur = u.bounding_box + assert ll == pytest.approx((-25.0, -25.0, -25)) + assert ur == pytest.approx((25.0, 25.0, 25)) + + +def test_bounding_region(request): + """Checks that the DAGMCUniverse.bounding_region() returns a region with + correct surfaces and boundary types""" + + u = openmc.DAGMCUniverse(Path(request.fspath).parent / "dagmc.h5m") + + region = u.bounding_region() # should default to bounded_type='box' + assert isinstance(region, openmc.Region) + assert len(region) == 6 + assert region[0].surface.type == "x-plane" + assert region[1].surface.type == "x-plane" + assert region[2].surface.type == "y-plane" + assert region[3].surface.type == "y-plane" + assert region[4].surface.type == "z-plane" + assert region[5].surface.type == "z-plane" + assert region[0].surface.boundary_type == "vacuum" + assert region[1].surface.boundary_type == "vacuum" + assert region[2].surface.boundary_type == "vacuum" + assert region[3].surface.boundary_type == "vacuum" + assert region[4].surface.boundary_type == "vacuum" + assert region[5].surface.boundary_type == "vacuum" + + region = u.bounding_region(bounded_type="sphere", boundary_type="reflective") + assert isinstance(region, openmc.Region) + assert isinstance(region, openmc.Halfspace) + assert region.surface.type == "sphere" + assert region.surface.boundary_type == "reflective" + + +def test_bounded_universe(request): + """Checks that the DAGMCUniverse.bounded_universe() returns a + openmc.Universe with correct surface ids and cell ids""" + + u = openmc.DAGMCUniverse(Path(request.fspath).parent / "dagmc.h5m") + + # bounded with defaults + bu = u.bounded_universe() + + cells = list(bu.get_all_cells().items()) + assert isinstance(bu, openmc.Universe) + assert len(cells) == 1 + assert cells[0][0] == 10000 # default bounding_cell_id is 10000 + assert cells[0][1].id == 10000 # default bounding_cell_id is 10000 + surfaces = list(cells[0][1].region.get_surfaces().items()) + assert len(surfaces) == 6 + assert surfaces[0][1].id == 10000 + + # bounded with non defaults + bu = u.bounded_universe(bounding_cell_id=42, bounded_type="sphere", starting_id=43) + + cells = list(bu.get_all_cells().items()) + assert isinstance(bu, openmc.Universe) + assert len(cells) == 1 + assert cells[0][0] == 42 # default bounding_cell_id is 10000 + assert cells[0][1].id == 42 # default bounding_cell_id is 10000 + surfaces = list(cells[0][1].region.get_surfaces().items()) + assert surfaces[0][1].type == "sphere" + assert surfaces[0][1].id == 43