mirror of
https://github.com/openmc-dev/openmc.git
synced 2026-07-21 14:35:27 -04:00
Co-authored-by: Gavin Ridley <gavin.keith.ridley@gmail.com> Co-authored-by: Paul Romano <paul.k.romano@gmail.com>
232 lines
10 KiB
Python
232 lines
10 KiB
Python
""" Tests for TransferRates class """
|
|
|
|
from pathlib import Path
|
|
from math import exp
|
|
|
|
import pytest
|
|
import numpy as np
|
|
|
|
import openmc
|
|
from openmc.deplete import CoupledOperator
|
|
from openmc.deplete.transfer_rates import TransferRates
|
|
from openmc.deplete.abc import (_SECONDS_PER_MINUTE, _SECONDS_PER_HOUR,
|
|
_SECONDS_PER_DAY, _SECONDS_PER_JULIAN_YEAR)
|
|
|
|
CHAIN_PATH = Path(__file__).parents[1] / "chain_simple.xml"
|
|
|
|
@pytest.fixture
|
|
def model():
|
|
openmc.reset_auto_ids()
|
|
f = openmc.Material(name="f")
|
|
f.add_element("U", 1, percent_type="ao", enrichment=4.25)
|
|
f.add_element("O", 2)
|
|
f.set_density("g/cc", 10.4)
|
|
|
|
w = openmc.Material(name="w")
|
|
w.add_element("O", 1)
|
|
w.add_element("H", 2)
|
|
w.set_density("g/cc", 1.0)
|
|
w.depletable = True
|
|
|
|
# material just to test multiple destination material
|
|
h = openmc.Material(name="h")
|
|
h.add_element("He", 1)
|
|
h.set_density("g/cc", 1.78e-4)
|
|
h.depletable = True
|
|
|
|
radii = [0.42, 0.45]
|
|
f.volume = np.pi * radii[0] ** 2
|
|
w.volume = np.pi * (radii[1]**2 - radii[0]**2)
|
|
h.volume = 1
|
|
materials = openmc.Materials([f, w, h])
|
|
|
|
surf_f = openmc.Sphere(r=radii[0])
|
|
surf_w = openmc.Sphere(r=radii[1], boundary_type='vacuum')
|
|
surf_h = openmc.Sphere(x0=10, r=1, boundary_type='vacuum')
|
|
cell_f = openmc.Cell(fill=f, region=-surf_f)
|
|
cell_w = openmc.Cell(fill=w, region=+surf_f & -surf_w)
|
|
cell_h = openmc.Cell(fill=h, region=-surf_h)
|
|
geometry = openmc.Geometry([cell_f, cell_w, cell_h])
|
|
|
|
settings = openmc.Settings()
|
|
settings.particles = 1000
|
|
settings.inactive = 10
|
|
settings.batches = 50
|
|
|
|
return openmc.Model(geometry, materials, settings)
|
|
|
|
@pytest.mark.parametrize("case_name, transfer_rates, timesteps", [
|
|
('elements', {'U': 0.01, 'Xe': 0.1}, None),
|
|
('nuclides', {'I135': 0.01, 'Gd156': 0.1, 'Gd157': 0.01}, None),
|
|
('nuclides_elements', {'I135': 0.01, 'Gd156': 0.1, 'Gd157': 0.01, 'U': 0.01,
|
|
'Xe': 0.1}, None),
|
|
('elements_nuclides', {'U': 0.01, 'Xe': 0.1, 'I135': 0.01, 'Gd156': 0.1,
|
|
'Gd157': 0.01}, None),
|
|
('multiple_transfer', {'U': 0.01, 'Xe': 0.1, 'I135': 0.01, 'Gd156': 0.1,
|
|
'Gd157': 0.01}, None),
|
|
('timesteps', {'U': 0.01, 'Xe': 0.1}, [1]),
|
|
('rates_invalid_1', {'Gd': 0.01, 'Gd157': 0.01, 'Gd156': 0.01}, None),
|
|
('rates_invalid_2', {'Gd156': 0.01, 'Gd157': 0.01, 'Gd': 0.01}, None),
|
|
('rates_invalid_3', {'Gb156': 0.01}, None),
|
|
('rates_invalid_4', {'Gb': 0.01}, None)
|
|
])
|
|
def test_get_set(model, case_name, transfer_rates, timesteps):
|
|
"""Tests the get/set methods"""
|
|
op = CoupledOperator(model, CHAIN_PATH)
|
|
number_of_timesteps = 2
|
|
transfer = TransferRates(op, model.materials, number_of_timesteps)
|
|
|
|
if timesteps is None:
|
|
timesteps = np.arange(number_of_timesteps)
|
|
|
|
# Test by Openmc material, material name and material id
|
|
material, dest_material, dest_material2 = [m for m in model.materials
|
|
if m.depletable]
|
|
for material_input in [material, material.name, material.id]:
|
|
for dest_material_input in [None, dest_material, dest_material.name,
|
|
dest_material.id]:
|
|
if case_name == 'rates_invalid_1':
|
|
with pytest.raises(ValueError, match='Cannot add transfer '
|
|
'rate for nuclide Gd157 to material 1 '
|
|
'where element Gd already has a '
|
|
'transfer rate.'):
|
|
for component, transfer_rate in transfer_rates.items():
|
|
transfer.set_transfer_rate(material_input,
|
|
[component],
|
|
transfer_rate)
|
|
elif case_name == 'rates_invalid_2':
|
|
with pytest.raises(ValueError, match='Cannot add transfer '
|
|
f'rate for element Gd to material 1 with '
|
|
r'transfer rate\(s\) for nuclide\(s\) '
|
|
'Gd156, Gd157.'):
|
|
for component, transfer_rate in transfer_rates.items():
|
|
transfer.set_transfer_rate(material_input,
|
|
[component],
|
|
transfer_rate)
|
|
elif case_name == 'rates_invalid_3':
|
|
with pytest.raises(ValueError, match='Gb156 is not a valid '
|
|
'nuclide or element.'):
|
|
for component, transfer_rate in transfer_rates.items():
|
|
transfer.set_transfer_rate(material_input,
|
|
[component],
|
|
transfer_rate)
|
|
elif case_name == 'rates_invalid_4':
|
|
with pytest.raises(ValueError, match='Gb is not a valid '
|
|
'nuclide or element.'):
|
|
for component, transfer_rate in transfer_rates.items():
|
|
transfer.set_transfer_rate(material_input,
|
|
[component],
|
|
transfer_rate)
|
|
else:
|
|
for component, transfer_rate in transfer_rates.items():
|
|
transfer.set_transfer_rate(material_input, [component],
|
|
transfer_rate,
|
|
timesteps=timesteps,
|
|
destination_material=\
|
|
dest_material_input)
|
|
assert transfer.get_external_rate(
|
|
material_input, component, timesteps,
|
|
dest_material_input)[0] == transfer_rate
|
|
assert np.all(transfer.external_timesteps == timesteps)
|
|
|
|
if timesteps is not None:
|
|
for timestep in timesteps:
|
|
assert transfer.get_components(material_input, timestep,
|
|
dest_material_input) == list(transfer_rates.keys())
|
|
else:
|
|
assert transfer.get_components(material_input, timesteps,
|
|
dest_material_input) == list(transfer_rates.keys())
|
|
|
|
if case_name == 'multiple_transfer':
|
|
for dest2_material_input in [dest_material2, dest_material2.name,
|
|
dest_material2.id]:
|
|
for component, transfer_rate in transfer_rates.items():
|
|
transfer.set_transfer_rate(material_input, [component],
|
|
transfer_rate,
|
|
destination_material=\
|
|
dest2_material_input)
|
|
for id, dest_mat in zip([0,1],[dest_material,dest_material2]):
|
|
assert transfer.get_external_rate(
|
|
material_input, component, timesteps)[0] == transfer_rate
|
|
|
|
@pytest.mark.parametrize("transfer_rate_units, unit_conv", [
|
|
('1/s', 1),
|
|
('1/sec', 1),
|
|
('1/min', _SECONDS_PER_MINUTE),
|
|
('1/minute', _SECONDS_PER_MINUTE),
|
|
('1/h', _SECONDS_PER_HOUR),
|
|
('1/hr', _SECONDS_PER_HOUR),
|
|
('1/hour', _SECONDS_PER_HOUR),
|
|
('1/d', _SECONDS_PER_DAY),
|
|
('1/day', _SECONDS_PER_DAY),
|
|
('1/a', _SECONDS_PER_JULIAN_YEAR),
|
|
('1/year', _SECONDS_PER_JULIAN_YEAR),
|
|
])
|
|
def test_units(transfer_rate_units, unit_conv, model):
|
|
""" Units testing"""
|
|
# create transfer rate Xe
|
|
components = ['Xe', 'U235']
|
|
transfer_rate = 1e-5
|
|
number_of_timesteps = 2
|
|
op = CoupledOperator(model, CHAIN_PATH)
|
|
transfer = TransferRates(op, model.materials, number_of_timesteps)
|
|
|
|
for component in components:
|
|
transfer.set_transfer_rate('f', [component], transfer_rate * unit_conv,
|
|
transfer_rate_units=transfer_rate_units)
|
|
for timestep in range(transfer.number_of_timesteps):
|
|
assert transfer.get_external_rate('f', component, timestep)[0] == transfer_rate
|
|
|
|
|
|
def test_transfer(run_in_tmpdir, model):
|
|
"""Tests transfer depletion class without neither reaction rates nor decay
|
|
but only transfer rates"""
|
|
|
|
# create transfer rate for U
|
|
element = ['U']
|
|
transfer_rate = 1e-5
|
|
op = CoupledOperator(model, CHAIN_PATH)
|
|
integrator = openmc.deplete.PredictorIntegrator(
|
|
op, [1,1], 0.0, timestep_units = 'd')
|
|
integrator.add_transfer_rate('f', element, transfer_rate)
|
|
integrator.integrate()
|
|
|
|
# Get number of U238 atoms from results
|
|
results = openmc.deplete.Results('depletion_results.h5')
|
|
_, atoms = results.get_atoms(model.materials[0], "U238")
|
|
|
|
# Ensure number of atoms equal transfer decay
|
|
assert atoms[1] == pytest.approx(atoms[0]*exp(-transfer_rate*3600*24))
|
|
assert atoms[2] == pytest.approx(atoms[1]*exp(-transfer_rate*3600*24))
|
|
|
|
@pytest.mark.parametrize("case_name, buffer, ox", [
|
|
('redox', {'Gd157':1}, {'Gd': 3, 'U': 4}),
|
|
('buffer_invalid', {'Gd158':1}, {'Gd': 3, 'U': 4}),
|
|
('elm_invalid', {'Gd157':1}, {'Gb': 3, 'U': 4}),
|
|
])
|
|
def test_redox(case_name, buffer, ox, model):
|
|
op = CoupledOperator(model, CHAIN_PATH)
|
|
number_of_timesteps = 2
|
|
transfer = TransferRates(op, model.materials, number_of_timesteps)
|
|
|
|
# Test by Openmc material, material name and material id
|
|
material, dest_material, dest_material2 = [m for m in model.materials
|
|
if m.depletable]
|
|
for material_input in [material, material.name, material.id]:
|
|
for dest_material_input in [dest_material, dest_material.name,
|
|
dest_material.id]:
|
|
|
|
if case_name == 'buffer_invalid':
|
|
with pytest.raises(ValueError, match='Gd158 is not a valid '
|
|
'nuclide.'):
|
|
transfer.set_redox(material_input, buffer, ox)
|
|
|
|
elif case_name == 'elm_invalid':
|
|
with pytest.raises(ValueError, match='Gb is not a valid '
|
|
'element.'):
|
|
transfer.set_redox(material_input, buffer, ox)
|
|
else:
|
|
transfer.set_redox(material_input, buffer, ox)
|
|
mat_id = transfer._get_material_id(material_input)
|
|
assert transfer.redox[mat_id][0] == buffer
|
|
assert transfer.redox[mat_id][1] == ox
|