diff --git a/docs/source/pythonapi/data.rst b/docs/source/pythonapi/data.rst index 9631f055f..95fdfeca9 100644 --- a/docs/source/pythonapi/data.rst +++ b/docs/source/pythonapi/data.rst @@ -60,8 +60,10 @@ Core Functions :template: myfunction.rst atomic_mass + atomic_weight dose_coefficients gnd_name + isotopes linearize thin water_density diff --git a/openmc/data/data.py b/openmc/data/data.py index 4a3ebbf32..db9972afe 100644 --- a/openmc/data/data.py +++ b/openmc/data/data.py @@ -236,10 +236,8 @@ def atomic_mass(isotope): for element in ['C', 'Zn', 'Pt', 'Os', 'Tl']: isotope_zero = element.lower() + '0' _ATOMIC_MASS[isotope_zero] = 0. - for iso, abundance in NATURAL_ABUNDANCE.items(): - if re.match(r'{}\d+'.format(element), iso): - _ATOMIC_MASS[isotope_zero] += abundance * \ - _ATOMIC_MASS[iso.lower()] + for iso, abundance in isotopes(element): + _ATOMIC_MASS[isotope_zero] += abundance * _ATOMIC_MASS[iso.lower()] # Get rid of metastable information if '_' in isotope: @@ -257,7 +255,7 @@ def atomic_weight(element): Parameters ---------- element : str - Name of element, e.g. 'H', 'U' + Element symbol (e.g., 'H') or name (e.g., 'helium') Returns ------- @@ -266,9 +264,8 @@ def atomic_weight(element): """ weight = 0. - for nuclide, abundance in NATURAL_ABUNDANCE.items(): - if re.match(r'{}\d+'.format(element), nuclide): - weight += atomic_mass(nuclide) * abundance + for nuclide, abundance in isotopes(element): + weight += atomic_mass(nuclide) * abundance if weight > 0.: return weight else: @@ -404,6 +401,41 @@ def gnd_name(Z, A, m=0): return '{}{}'.format(ATOMIC_SYMBOL[Z], A) +def isotopes(element): + """Return naturally-occurring isotopes and their abundances + + Parameters + ---------- + element : str + Element symbol (e.g., 'H') or name (e.g., 'helium') + + Returns + ------- + list + A list of tuples of (isotope, abundance) + + Raises + ------ + ValueError + If the element name is not recognized + + """ + # Convert name to symbol if needed + if len(element) > 2: + symbol = ELEMENT_SYMBOL.get(element.lower()) + if symbol is None: + raise ValueError('Element name "{}" not recognised'.format(element)) + element = symbol + + # Get the nuclides present in nature + result = [] + for kv in sorted(NATURAL_ABUNDANCE.items()): + if re.match(r'{}\d+'.format(element), kv[0]): + result.append(kv) + + return result + + def zam(name): """Return tuple of (atomic number, mass number, metastable state) diff --git a/openmc/data/thermal.py b/openmc/data/thermal.py index b940994e0..9c30634d0 100644 --- a/openmc/data/thermal.py +++ b/openmc/data/thermal.py @@ -16,7 +16,7 @@ import openmc.checkvalue as cv from openmc.mixin import EqualityMixin from openmc.stats import Discrete, Tabular from . import HDF5_VERSION, HDF5_VERSION_MAJOR, endf -from .data import K_BOLTZMANN, ATOMIC_SYMBOL, EV_PER_MEV, NATURAL_ABUNDANCE +from .data import K_BOLTZMANN, ATOMIC_SYMBOL, EV_PER_MEV, isotopes from .ace import Table, get_table, Library from .angle_energy import AngleEnergy from .function import Tabulated1D, Function1D @@ -722,10 +722,9 @@ class ThermalScattering(EqualityMixin): else: if element + '0' not in table.nuclides: table.nuclides.append(element + '0') - for isotope in sorted(NATURAL_ABUNDANCE): - if re.match(r'{}\d+'.format(element), isotope): - if isotope not in table.nuclides: - table.nuclides.append(isotope) + for isotope, _ in isotopes(element): + if isotope not in table.nuclides: + table.nuclides.append(isotope) return table diff --git a/openmc/element.py b/openmc/element.py index 1a258715f..6a808df62 100644 --- a/openmc/element.py +++ b/openmc/element.py @@ -4,7 +4,8 @@ import re from xml.etree import ElementTree as ET import openmc.checkvalue as cv -from openmc.data import NATURAL_ABUNDANCE, atomic_mass +from openmc.data import NATURAL_ABUNDANCE, atomic_mass, \ + isotopes as natural_isotopes class Element(str): @@ -119,10 +120,7 @@ class Element(str): cv.check_greater_than('enrichment', enrichment, 0., equality=True) # Get the nuclides present in nature - natural_nuclides = set() - for nuclide in sorted(NATURAL_ABUNDANCE.keys()): - if re.match(r'{}\d+'.format(self), nuclide): - natural_nuclides.add(nuclide) + natural_nuclides = {name for name, abundance in natural_isotopes(self)} # Create dict to store the expanded nuclides and abundances abundances = OrderedDict() diff --git a/tests/unit_tests/test_data_misc.py b/tests/unit_tests/test_data_misc.py index 8244ca7f0..6a81fb1e0 100644 --- a/tests/unit_tests/test_data_misc.py +++ b/tests/unit_tests/test_data_misc.py @@ -84,6 +84,7 @@ def test_atomic_mass(): def test_atomic_weight(): assert openmc.data.atomic_weight('C') == 12.011115164864455 + assert openmc.data.atomic_weight('carbon') == 12.011115164864455 with pytest.raises(ValueError): openmc.data.atomic_weight('Qt') @@ -106,6 +107,17 @@ def test_gnd_name(): assert openmc.data.gnd_name(95, 242, 10) == ('Am242_m10') +def test_isotopes(): + hydrogen_isotopes = [('H1', 0.99984426), ('H2', 0.00015574)] + assert openmc.data.isotopes('H') == hydrogen_isotopes + assert openmc.data.isotopes('hydrogen') == hydrogen_isotopes + assert openmc.data.isotopes('Al') == [('Al27', 1.0)] + assert openmc.data.isotopes('Aluminum') == [('Al27', 1.0)] + assert openmc.data.isotopes('aluminium') == [('Al27', 1.0)] + with pytest.raises(ValueError): + openmc.data.isotopes('Чорнобиль') + + def test_zam(): assert openmc.data.zam('H1') == (1, 1, 0) assert openmc.data.zam('Zr90') == (40, 90, 0)