|
5 | 5 | import pytest |
6 | 6 | import openmc |
7 | 7 | import openmc.lib |
| 8 | +import h5py |
8 | 9 | from openmc.utility_funcs import change_directory |
9 | 10 |
|
10 | 11 | pytestmark = pytest.mark.skipif( |
@@ -258,6 +259,86 @@ def test_dagmc_xml_reject_region_override(): |
258 | 259 | openmc.DAGMCUniverse.from_xml_element(elem, mats) |
259 | 260 |
|
260 | 261 |
|
| 262 | +def test_dagmc_length_multiplier_xml_roundtrip(): |
| 263 | + dagmc_u = openmc.DAGMCUniverse(filename="dagmc.h5m", universe_id=100, length_multiplier=0.1) |
| 264 | + root = ET.Element('geometry') |
| 265 | + dagmc_u.create_xml_subelement(root) |
| 266 | + dagmc_elem = root.find('dagmc_universe') |
| 267 | + assert dagmc_elem.get('length_multiplier') == '0.1' |
| 268 | + dagmc_u_roundtrip = openmc.DAGMCUniverse.from_xml_element(dagmc_elem) |
| 269 | + assert dagmc_u_roundtrip.length_multiplier == 0.1 |
| 270 | + default_elem = ET.fromstring('<dagmc_universe id="100" filename="dagmc.h5m"/>') |
| 271 | + default_univ = openmc.DAGMCUniverse.from_xml_element(default_elem) |
| 272 | + assert default_univ.length_multiplier == 1.0 |
| 273 | + |
| 274 | + |
| 275 | +def test_dagmc_length_multiplier_from_hdf5(run_in_tmpdir): |
| 276 | + # length_multiplier explicitly defined |
| 277 | + with h5py.File("test_dagmc.h5", "w") as f: |
| 278 | + g = f.create_group("geometry/universe 100") |
| 279 | + g.create_dataset("filename", data=np.bytes_("dagmc.h5m")) |
| 280 | + g.attrs["auto_geom_ids"] = np.int32(0) |
| 281 | + g.attrs["auto_mat_ids"] = np.int32(0) |
| 282 | + g.attrs["length_multiplier"] = 0.1 |
| 283 | + |
| 284 | + with h5py.File("test_dagmc.h5", "r") as f: |
| 285 | + u = openmc.DAGMCUniverse.from_hdf5(f["geometry/universe 100"]) |
| 286 | + |
| 287 | + assert u.id == 100 |
| 288 | + assert u.filename == Path("dagmc.h5m") |
| 289 | + assert u.length_multiplier == pytest.approx(0.1) |
| 290 | + |
| 291 | + # length_multiplier not defined - should default to 1.0 |
| 292 | + with h5py.File("test_dagmc_default.h5", "w") as f: |
| 293 | + g = f.create_group("geometry/universe 101") |
| 294 | + g.create_dataset("filename", data=np.bytes_("dagmc.h5m")) |
| 295 | + g.attrs["auto_geom_ids"] = np.int32(0) |
| 296 | + g.attrs["auto_mat_ids"] = np.int32(0) |
| 297 | + |
| 298 | + with h5py.File("test_dagmc_default.h5", "r") as f: |
| 299 | + u_default = openmc.DAGMCUniverse.from_hdf5(f["geometry/universe 101"]) |
| 300 | + |
| 301 | + assert u_default.id == 101 |
| 302 | + assert u_default.filename == Path("dagmc.h5m") |
| 303 | + assert u_default.length_multiplier == 1.0 |
| 304 | + |
| 305 | + |
| 306 | +def test_dagmc_length_multiplier_hdf5_roundtrip(request): |
| 307 | + p = Path(request.fspath).parent / "dagmc_sphere_r5.h5m" |
| 308 | + |
| 309 | + daguniv = openmc.DAGMCUniverse(p, auto_geom_ids=True, length_multiplier=0.5) |
| 310 | + root = daguniv.bounded_universe() |
| 311 | + |
| 312 | + mat = openmc.Material(name="test_mat") |
| 313 | + mat.add_nuclide("H1", 1.0) |
| 314 | + mat.set_density("g/cm3", 1.0) |
| 315 | + |
| 316 | + settings = openmc.Settings() |
| 317 | + settings.batches = 100 |
| 318 | + settings.inactive = 10 |
| 319 | + settings.particles = 1000 |
| 320 | + ll, ur = daguniv.bounding_box |
| 321 | + |
| 322 | + model = openmc.Model() |
| 323 | + model.geometry = openmc.Geometry(root) |
| 324 | + model.materials = openmc.Materials([mat]) |
| 325 | + model.settings = settings |
| 326 | + |
| 327 | + with change_directory(tmpdir=True): |
| 328 | + try: |
| 329 | + model.init_lib() |
| 330 | + model.sync_dagmc_universes() |
| 331 | + summary = openmc.Summary("summary.h5") |
| 332 | + finally: |
| 333 | + model.finalize_lib() |
| 334 | + openmc.reset_auto_ids() |
| 335 | + |
| 336 | + all_univs = summary.geometry.get_all_universes() |
| 337 | + u = all_univs[daguniv.id] |
| 338 | + assert isinstance(u, openmc.DAGMCUniverse) |
| 339 | + assert u.length_multiplier == pytest.approx(0.5) |
| 340 | + |
| 341 | + |
261 | 342 | def _legacy_xml(cell_overrides): |
262 | 343 | """Helper to build a <dagmc_universe> with old-format <material_overrides>.""" |
263 | 344 | inner = ''.join( |
@@ -363,3 +444,51 @@ def test_dagmc_xml_temperature_roundtrip(): |
363 | 444 | dag_univ_roundtrip = openmc.DAGMCUniverse.from_xml_element(dagmc_elem, mats) |
364 | 445 | assert dag_univ_roundtrip.cells[7].fill.id == 1 |
365 | 446 | assert dag_univ_roundtrip.cells[7].temperature == pytest.approx(825.0) |
| 447 | + |
| 448 | + |
| 449 | +def test_dagmc_length_multiplier_volume_scaling(request): |
| 450 | + """Stochastic volume of a DAGMC sphere should scale as length_multiplier^3. |
| 451 | + A DAGMC sphere with radius 5 cm (and no graveyard) is checked against the |
| 452 | + analytical volume (4/3 * pi * r^3) for length_multiplier values of 1.0 and 10.0. |
| 453 | + """ |
| 454 | + p = Path(request.fspath).parent / "dagmc_sphere_r5.h5m" |
| 455 | + n_samples = 1000000 |
| 456 | + |
| 457 | + def _compute_sphere_volume(length_multiplier): |
| 458 | + openmc.reset_auto_ids() |
| 459 | + daguniv = openmc.DAGMCUniverse(p, auto_geom_ids=True, |
| 460 | + length_multiplier=length_multiplier) |
| 461 | + root = daguniv.bounded_universe() |
| 462 | + |
| 463 | + mat = openmc.Material(name="test_mat") |
| 464 | + mat.add_nuclide("H1", 1.0) |
| 465 | + mat.set_density("g/cm3", 1.0) |
| 466 | + |
| 467 | + settings = openmc.Settings() |
| 468 | + settings.batches = 100 |
| 469 | + settings.inactive = 10 |
| 470 | + settings.particles = 1000 |
| 471 | + ll, ur = daguniv.bounding_box |
| 472 | + vol_calc = openmc.VolumeCalculation([mat], n_samples, ll, ur) |
| 473 | + settings.volume_calculations = [vol_calc] |
| 474 | + model = openmc.Model() |
| 475 | + model.geometry = openmc.Geometry(root) |
| 476 | + model.materials = openmc.Materials([mat]) |
| 477 | + model.settings = settings |
| 478 | + with change_directory(tmpdir=True): |
| 479 | + try: |
| 480 | + model.init_lib() |
| 481 | + model.sync_dagmc_universes() |
| 482 | + model.calculate_volumes() |
| 483 | + finally: |
| 484 | + model.finalize_lib() |
| 485 | + openmc.reset_auto_ids() |
| 486 | + return mat.volume |
| 487 | + |
| 488 | + v1 = _compute_sphere_volume(length_multiplier=1.0) |
| 489 | + v10 = _compute_sphere_volume(length_multiplier=10.0) |
| 490 | + expected_v1 = 4.0 / 3.0 * np.pi * 5.0**3 |
| 491 | + expected_v10 = expected_v1 * 10.0**3 |
| 492 | + assert v1 == pytest.approx(expected_v1, rel=0.02) |
| 493 | + assert v10 == pytest.approx(expected_v10, rel=0.02) |
| 494 | + assert v10 / v1 == pytest.approx(10.0**3, rel=0.02) |
0 commit comments