From 01fc85ed9a1cb24c4116c1648d9a82c58717f463 Mon Sep 17 00:00:00 2001 From: Paul Cosgrove Date: Sat, 22 Feb 2020 16:14:31 +0000 Subject: [PATCH 1/7] Allowed adding element by name Added an ELEMENT_SYMBOL dictionary to data.py with various spellings. Modified add_element to include checks for element names as well as symbols --- openmc/data/data.py | 44 +++++++++++++++++++++++++++++++++++++++++++- openmc/material.py | 21 +++++++++++++++------ 2 files changed, 58 insertions(+), 7 deletions(-) diff --git a/openmc/data/data.py b/openmc/data/data.py index e813209f0a..e34ab8d462 100644 --- a/openmc/data/data.py +++ b/openmc/data/data.py @@ -4,7 +4,6 @@ import os import re from warnings import warn - # Isotopic abundances from Meija J, Coplen T B, et al, "Isotopic compositions # of the elements 2013 (IUPAC Technical Report)", Pure. Appl. Chem. 88 (3), # pp. 293-306 (2013). The "representative isotopic abundance" values from @@ -110,6 +109,49 @@ NATURAL_ABUNDANCE = { 'U238': 0.992742 } +# Dictionary to give element symbols from IUPAC names +# (and some common mispellings) +ELEMENT_SYMBOL = {'neutron': 'n', 'hydrogen': 'H', 'helium': 'He', + 'lithium': 'Li', 'beryllium': 'Be', 'boron': 'B', + 'carbon': 'C', 'nitrogen': 'N', 'oxygen': 'O', 'fluorine': 'F', + 'neon': 'Ne', 'sodium': 'Na', 'magnesium': 'Mg', + 'aluminium': 'Al', 'aluminum':'Al', 'silicon': 'Si', + 'phosphorus': 'P', 'sulfur': 'S', 'sulphur': 'S', + 'chlorine': 'Cl', 'argon': 'Ar', 'potassium': 'K', + 'calcium': 'Ca', 'scandium': 'Sc', 'titanium': 'Ti', + 'vanadium': 'V', 'chromium': 'Cr', 'manganese': 'Mn', + 'iron': 'Fe', 'cobalt': 'Co', 'nickel': 'Ni', 'copper': 'Cu', + 'zinc': 'Zn', 'gallium': 'Ga', 'germanium': 'Ge', + 'arsenic': 'As', 'selenium': 'Se', 'bromine': 'Br', + 'krypton': 'Kr', 'rubidium': 'Rb', 'strontium': 'Sr', + 'yttrium': 'Y', 'zirconium': 'Zr', 'niobium': 'Nb', + 'molybdenum': 'Mo', 'technetium': 'Tc', 'ruthenium': 'Ru', + 'rhodium': 'Rh', 'palladium': 'Pd', 'silver': 'Ag', + 'cadmium': 'Cd', 'indium': 'In', 'tin': 'Sn', 'antimony': 'Sb', + 'tellurium': 'Te', 'iodine': 'I', 'xenon': 'Xe', + 'caesium': 'Cs', 'cesium': 'Cs', 'barium': 'Ba', + 'lanthanum': 'La', 'cerium': 'Ce', 'praseodymium': 'Pr', + 'neodymium': 'Nd', 'promethium': 'Pm', 'samarium': 'Sm', + 'europium': 'Eu', 'gadolinium': 'Gd', 'terbium': 'Tb', + 'dysprosium': 'Dy', 'holmium': 'Ho', 'erbium': 'Er', + 'thulium': 'Tm', 'ytterbium': 'Yb', 'lutetium': 'Lu', + 'hafnium': 'Hf', 'tantalum': 'Ta', 'tungsten': 'W', + 'wolfram': 'W', 'rhenium': 'Re', 'osmium': 'Os', + 'iridium': 'Ir', 'platinum': 'Pt', 'gold': 'Au', + 'mercury': 'Hg', 'thallium': 'Tl', 'lead': 'Pb', + 'bismuth': 'Bi', 'polonium': 'Po', 'astatine': 'At', + 'radon': 'Rn', 'francium': 'Fr', 'radium': 'Ra', + 'actinium': 'Ac', 'thorium': 'Th', 'protactinium': 'Pa', + 'uranium': 'U', 'neptunium': 'Np', 'plutonium': 'Pu', + 'americium': 'Am', 'curium': 'Cm', 'berkelium': 'Bk', + 'californium': 'Cf', 'einsteinium': 'Es', 'fermium': 'Fm', + 'mendelevium': 'Md', 'nobelium': 'No', 'lawrencium': 'Lr', + 'rutherfordium': 'Rf', 'dubnium': 'Db', 'seaborgium': 'Sg', + 'bohrium': 'Bh', 'hassium': 'Hs', 'meitnerium': 'Mt', + 'darmstadtium': 'Ds', 'roentgenium': 'Rg', 'copernicium': 'Cn', + 'nihonium': 'Nh', 'flerovium': 'Fl', 'moscovium': 'Mc', + 'livermorium': 'Lv', 'tennessine': 'Ts', 'oganesson': 'Og'} + ATOMIC_SYMBOL = {0: 'n', 1: 'H', 2: 'He', 3: 'Li', 4: 'Be', 5: 'B', 6: 'C', 7: 'N', 8: 'O', 9: 'F', 10: 'Ne', 11: 'Na', 12: 'Mg', 13: 'Al', 14: 'Si', 15: 'P', 16: 'S', 17: 'Cl', 18: 'Ar', 19: 'K', diff --git a/openmc/material.py b/openmc/material.py index 996d6a3327..542ed90282 100644 --- a/openmc/material.py +++ b/openmc/material.py @@ -505,7 +505,7 @@ class Material(IDManagerMixin): Parameters ---------- element : str - Element to add, e.g., 'Zr' + Element to add, e.g., 'Zr' or 'Zirconium' percent : float Atom or weight percent percent_type : {'ao', 'wo'}, optional @@ -517,10 +517,24 @@ 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'}) + # Make sure element name is just that + if not element.isalpha(): + raise ValueError("Element name should be given by the " + "element's symbol or name, e.g., 'Zr', 'zirconium'") + + # Allow for element identifier to be given as a symbol or name + if len(element)>2: + el = element.lower() + element = openmc.data.ELEMENT_SYMBOL.get(el,"empty") + if element == "empty": + msg = 'Element name "{}" not recognised'.format(el) + raise ValueError(msg) + 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) @@ -551,11 +565,6 @@ 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): From dce773dd14767ad799588bbce874dd80a45bacb4 Mon Sep 17 00:00:00 2001 From: Paul Cosgrove Date: Tue, 25 Feb 2020 12:34:56 +0000 Subject: [PATCH 2/7] Added simple test for adding elements by name --- tests/unit_tests/test_material.py | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/tests/unit_tests/test_material.py b/tests/unit_tests/test_material.py index cbff16e403..35b10b8b3e 100644 --- a/tests/unit_tests/test_material.py +++ b/tests/unit_tests/test_material.py @@ -34,6 +34,22 @@ def test_elements(): with pytest.raises(ValueError): m.add_element('Pu', 1.0, enrichment=3.0) +def test_elements_by_name(): + """Test adding elements by name""" + m = openmc.Material() + m.add_element('woLfrAm',1.0) + with pytest.raises(ValueError): + m.add_element('uranum',1.0) + m.add_element('uRaNiUm',1.0) + m.add_element('Aluminium',1.0) + a = openmc.Material() + b = openmc.Material() + c = openmc.Material() + a.add_element('sulfur',1.0) + b.add_element('SulPhUR',1.0) + c.add_element('S',1.0) + assert a._nuclides == b._nuclides + assert b._nuclides == c._nuclides def test_density(): m = openmc.Material() From 04e57d06f264700168441fbfd45fe35eaa0b4dac Mon Sep 17 00:00:00 2001 From: Paul Cosgrove Date: Tue, 25 Feb 2020 13:15:59 +0000 Subject: [PATCH 3/7] Modified docs to mention adding elements by name --- docs/source/usersguide/materials.rst | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/docs/source/usersguide/materials.rst b/docs/source/usersguide/materials.rst index 8472768489..5e9e74244a 100644 --- a/docs/source/usersguide/materials.rst +++ b/docs/source/usersguide/materials.rst @@ -40,6 +40,12 @@ of an element, you specify the element itself. For example, mat.add_element('C', 1.0) +This method can also accept element names, insensitive to character, such as + +:: + + mat.add_element('aluminium', 1.0) + 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 From bf7f7327a5faaa62ca709834816da1404e3b57e3 Mon Sep 17 00:00:00 2001 From: Paul Cosgrove Date: Tue, 25 Feb 2020 13:18:02 +0000 Subject: [PATCH 4/7] Changed a word in docs to clarify meaning --- docs/source/usersguide/materials.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/source/usersguide/materials.rst b/docs/source/usersguide/materials.rst index 5e9e74244a..90b624192d 100644 --- a/docs/source/usersguide/materials.rst +++ b/docs/source/usersguide/materials.rst @@ -40,7 +40,7 @@ of an element, you specify the element itself. For example, mat.add_element('C', 1.0) -This method can also accept element names, insensitive to character, such as +This method can also accept element names, insensitive to case, such as :: From d9b2c4dcccd222cddc3ac7d556a9f35ee6cbfd81 Mon Sep 17 00:00:00 2001 From: Paul Cosgrove Date: Thu, 27 Feb 2020 12:44:58 +0000 Subject: [PATCH 5/7] Requested changes for PR Modified data.py to align with OpenMC Python convention, added more elegant check for element names --- openmc/data/data.py | 1 + openmc/material.py | 5 +++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/openmc/data/data.py b/openmc/data/data.py index e34ab8d462..b2ab9462a9 100644 --- a/openmc/data/data.py +++ b/openmc/data/data.py @@ -4,6 +4,7 @@ import os import re from warnings import warn + # Isotopic abundances from Meija J, Coplen T B, et al, "Isotopic compositions # of the elements 2013 (IUPAC Technical Report)", Pure. Appl. Chem. 88 (3), # pp. 293-306 (2013). The "representative isotopic abundance" values from diff --git a/openmc/material.py b/openmc/material.py index 542ed90282..2bb461b02a 100644 --- a/openmc/material.py +++ b/openmc/material.py @@ -530,8 +530,9 @@ class Material(IDManagerMixin): # Allow for element identifier to be given as a symbol or name if len(element)>2: el = element.lower() - element = openmc.data.ELEMENT_SYMBOL.get(el,"empty") - if element == "empty": + if el in openmc.data.ELEMENT_SYMBOL: + element = openmc.data.ELEMENT_SYMBOL[el] + else: msg = 'Element name "{}" not recognised'.format(el) raise ValueError(msg) From 70b2f968f830d72ac727c982d43a4d0109907cd1 Mon Sep 17 00:00:00 2001 From: Paul Cosgrove Date: Thu, 27 Feb 2020 12:50:44 +0000 Subject: [PATCH 6/7] Even more elegant error check on element names --- openmc/material.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/openmc/material.py b/openmc/material.py index 2bb461b02a..d6147b3419 100644 --- a/openmc/material.py +++ b/openmc/material.py @@ -530,9 +530,8 @@ class Material(IDManagerMixin): # Allow for element identifier to be given as a symbol or name if len(element)>2: el = element.lower() - if el in openmc.data.ELEMENT_SYMBOL: - element = openmc.data.ELEMENT_SYMBOL[el] - else: + element = openmc.data.ELEMENT_SYMBOL.get(el) + if element is None: msg = 'Element name "{}" not recognised'.format(el) raise ValueError(msg) From abd8175a15d5d3d2f65cd50ca39da2e3485a3398 Mon Sep 17 00:00:00 2001 From: Paul Cosgrove Date: Fri, 28 Feb 2020 12:36:57 +0000 Subject: [PATCH 7/7] Changes to be consistent with PEP8 style --- docs/source/usersguide/materials.rst | 2 +- openmc/data/data.py | 28 ++++++++++++++-------------- openmc/material.py | 2 +- tests/unit_tests/test_material.py | 14 +++++++------- 4 files changed, 23 insertions(+), 23 deletions(-) diff --git a/docs/source/usersguide/materials.rst b/docs/source/usersguide/materials.rst index 90b624192d..69647342a4 100644 --- a/docs/source/usersguide/materials.rst +++ b/docs/source/usersguide/materials.rst @@ -40,7 +40,7 @@ of an element, you specify the element itself. For example, mat.add_element('C', 1.0) -This method can also accept element names, insensitive to case, such as +This method can also accept case-insensitive element names such as :: diff --git a/openmc/data/data.py b/openmc/data/data.py index b2ab9462a9..5440dec7cf 100644 --- a/openmc/data/data.py +++ b/openmc/data/data.py @@ -112,30 +112,30 @@ NATURAL_ABUNDANCE = { # Dictionary to give element symbols from IUPAC names # (and some common mispellings) -ELEMENT_SYMBOL = {'neutron': 'n', 'hydrogen': 'H', 'helium': 'He', - 'lithium': 'Li', 'beryllium': 'Be', 'boron': 'B', +ELEMENT_SYMBOL = {'neutron': 'n', 'hydrogen': 'H', 'helium': 'He', + 'lithium': 'Li', 'beryllium': 'Be', 'boron': 'B', 'carbon': 'C', 'nitrogen': 'N', 'oxygen': 'O', 'fluorine': 'F', 'neon': 'Ne', 'sodium': 'Na', 'magnesium': 'Mg', - 'aluminium': 'Al', 'aluminum':'Al', 'silicon': 'Si', - 'phosphorus': 'P', 'sulfur': 'S', 'sulphur': 'S', - 'chlorine': 'Cl', 'argon': 'Ar', 'potassium': 'K', + 'aluminium': 'Al', 'aluminum': 'Al', 'silicon': 'Si', + 'phosphorus': 'P', 'sulfur': 'S', 'sulphur': 'S', + 'chlorine': 'Cl', 'argon': 'Ar', 'potassium': 'K', 'calcium': 'Ca', 'scandium': 'Sc', 'titanium': 'Ti', 'vanadium': 'V', 'chromium': 'Cr', 'manganese': 'Mn', 'iron': 'Fe', 'cobalt': 'Co', 'nickel': 'Ni', 'copper': 'Cu', 'zinc': 'Zn', 'gallium': 'Ga', 'germanium': 'Ge', - 'arsenic': 'As', 'selenium': 'Se', 'bromine': 'Br', - 'krypton': 'Kr', 'rubidium': 'Rb', 'strontium': 'Sr', - 'yttrium': 'Y', 'zirconium': 'Zr', 'niobium': 'Nb', - 'molybdenum': 'Mo', 'technetium': 'Tc', 'ruthenium': 'Ru', - 'rhodium': 'Rh', 'palladium': 'Pd', 'silver': 'Ag', + 'arsenic': 'As', 'selenium': 'Se', 'bromine': 'Br', + 'krypton': 'Kr', 'rubidium': 'Rb', 'strontium': 'Sr', + 'yttrium': 'Y', 'zirconium': 'Zr', 'niobium': 'Nb', + 'molybdenum': 'Mo', 'technetium': 'Tc', 'ruthenium': 'Ru', + 'rhodium': 'Rh', 'palladium': 'Pd', 'silver': 'Ag', 'cadmium': 'Cd', 'indium': 'In', 'tin': 'Sn', 'antimony': 'Sb', 'tellurium': 'Te', 'iodine': 'I', 'xenon': 'Xe', 'caesium': 'Cs', 'cesium': 'Cs', 'barium': 'Ba', 'lanthanum': 'La', 'cerium': 'Ce', 'praseodymium': 'Pr', - 'neodymium': 'Nd', 'promethium': 'Pm', 'samarium': 'Sm', - 'europium': 'Eu', 'gadolinium': 'Gd', 'terbium': 'Tb', - 'dysprosium': 'Dy', 'holmium': 'Ho', 'erbium': 'Er', - 'thulium': 'Tm', 'ytterbium': 'Yb', 'lutetium': 'Lu', + 'neodymium': 'Nd', 'promethium': 'Pm', 'samarium': 'Sm', + 'europium': 'Eu', 'gadolinium': 'Gd', 'terbium': 'Tb', + 'dysprosium': 'Dy', 'holmium': 'Ho', 'erbium': 'Er', + 'thulium': 'Tm', 'ytterbium': 'Yb', 'lutetium': 'Lu', 'hafnium': 'Hf', 'tantalum': 'Ta', 'tungsten': 'W', 'wolfram': 'W', 'rhenium': 'Re', 'osmium': 'Os', 'iridium': 'Ir', 'platinum': 'Pt', 'gold': 'Au', diff --git a/openmc/material.py b/openmc/material.py index d6147b3419..122d7d8ca8 100644 --- a/openmc/material.py +++ b/openmc/material.py @@ -528,7 +528,7 @@ class Material(IDManagerMixin): "element's symbol or name, e.g., 'Zr', 'zirconium'") # Allow for element identifier to be given as a symbol or name - if len(element)>2: + if len(element) > 2: el = element.lower() element = openmc.data.ELEMENT_SYMBOL.get(el) if element is None: diff --git a/tests/unit_tests/test_material.py b/tests/unit_tests/test_material.py index 35b10b8b3e..095df8df9b 100644 --- a/tests/unit_tests/test_material.py +++ b/tests/unit_tests/test_material.py @@ -37,17 +37,17 @@ def test_elements(): def test_elements_by_name(): """Test adding elements by name""" m = openmc.Material() - m.add_element('woLfrAm',1.0) + m.add_element('woLfrAm', 1.0) with pytest.raises(ValueError): - m.add_element('uranum',1.0) - m.add_element('uRaNiUm',1.0) - m.add_element('Aluminium',1.0) + m.add_element('uranum', 1.0) + m.add_element('uRaNiUm', 1.0) + m.add_element('Aluminium', 1.0) a = openmc.Material() b = openmc.Material() c = openmc.Material() - a.add_element('sulfur',1.0) - b.add_element('SulPhUR',1.0) - c.add_element('S',1.0) + a.add_element('sulfur', 1.0) + b.add_element('SulPhUR', 1.0) + c.add_element('S', 1.0) assert a._nuclides == b._nuclides assert b._nuclides == c._nuclides