allowing different volume methods for diff mat (#2691)

Co-authored-by: Paul Romano <paul.k.romano@gmail.com>
This commit is contained in:
Jonathan Shimwell 2023-09-26 01:37:25 +01:00 committed by GitHub
parent 0f429e7ea7
commit 989875b070
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 120 additions and 23 deletions

View file

@ -164,6 +164,13 @@ class CoupledOperator(OpenMCOperator):
``None`` implies no limit on the depth.
.. versionadded:: 0.12
diff_volume_method : str
Specifies how the volumes of the new materials should be found. Default
is to 'divide equally' which divides the original material volume
equally between the new materials, 'match cell' sets the volume of the
material to volume of the cell they fill.
.. versionadded:: 0.13.4
Attributes
----------
@ -206,8 +213,8 @@ class CoupledOperator(OpenMCOperator):
}
def __init__(self, model, chain_file=None, prev_results=None,
diff_burnable_mats=False, normalization_mode="fission-q",
fission_q=None,
diff_burnable_mats=False, diff_volume_method="divide equally",
normalization_mode="fission-q", fission_q=None,
fission_yield_mode="constant", fission_yield_opts=None,
reaction_rate_mode="direct", reaction_rate_opts=None,
reduce_chain=False, reduce_chain_level=None):
@ -257,15 +264,16 @@ class CoupledOperator(OpenMCOperator):
}
super().__init__(
model.materials,
cross_sections,
chain_file,
prev_results,
diff_burnable_mats,
fission_q,
helper_kwargs,
reduce_chain,
reduce_chain_level)
materials=model.materials,
cross_sections=cross_sections,
chain_file=chain_file,
prev_results=prev_results,
diff_burnable_mats=diff_burnable_mats,
diff_volume_method=diff_volume_method,
fission_q=fission_q,
helper_kwargs=helper_kwargs,
reduce_chain=reduce_chain,
reduce_chain_level=reduce_chain_level)
def _differentiate_burnable_mats(self):
"""Assign distribmats for each burnable material"""
@ -278,19 +286,30 @@ class CoupledOperator(OpenMCOperator):
[mat for mat in self.materials
if mat.depletable and mat.num_instances > 1])
for mat in distribmats:
if mat.volume is None:
raise RuntimeError("Volume not specified for depletable "
"material with ID={}.".format(mat.id))
mat.volume /= mat.num_instances
if self.diff_volume_method == 'divide equally':
for mat in distribmats:
if mat.volume is None:
raise RuntimeError("Volume not specified for depletable "
f"material with ID={mat.id}.")
mat.volume /= mat.num_instances
if distribmats:
# Assign distribmats to cells
for cell in self.geometry.get_all_material_cells().values():
if cell.fill in distribmats:
mat = cell.fill
cell.fill = [mat.clone()
for i in range(cell.num_instances)]
if self.diff_volume_method == 'divide equally':
cell.fill = [mat.clone() for _ in range(cell.num_instances)]
elif self.diff_volume_method == 'match cell':
for _ in range(cell.num_instances):
cell.fill = mat.clone()
if not cell.volume:
raise ValueError(
f"Volume of cell ID={cell.id} not specified. "
"Set volumes of cells prior to using "
"diff_volume_method='match cell'."
)
cell.fill.volume = cell.volume
self.materials = openmc.Materials(
self.model.geometry.get_all_materials().values()

View file

@ -148,10 +148,10 @@ class IndependentOperator(OpenMCOperator):
self.fluxes = fluxes
super().__init__(
materials,
micros,
chain_file,
prev_results,
materials=materials,
cross_sections=micros,
chain_file=chain_file,
prev_results=prev_results,
fission_q=fission_q,
helper_kwargs=helper_kwargs,
reduce_chain=reduce_chain,

View file

@ -12,6 +12,7 @@ from typing import List, Tuple, Dict
import numpy as np
import openmc
from openmc.checkvalue import check_value
from openmc.exceptions import DataError
from openmc.mpi import comm
from .abc import TransportOperator, OperatorResult
@ -45,7 +46,6 @@ class OpenMCOperator(TransportOperator):
in the previous results.
diff_burnable_mats : bool, optional
Whether to differentiate burnable materials with multiple instances.
Volumes are divided equally from the original material volume.
fission_q : dict, optional
Dictionary of nuclides and their fission Q values [eV].
helper_kwargs : dict
@ -58,6 +58,14 @@ class OpenMCOperator(TransportOperator):
if ``reduce_chain`` evaluates to true. The default value of
``None`` implies no limit on the depth.
diff_volume_method : str
Specifies how the volumes of the new materials should be found. Default
is to 'divide equally' which divides the original material volume
equally between the new materials, 'match cell' sets the volume of the
material to volume of the cell they fill.
.. versionadded:: 0.13.4
Attributes
----------
materials : openmc.Materials
@ -97,6 +105,7 @@ class OpenMCOperator(TransportOperator):
chain_file=None,
prev_results=None,
diff_burnable_mats=False,
diff_volume_method='divide equally',
fission_q=None,
helper_kwargs=None,
reduce_chain=False,
@ -116,6 +125,10 @@ class OpenMCOperator(TransportOperator):
self.materials = materials
self.cross_sections = cross_sections
check_value('diff volume method', diff_volume_method,
{'divide equally', 'match cell'})
self.diff_volume_method = diff_volume_method
# Reduce the chain to only those nuclides present
if reduce_chain:
init_nuclides = set()

View file

@ -11,6 +11,7 @@ import numpy as np
CHAIN_PATH = Path(__file__).parents[1] / "chain_simple.xml"
@pytest.fixture(scope="module")
def model():
fuel = openmc.Material(name="uo2")
@ -48,8 +49,72 @@ def model():
return openmc.Model(geometry, materials, settings)
@pytest.fixture()
def model_with_volumes():
mat1 = openmc.Material()
mat1.add_element("Ag", 1, percent_type="ao")
mat1.set_density("g/cm3", 10.49)
mat1.depletable = True
mat1.volume = 102
mat2 = openmc.Material()
mat2.add_element("Ag", 1, percent_type="ao")
mat2.set_density("g/cm3", 10.49)
sph1 = openmc.Sphere(r=1.0)
sph2 = openmc.Sphere(r=2.0, x0=3)
sph3 = openmc.Sphere(r=5.0, boundary_type="vacuum")
cell1 = openmc.Cell(region=-sph1, fill=mat1)
cell1.volume = 4.19
cell2 = openmc.Cell(region=-sph2, fill=mat1)
cell2.volume = 33.51
cell3 = openmc.Cell(region=-sph3 & +sph1 & +sph2, fill=mat2)
cell3.volume = 485.9
geometry = openmc.Geometry([cell1, cell2, cell3])
return openmc.Model(geometry)
def test_operator_init(model):
"""The test uses a temporary dummy chain. This file will be removed
at the end of the test, and only contains a depletion_chain node."""
CoupledOperator(model, CHAIN_PATH)
def test_diff_volume_method_match_cell(model_with_volumes):
"""Tests the volumes assigned to the materials match the cell volumes"""
operator = openmc.deplete.CoupledOperator(
model=model_with_volumes,
diff_burnable_mats=True,
diff_volume_method='match cell',
chain_file=CHAIN_PATH
)
all_cells = list(operator.geometry.get_all_cells().values())
assert all_cells[0].fill.volume == 4.19
assert all_cells[1].fill.volume == 33.51
# mat2 is not depletable
assert all_cells[2].fill.volume is None
def test_diff_volume_method_divide_equally(model_with_volumes):
"""Tests the volumes assigned to the materials are divided equally"""
operator = openmc.deplete.CoupledOperator(
model=model_with_volumes,
diff_burnable_mats=True,
diff_volume_method='divide equally',
chain_file=CHAIN_PATH
)
all_cells = list(operator.geometry.get_all_cells().values())
assert all_cells[0].fill[0].volume == 51
assert all_cells[1].fill[0].volume == 51
# mat2 is not depletable
assert all_cells[2].fill.volume is None