mirror of
https://github.com/openmc-dev/openmc.git
synced 2026-07-28 14:15:42 -04:00
Merge pull request #32 from openmsr/reactivity_control_abstrac
Reactivity control abstrac
This commit is contained in:
commit
c3a67058d8
7 changed files with 338 additions and 707 deletions
|
|
@ -31,11 +31,9 @@ from .reaction_rates import ReactionRates
|
|||
from .transfer_rates import TransferRates
|
||||
from openmc import Material, Cell
|
||||
from .reactivity_control import (
|
||||
ReactivityController,
|
||||
CellReactivityController,
|
||||
GeometricalCellReactivityController,
|
||||
TemperatureCellReactivityController,
|
||||
MaterialReactivityController,
|
||||
RefuelMaterialReactivityController
|
||||
MaterialReactivityController
|
||||
)
|
||||
|
||||
__all__ = [
|
||||
|
|
@ -718,25 +716,7 @@ class Integrator(ABC):
|
|||
|
||||
@reactivity_control.setter
|
||||
def reactivity_control(self, reactivity_control):
|
||||
if isinstance(reactivity_control, CellReactivityController):
|
||||
if not isinstance(reactivity_control.cell, Cell):
|
||||
raise TypeError(
|
||||
"Reactivity control attribute must be Cell "
|
||||
"not {}".format(type(reactivity_control.cell)))
|
||||
elif isinstance(reactivity_control, MaterialReactivityController):
|
||||
if not isinstance(reactivity_control.material, Material):
|
||||
raise TypeError(
|
||||
"Reactivity control attribute must be Material "
|
||||
"not {}".format(type(reactivity_control.material)))
|
||||
else:
|
||||
raise TypeError(
|
||||
"Reactivity Control must either be "
|
||||
"CellReactivityController, or MaterialReactivityController, "
|
||||
"not {}".format(type(reactivity_control)))
|
||||
|
||||
check_value('attribute', reactivity_control.attrib_name,
|
||||
('translation', 'rotation', 'temperature', 'refuel'))
|
||||
|
||||
check_type('reactivity control', reactivity_control, ReactivityController)
|
||||
self._reactivity_control = reactivity_control
|
||||
|
||||
def _timed_deplete(self, n, rates, dt, matrix_func=None):
|
||||
|
|
@ -945,34 +925,26 @@ class Integrator(ABC):
|
|||
|
||||
def add_reactivity_control(
|
||||
self,
|
||||
obj: Union[Cell, Material, int, str],
|
||||
attr: str,
|
||||
obj: Union[Cell, Material],
|
||||
**kwargs):
|
||||
"""Add reactivity control to integrator scheme.
|
||||
"""Add pre-defined Cell based or Material bases reactivity control to
|
||||
integrator scheme.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
obj : openmc.Cell or openmc.Material object or id or str name
|
||||
Cell or Materials identifier to where add reactivity control
|
||||
attr : str
|
||||
Attribute to specify the type of reactivity control. Accepted values
|
||||
are: 'translation', 'rotation', 'temperature' for an openmc.Cell
|
||||
object; 'refuel' for an openmc.Material object.
|
||||
obj : openmc.Cell or openmc.Material
|
||||
Cell or Material identifier to where add reactivity control
|
||||
**kwargs
|
||||
keyword arguments that are passed to the ReactivityController class.
|
||||
keyword arguments that are passed to the specific ReactivityController
|
||||
class.
|
||||
|
||||
"""
|
||||
check_value('attribute', attr, ('translation', 'rotation',
|
||||
'temperature', 'refuel'))
|
||||
if attr in ('translation', 'rotation'):
|
||||
reactivity_control = GeometricalCellReactivityController
|
||||
elif attr == 'temperature':
|
||||
reactivity_control = TemperatureCellReactivityController
|
||||
elif attr == 'refuel':
|
||||
reactivity_control = RefuelMaterialReactivityController
|
||||
|
||||
self._reactivity_control = reactivity_control.from_params(obj, attr,
|
||||
self.operator, **kwargs)
|
||||
if isinstance(obj, Cell):
|
||||
reactivity_control = CellReactivityController
|
||||
elif isinstance(obj, Material):
|
||||
reactivity_control = MaterialReactivityController
|
||||
self._reactivity_control = reactivity_control.from_params(obj,
|
||||
self.operator, **kwargs)
|
||||
|
||||
@add_params
|
||||
class SIIntegrator(Integrator):
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
|
@ -10,6 +10,10 @@ import numpy as np
|
|||
import openmc
|
||||
import openmc.lib
|
||||
from openmc.deplete import CoupledOperator
|
||||
from openmc.deplete import (
|
||||
CellReactivityController,
|
||||
MaterialReactivityController
|
||||
)
|
||||
|
||||
from tests.regression_tests import config
|
||||
|
||||
|
|
@ -78,13 +82,21 @@ def model():
|
|||
|
||||
return openmc.Model(geometry, materials, settings)
|
||||
|
||||
@pytest.mark.parametrize("obj, attribute, bracket_limit, axis, vec, ref_result", [
|
||||
('trans_cell', 'translation', [-40,40], 2, None, 'depletion_with_translation'),
|
||||
('rot_cell', 'rotation', [-90,90], 2, None, 'depletion_with_rotation'),
|
||||
('f', 'refuel', [-100,100], None, {'U235':0.9, 'U238':0.1}, 'depletion_with_refuel')
|
||||
@pytest.fixture
|
||||
def mix_mat():
|
||||
mix_mat = openmc.Material()
|
||||
mix_mat.add_element("U", 1, percent_type="ao", enrichment=90)
|
||||
mix_mat.add_element("O", 2)
|
||||
mix_mat.set_density("g/cc", 10.4)
|
||||
return mix_mat
|
||||
|
||||
@pytest.mark.parametrize("obj, attribute, bracket, bracket_limit, axis, ref_result", [
|
||||
('trans_cell', 'translation', [-5,5], [-40,40], 2, 'depletion_with_translation'),
|
||||
('rot_cell', 'rotation', [-5,5], [-90,90], 2, 'depletion_with_rotation'),
|
||||
('f', None, [-1,2], [-100,100], None, 'depletion_with_refuel')
|
||||
])
|
||||
def test_reactivity_control(run_in_tmpdir, model, obj, attribute, bracket_limit,
|
||||
axis, vec, ref_result):
|
||||
def test_reactivity_control(run_in_tmpdir, model, obj, attribute, bracket,
|
||||
bracket_limit, axis, ref_result, mix_mat):
|
||||
|
||||
chain_file = Path(__file__).parents[2] / 'chain_simple.xml'
|
||||
op = CoupledOperator(model, chain_file)
|
||||
|
|
@ -92,16 +104,23 @@ def test_reactivity_control(run_in_tmpdir, model, obj, attribute, bracket_limit,
|
|||
integrator = openmc.deplete.PredictorIntegrator(
|
||||
op, [1], 174., timestep_units = 'd')
|
||||
|
||||
kwargs = {'bracket': [-4,4], 'bracket_limit':bracket_limit,
|
||||
'tol': 0.1,}
|
||||
|
||||
if vec is not None:
|
||||
kwargs['mat_vector']=vec
|
||||
|
||||
if axis is not None:
|
||||
kwargs['axis'] = axis
|
||||
|
||||
integrator.add_reactivity_control(obj, attribute, **kwargs)
|
||||
if attribute:
|
||||
integrator.reactivity_control = CellReactivityController(
|
||||
cell=obj,
|
||||
operator=op,
|
||||
attribute=attribute,
|
||||
bracket=bracket,
|
||||
bracket_limit=bracket_limit,
|
||||
axis=axis
|
||||
)
|
||||
else:
|
||||
integrator.reactivity_control = MaterialReactivityController(
|
||||
material=obj,
|
||||
operator=op,
|
||||
material_to_mix=mix_mat,
|
||||
bracket=bracket,
|
||||
bracket_limit=bracket_limit,
|
||||
)
|
||||
integrator.integrate()
|
||||
|
||||
# Get path to test and reference results
|
||||
|
|
|
|||
|
|
@ -9,9 +9,8 @@ import openmc
|
|||
import openmc.lib
|
||||
from openmc.deplete import CoupledOperator
|
||||
from openmc.deplete import (
|
||||
GeometricalCellReactivityController,
|
||||
TemperatureCellReactivityController,
|
||||
RefuelMaterialReactivityController
|
||||
CellReactivityController,
|
||||
MaterialReactivityController
|
||||
)
|
||||
|
||||
CHAIN_PATH = Path(__file__).parents[1] / "chain_simple.xml"
|
||||
|
|
@ -74,62 +73,52 @@ def integrator(operator):
|
|||
return openmc.deplete.PredictorIntegrator(
|
||||
operator, [1,1], 0.0, timestep_units = 'd')
|
||||
|
||||
@pytest.mark.parametrize("case_name, obj, attribute, bracket, limit, axis, vec", [
|
||||
('cell translation','universe_cell', 'translation', [-1,1], [-10,10], 2, None),
|
||||
('cell rotation', 'universe_cell', 'rotation', [-1,1], [-10,10], 2, None),
|
||||
('single cell temperature', 'fuel_cell', 'temperature', [-1,1], [-10,10], 2, None ),
|
||||
('multi cell', 'universe_cell', 'temperature', [-1,1], [-10,10], 2, None ),
|
||||
('material refuel', 'fuel', 'refuel', [-1,1], [-10,10], None, {'U235':0.1, 'U238':0.9}),
|
||||
('invalid_1', 'universe_cell', 'refuel', [-1,1], [-10,10], None, {'U235':0.1, 'U238':0.9}),
|
||||
('invalid_2', 'fuel', 'temperature', [-1,1], [-10,10], 2, None ),
|
||||
('invalid_3', 'fuel', 'translation', [-1,1], [-10,10], 2, None),
|
||||
@pytest.fixture
|
||||
def mix_mat():
|
||||
mix_mat = openmc.Material()
|
||||
mix_mat.add_element("U", 1, percent_type="ao", enrichment=90)
|
||||
mix_mat.add_element("O", 2)
|
||||
mix_mat.set_density("g/cc", 10.4)
|
||||
return mix_mat
|
||||
|
||||
@pytest.mark.parametrize("case_name, obj, attribute, bracket, limit, axis", [
|
||||
('cell translation','universe_cell', 'translation', [-1,1], [-10,10], 2),
|
||||
('cell rotation', 'universe_cell', 'rotation', [-1,1], [-10,10], 2),
|
||||
('material mix', 'fuel', None, [0,5], [-10,10], None),
|
||||
])
|
||||
def test_attributes(case_name, model, operator, integrator, obj, attribute,
|
||||
bracket, limit, axis, vec):
|
||||
bracket, limit, axis, mix_mat):
|
||||
"""
|
||||
Test classes attributes are set correctly
|
||||
"""
|
||||
if attribute:
|
||||
integrator.reactivity_control = CellReactivityController(
|
||||
cell=obj,
|
||||
operator=operator,
|
||||
attribute=attribute,
|
||||
bracket=bracket,
|
||||
bracket_limit=limit,
|
||||
axis=axis
|
||||
)
|
||||
assert integrator.reactivity_control.depletable_cells == [cell for cell in \
|
||||
model.geometry.get_cells_by_name(obj)[0].fill.cells.values() \
|
||||
if cell.fill.depletable]
|
||||
assert integrator.reactivity_control.axis == axis
|
||||
|
||||
kwargs = {'bracket': bracket, 'bracket_limit':limit, 'tol': 0.1,}
|
||||
|
||||
if vec is not None:
|
||||
kwargs['mat_vector']=vec
|
||||
|
||||
if axis is not None:
|
||||
kwargs['axis'] = axis
|
||||
|
||||
if case_name == "invalid_1":
|
||||
with pytest.raises(ValueError) as e:
|
||||
integrator.add_reactivity_control(obj, attribute, **kwargs)
|
||||
assert str(e.value) == 'Unable to set "Material name" to "universe_cell" '\
|
||||
'since it is not in "[\'fuel\', \'water\']"'
|
||||
elif case_name == "invalid_2":
|
||||
with pytest.raises(ValueError) as e:
|
||||
integrator.add_reactivity_control(obj, attribute, **kwargs)
|
||||
assert str(e.value) == 'Unable to set "Cell name exists" to "fuel" since '\
|
||||
'it is not in "[\'fuel_cell\', \'universe_cell\', \'\', \'\']"'
|
||||
|
||||
elif case_name == "invalid_3":
|
||||
with pytest.raises(ValueError) as e:
|
||||
integrator.add_reactivity_control(obj, attribute, **kwargs)
|
||||
assert str(e.value) == 'Unable to set "Cell name exists" to "fuel" since '\
|
||||
'it is not in "[\'fuel_cell\', \'universe_cell\', \'\', \'\']"'
|
||||
else:
|
||||
integrator.add_reactivity_control(obj, attribute, **kwargs)
|
||||
if attribute in ('translation','rotation'):
|
||||
assert integrator.reactivity_control.universe_cells == [cell for cell in \
|
||||
model.geometry.get_cells_by_name(obj)[0].fill.cells.values() \
|
||||
if cell.fill.depletable]
|
||||
assert integrator.reactivity_control.axis == axis
|
||||
integrator.reactivity_control = MaterialReactivityController(
|
||||
material=obj,
|
||||
operator=operator,
|
||||
material_to_mix=mix_mat,
|
||||
bracket=bracket,
|
||||
bracket_limit=limit
|
||||
)
|
||||
assert integrator.reactivity_control.material_to_mix == mix_mat
|
||||
|
||||
elif attribute == 'refuel':
|
||||
assert integrator.reactivity_control.mat_vector == vec
|
||||
|
||||
assert integrator.reactivity_control.attrib_name == attribute
|
||||
assert integrator.reactivity_control.bracket == bracket
|
||||
assert integrator.reactivity_control.bracket_limit == limit
|
||||
assert integrator.reactivity_control.burn_mats == operator.burnable_mats
|
||||
assert integrator.reactivity_control.local_mats == operator.local_mats
|
||||
assert integrator.reactivity_control.bracket == bracket
|
||||
assert integrator.reactivity_control.bracket_limit == limit
|
||||
assert integrator.reactivity_control.burn_mats == operator.burnable_mats
|
||||
assert integrator.reactivity_control.local_mats == operator.local_mats
|
||||
|
||||
@pytest.mark.parametrize("obj, attribute, value_to_set", [
|
||||
('universe_cell', 'translation', 0),
|
||||
|
|
@ -140,9 +129,14 @@ def test_cell_methods(run_in_tmpdir, model, operator, integrator, obj, attribute
|
|||
"""
|
||||
Test cell base class internal method
|
||||
"""
|
||||
kwargs = {'bracket':[-1,1], 'bracket_limit':[-10,10], 'axis':2, 'tol':0.1}
|
||||
|
||||
integrator.add_reactivity_control(obj, attribute, **kwargs)
|
||||
integrator.reactivity_control = CellReactivityController(
|
||||
cell=obj,
|
||||
operator=operator,
|
||||
attribute=attribute,
|
||||
bracket=[-1,1],
|
||||
bracket_limit=[-10,10],
|
||||
axis=2
|
||||
)
|
||||
|
||||
model.export_to_xml()
|
||||
openmc.lib.init()
|
||||
|
|
@ -150,63 +144,79 @@ def test_cell_methods(run_in_tmpdir, model, operator, integrator, obj, attribute
|
|||
integrator.reactivity_control._set_cell_attrib(value_to_set)
|
||||
assert integrator.reactivity_control._get_cell_attrib() == value_to_set
|
||||
|
||||
vol = integrator.reactivity_control._calculate_volumes()
|
||||
vol = integrator.reactivity_control._adjust_volumes()
|
||||
integrator.reactivity_control._update_x_and_set_volumes(operator.number.number, vol)
|
||||
|
||||
for cell in integrator.reactivity_control.universe_cells:
|
||||
for cell in integrator.reactivity_control.depletable_cells:
|
||||
mat_id = str(cell.fill.id)
|
||||
index_mat = operator.number.index_mat[mat_id]
|
||||
assert vol[mat_id] == operator.number.volume[index_mat]
|
||||
|
||||
openmc.lib.finalize()
|
||||
|
||||
@pytest.mark.parametrize("nuclide, atoms_to_add", [
|
||||
('U238', 1.0e22),
|
||||
('Xe135', 1.0e21)
|
||||
@pytest.mark.parametrize("units, value, dilute", [
|
||||
('cc', 1.0, True),
|
||||
('cm3', 1.0, False),
|
||||
('grams', 1.0, True),
|
||||
('grams', 1.0, False),
|
||||
('atoms', 1.0, True),
|
||||
('atoms', 1.0, False),
|
||||
])
|
||||
def test_internal_methods(run_in_tmpdir, model, operator, integrator, nuclide,
|
||||
atoms_to_add):
|
||||
def test_internal_methods(run_in_tmpdir, model, operator, integrator, mix_mat,
|
||||
units, value, dilute):
|
||||
"""
|
||||
Method to update volume in AtomNumber after depletion step.
|
||||
Method inheritated by all derived classes so one check is enough.
|
||||
"""
|
||||
|
||||
kwargs = {'bracket':[-1,1], 'bracket_limit':[-10,10], 'mat_vector':{}}
|
||||
|
||||
integrator.add_reactivity_control('fuel', 'refuel', **kwargs)
|
||||
integrator.reactivity_control = MaterialReactivityController(
|
||||
material='fuel',
|
||||
operator=operator,
|
||||
material_to_mix=mix_mat,
|
||||
bracket=[-1,1],
|
||||
bracket_limit=[-10,10],
|
||||
units=units,
|
||||
dilute=dilute
|
||||
)
|
||||
|
||||
model.export_to_xml()
|
||||
openmc.lib.init()
|
||||
|
||||
#Increase number of atoms of U238 in fuel by fix amount and check the
|
||||
# volume increase at constant-density
|
||||
#extract fuel material from model materials
|
||||
# check material volume are adjusted correctly
|
||||
mat = integrator.reactivity_control.material
|
||||
mat_index = operator.number.index_mat[str(mat.id)]
|
||||
nuc_index = operator.number.index_nuc[nuclide]
|
||||
vol = operator.number.get_mat_volume(str(mat.id))
|
||||
operator.number.number[mat_index][nuc_index] += atoms_to_add
|
||||
integrator.reactivity_control._update_volumes()
|
||||
nuc_index = operator.number.index_nuc['U235']
|
||||
vol_before_mix = operator.number.get_mat_volume(str(mat.id))
|
||||
|
||||
vol_to_compare = vol + (atoms_to_add * openmc.data.atomic_mass(nuclide) /\
|
||||
openmc.data.AVOGADRO / mat.density)
|
||||
# set mix_mat volume
|
||||
integrator.reactivity_control._set_mix_material_volume(value)
|
||||
mix_mat_vol = mix_mat.volume
|
||||
#extract nuclide in atoms
|
||||
mix_nuc_atoms = mix_mat.get_nuclide_atoms()['U235']
|
||||
operator.number.number[mat_index][nuc_index] += mix_nuc_atoms
|
||||
#update volume
|
||||
vol_after_mix = integrator.reactivity_control._adjust_volumes(mix_mat_vol)
|
||||
|
||||
assert operator.number.get_mat_volume(str(mat.id)) == pytest.approx(vol_to_compare)
|
||||
if dilute:
|
||||
assert vol_before_mix + mix_mat_vol == vol_after_mix[str(mat.id)]
|
||||
else:
|
||||
assert vol_before_mix == vol_after_mix[str(mat.id)]
|
||||
|
||||
#check nuclide densities get assigned correctly in memory
|
||||
x = [i[:operator.number.n_nuc_burn] for i in operator.number.number]
|
||||
integrator.reactivity_control._update_materials(x)
|
||||
nuc_index_lib = openmc.lib.materials[mat.id].nuclides.index(nuclide)
|
||||
dens_to_compare = 1.0e-24 * operator.number.get_atom_density(str(mat.id), nuclide)
|
||||
nuc_index_lib = openmc.lib.materials[mat.id].nuclides.index('U235')
|
||||
dens_to_compare = 1.0e-24 * operator.number.get_atom_density(str(mat.id), 'U235')
|
||||
|
||||
assert openmc.lib.materials[mat.id].densities[nuc_index_lib] == pytest.approx(dens_to_compare)
|
||||
|
||||
volumes = {str(mat.id): vol + 1}
|
||||
new_x = integrator.reactivity_control._update_x_and_set_volumes(x, volumes)
|
||||
dens_to_compare = 1.0e24 * volumes[str(mat.id)] *\
|
||||
# check volumes get assigned correctly in AtomNumber
|
||||
new_x = integrator.reactivity_control._update_x_and_set_volumes(x, vol_after_mix)
|
||||
dens_to_compare = 1.0e24 * vol_after_mix[str(mat.id)] *\
|
||||
openmc.lib.materials[mat.id].densities[nuc_index_lib]
|
||||
assert new_x[mat_index][nuc_index] == pytest.approx(dens_to_compare)
|
||||
|
||||
# assert volume in AtomNumber is set correctly
|
||||
assert operator.number.get_mat_volume(str(mat.id)) == volumes[str(mat.id)]
|
||||
assert operator.number.get_mat_volume(str(mat.id)) == vol_after_mix[str(mat.id)]
|
||||
|
||||
openmc.lib.finalize()
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue