From a042ff60ed86dd70a71783b09bbe1a3efa0c74b4 Mon Sep 17 00:00:00 2001 From: Sam Shaner Date: Tue, 25 Oct 2016 20:54:56 -0400 Subject: [PATCH] addressed PR comments --- .../pythonapi/examples/mgxs-part-iv.ipynb | 223 ++++++------- openmc/element.py | 147 ++++---- openmc/material.py | 8 +- openmc/nuclide.py | 13 - src/input_xml.F90 | 313 +++++++----------- src/relaxng/materials.rnc | 4 + src/relaxng/settings.rnc | 4 - tests/input_set.py | 25 +- tests/test_element_wo/inputs_true.dat | 1 - tests/test_element_wo/results_true.dat | 5 - tests/test_element_wo/test_element_wo.py | 123 ++----- tests/test_enrichment/inputs_true.dat | 1 - tests/test_enrichment/results_true.dat | 5 - tests/test_enrichment/test_enrichment.py | 108 ++---- 14 files changed, 349 insertions(+), 631 deletions(-) delete mode 100644 tests/test_element_wo/inputs_true.dat delete mode 100644 tests/test_element_wo/results_true.dat delete mode 100644 tests/test_enrichment/inputs_true.dat delete mode 100644 tests/test_enrichment/results_true.dat diff --git a/docs/source/pythonapi/examples/mgxs-part-iv.ipynb b/docs/source/pythonapi/examples/mgxs-part-iv.ipynb index 74bbfb7d35..eb100c60d6 100644 --- a/docs/source/pythonapi/examples/mgxs-part-iv.ipynb +++ b/docs/source/pythonapi/examples/mgxs-part-iv.ipynb @@ -429,7 +429,7 @@ "outputs": [ { "data": { - "image/png": "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\n", + "image/png": "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\n", "text/plain": [ "" ] @@ -575,7 +575,7 @@ "name": "stderr", "output_type": "stream", "text": [ - "/home/nelsonag/git/openmc/openmc/mgxs/library.py:373: RuntimeWarning: The P0 correction will be ignored since the scattering order 0 is greater than zero\n", + "/Users/sam/.local/lib/python2.7/site-packages/openmc-0.8.0-py2.7-macosx-10.10-x86_64.egg/openmc/mgxs/library.py:370: RuntimeWarning: The P0 correction will be ignored since the scattering order 0 is greater than zero\n", " warn(msg, RuntimeWarning)\n" ] } @@ -731,9 +731,9 @@ " Copyright | 2011-2016 Massachusetts Institute of Technology\n", " License | http://openmc.readthedocs.io/en/latest/license.html\n", " Version | 0.8.0\n", - " Git SHA1 | 9d769378838a8404a7e878a65a6bf7f9fb8e083d\n", - " Date/Time | 2016-10-04 19:54:41\n", - " OpenMP Threads | 8\n", + " Git SHA1 | 6b1ff6128464ff7f0d9fad31bc4bbbf58cdf566c\n", + " Date/Time | 2016-10-25 20:51:15\n", + " MPI Processes | 1\n", "\n", " ===========================================================================\n", " ========================> INITIALIZATION <=========================\n", @@ -741,14 +741,14 @@ "\n", " Reading settings XML file...\n", " Reading geometry XML file...\n", - " Reading cross sections XML file...\n", " Reading materials XML file...\n", - " Reading U235 from /opt/xsdata/nndc/U235.h5\n", - " Reading U238 from /opt/xsdata/nndc/U238.h5\n", - " Reading O16 from /opt/xsdata/nndc/O16.h5\n", - " Reading Zr90 from /opt/xsdata/nndc/Zr90.h5\n", - " Reading H1 from /opt/xsdata/nndc/H1.h5\n", - " Reading B10 from /opt/xsdata/nndc/B10.h5\n", + " Reading cross sections XML file...\n", + " Reading U235 from /Users/sam/git/openmc-sam/data/nndc_hdf5/U235.h5\n", + " Reading U238 from /Users/sam/git/openmc-sam/data/nndc_hdf5/U238.h5\n", + " Reading O16 from /Users/sam/git/openmc-sam/data/nndc_hdf5/O16.h5\n", + " Reading Zr90 from /Users/sam/git/openmc-sam/data/nndc_hdf5/Zr90.h5\n", + " Reading H1 from /Users/sam/git/openmc-sam/data/nndc_hdf5/H1.h5\n", + " Reading B10 from /Users/sam/git/openmc-sam/data/nndc_hdf5/B10.h5\n", " Maximum neutron transport energy: 20.0000 MeV for U235\n", " Reading tallies XML file...\n", " Building neighboring cells lists for each surface...\n", @@ -819,20 +819,20 @@ "\n", " =======================> TIMING STATISTICS <=======================\n", "\n", - " Total time for initialization = 2.5432E-01 seconds\n", - " Reading cross sections = 1.4823E-01 seconds\n", - " Total time in simulation = 7.6226E+00 seconds\n", - " Time in transport only = 7.5567E+00 seconds\n", - " Time in inactive batches = 8.4858E-01 seconds\n", - " Time in active batches = 6.7740E+00 seconds\n", - " Time synchronizing fission bank = 4.9022E-03 seconds\n", - " Sampling source sites = 3.4092E-03 seconds\n", - " SEND/RECV source sites = 1.4584E-03 seconds\n", - " Time accumulating tallies = 1.0030E-04 seconds\n", - " Total time for finalization = 3.2380E-06 seconds\n", - " Total time elapsed = 7.8942E+00 seconds\n", - " Calculation Rate (inactive) = 58922.0 neutrons/second\n", - " Calculation Rate (active) = 29524.6 neutrons/second\n", + " Total time for initialization = 6.7087E-01 seconds\n", + " Reading cross sections = 4.9140E-01 seconds\n", + " Total time in simulation = 8.2685E+01 seconds\n", + " Time in transport only = 8.2657E+01 seconds\n", + " Time in inactive batches = 1.0173E+01 seconds\n", + " Time in active batches = 7.2513E+01 seconds\n", + " Time synchronizing fission bank = 1.0907E-02 seconds\n", + " Sampling source sites = 6.1890E-03 seconds\n", + " SEND/RECV source sites = 2.7820E-03 seconds\n", + " Time accumulating tallies = 9.7300E-04 seconds\n", + " Total time for finalization = 1.4000E-05 seconds\n", + " Total time elapsed = 8.3405E+01 seconds\n", + " Calculation Rate (inactive) = 4915.21 neutrons/second\n", + " Calculation Rate (active) = 2758.14 neutrons/second\n", "\n", " ============================> RESULTS <============================\n", "\n", @@ -970,20 +970,7 @@ "metadata": { "collapsed": false }, - "outputs": [ - { - "name": "stderr", - "output_type": "stream", - "text": [ - "/home/nelsonag/git/openmc/openmc/tallies.py:1945: RuntimeWarning: invalid value encountered in true_divide\n", - " self_rel_err = data['self']['std. dev.'] / data['self']['mean']\n", - "/home/nelsonag/git/openmc/openmc/tallies.py:1946: RuntimeWarning: invalid value encountered in true_divide\n", - " other_rel_err = data['other']['std. dev.'] / data['other']['mean']\n", - "/home/nelsonag/git/openmc/openmc/tallies.py:1947: RuntimeWarning: invalid value encountered in true_divide\n", - " new_tally._mean = data['self']['mean'] / data['other']['mean']\n" - ] - } - ], + "outputs": [], "source": [ "# Create a MGXS File which can then be written to disk\n", "mgxs_file = mgxs_lib.create_mg_library(xs_type='macro', xsdata_names=['fuel', 'zircaloy', 'water'])\n", @@ -1033,8 +1020,11 @@ "# Finally, instantiate our Materials object\n", "materials_file = openmc.Materials((fuel, zircaloy, water))\n", "\n", + "# Set the location of the cross sections file\n", + "materials_file.cross_sections = './mgxs.h5'\n", + "\n", "# Export to \"materials.xml\"\n", - "materials_file.export_to_xml()\n" + "materials_file.export_to_xml()" ] }, { @@ -1060,8 +1050,7 @@ }, "outputs": [], "source": [ - "# Set the location of the cross sections file\n", - "settings_file.cross_sections = './mgxs.h5'\n", + "# Set the energy mode\n", "settings_file.energy_mode = 'multi-group'\n", "\n", "# Export to \"settings.xml\"\n", @@ -1118,9 +1107,9 @@ " Copyright | 2011-2016 Massachusetts Institute of Technology\n", " License | http://openmc.readthedocs.io/en/latest/license.html\n", " Version | 0.8.0\n", - " Git SHA1 | 9d769378838a8404a7e878a65a6bf7f9fb8e083d\n", - " Date/Time | 2016-10-04 19:54:49\n", - " OpenMP Threads | 8\n", + " Git SHA1 | 6b1ff6128464ff7f0d9fad31bc4bbbf58cdf566c\n", + " Date/Time | 2016-10-25 20:52:38\n", + " MPI Processes | 1\n", "\n", " ===========================================================================\n", " ========================> INITIALIZATION <=========================\n", @@ -1128,8 +1117,8 @@ "\n", " Reading settings XML file...\n", " Reading geometry XML file...\n", - " Reading cross sections HDF5 file...\n", " Reading materials XML file...\n", + " Reading cross sections HDF5 file...\n", " Reading tallies XML file...\n", " Loading Cross Section Data...\n", " Loading fuel Data...\n", @@ -1152,48 +1141,48 @@ " 6/1 1.04127 \n", " 7/1 1.01783 \n", " 8/1 1.03856 \n", - " 9/1 1.03637 \n", - " 10/1 1.03884 \n", - " 11/1 1.04466 \n", - " 12/1 1.01060 1.02763 +/- 0.01703\n", - " 13/1 1.02517 1.02681 +/- 0.00987\n", - " 14/1 1.05287 1.03333 +/- 0.00954\n", - " 15/1 1.04369 1.03540 +/- 0.00768\n", - " 16/1 1.01304 1.03167 +/- 0.00729\n", - " 17/1 1.04258 1.03323 +/- 0.00636\n", - " 18/1 1.02301 1.03195 +/- 0.00565\n", - " 19/1 1.03906 1.03274 +/- 0.00505\n", - " 20/1 1.04148 1.03362 +/- 0.00460\n", - " 21/1 1.01271 1.03172 +/- 0.00457\n", - " 22/1 1.02021 1.03076 +/- 0.00428\n", - " 23/1 0.99553 1.02805 +/- 0.00478\n", - " 24/1 1.02434 1.02778 +/- 0.00443\n", - " 25/1 1.02987 1.02792 +/- 0.00413\n", - " 26/1 1.01676 1.02722 +/- 0.00393\n", - " 27/1 1.02738 1.02723 +/- 0.00369\n", - " 28/1 1.04014 1.02795 +/- 0.00355\n", - " 29/1 1.02831 1.02797 +/- 0.00336\n", - " 30/1 1.02643 1.02789 +/- 0.00319\n", - " 31/1 1.03939 1.02844 +/- 0.00308\n", - " 32/1 1.03282 1.02864 +/- 0.00294\n", - " 33/1 1.00098 1.02744 +/- 0.00306\n", - " 34/1 1.01763 1.02703 +/- 0.00296\n", - " 35/1 1.01412 1.02651 +/- 0.00288\n", - " 36/1 1.01564 1.02609 +/- 0.00280\n", - " 37/1 1.02379 1.02601 +/- 0.00270\n", - " 38/1 1.03648 1.02638 +/- 0.00263\n", - " 39/1 1.03237 1.02659 +/- 0.00254\n", - " 40/1 1.03501 1.02687 +/- 0.00247\n", - " 41/1 1.02054 1.02666 +/- 0.00240\n", - " 42/1 1.05751 1.02763 +/- 0.00252\n", - " 43/1 1.00751 1.02702 +/- 0.00251\n", - " 44/1 1.04743 1.02762 +/- 0.00251\n", - " 45/1 1.05212 1.02832 +/- 0.00254\n", - " 46/1 1.01839 1.02804 +/- 0.00248\n", - " 47/1 1.00424 1.02740 +/- 0.00250\n", - " 48/1 1.03117 1.02750 +/- 0.00243\n", - " 49/1 1.00988 1.02705 +/- 0.00241\n", - " 50/1 1.01943 1.02686 +/- 0.00236\n", + " 9/1 1.03626 \n", + " 10/1 1.03858 \n", + " 11/1 1.03725 \n", + " 12/1 1.01497 1.02611 +/- 0.01114\n", + " 13/1 1.03853 1.03025 +/- 0.00765\n", + " 14/1 1.02754 1.02957 +/- 0.00545\n", + " 15/1 1.03576 1.03081 +/- 0.00440\n", + " 16/1 1.02338 1.02957 +/- 0.00380\n", + " 17/1 1.03089 1.02976 +/- 0.00322\n", + " 18/1 1.05856 1.03336 +/- 0.00455\n", + " 19/1 1.00958 1.03072 +/- 0.00481\n", + " 20/1 1.01074 1.02872 +/- 0.00474\n", + " 21/1 1.00291 1.02637 +/- 0.00489\n", + " 22/1 1.00197 1.02434 +/- 0.00490\n", + " 23/1 1.01859 1.02390 +/- 0.00453\n", + " 24/1 1.03854 1.02494 +/- 0.00432\n", + " 25/1 1.01060 1.02399 +/- 0.00414\n", + " 26/1 1.04206 1.02512 +/- 0.00403\n", + " 27/1 1.01329 1.02442 +/- 0.00385\n", + " 28/1 1.04189 1.02539 +/- 0.00376\n", + " 29/1 1.04326 1.02633 +/- 0.00368\n", + " 30/1 1.01600 1.02582 +/- 0.00353\n", + " 31/1 0.99692 1.02444 +/- 0.00363\n", + " 32/1 0.97135 1.02203 +/- 0.00422\n", + " 33/1 1.04856 1.02318 +/- 0.00419\n", + " 34/1 1.01941 1.02302 +/- 0.00402\n", + " 35/1 1.00792 1.02242 +/- 0.00390\n", + " 36/1 1.05356 1.02362 +/- 0.00393\n", + " 37/1 1.04524 1.02442 +/- 0.00387\n", + " 38/1 1.02502 1.02444 +/- 0.00373\n", + " 39/1 1.01854 1.02424 +/- 0.00360\n", + " 40/1 1.02803 1.02436 +/- 0.00348\n", + " 41/1 0.99161 1.02331 +/- 0.00353\n", + " 42/1 1.06681 1.02466 +/- 0.00368\n", + " 43/1 1.03784 1.02506 +/- 0.00359\n", + " 44/1 1.01966 1.02491 +/- 0.00348\n", + " 45/1 1.02400 1.02488 +/- 0.00338\n", + " 46/1 0.99642 1.02409 +/- 0.00338\n", + " 47/1 1.05020 1.02479 +/- 0.00336\n", + " 48/1 1.02607 1.02483 +/- 0.00327\n", + " 49/1 1.00497 1.02432 +/- 0.00323\n", + " 50/1 1.03585 1.02461 +/- 0.00316\n", " Creating state point statepoint.50.h5...\n", "\n", " ===========================================================================\n", @@ -1203,27 +1192,27 @@ "\n", " =======================> TIMING STATISTICS <=======================\n", "\n", - " Total time for initialization = 9.9611E-02 seconds\n", - " Reading cross sections = 2.2051E-02 seconds\n", - " Total time in simulation = 6.3645E+00 seconds\n", - " Time in transport only = 6.3383E+00 seconds\n", - " Time in inactive batches = 6.3592E-01 seconds\n", - " Time in active batches = 5.7285E+00 seconds\n", - " Time synchronizing fission bank = 5.1108E-03 seconds\n", - " Sampling source sites = 3.7109E-03 seconds\n", - " SEND/RECV source sites = 1.3393E-03 seconds\n", - " Time accumulating tallies = 8.0199E-05 seconds\n", - " Total time for finalization = 2.9170E-06 seconds\n", - " Total time elapsed = 6.4828E+00 seconds\n", - " Calculation Rate (inactive) = 78625.7 neutrons/second\n", - " Calculation Rate (active) = 34912.9 neutrons/second\n", + " Total time for initialization = 4.1107E-02 seconds\n", + " Reading cross sections = 5.7660E-03 seconds\n", + " Total time in simulation = 6.6928E+01 seconds\n", + " Time in transport only = 6.6906E+01 seconds\n", + " Time in inactive batches = 6.9962E+00 seconds\n", + " Time in active batches = 5.9932E+01 seconds\n", + " Time synchronizing fission bank = 9.4430E-03 seconds\n", + " Sampling source sites = 6.5990E-03 seconds\n", + " SEND/RECV source sites = 2.2240E-03 seconds\n", + " Time accumulating tallies = 9.4200E-04 seconds\n", + " Total time for finalization = 1.4000E-05 seconds\n", + " Total time elapsed = 6.7022E+01 seconds\n", + " Calculation Rate (inactive) = 7146.75 neutrons/second\n", + " Calculation Rate (active) = 3337.11 neutrons/second\n", "\n", " ============================> RESULTS <============================\n", "\n", - " k-effective (Collision) = 1.02515 +/- 0.00252\n", - " k-effective (Track-length) = 1.02686 +/- 0.00236\n", - " k-effective (Absorption) = 1.02678 +/- 0.00178\n", - " Combined k-effective = 1.02710 +/- 0.00176\n", + " k-effective (Collision) = 1.02644 +/- 0.00247\n", + " k-effective (Track-length) = 1.02461 +/- 0.00316\n", + " k-effective (Absorption) = 1.02785 +/- 0.00173\n", + " Combined k-effective = 1.02718 +/- 0.00166\n", " Leakage Fraction = 0.00000 +/- 0.00000\n", "\n" ] @@ -1305,8 +1294,8 @@ "output_type": "stream", "text": [ "Continuous-Energy keff = 1.024295\n", - "Multi-Group keff = 1.027098\n", - "bias [pcm]: -280.3\n" + "Multi-Group keff = 1.027176\n", + "bias [pcm]: -288.2\n" ] } ], @@ -1403,7 +1392,7 @@ { "data": { "text/plain": [ - "" + "" ] }, "execution_count": 40, @@ -1412,9 +1401,9 @@ }, { "data": { - "image/png": "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\nrkJggg==\n", + "image/png": "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\nrkJggg==\n", "text/plain": [ - "" + "" ] }, "metadata": {}, @@ -1459,21 +1448,21 @@ ], "metadata": { "kernelspec": { - "display_name": "Python 3", + "display_name": "Python 2", "language": "python", - "name": "python3" + "name": "python2" }, "language_info": { "codemirror_mode": { "name": "ipython", - "version": 3 + "version": 2 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.5.2" + "pygments_lexer": "ipython2", + "version": "2.7.12" } }, "nbformat": 4, diff --git a/openmc/element.py b/openmc/element.py index bd601f2587..27046266d5 100644 --- a/openmc/element.py +++ b/openmc/element.py @@ -3,16 +3,18 @@ import sys import os from six import string_types +from xml.etree import ElementTree as ET import openmc from openmc.checkvalue import check_type, check_length -from openmc.data import NATURAL_ABUNDANCE -from xml.etree import ElementTree as ET +from openmc.data import NATURAL_ABUNDANCE, atomic_mass + class Element(object): - """A natural element used in a material via . Internally, OpenMC - will expand the natural element into isotopes based on the known natural - abundances. + """A natural element that auto-expands to add the isotopes of an element to + a material in their natural abundance. Internally, the OpenMC Python API + expands the natural element into isotopes only when the materials.xml file + is created. Parameters ---------- @@ -109,7 +111,8 @@ class Element(object): percent_type : {'ao', 'wo'} 'ao' for atom percent and 'wo' for weight percent enrichment : float, optional - Enrichment percent for U235 in U. Default is None + Enrichment for U235 in weight percent. For example, input 4.95 for + 4.95 weight percent enriched U. Default is None (natural composition). cross_sections : str, optional Location of cross_sections.xml file. Default is None. @@ -123,18 +126,14 @@ class Element(object): """ - # Get the length of this elements atomic symbol - name_len = len(self.name) - # Get the nuclides present in nature natural_nuclides = set() for nuclide in sorted(NATURAL_ABUNDANCE.keys()): if re.match(r'{}\d+'.format(self.name), nuclide): - natural_nuclides.add(int(nuclide[name_len:])) + natural_nuclides.add(nuclide) - # Create lists to store the expanded nuclides and abundances - nuclides = [] - abundances = [] + # Create dict to store the expanded nuclides and abundances + abundances = {} # If cross_sections is None, get the cross sections from the # OPENMC_CROSS_SECTIONS environment variable @@ -152,9 +151,10 @@ class Element(object): nuclide = child.attrib['materials'] if re.match(r'{}\d+'.format(self.name), nuclide) and \ '_m' not in nuclide: - library_nuclides.add(int(nuclide[name_len:])) + library_nuclides.add(nuclide) - # Get a set of the mutual and absent nuclides + # Get a set of the mutual and absent nuclides. Convert to lists + # and sort to avoid different ordering between Python 2 and 3. mutual_nuclides = natural_nuclides.intersection(library_nuclides) absent_nuclides = natural_nuclides.difference(mutual_nuclides) mutual_nuclides = sorted(list(mutual_nuclides)) @@ -163,22 +163,16 @@ class Element(object): # If all natural nuclides are present in the library, expand element # using all natural nuclides if len(absent_nuclides) == 0: - for nuclide, abundance in sorted(NATURAL_ABUNDANCE.items()): - if re.match(r'{}\d+'.format(self.name), nuclide): - nuc = openmc.Nuclide(nuclide) - nuc.scattering = self.scattering - nuclides.append(nuc) - abundances.append(abundance) + for nuclide in mutual_nuclides: + abundances[nuclide] = NATURAL_ABUNDANCE[nuclide] # If no natural elements are present in the library, check if the - # 0 element is present. If so, set the abundance to 1 for this + # 0 nuclide is present. If so, set the abundance to 1 for this # nuclide. Else, raise an error. elif len(mutual_nuclides) == 0: - if 0 in library_nuclides: - nuc = openmc.Nuclide(self.name + '0') - nuc.scattering = self.scattering - nuclides.append(nuc) - abundances.append(1.0) + nuclide_0 = self.name + '0' + if nuclide_0 in library_nuclides: + abundances[nuclide_0] = 1.0 else: msg = 'Unable to expand element {0} because the cross '\ 'section library provided does not contain any of '\ @@ -187,73 +181,54 @@ class Element(object): raise ValueError(msg) # If some, but not all, natural nuclides are in the library, add - # the mutual nuclides. For the absent nuclides, increment the - # abundance of the nearest mutual nuclide with their abundances. + # the mutual nuclides. For the absent nuclides, add them based on + # our knowledge of the common cross section libraries + # (ENDF, JEFF, and JENDL) else: # Add the mutual isotopes - nuclides_a = [] - for nuclide, abundance in sorted(NATURAL_ABUNDANCE.items()): - if re.match(r'{}\d+'.format(self.name), nuclide) and \ - int(nuclide[name_len:]) in mutual_nuclides: - nuc = openmc.Nuclide(nuclide) - nuc.scattering = self.scattering - nuclides.append(nuc) - nuclides_a.append(int(nuclide[name_len:])) - abundances.append(abundance) + for nuclide in mutual_nuclides: + abundances[nuclide] = NATURAL_ABUNDANCE[nuclide] # Adjust the abundances for the absent nuclides - for nuclide, abundance in sorted(NATURAL_ABUNDANCE.items()): - if re.match(r'{}\d+'.format(self.name), nuclide) and \ - int(nuclide[name_len:]) in absent_nuclides: + for nuclide in absent_nuclides: - # Get index to the nearest nuclide - a = int(nuclide[name_len:]) - i = min(list(range(len(nuclides_a))), key=lambda j: \ - abs(nuclides_a[j] - a)) - - # Increment abundance of the nearest nuclide - abundances[i] += abundance + if nuclide == 'O18' and 'O16' in mutual_nuclides: + abundances['O16'] += NATURAL_ABUNDANCE[nuclide] + elif nuclide == 'Ta180' and 'Ta181' in mutual_nuclides: + abundances['Ta181'] += NATURAL_ABUNDANCE[nuclide] + elif nuclide == 'W180' and 'W182' in mutual_nuclides: + abundances['W182'] += NATURAL_ABUNDANCE[nuclide] + else: + msg = 'Unsure how to partition natural abundance of ' \ + 'isotope {0} into other natural isotopes of ' \ + 'this element that are present in the cross ' \ + 'section library provided. Consider adding ' \ + 'the isotopes of this element individually.' + raise ValueError(msg) # If a cross_section library is not present, expand the element into # its natural nuclides else: - for nuclide, abundance in sorted(NATURAL_ABUNDANCE.items()): - if re.match(r'{}\d+'.format(self.name), nuclide): - nuclides.append(openmc.Nuclide(nuclide)) - abundances.append(abundance) - - # Create a list of atomic masses - n_nuclides = len(nuclides) - atomic_masses = [] - for nuclide in nuclides: - atomic_masses.append(openmc.data.atomic_mass(nuclide.name)) + for nuclide in natural_nuclides: + abundances[nuclide] = NATURAL_ABUNDNACE[nuclide] # Modify mole fractions if enrichment provided if enrichment is not None: - # Get the indices for the uranium nuclides - for i,nuc in enumerate(nuclides): - if nuc.name == 'U234': - u234 = i - elif nuc.name == 'U235': - u235 = i - elif nuc.name == 'U238': - u238 = i - # Calculate the mass fractions of isotopes - abundances[u234] = 0.008 * enrichment - abundances[u235] = enrichment - abundances[u238] = 1.0 - 1.008 * enrichment + abundances['U234'] = 0.008 * enrichment + abundances['U235'] = enrichment + abundances['U238'] = 100.0 - 1.008 * enrichment # Convert the mass fractions to mole fractions - for i in range(n_nuclides): - abundances[i] /= atomic_masses[i] + for nuclide in abundances.keys(): + abundances[nuclide] /= atomic_mass(nuclide) # Normalize the mole fractions to one - sum_abundances = sum(abundances) - for i in range(n_nuclides): - abundances[i] /= sum_abundances + sum_abundances = sum(abundances.values()) + for nuclide in abundances.keys(): + abundances[nuclide] /= sum_abundances # Compute the ratio of the nuclide atomic massess to the element # atomic mass @@ -261,23 +236,23 @@ class Element(object): # Compute the element atomic mass element_am = 0. - for i in range(n_nuclides): - element_am += atomic_masses[i] * abundances[i] + for nuclide in abundances.keys(): + element_am += atomic_mass(nuclide) * abundances[nuclide] # Convert the molar fractions to mass fractions - for i in range(n_nuclides): - abundances[i] *= atomic_masses[i] / element_am + for nuclide in abundances.keys(): + abundances[nuclide] *= atomic_mass(nuclide) / element_am # Normalize the mass fractions to one - sum_abundances = sum(abundances) - for i in range(n_nuclides): - abundances[i] /= sum_abundances + sum_abundances = sum(abundances.values()) + for nuclide in abundances.keys(): + abundances[nuclide] /= sum_abundances # Create a list of the isotopes in this element isotopes = [] - for nuclide, abundance in zip(nuclides, abundances): - #pct = float('{:2.8g}'.format()) - pct = percent*abundance - isotopes.append((nuclide, pct, percent_type)) + for nuclide, abundance in abundances.items(): + nuc = openmc.Nuclide(nuclide) + nuc.scattering = self.scattering + isotopes.append((nuc, percent*abundance, percent_type)) return isotopes diff --git a/openmc/material.py b/openmc/material.py index f203878c1f..e336156428 100644 --- a/openmc/material.py +++ b/openmc/material.py @@ -418,7 +418,9 @@ class Material(object): 'ao' for atom percent and 'wo' for weight percent. Defaults to atom percent. enrichment : float, optional - Optional weight percent enrichment for uranium. Defaults to None. + Enrichment for U235 in weight percent. For example, input 4.95 for + 4.95 weight percent enriched U. Default is None + (natural composition). """ @@ -462,10 +464,10 @@ class Material(object): raise ValueError(msg) # Check that the enrichment is in the valid range - cv.check_less_than('enrichment', enrichment, 1/1.008, equality=True) + cv.check_less_than('enrichment', enrichment, 100./1.008) cv.check_greater_than('enrichment', enrichment, 0., equality=True) - if enrichment > 0.05: + if enrichment > 5.0: msg = 'A uranium enrichment of {0} was given for Material ID='\ '"{1}". OpenMC assumes the U234/U235 mass ratio is '\ 'constant at 0.008, which is only valid at low ' \ diff --git a/openmc/nuclide.py b/openmc/nuclide.py index 79b51e68a2..7d566f2d55 100644 --- a/openmc/nuclide.py +++ b/openmc/nuclide.py @@ -95,16 +95,3 @@ class Nuclide(object): raise ValueError(msg) self._scattering = scattering - - def get_element(self): - """Returns the element of a nuclide - - Returns - ------- - element : openmc.Element - Element of nuclide - - """ - - element_name = "".join(itertools.takewhile(str.isalpha, name)) - return openmc.Element(element_name) diff --git a/src/input_xml.F90 b/src/input_xml.F90 index cb65a0d351..ceff3c936f 100644 --- a/src/input_xml.F90 +++ b/src/input_xml.F90 @@ -2163,9 +2163,6 @@ contains call time_read_xs % stop() end if - ! Assign and normalize nuclide densities - call assign_nuclide_densities() - ! Clear dictionary call library_dict % clear() end subroutine read_materials @@ -2184,13 +2181,19 @@ contains integer :: index_sab ! index in sab_tables logical :: file_exists ! does materials.xml exist? character(20) :: name ! name of nuclide, e.g. 92235.03c + character(MAX_WORD_LEN) :: units ! units on density character(MAX_LINE_LEN) :: filename ! absolute path to materials.xml character(MAX_LINE_LEN) :: temp_str ! temporary string when reading + real(8) :: val ! value entered for density + real(8) :: temp_dble ! temporary double prec. real + logical :: sum_density ! density is sum of nuclide densities type(VectorChar) :: names ! temporary list of nuclide names type(VectorInt) :: list_iso_lab ! temporary list of isotropic lab scatterers + type(VectorReal) :: densities ! temporary list of nuclide densities type(Material), pointer :: mat => null() type(Node), pointer :: doc => null() type(Node), pointer :: node_mat => null() + type(Node), pointer :: node_dens => null() type(Node), pointer :: node_nuc => null() type(Node), pointer :: node_sab => null() type(NodeList), pointer :: node_mat_list => null() @@ -2252,6 +2255,60 @@ contains material_temps(i) = ERROR_REAL end if + ! Get pointer to density element + if (check_for_node(node_mat, "density")) then + call get_node_ptr(node_mat, "density", node_dens) + else + call fatal_error("Must specify density element in material " & + // trim(to_str(mat % id))) + end if + + ! Copy units + call get_node_value(node_dens, "units", units) + + ! If the units is 'sum', then the total density of the material is taken + ! to be the sum of the atom fractions listed on the nuclides + if (units == 'sum') then + sum_density = .true. + + else if (units == 'macro') then + if (check_for_node(node_dens, "value")) then + call get_node_value(node_dens, "value", val) + else + val = ONE + end if + + ! Set density + mat % density = val + + sum_density = .false. + + else + call get_node_value(node_dens, "value", val) + + ! Check for erroneous density + sum_density = .false. + if (val <= ZERO) then + call fatal_error("Need to specify a positive density on material " & + // trim(to_str(mat % id)) // ".") + end if + + ! Adjust material density based on specified units + select case(to_lower(units)) + case ('g/cc', 'g/cm3') + mat % density = -val + case ('kg/m3') + mat % density = -0.001_8 * val + case ('atom/b-cm') + mat % density = val + case ('atom/cm3', 'atom/cc') + mat % density = 1.0e-24_8 * val + case default + call fatal_error("Unkwown units '" // trim(units) & + // "' specified on material " // trim(to_str(mat % id))) + end select + end if + ! ======================================================================= ! READ AND PARSE TAGS @@ -2290,6 +2347,15 @@ contains ! save name to list call names % push_back(name) + + ! Check if no atom/weight percents were specified or if both atom and + ! weight percents were specified + if (units == 'macro') then + call densities % push_back(ONE) + else + call fatal_error("Units can only be macro for macroscopic data " & + // trim(name)) + end if else ! Get pointer list of XML @@ -2306,6 +2372,31 @@ contains // trim(to_str(mat % id))) end if + ! Check if no atom/weight percents were specified or if both atom and + ! weight percents were specified + if (units == 'macro') then + call densities % push_back(ONE) + else + if (.not. check_for_node(node_nuc, "ao") .and. & + .not. check_for_node(node_nuc, "wo")) then + call fatal_error("No atom or weight percent specified for & + &nuclide" // trim(name)) + elseif (check_for_node(node_nuc, "ao") .and. & + check_for_node(node_nuc, "wo")) then + call fatal_error("Cannot specify both atom and weight percents & + &for a nuclide: " // trim(name)) + end if + + ! Copy atom/weight percents + if (check_for_node(node_nuc, "ao")) then + call get_node_value(node_nuc, "ao", temp_dble) + call densities % push_back(temp_dble) + else + call get_node_value(node_nuc, "wo", temp_dble) + call densities % push_back(-temp_dble) + end if + end if + ! Check enforced isotropic lab scattering if (run_CE) then if (check_for_node(node_nuc, "scattering")) then @@ -2374,6 +2465,7 @@ contains ! Copy name and atom/weight percent mat % names(j) = name + mat % atom_density(j) = densities % data(j) ! Cast integer isotropic lab scattering flag to boolean if (run_CE) then @@ -2386,8 +2478,20 @@ contains end do ALL_NUCLIDES + ! Check to make sure either all atom percents or all weight percents are + ! given + if (.not. (all(mat % atom_density >= ZERO) .or. & + all(mat % atom_density <= ZERO))) then + call fatal_error("Cannot mix atom and weight percents in material " & + // to_str(mat % id)) + end if + + ! Determine density if it is a sum value + if (sum_density) mat % density = sum(mat % atom_density) + ! Clear lists call names % clear() + call densities % clear() call list_iso_lab % clear() ! ======================================================================= @@ -4631,207 +4735,18 @@ contains end do end subroutine generate_rpn -!=============================================================================== -! ASSIGN_NUCLIDE_DENSITIES Read in the nuclide densities from materials.xml -! and assign to the corresponding nuclides. -!=============================================================================== - - subroutine assign_nuclide_densities() - integer :: i ! index in materials array - integer :: j ! index over nuclides in material - logical :: file_exists ! does materials.xml exist? - character(20) :: name ! name of nuclide, e.g. 92235.03c - character(MAX_WORD_LEN) :: units ! units on density - character(MAX_LINE_LEN) :: filename ! materials.xml filename - real(8) :: val ! value entered for density - real(8) :: temp_dble ! temporary double prec. real - logical :: sum_density ! density is sum of nuclide densities - type(VectorReal) :: densities ! temporary list of nuclide densities - type(Material), pointer :: mat => null() - type(Node), pointer :: doc => null() - type(Node), pointer :: node_mat => null() - type(Node), pointer :: node_dens => null() - type(Node), pointer :: node_nuc => null() - type(NodeList), pointer :: node_mat_list => null() - type(NodeList), pointer :: node_nuc_list => null() - type(NodeList), pointer :: node_macro_list => null() - - ! Display output message - call write_message("Reading material densities from XML file...", 5) - - ! Check is materials.xml exists - filename = trim(path_input) // "materials.xml" - inquire(FILE=filename, EXIST=file_exists) - if (.not. file_exists) then - call fatal_error("Material XML file '" // trim(filename) // "' does not & - &exist!") - end if - - ! Parse materials.xml file - call open_xmldoc(doc, filename) - - ! Get pointer to list of XML - call get_node_list(doc, "material", node_mat_list) - - do i = 1, n_materials - mat => materials(i) - - ! Get pointer to i-th material node - call get_list_item(node_mat_list, i, node_mat) - - ! Get pointer to density element - if (check_for_node(node_mat, "density")) then - call get_node_ptr(node_mat, "density", node_dens) - else - call fatal_error("Must specify density element in material " & - // trim(to_str(mat % id))) - end if - - ! Copy units - call get_node_value(node_dens, "units", units) - - ! If the units is 'sum', then the total density of the material is taken - ! to be the sum of the atom fractions listed on the nuclides - if (units == 'sum') then - sum_density = .true. - - else if (units == 'macro') then - if (check_for_node(node_dens, "value")) then - call get_node_value(node_dens, "value", val) - else - val = ONE - end if - - ! Set density - mat % density = val - - sum_density = .false. - - else - call get_node_value(node_dens, "value", val) - - ! Check for erroneous density - sum_density = .false. - if (val <= ZERO) then - call fatal_error("Need to specify a positive density on material " & - // trim(to_str(mat % id)) // ".") - end if - - ! Adjust material density based on specified units - select case(to_lower(units)) - case ('g/cc', 'g/cm3') - mat % density = -val - case ('kg/m3') - mat % density = -0.001_8 * val - case ('atom/b-cm') - mat % density = val - case ('atom/cm3', 'atom/cc') - mat % density = 1.0e-24_8 * val - case default - call fatal_error("Unkwown units '" // trim(units) & - // "' specified on material " // trim(to_str(mat % id))) - end select - end if - - ! ======================================================================== - ! READ IN NUCLIDE DENSITIES - - ! Get pointer list of XML - call get_node_list(node_mat, "macroscopic", node_macro_list) - if (get_list_size(node_macro_list) == 1) then - - call get_list_item(node_macro_list, 1, node_nuc) - - ! store nuclide name - call get_node_value(node_nuc, "name", name) - name = trim(name) - - ! Check if no atom/weight percents were specified or if both atom and - ! weight percents were specified - if (units == 'macro') then - call densities % push_back(ONE) - else - call fatal_error("Units can only be macro for macroscopic data " & - // trim(name)) - end if - else - - ! Get pointer list of XML - call get_node_list(node_mat, "nuclide", node_nuc_list) - - ! Create list of nuclides based on those specified - INDIVIDUAL_NUCLIDES: do j = 1, get_list_size(node_nuc_list) - - ! Combine nuclide identifier and cross section and copy into names - call get_list_item(node_nuc_list, j, node_nuc) - - ! store nuclide name - call get_node_value(node_nuc, "name", name) - name = trim(name) - - ! Check if no atom/weight percents were specified or if both atom and - ! weight percents were specified - if (units == 'macro') then - call densities % push_back(ONE) - else - if (.not. check_for_node(node_nuc, "ao") .and. & - .not. check_for_node(node_nuc, "wo")) then - call fatal_error("No atom or weight percent specified for & - &nuclide" // trim(name)) - elseif (check_for_node(node_nuc, "ao") .and. & - check_for_node(node_nuc, "wo")) then - call fatal_error("Cannot specify both atom and weight percents & - &for a nuclide: " // trim(name)) - end if - - ! Copy atom/weight percents - if (check_for_node(node_nuc, "ao")) then - call get_node_value(node_nuc, "ao", temp_dble) - call densities % push_back(temp_dble) - else - call get_node_value(node_nuc, "wo", temp_dble) - call densities % push_back(-temp_dble) - end if - end if - end do INDIVIDUAL_NUCLIDES - end if - - ! ======================================================================== - ! SET MATERIAL ATOM DENSITIES - - ALL_NUCLIDES: do j = 1, mat % n_nuclides - mat % atom_density(j) = densities % data(j) - end do ALL_NUCLIDES - - ! Check to make sure either all atom percents or all weight percents are - ! given - if (.not. (all(mat % atom_density >= ZERO) .or. & - all(mat % atom_density <= ZERO))) then - call fatal_error("Cannot mix atom and weight percents in material " & - // to_str(mat % id)) - end if - - ! Determine density if it is a sum value - if (sum_density) mat % density = sum(mat % atom_density) - - ! Clear lists - call densities % clear() - end do - - end subroutine assign_nuclide_densities - !=============================================================================== ! NORMALIZE_AO Normalize the nuclide atom percents !=============================================================================== subroutine normalize_ao() - integer :: i ! index in materials array - integer :: j ! index over nuclides in material - real(8) :: sum_percent ! summation - real(8) :: awr ! atomic weight ratio - real(8) :: x ! atom percent - logical :: percent_in_atom ! nuclides specified in atom percent? - logical :: density_in_atom ! density specified in atom/b-cm? + integer :: i ! index in materials array + integer :: j ! index over nuclides in material + real(8) :: sum_percent ! summation + real(8) :: awr ! atomic weight ratio + real(8) :: x ! atom percent + logical :: percent_in_atom ! nuclides specified in atom percent? + logical :: density_in_atom ! density specified in atom/b-cm? do i = 1, size(materials) associate (mat => materials(i)) diff --git a/src/relaxng/materials.rnc b/src/relaxng/materials.rnc index c5f4efd6f3..134fb86cae 100644 --- a/src/relaxng/materials.rnc +++ b/src/relaxng/materials.rnc @@ -42,4 +42,8 @@ element materials { (element name { xsd:string } | attribute name { xsd:string }) }* }+ + + element cross_sections { xsd:string { maxLength = "255" } }? & + + element multipole_library { xsd:string { maxLength = "255" } }? & } diff --git a/src/relaxng/settings.rnc b/src/relaxng/settings.rnc index b05ab7d6b5..62d9451c3d 100644 --- a/src/relaxng/settings.rnc +++ b/src/relaxng/settings.rnc @@ -25,10 +25,6 @@ element settings { } ) & - element cross_sections { xsd:string { maxLength = "255" } }? & - - element multipole_library { xsd:string { maxLength = "255" } }? & - element cutoff { (element weight { xsd:double } | attribute weight { xsd:double })? & (element weight_avg { xsd:double } | attribute weight_avg { xsd:double })? diff --git a/tests/input_set.py b/tests/input_set.py index 458c1ef35e..7971a8a4cc 100644 --- a/tests/input_set.py +++ b/tests/input_set.py @@ -524,31 +524,22 @@ class PinCellInputSet(object): # Instantiate ZCylinder surfaces fuel_or = openmc.ZCylinder(x0=0, y0=0, R=0.39218, name='Fuel OR') clad_or = openmc.ZCylinder(x0=0, y0=0, R=0.45720, name='Clad OR') - left = openmc.XPlane(x0=-0.63, name='left') - right = openmc.XPlane(x0=0.63, name='right') - bottom = openmc.YPlane(y0=-0.63, name='bottom') - top = openmc.YPlane(y0=0.63, name='top') - - left.boundary_type = 'reflective' - right.boundary_type = 'reflective' - top.boundary_type = 'reflective' - bottom.boundary_type = 'reflective' + left = openmc.XPlane(x0=-0.63, name='left', boundary_type='reflective') + right = openmc.XPlane(x0=0.63, name='right', boundary_type='reflective') + bottom = openmc.YPlane(y0=-0.63, name='bottom', + boundary_type='reflective') + top = openmc.YPlane(y0=0.63, name='top', boundary_type='reflective') # Instantiate Cells - fuel_pin = openmc.Cell(name='cell 1') - cladding = openmc.Cell(name='cell 3') - water = openmc.Cell(name='cell 2') + fuel_pin = openmc.Cell(name='cell 1', fill=fuel) + cladding = openmc.Cell(name='cell 3', fill=clad) + water = openmc.Cell(name='cell 2', fill=hot_water) # Use surface half-spaces to define regions fuel_pin.region = -fuel_or cladding.region = +fuel_or & -clad_or water.region = +clad_or & +left & -right & +bottom & -top - # Register Materials with Cells - fuel_pin.fill = fuel - cladding.fill = clad - water.fill = hot_water - # Instantiate Universe root = openmc.Universe(universe_id=0, name='root universe') diff --git a/tests/test_element_wo/inputs_true.dat b/tests/test_element_wo/inputs_true.dat deleted file mode 100644 index da97abc339..0000000000 --- a/tests/test_element_wo/inputs_true.dat +++ /dev/null @@ -1 +0,0 @@ -f270ae43a29c53065678b419629ad713f5a4cc23c75825fee4da049d4159756f463fec86263a8dea6ce10fff6d60b24ebf100e8f5cc80e6d4fc31297ae1709ed \ No newline at end of file diff --git a/tests/test_element_wo/results_true.dat b/tests/test_element_wo/results_true.dat deleted file mode 100644 index 6ff7f2872e..0000000000 --- a/tests/test_element_wo/results_true.dat +++ /dev/null @@ -1,5 +0,0 @@ -k-combined: -8.781218E-01 2.426380E-02 -tally 1: -8.505928E+01 -1.447208E+03 diff --git a/tests/test_element_wo/test_element_wo.py b/tests/test_element_wo/test_element_wo.py index 1acb73137a..de3957f31e 100644 --- a/tests/test_element_wo/test_element_wo.py +++ b/tests/test_element_wo/test_element_wo.py @@ -1,98 +1,37 @@ #!/usr/bin/env python -import os -import sys -import glob -import hashlib -sys.path.insert(0, os.pardir) -from testing_harness import PyAPITestHarness -from input_set import PinCellInputSet +import numpy as np import openmc -import openmc.mgxs - - -class ElementWOTestHarness(PyAPITestHarness): - def _build_inputs(self): - - # Set the input set to use the pincell model - self._input_set = PinCellInputSet() - - # Define materials. - fuel = openmc.Material(name='Fuel') - fuel.set_density('g/cm3', 10.29769) - fuel.add_element("U", 0.88, 'wo') - fuel.add_element("O", 0.12, 'wo') - - # Add some natural elements to the fuel - for element in ['Ir', 'Au', 'Hg', 'Tl', 'Pb', 'Bi', 'Th', 'Pa']: - fuel.add_element(element, 1.e-8, 'wo') - - clad = openmc.Material(name='Cladding') - clad.set_density('g/cm3', 6.55) - clad.add_element("Zr", 1.0, 'wo') - - hot_water = openmc.Material(name='Hot borated water') - hot_water.set_density('g/cm3', 0.740582) - hot_water.add_element("H", 0.1111, 'wo') - hot_water.add_element("O", 0.8889, 'wo') - hot_water.add_s_alpha_beta('c_H_in_H2O') - - # Define the materials file. - self._input_set.materials += (fuel, clad, hot_water) - - # Instantiate ZCylinder surfaces - fuel_or = openmc.ZCylinder(x0=0, y0=0, R=0.39218, name='Fuel OR') - clad_or = openmc.ZCylinder(x0=0, y0=0, R=0.45720, name='Clad OR') - left = openmc.XPlane(x0=-0.63, name='left') - right = openmc.XPlane(x0=0.63, name='right') - bottom = openmc.YPlane(y0=-0.63, name='bottom') - top = openmc.YPlane(y0=0.63, name='top') - - left.boundary_type = 'reflective' - right.boundary_type = 'reflective' - top.boundary_type = 'reflective' - bottom.boundary_type = 'reflective' - - # Instantiate Cells - fuel_pin = openmc.Cell(name='cell 1') - cladding = openmc.Cell(name='cell 3') - water = openmc.Cell(name='cell 2') - - # Use surface half-spaces to define regions - fuel_pin.region = -fuel_or - cladding.region = +fuel_or & -clad_or - water.region = +clad_or & +left & -right & +bottom & -top - - # Register Materials with Cells - fuel_pin.fill = fuel - cladding.fill = clad - water.fill = hot_water - - # Instantiate Universe - root = openmc.Universe(universe_id=0, name='root universe') - - # Register Cells with Universe - root.add_cells([fuel_pin, cladding, water]) - - # Instantiate a Geometry, register the root Universe, and export to XML - self._input_set.geometry.root_universe = root - - mat_filter = openmc.MaterialFilter((fuel.id,)) - flux_tally = openmc.Tally() - flux_tally.filters = [mat_filter] - flux_tally.scores = ['flux'] - - self._input_set.tallies = openmc.Tallies() - self._input_set.tallies += [flux_tally] - self._input_set.build_default_settings() - self._input_set.export() - - def _cleanup(self): - super(ElementWOTestHarness, self)._cleanup() - f = os.path.join(os.getcwd(), 'tallies.xml') - if os.path.exists(f): os.remove(f) +from openmc.data import NATURAL_ABUNDANCE, atomic_mass if __name__ == '__main__': - harness = ElementWOTestHarness('statepoint.10.*', True) - harness.main() + # This test doesn't require an OpenMC run. We just need to make sure the + # element.expand() method expands elements with the proper nuclide + # compositions. + + h_am = (NATURAL_ABUNDANCE['H1'] * atomic_mass('H1') + + NATURAL_ABUNDANCE['H2'] * atomic_mass('H2')) + o_am = (NATURAL_ABUNDANCE['O17'] * atomic_mass('O17') + + (NATURAL_ABUNDANCE['O16'] + NATURAL_ABUNDANCE['O18']) + * atomic_mass('O16')) + water_am = 2 * h_am + o_am + + water = openmc.Material() + water.add_element('O', o_am / water_am, 'wo') + water.add_element('H', 2 * h_am / water_am, 'wo') + densities = water.get_nuclide_densities() + + for nuc in densities.keys(): + assert nuc in ('H1', 'H2', 'O16', 'O17') + + if nuc in ('H1', 'H2'): + val = 2 * NATURAL_ABUNDANCE[nuc] * atomic_mass(nuc) / water_am + assert np.isclose(densities[nuc][1], val, rtol=1.e-8) + if nuc == 'O16': + val = (NATURAL_ABUNDANCE[nuc] + NATURAL_ABUNDANCE['O18']) \ + * atomic_mass(nuc) / water_am + assert np.isclose(densities[nuc][1], val, rtol=1.e-8) + if nuc == 'O17': + val = NATURAL_ABUNDANCE[nuc] * atomic_mass(nuc) / water_am + assert np.isclose(densities[nuc][1], val, rtol=1.e-8) diff --git a/tests/test_enrichment/inputs_true.dat b/tests/test_enrichment/inputs_true.dat deleted file mode 100644 index 49acd2945a..0000000000 --- a/tests/test_enrichment/inputs_true.dat +++ /dev/null @@ -1 +0,0 @@ -835357f7b3c10f1153bb5842978075d9bb788d639759f143dfe58064865712fdf4e17ce50747949411e7c5215f33371e883e48b670509e222fa338bbfe613b80 \ No newline at end of file diff --git a/tests/test_enrichment/results_true.dat b/tests/test_enrichment/results_true.dat deleted file mode 100644 index b457c2071c..0000000000 --- a/tests/test_enrichment/results_true.dat +++ /dev/null @@ -1,5 +0,0 @@ -k-combined: -1.508419E+00 3.763047E-02 -tally 1: -6.274668E+01 -7.902869E+02 diff --git a/tests/test_enrichment/test_enrichment.py b/tests/test_enrichment/test_enrichment.py index ac22f43ed4..ffc1074904 100644 --- a/tests/test_enrichment/test_enrichment.py +++ b/tests/test_enrichment/test_enrichment.py @@ -1,94 +1,26 @@ #!/usr/bin/env python -import os -import sys -import glob -import hashlib -sys.path.insert(0, os.pardir) -from testing_harness import PyAPITestHarness -from input_set import PinCellInputSet +import numpy as np import openmc -import openmc.mgxs - - -class EnrichmentTestHarness(PyAPITestHarness): - def _build_inputs(self): - - # Set the input set to use the pincell model - self._input_set = PinCellInputSet() - - # Define materials. - fuel = openmc.Material(name='Fuel') - fuel.set_density('g/cm3', 10.29769) - fuel.add_element("U", 0.88, 'wo', enrichment=0.0495) - fuel.add_element("O", 0.12, 'wo') - - clad = openmc.Material(name='Cladding') - clad.set_density('g/cm3', 6.55) - clad.add_element("Zr", 1.0, 'wo') - - hot_water = openmc.Material(name='Hot borated water') - hot_water.set_density('g/cm3', 0.740582) - hot_water.add_element("H", 0.1111, 'wo') - hot_water.add_element("O", 0.8889, 'wo') - hot_water.add_s_alpha_beta('c_H_in_H2O') - - # Define the materials file. - self._input_set.materials += (fuel, clad, hot_water) - - # Instantiate ZCylinder surfaces - fuel_or = openmc.ZCylinder(x0=0, y0=0, R=0.39218, name='Fuel OR') - clad_or = openmc.ZCylinder(x0=0, y0=0, R=0.45720, name='Clad OR') - left = openmc.XPlane(x0=-0.63, name='left') - right = openmc.XPlane(x0=0.63, name='right') - bottom = openmc.YPlane(y0=-0.63, name='bottom') - top = openmc.YPlane(y0=0.63, name='top') - - left.boundary_type = 'reflective' - right.boundary_type = 'reflective' - top.boundary_type = 'reflective' - bottom.boundary_type = 'reflective' - - # Instantiate Cells - fuel_pin = openmc.Cell(name='cell 1') - cladding = openmc.Cell(name='cell 3') - water = openmc.Cell(name='cell 2') - - # Use surface half-spaces to define regions - fuel_pin.region = -fuel_or - cladding.region = +fuel_or & -clad_or - water.region = +clad_or & +left & -right & +bottom & -top - - # Register Materials with Cells - fuel_pin.fill = fuel - cladding.fill = clad - water.fill = hot_water - - # Instantiate Universe - root = openmc.Universe(universe_id=0, name='root universe') - - # Register Cells with Universe - root.add_cells([fuel_pin, cladding, water]) - - # Instantiate a Geometry, register the root Universe, and export to XML - self._input_set.geometry.root_universe = root - - mat_filter = openmc.MaterialFilter((fuel.id,)) - flux_tally = openmc.Tally() - flux_tally.filters = [mat_filter] - flux_tally.scores = ['flux'] - - self._input_set.tallies = openmc.Tallies() - self._input_set.tallies += [flux_tally] - self._input_set.build_default_settings() - self._input_set.export() - - def _cleanup(self): - super(EnrichmentTestHarness, self)._cleanup() - f = os.path.join(os.getcwd(), 'tallies.xml') - if os.path.exists(f): os.remove(f) if __name__ == '__main__': - harness = EnrichmentTestHarness('statepoint.10.*', True) - harness.main() + # This test doesn't require an OpenMC run. We just need to make sure the + # element.expand() method expands Uranium to the proper enrichment. + + uranium = openmc.Material() + uranium.add_element('U', 1.0, 'wo', 4.95) + densities = uranium.get_nuclide_densities() + + sum_densities = 0. + for nuc in densities.keys(): + assert nuc in ('U234', 'U235', 'U238') + sum_densities += densities[nuc][1] + + # Compute the weight percent U235 + enrichment = densities['U235'][1] / sum_densities + assert np.isclose(enrichment, 0.0495, rtol=1.e-8) + + # Compute the ratio of U234/U235 + u234_to_u235 = densities['U234'][1] / densities['U235'][1] + assert np.isclose(u234_to_u235, 0.008, rtol=1.e-8)