OpenMC/tests/unit_tests/dagmc/test_model.py
2025-11-27 10:03:38 -06:00

258 lines
9.1 KiB
Python

from pathlib import Path
import lxml.etree as ET
import numpy as np
import pytest
import openmc
import openmc.lib
from openmc.utility_funcs import change_directory
pytestmark = pytest.mark.skipif(
not openmc.lib._dagmc_enabled(),
reason="DAGMC CAD geometry is not enabled.")
@pytest.fixture()
def model(request):
pitch = 1.26
mats = {}
mats["no-void fuel"] = openmc.Material(1, name="no-void fuel")
mats["no-void fuel"].add_nuclide("U235", 0.03)
mats["no-void fuel"].add_nuclide("U238", 0.97)
mats["no-void fuel"].add_nuclide("O16", 2.0)
mats["no-void fuel"].set_density("g/cm3", 10.0)
mats["41"] = openmc.Material(name="41")
mats["41"].add_nuclide("H1", 2.0)
mats["41"].add_element("O", 1.0)
mats["41"].set_density("g/cm3", 1.0)
mats["41"].add_s_alpha_beta("c_H_in_H2O")
p = Path(request.fspath).parent / "dagmc.h5m"
daguniv = openmc.DAGMCUniverse(p, name='simple-dagmc', auto_geom_ids=True)
lattice = openmc.RectLattice()
lattice.dimension = [2, 2]
lattice.lower_left = [-pitch, -pitch]
lattice.pitch = [pitch, pitch]
lattice.universes = [
[daguniv, daguniv],
[daguniv, daguniv]]
box = openmc.model.RectangularParallelepiped(-pitch, pitch, -pitch, pitch, -5, 5)
root = openmc.Universe(cells=[openmc.Cell(region=-box, fill=lattice)])
settings = openmc.Settings()
settings.batches = 100
settings.inactive = 10
settings.particles = 1000
ll, ur = root.bounding_box
mat_vol = openmc.VolumeCalculation([mats["no-void fuel"]], 1000000, ll, ur)
cell_vol = openmc.VolumeCalculation(list(root.cells.values()), 1000000, ll, ur)
settings.volume_calculations = [mat_vol, cell_vol]
model = openmc.Model()
model.materials = openmc.Materials(mats.values())
model.geometry = openmc.Geometry(root=root)
model.settings = settings
with change_directory(tmpdir=True):
try:
model.init_lib()
model.sync_dagmc_universes()
yield model
finally:
model.finalize_lib()
openmc.reset_auto_ids()
def test_dagmc_replace_material_assignment(model):
mats = {}
mats["foo"] = openmc.Material(name="foo")
mats["foo"].add_nuclide("H1", 2.0)
mats["foo"].add_element("O", 1.0)
mats["foo"].set_density("g/cm3", 1.0)
mats["foo"].add_s_alpha_beta("c_H_in_H2O")
for univ in model.geometry.get_all_universes().values():
if not isinstance(univ, openmc.DAGMCUniverse):
break
cells_with_41 = []
for cell in univ.cells.values():
if cell.fill is None:
continue
if cell.fill.name == "41":
cells_with_41.append(cell.id)
univ.replace_material_assignment("41", mats["foo"])
for cell_id in cells_with_41:
assert univ.cells[cell_id] == mats["foo"]
def test_dagmc_add_material_override_with_id(model):
mats = {}
mats["foo"] = openmc.Material(name="foo")
mats["foo"].add_nuclide("H1", 2.0)
mats["foo"].add_element("O", 1.0)
mats["foo"].set_density("g/cm3", 1.0)
mats["foo"].add_s_alpha_beta("c_H_in_H2O")
for univ in model.geometry.get_all_universes().values():
if not isinstance(univ, openmc.DAGMCUniverse):
break
cells_with_41 = []
for cell in univ.cells.values():
if cell.fill is None:
continue
if cell.fill.name == "41":
cells_with_41.append(cell.id)
univ.add_material_override(cell.id, mats["foo"])
for cell_id in cells_with_41:
assert univ.cells[cell_id] == mats["foo"]
def test_dagmc_add_material_override_with_cell(model):
mats = {}
mats["foo"] = openmc.Material(name="foo")
mats["foo"].add_nuclide("H1", 2.0)
mats["foo"].add_element("O", 1.0)
mats["foo"].set_density("g/cm3", 1.0)
mats["foo"].add_s_alpha_beta("c_H_in_H2O")
for univ in model.geometry.get_all_universes().values():
if not isinstance(univ, openmc.DAGMCUniverse):
break
cells_with_41 = []
for cell in univ.cells.values():
if cell.fill is None:
continue
if cell.fill.name == "41":
cells_with_41.append(cell.id)
univ.add_material_override(cell, mats["foo"])
for cell_id in cells_with_41:
assert univ.cells[cell_id] == mats["foo"]
def test_model_differentiate_depletable_with_dagmc(model, run_in_tmpdir):
model.calculate_volumes()
# Get the volume of the no-void fuel material before differentiation
volume_before = np.sum([m.volume for m in model.materials if m.name == "no-void fuel"])
# Differentiate the depletable materials
model.differentiate_depletable_mats(diff_volume_method="divide equally")
# Get the volume of the no-void fuel material after differentiation
volume_after = np.sum([m.volume for m in model.materials if "fuel" in m.name])
assert np.isclose(volume_before, volume_after)
assert len(model.materials) == 4*2 +1
def test_model_differentiate_with_dagmc(model):
root = model.geometry.root_universe
ll, ur = root.bounding_box
model.calculate_volumes()
# Get the volume of the no-void fuel material before differentiation
volume_before = np.sum([m.volume for m in model.materials if m.name == "no-void fuel"])
# Differentiate all the materials
model.differentiate_mats(depletable_only=False)
# Get the volume of the no-void fuel material after differentiation
mat_vol = openmc.VolumeCalculation(model.materials, 1000000, ll, ur)
model.settings.volume_calculations = [mat_vol]
model.init_lib() # need to reinitialize the lib after differentiating the materials
model.calculate_volumes()
volume_after = np.sum([m.volume for m in model.materials if "fuel" in m.name])
assert np.isclose(volume_before, volume_after)
assert len(model.materials) == 4*2 + 4
def test_bad_override_cell_id(model):
for univ in model.geometry.get_all_universes().values():
if isinstance(univ, openmc.DAGMCUniverse):
break
with pytest.raises(ValueError, match="Cell ID '1' not found in DAGMC universe"):
univ.material_overrides = {1: model.materials[0]}
def test_bad_override_type(model):
not_a_dag_cell = openmc.Cell()
for univ in model.geometry.get_all_universes().values():
if isinstance(univ, openmc.DAGMCUniverse):
break
with pytest.raises(ValueError, match="Unrecognized key type. Must be an integer or openmc.DAGMCCell object"):
univ.material_overrides = {not_a_dag_cell: model.materials[0]}
def test_bad_replacement_mat_name(model):
for univ in model.geometry.get_all_universes().values():
if isinstance(univ, openmc.DAGMCUniverse):
break
with pytest.raises(ValueError, match="No material with name 'not_a_mat' found in the DAGMC universe"):
univ.replace_material_assignment("not_a_mat", model.materials[0])
def test_dagmc_xml(model):
# Set the environment
mats = {}
mats["no-void fuel"] = openmc.Material(1, name="no-void fuel")
mats["no-void fuel"].add_nuclide("U235", 0.03)
mats["no-void fuel"].add_nuclide("U238", 0.97)
mats["no-void fuel"].add_nuclide("O16", 2.0)
mats["no-void fuel"].set_density("g/cm3", 10.0)
mats[5] = openmc.Material(name="41")
mats[5].add_nuclide("H1", 2.0)
mats[5].add_element("O", 1.0)
mats[5].set_density("g/cm3", 1.0)
mats[5].add_s_alpha_beta("c_H_in_H2O")
for univ in model.geometry.get_all_universes().values():
if isinstance(univ, openmc.DAGMCUniverse):
dag_univ = univ
break
for k, v in mats.items():
if isinstance(k, int):
dag_univ.add_material_override(k, v)
model.materials.append(v)
elif isinstance(k, str):
dag_univ.replace_material_assignment(k, v)
# Tesing the XML subelement generation
root = ET.Element('dagmc_universe')
dag_univ.create_xml_subelement(root)
dagmc_ele = root.find('dagmc_universe')
assert dagmc_ele.get('id') == str(dag_univ.id)
assert dagmc_ele.get('name') == str(dag_univ.name)
assert dagmc_ele.get('filename') == str(dag_univ.filename)
assert dagmc_ele.get('auto_geom_ids') == str(dag_univ.auto_geom_ids).lower()
override_eles = dagmc_ele.find('material_overrides').findall('cell_override')
assert len(override_eles) == 4
for i, override_ele in enumerate(override_eles):
cell_id = override_ele.get('id')
assert dag_univ.material_overrides[int(cell_id)][0].id == int(override_ele.find('material_ids').text)
model.export_to_model_xml()
xml_model = openmc.Model.from_model_xml()
for univ in xml_model.geometry.get_all_universes().values():
if isinstance(univ, openmc.DAGMCUniverse):
xml_dagmc_univ = univ
break
assert xml_dagmc_univ._material_overrides.keys() == dag_univ._material_overrides.keys()
for xml_mats, model_mats in zip(xml_dagmc_univ._material_overrides.values(), dag_univ._material_overrides.values()):
assert all([xml_mat.id == orig_mat.id for xml_mat, orig_mat in zip(xml_mats, model_mats)])