Add useful warnings for add_nuclide/add_element

This commit is contained in:
Paul Romano 2018-03-02 10:36:08 -06:00
parent 395a5a53d0
commit 0508274a3d
6 changed files with 38 additions and 42 deletions

View file

@ -43,14 +43,22 @@ of an element, you specify the element itself. For example,
Internally, OpenMC stores data on the atomic masses and natural abundances of
all known isotopes and then uses this data to determine what isotopes should be
added to the material. When the material is later exported to XML for use by the
:ref:`scripts_openmc` executable, you'll see that any natural elements are
:ref:`scripts_openmc` executable, you'll see that any natural elements were
expanded to the naturally-occurring isotopes.
The :meth:`Material.add_element` method can also be used to add uranium at a
specified enrichment through the `enrichment` argument. For example, the
following would add 3.2% enriched uranium to a material::
mat.add_element('U', 1.0, enrichment=3.2)
In addition to U235 and U238, concentrations of U234 and U236 will be present
and are determined through a correlation based on measured data.
Often, cross section libraries don't actually have all naturally-occurring
isotopes for a given element. For example, in ENDF/B-VII.1, cross section
evaluations are given for O16 and O17 but not for O18. If OpenMC is aware of
what cross sections you will be using (either through the
:attr:`Materials.cross_sections` attribute or the
what cross sections you will be using (through the
:envvar:`OPENMC_CROSS_SECTIONS` environment variable), it will attempt to only
put isotopes in your model for which you have cross section data. In the case of
oxygen in ENDF/B-VII.1, the abundance of O18 would end up being lumped with O16.

View file

@ -22,7 +22,7 @@ import sys
import numpy as np
from openmc.mixin import EqualityMixin
from openmc.data.endf import ENDF_FLOAT_RE
from openmc.data.endf import _ENDF_FLOAT_RE
def ascii_to_binary(ascii_file, binary_file):
"""Convert an ACE file in ASCII format (type 1) to binary format (type 2).
@ -349,7 +349,7 @@ class Library(EqualityMixin):
# after it). If it's too short, then we apply the ENDF float regular
# expression. We don't do this by default because it's expensive!
if xss.size != nxs[1] + 1:
datastr = ENDF_FLOAT_RE.sub(r'\1e\2', datastr)
datastr = _ENDF_FLOAT_RE.sub(r'\1e\2', datastr)
xss = np.fromstring(datastr, sep=' ')
assert xss.size == nxs[1] + 1

View file

@ -136,6 +136,8 @@ ATOMIC_NUMBER = {value: key for key, value in ATOMIC_SYMBOL.items()}
_ATOMIC_MASS = {}
_GND_NAME_RE = re.compile(r'([A-Zn][a-z]*)(\d+)((?:_[em]\d+)?)')
def atomic_mass(isotope):
"""Return atomic mass of isotope in atomic mass units.
@ -352,8 +354,7 @@ def zam(name):
"""
try:
symbol, A, state = re.match(r'([A-Zn][a-z]*)(\d+)((?:_[em]\d+)?)',
name).groups()
symbol, A, state = _GND_NAME_RE.match(name).groups()
except AttributeError:
raise ValueError("'{}' does not appear to be a nuclide name in GND "
"format.".format(name))

View file

@ -45,7 +45,7 @@ SUM_RULES = {1: [2, 3],
106: list(range(750, 800)),
107: list(range(800, 850))}
ENDF_FLOAT_RE = re.compile(r'([\s\-\+]?\d*\.\d+)([\+\-]\d+)')
_ENDF_FLOAT_RE = re.compile(r'([\s\-\+]?\d*\.\d+)([\+\-]\d+)')
def float_endf(s):
@ -68,7 +68,7 @@ def float_endf(s):
The number
"""
return float(ENDF_FLOAT_RE.sub(r'\1e\2', s))
return float(_ENDF_FLOAT_RE.sub(r'\1e\2', s))
def get_text_record(file_obj):

View file

@ -379,33 +379,27 @@ class Material(IDManagerMixin):
Parameters
----------
nuclide : str
Nuclide to add
Nuclide to add, e.g., 'Mo95'
percent : float
Atom or weight percent
percent_type : {'ao', 'wo'}
'ao' for atom percent and 'wo' for weight percent
"""
cv.check_type('nuclide', nuclide, str)
cv.check_type('percent', percent, Real)
cv.check_value('percent type', percent_type, {'ao', 'wo'})
if self._macroscopic is not None:
msg = 'Unable to add a Nuclide to Material ID="{}" as a ' \
'macroscopic data-set has already been added'.format(self._id)
raise ValueError(msg)
if not isinstance(nuclide, str):
msg = 'Unable to add a Nuclide to Material ID="{}" with a ' \
'non-string value "{}"'.format(self._id, nuclide)
raise ValueError(msg)
elif not isinstance(percent, Real):
msg = 'Unable to add a Nuclide to Material ID="{}" with a ' \
'non-floating point value "{}"'.format(self._id, percent)
raise ValueError(msg)
elif percent_type not in ('ao', 'wo'):
msg = 'Unable to add a Nuclide to Material ID="{}" with a ' \
'percent type "{}"'.format(self._id, percent_type)
raise ValueError(msg)
# If nuclide name doesn't look valid, give a warning
try:
openmc.data.zam(nuclide)
except ValueError as e:
warnings.warn(str(e))
self._nuclides.append((nuclide, percent, percent_type))
@ -493,7 +487,7 @@ class Material(IDManagerMixin):
Parameters
----------
element : str
Element to add
Element to add, e.g., 'Zr'
percent : float
Atom or weight percent
percent_type : {'ao', 'wo'}, optional
@ -505,27 +499,15 @@ class Material(IDManagerMixin):
(natural composition).
"""
cv.check_type('nuclide', element, str)
cv.check_type('percent', percent, Real)
cv.check_value('percent type', percent_type, {'ao', 'wo'})
if self._macroscopic is not None:
msg = 'Unable to add an Element to Material ID="{}" as a ' \
'macroscopic data-set has already been added'.format(self._id)
raise ValueError(msg)
if not isinstance(element, str):
msg = 'Unable to add an Element to Material ID="{}" with a ' \
'non-string value "{}"'.format(self._id, element)
raise ValueError(msg)
if not isinstance(percent, Real):
msg = 'Unable to add an Element to Material ID="{}" with a ' \
'non-floating point value "{}"'.format(self._id, percent)
raise ValueError(msg)
if percent_type not in ['ao', 'wo']:
msg = 'Unable to add an Element to Material ID="{}" with a ' \
'percent type "{}"'.format(self._id, percent_type)
raise ValueError(msg)
if enrichment is not None:
if not isinstance(enrichment, Real):
msg = 'Unable to add an Element to Material ID="{}" with a ' \
@ -551,6 +533,11 @@ class Material(IDManagerMixin):
format(enrichment, self._id)
warnings.warn(msg)
# Make sure element name is just that
if not element.isalpha():
raise ValueError("Element name should be given by the "
"element's symbol, e.g., 'Zr'")
# Add naturally-occuring isotopes
element = openmc.Element(element)
for nuclide in element.expand(percent, percent_type, enrichment):

View file

@ -15,9 +15,9 @@ def test_nuclides(uo2):
"""Test adding/removing nuclides."""
m = openmc.Material()
m.add_nuclide('U235', 1.0)
with pytest.raises(ValueError):
with pytest.raises(TypeError):
m.add_nuclide('H1', '1.0')
with pytest.raises(ValueError):
with pytest.raises(TypeError):
m.add_nuclide(1.0, 'H1')
with pytest.raises(ValueError):
m.add_nuclide('H1', 1.0, 'oa')