From 0508274a3dd97029b914c9031df5e9ff753f042b Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Fri, 2 Mar 2018 10:36:08 -0600 Subject: [PATCH 01/15] Add useful warnings for add_nuclide/add_element --- docs/source/usersguide/materials.rst | 14 ++++++-- openmc/data/ace.py | 4 +-- openmc/data/data.py | 5 +-- openmc/data/endf.py | 4 +-- openmc/material.py | 49 ++++++++++------------------ tests/unit_tests/test_material.py | 4 +-- 6 files changed, 38 insertions(+), 42 deletions(-) diff --git a/docs/source/usersguide/materials.rst b/docs/source/usersguide/materials.rst index b1e0c151f..847276848 100644 --- a/docs/source/usersguide/materials.rst +++ b/docs/source/usersguide/materials.rst @@ -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. diff --git a/openmc/data/ace.py b/openmc/data/ace.py index 385408bd4..fa2705220 100644 --- a/openmc/data/ace.py +++ b/openmc/data/ace.py @@ -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 diff --git a/openmc/data/data.py b/openmc/data/data.py index fd1329961..3a625b622 100644 --- a/openmc/data/data.py +++ b/openmc/data/data.py @@ -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)) diff --git a/openmc/data/endf.py b/openmc/data/endf.py index c44c66be0..0d1f402c2 100644 --- a/openmc/data/endf.py +++ b/openmc/data/endf.py @@ -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): diff --git a/openmc/material.py b/openmc/material.py index d52d8a27b..053e516fa 100644 --- a/openmc/material.py +++ b/openmc/material.py @@ -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): diff --git a/tests/unit_tests/test_material.py b/tests/unit_tests/test_material.py index c251df3a6..b7b745408 100644 --- a/tests/unit_tests/test_material.py +++ b/tests/unit_tests/test_material.py @@ -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') From f415700c86d5e4bbb8498b216c95e5fa5a78e00c Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Fri, 2 Mar 2018 10:57:02 -0600 Subject: [PATCH 02/15] Make materials with actinides depletable by default --- openmc/material.py | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/openmc/material.py b/openmc/material.py index 053e516fa..88479d8df 100644 --- a/openmc/material.py +++ b/openmc/material.py @@ -88,7 +88,7 @@ class Material(IDManagerMixin): self.name = name self.temperature = temperature self._density = None - self._density_units = '' + self._density_units = 'sum' self._depletable = False self._paths = None self._num_instances = None @@ -397,9 +397,13 @@ class Material(IDManagerMixin): # If nuclide name doesn't look valid, give a warning try: - openmc.data.zam(nuclide) + Z, _, _ = openmc.data.zam(nuclide) except ValueError as e: warnings.warn(str(e)) + else: + # For actinides, have the material be depletable by default + if Z >= 89: + self.depletable = True self._nuclides.append((nuclide, percent, percent_type)) @@ -541,7 +545,7 @@ class Material(IDManagerMixin): # Add naturally-occuring isotopes element = openmc.Element(element) for nuclide in element.expand(percent, percent_type, enrichment): - self._nuclides.append(nuclide) + self.add_nuclide(*nuclide) def add_s_alpha_beta(self, name, fraction=1.0): r"""Add an :math:`S(\alpha,\beta)` table to the material From ed7edf414179f34ccb9247f847b931e507c3ec21 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Fri, 2 Mar 2018 12:09:27 -0600 Subject: [PATCH 03/15] Have Universe.plot return AxesImage. Add Plot.to_image method --- openmc/plots.py | 37 +++++++++++++++++++++++++++++++++++++ openmc/plotter.py | 3 ++- openmc/universe.py | 27 ++++++++++++++------------- 3 files changed, 53 insertions(+), 14 deletions(-) diff --git a/openmc/plots.py b/openmc/plots.py index 4414a39e1..a948c2a48 100644 --- a/openmc/plots.py +++ b/openmc/plots.py @@ -1,6 +1,7 @@ from collections.abc import Iterable, Mapping from numbers import Real, Integral from xml.etree import ElementTree as ET +import subprocess import sys import warnings @@ -650,6 +651,42 @@ class Plot(IDManagerMixin): return element + def to_image(self, openmc_exec='openmc', cwd='.', convert_exec='convert'): + """Render plot as an image + + Parameters + ---------- + openmc_exec : str + Path to OpenMC executable + cwd : str, optional + Path to working directory to run in + convert_exec : str, optional + Command that can convert PPM files into PNG files + + Returns + ------- + IPython.display.Image + Image generated + + """ + from IPython.display import Image + + # Create plots.xml + Plots([self]).export_to_xml() + + # Run OpenMC in geometry plotting mode + openmc.plot_geometry(False, openmc_exec, cwd) + + # Convert to .png + if self.filename is not None: + ppm_file = '{}.ppm'.format(self.filename) + else: + ppm_file = 'plot_{}.ppm'.format(self.id) + png_file = ppm_file.replace('.ppm', '.png') + subprocess.check_call([convert_exec, ppm_file, png_file]) + + return Image(png_file) + class Plots(cv.CheckedList): """Collection of Plots used for an OpenMC simulation. diff --git a/openmc/plotter.py b/openmc/plotter.py index 1bf6fe46f..191b50c56 100644 --- a/openmc/plotter.py +++ b/openmc/plotter.py @@ -2,7 +2,6 @@ from numbers import Integral, Real from itertools import chain import string -import matplotlib.pyplot as plt import numpy as np import openmc.checkvalue as cv @@ -125,6 +124,8 @@ def plot_xs(this, types, divisor_types=None, temperature=294., data_type=None, generated. """ + import matplotlib.pyplot as plt + cv.check_type("plot_CE", plot_CE, bool) if data_type is None: diff --git a/openmc/universe.py b/openmc/universe.py index 55f574c53..77138adcc 100644 --- a/openmc/universe.py +++ b/openmc/universe.py @@ -4,7 +4,6 @@ from numbers import Integral, Real import random import sys -import matplotlib.pyplot as plt import numpy as np import openmc @@ -184,10 +183,14 @@ class Universe(IDManagerMixin): return [] def plot(self, origin=(0., 0., 0.), width=(1., 1.), pixels=(200, 200), - basis='xy', color_by='cell', colors=None, filename=None, seed=None, + basis='xy', color_by='cell', colors=None, seed=None, **kwargs): """Display a slice plot of the universe. + To display or save the plot, call :func:`matplotlib.pyplot.show` or + :func:`matplotlib.pyplot.savefig`. In a Jupyter notebook, enabling the + matplotlib inline backend will show the plot inline. + Parameters ---------- origin : Iterable of float @@ -212,9 +215,6 @@ class Universe(IDManagerMixin): water = openmc.Cell(fill=h2o) universe.plot(..., colors={water: (0., 0., 1.)) - filename : str or None - Filename to save plot to. If no filename is given, the plot will be - displayed using the currently enabled matplotlib backend. seed : hashable object or None Hashable object which is used to seed the random number generator used to select colors. If None, the generator is seeded from the @@ -223,7 +223,14 @@ class Universe(IDManagerMixin): All keyword arguments are passed to :func:`matplotlib.pyplot.imshow`. + Returns + ------- + matplotlib.image.AxesImage + Resulting image + """ + import matplotlib.pyplot as plt + # Seed the random number generator if seed is not None: random.seed(seed) @@ -298,14 +305,8 @@ class Universe(IDManagerMixin): img[j, i, :] = colors[obj] # Display image - plt.imshow(img, extent=(x_min, x_max, y_min, y_max), - interpolation='nearest', **kwargs) - - # Show or save the plot - if filename is None: - plt.show() - else: - plt.savefig(filename) + return plt.imshow(img, extent=(x_min, x_max, y_min, y_max), + interpolation='nearest', **kwargs) def add_cell(self, cell): """Add a cell to the universe. From 23324fe24b62b0f92e609a4e78c40847277ed3d8 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Fri, 2 Mar 2018 16:18:51 -0600 Subject: [PATCH 04/15] Fix broken tests --- tests/regression_tests/asymmetric_lattice/inputs_true.dat | 2 +- .../create_fission_neutrons/inputs_true.dat | 2 +- tests/regression_tests/diff_tally/inputs_true.dat | 2 +- tests/regression_tests/distribmat/inputs_true.dat | 4 ++-- tests/regression_tests/filter_energyfun/inputs_true.dat | 4 ++-- tests/regression_tests/filter_mesh/inputs_true.dat | 2 +- tests/regression_tests/fixed_source/inputs_true.dat | 2 +- tests/regression_tests/iso_in_lab/inputs_true.dat | 2 +- .../mgxs_library_ce_to_mg/inputs_true.dat | 2 +- .../mgxs_library_condense/inputs_true.dat | 2 +- .../mgxs_library_distribcell/inputs_true.dat | 2 +- tests/regression_tests/mgxs_library_hdf5/inputs_true.dat | 2 +- tests/regression_tests/mgxs_library_mesh/inputs_true.dat | 2 +- .../mgxs_library_no_nuclides/inputs_true.dat | 2 +- .../mgxs_library_nuclides/inputs_true.dat | 2 +- tests/regression_tests/multipole/inputs_true.dat | 2 +- tests/regression_tests/periodic/inputs_true.dat | 2 +- .../regression_tests/resonance_scattering/inputs_true.dat | 2 +- tests/regression_tests/salphabeta/inputs_true.dat | 8 ++++---- tests/regression_tests/source/inputs_true.dat | 2 +- tests/regression_tests/surface_tally/inputs_true.dat | 2 +- tests/regression_tests/tallies/inputs_true.dat | 2 +- tests/regression_tests/tally_aggregation/inputs_true.dat | 2 +- tests/regression_tests/tally_arithmetic/inputs_true.dat | 2 +- tests/regression_tests/tally_slice_merge/inputs_true.dat | 2 +- tests/regression_tests/triso/inputs_true.dat | 2 +- tests/regression_tests/volume_calc/inputs_true.dat | 2 +- tests/unit_tests/test_universe.py | 1 - 28 files changed, 32 insertions(+), 33 deletions(-) diff --git a/tests/regression_tests/asymmetric_lattice/inputs_true.dat b/tests/regression_tests/asymmetric_lattice/inputs_true.dat index 672f6bee1..bbdc79715 100644 --- a/tests/regression_tests/asymmetric_lattice/inputs_true.dat +++ b/tests/regression_tests/asymmetric_lattice/inputs_true.dat @@ -56,7 +56,7 @@ - + diff --git a/tests/regression_tests/create_fission_neutrons/inputs_true.dat b/tests/regression_tests/create_fission_neutrons/inputs_true.dat index 9aeabbb57..b0ca89647 100644 --- a/tests/regression_tests/create_fission_neutrons/inputs_true.dat +++ b/tests/regression_tests/create_fission_neutrons/inputs_true.dat @@ -10,7 +10,7 @@ - + diff --git a/tests/regression_tests/diff_tally/inputs_true.dat b/tests/regression_tests/diff_tally/inputs_true.dat index ff134bd5c..909475f96 100644 --- a/tests/regression_tests/diff_tally/inputs_true.dat +++ b/tests/regression_tests/diff_tally/inputs_true.dat @@ -148,7 +148,7 @@ - + diff --git a/tests/regression_tests/distribmat/inputs_true.dat b/tests/regression_tests/distribmat/inputs_true.dat index 85d35b081..39e611e16 100644 --- a/tests/regression_tests/distribmat/inputs_true.dat +++ b/tests/regression_tests/distribmat/inputs_true.dat @@ -26,11 +26,11 @@ - + - + diff --git a/tests/regression_tests/filter_energyfun/inputs_true.dat b/tests/regression_tests/filter_energyfun/inputs_true.dat index d857451cb..418354fc2 100644 --- a/tests/regression_tests/filter_energyfun/inputs_true.dat +++ b/tests/regression_tests/filter_energyfun/inputs_true.dat @@ -148,7 +148,7 @@ - + @@ -156,7 +156,7 @@ - + diff --git a/tests/regression_tests/filter_mesh/inputs_true.dat b/tests/regression_tests/filter_mesh/inputs_true.dat index 6d14f9e7e..ca063b7ce 100644 --- a/tests/regression_tests/filter_mesh/inputs_true.dat +++ b/tests/regression_tests/filter_mesh/inputs_true.dat @@ -148,7 +148,7 @@ - + diff --git a/tests/regression_tests/fixed_source/inputs_true.dat b/tests/regression_tests/fixed_source/inputs_true.dat index 2e0d57b0c..f1aebb3b2 100644 --- a/tests/regression_tests/fixed_source/inputs_true.dat +++ b/tests/regression_tests/fixed_source/inputs_true.dat @@ -5,7 +5,7 @@ - + diff --git a/tests/regression_tests/iso_in_lab/inputs_true.dat b/tests/regression_tests/iso_in_lab/inputs_true.dat index 9e30f245f..2a302ada6 100644 --- a/tests/regression_tests/iso_in_lab/inputs_true.dat +++ b/tests/regression_tests/iso_in_lab/inputs_true.dat @@ -148,7 +148,7 @@ - + diff --git a/tests/regression_tests/mgxs_library_ce_to_mg/inputs_true.dat b/tests/regression_tests/mgxs_library_ce_to_mg/inputs_true.dat index 8e8cde281..70996fe37 100644 --- a/tests/regression_tests/mgxs_library_ce_to_mg/inputs_true.dat +++ b/tests/regression_tests/mgxs_library_ce_to_mg/inputs_true.dat @@ -12,7 +12,7 @@ - + diff --git a/tests/regression_tests/mgxs_library_condense/inputs_true.dat b/tests/regression_tests/mgxs_library_condense/inputs_true.dat index d2f28d0fe..ef6c4c520 100644 --- a/tests/regression_tests/mgxs_library_condense/inputs_true.dat +++ b/tests/regression_tests/mgxs_library_condense/inputs_true.dat @@ -12,7 +12,7 @@ - + diff --git a/tests/regression_tests/mgxs_library_distribcell/inputs_true.dat b/tests/regression_tests/mgxs_library_distribcell/inputs_true.dat index d7a4a186a..ba7dc05ff 100644 --- a/tests/regression_tests/mgxs_library_distribcell/inputs_true.dat +++ b/tests/regression_tests/mgxs_library_distribcell/inputs_true.dat @@ -39,7 +39,7 @@ - + diff --git a/tests/regression_tests/mgxs_library_hdf5/inputs_true.dat b/tests/regression_tests/mgxs_library_hdf5/inputs_true.dat index d2f28d0fe..ef6c4c520 100644 --- a/tests/regression_tests/mgxs_library_hdf5/inputs_true.dat +++ b/tests/regression_tests/mgxs_library_hdf5/inputs_true.dat @@ -12,7 +12,7 @@ - + diff --git a/tests/regression_tests/mgxs_library_mesh/inputs_true.dat b/tests/regression_tests/mgxs_library_mesh/inputs_true.dat index 4756b27bf..aa2c904b1 100644 --- a/tests/regression_tests/mgxs_library_mesh/inputs_true.dat +++ b/tests/regression_tests/mgxs_library_mesh/inputs_true.dat @@ -148,7 +148,7 @@ - + diff --git a/tests/regression_tests/mgxs_library_no_nuclides/inputs_true.dat b/tests/regression_tests/mgxs_library_no_nuclides/inputs_true.dat index d2f28d0fe..ef6c4c520 100644 --- a/tests/regression_tests/mgxs_library_no_nuclides/inputs_true.dat +++ b/tests/regression_tests/mgxs_library_no_nuclides/inputs_true.dat @@ -12,7 +12,7 @@ - + diff --git a/tests/regression_tests/mgxs_library_nuclides/inputs_true.dat b/tests/regression_tests/mgxs_library_nuclides/inputs_true.dat index 826eb5b62..b720bfcbb 100644 --- a/tests/regression_tests/mgxs_library_nuclides/inputs_true.dat +++ b/tests/regression_tests/mgxs_library_nuclides/inputs_true.dat @@ -12,7 +12,7 @@ - + diff --git a/tests/regression_tests/multipole/inputs_true.dat b/tests/regression_tests/multipole/inputs_true.dat index 0d1fe99bd..d1ef3e00a 100644 --- a/tests/regression_tests/multipole/inputs_true.dat +++ b/tests/regression_tests/multipole/inputs_true.dat @@ -27,7 +27,7 @@ - + diff --git a/tests/regression_tests/periodic/inputs_true.dat b/tests/regression_tests/periodic/inputs_true.dat index 61958701b..6f613a160 100644 --- a/tests/regression_tests/periodic/inputs_true.dat +++ b/tests/regression_tests/periodic/inputs_true.dat @@ -18,7 +18,7 @@ - + diff --git a/tests/regression_tests/resonance_scattering/inputs_true.dat b/tests/regression_tests/resonance_scattering/inputs_true.dat index 70fe165fd..2301ccf76 100644 --- a/tests/regression_tests/resonance_scattering/inputs_true.dat +++ b/tests/regression_tests/resonance_scattering/inputs_true.dat @@ -5,7 +5,7 @@ - + diff --git a/tests/regression_tests/salphabeta/inputs_true.dat b/tests/regression_tests/salphabeta/inputs_true.dat index 02e6813f0..ede96d376 100644 --- a/tests/regression_tests/salphabeta/inputs_true.dat +++ b/tests/regression_tests/salphabeta/inputs_true.dat @@ -12,19 +12,19 @@ - + - + - + @@ -32,7 +32,7 @@ - + diff --git a/tests/regression_tests/source/inputs_true.dat b/tests/regression_tests/source/inputs_true.dat index da230e0e5..6dd913edc 100644 --- a/tests/regression_tests/source/inputs_true.dat +++ b/tests/regression_tests/source/inputs_true.dat @@ -5,7 +5,7 @@ - + 294 diff --git a/tests/regression_tests/surface_tally/inputs_true.dat b/tests/regression_tests/surface_tally/inputs_true.dat index e66d44273..fc10110ee 100644 --- a/tests/regression_tests/surface_tally/inputs_true.dat +++ b/tests/regression_tests/surface_tally/inputs_true.dat @@ -11,7 +11,7 @@ - + diff --git a/tests/regression_tests/tallies/inputs_true.dat b/tests/regression_tests/tallies/inputs_true.dat index a85491e94..2c33a8fa0 100644 --- a/tests/regression_tests/tallies/inputs_true.dat +++ b/tests/regression_tests/tallies/inputs_true.dat @@ -148,7 +148,7 @@ - + diff --git a/tests/regression_tests/tally_aggregation/inputs_true.dat b/tests/regression_tests/tally_aggregation/inputs_true.dat index 7a8bf4613..86806572a 100644 --- a/tests/regression_tests/tally_aggregation/inputs_true.dat +++ b/tests/regression_tests/tally_aggregation/inputs_true.dat @@ -148,7 +148,7 @@ - + diff --git a/tests/regression_tests/tally_arithmetic/inputs_true.dat b/tests/regression_tests/tally_arithmetic/inputs_true.dat index 743ca3c58..3605005ad 100644 --- a/tests/regression_tests/tally_arithmetic/inputs_true.dat +++ b/tests/regression_tests/tally_arithmetic/inputs_true.dat @@ -148,7 +148,7 @@ - + diff --git a/tests/regression_tests/tally_slice_merge/inputs_true.dat b/tests/regression_tests/tally_slice_merge/inputs_true.dat index b1c089c96..ccd3655f9 100644 --- a/tests/regression_tests/tally_slice_merge/inputs_true.dat +++ b/tests/regression_tests/tally_slice_merge/inputs_true.dat @@ -148,7 +148,7 @@ - + diff --git a/tests/regression_tests/triso/inputs_true.dat b/tests/regression_tests/triso/inputs_true.dat index fdbc1cb5f..6d674b450 100644 --- a/tests/regression_tests/triso/inputs_true.dat +++ b/tests/regression_tests/triso/inputs_true.dat @@ -393,7 +393,7 @@ - + diff --git a/tests/regression_tests/volume_calc/inputs_true.dat b/tests/regression_tests/volume_calc/inputs_true.dat index 28f1cbd9f..607921af2 100644 --- a/tests/regression_tests/volume_calc/inputs_true.dat +++ b/tests/regression_tests/volume_calc/inputs_true.dat @@ -18,7 +18,7 @@ - + diff --git a/tests/unit_tests/test_universe.py b/tests/unit_tests/test_universe.py index 59e34e201..89904524b 100644 --- a/tests/unit_tests/test_universe.py +++ b/tests/unit_tests/test_universe.py @@ -59,7 +59,6 @@ def test_plot(run_in_tmpdir, sphere_model): pixels=(10, 10), color_by='material', colors=colors, - filename='test.png' ) From 8487915f2a66e2875b9970e65f77be45b32982aa Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Fri, 2 Mar 2018 16:19:10 -0600 Subject: [PATCH 05/15] Use ufloat for k_combined in statepoint --- openmc/mgxs/library.py | 2 +- openmc/model/model.py | 2 +- openmc/search.py | 4 ++-- openmc/statepoint.py | 17 ++++++++++------- tests/regression_tests/entropy/test.py | 4 ++-- tests/regression_tests/mg_convert/test.py | 4 ++-- tests/testing_harness.py | 2 +- 7 files changed, 19 insertions(+), 16 deletions(-) diff --git a/openmc/mgxs/library.py b/openmc/mgxs/library.py index 9add7004b..ed8e3f076 100644 --- a/openmc/mgxs/library.py +++ b/openmc/mgxs/library.py @@ -587,7 +587,7 @@ class Library(object): self._nuclides = statepoint.summary.nuclides if statepoint.run_mode == 'eigenvalue': - self._keff = statepoint.k_combined[0] + self._keff = statepoint.k_combined.n # Load tallies for each MGXS for each domain and mgxs type for domain in self.domains: diff --git a/openmc/model/model.py b/openmc/model/model.py index cd5153321..7a81292c1 100644 --- a/openmc/model/model.py +++ b/openmc/model/model.py @@ -210,7 +210,7 @@ class Model(object): Returns ------- - 2-tuple of float + uncertainties.UFloat Combined estimator of k-effective from the statepoint """ diff --git a/openmc/search.py b/openmc/search.py index 75935097e..6be8a50ea 100644 --- a/openmc/search.py +++ b/openmc/search.py @@ -60,9 +60,9 @@ def _search_keff(guess, target, model_builder, model_args, print_iterations, if print_iterations: text = 'Iteration: {}; Guess of {:.2e} produced a keff of ' + \ '{:1.5f} +/- {:1.5f}' - print(text.format(len(guesses), guess, keff[0], keff[1])) + print(text.format(len(guesses), guess, keff.n, keff.s)) - return (keff[0] - target) + return keff.n - target def search_for_keff(model_builder, initial_guess=None, target=1.0, diff --git a/openmc/statepoint.py b/openmc/statepoint.py index 4656e0856..eb011d874 100644 --- a/openmc/statepoint.py +++ b/openmc/statepoint.py @@ -1,3 +1,4 @@ +from datetime import datetime import re import os import warnings @@ -5,6 +6,7 @@ import glob import numpy as np import h5py +from uncertainties import ufloat import openmc import openmc.checkvalue as cv @@ -47,8 +49,8 @@ class StatePoint(object): CMFD fission source distribution over all mesh cells and energy groups. current_batch : int Number of batches simulated - date_and_time : str - Date and time when simulation began + date_and_time : datetime.datetime + Date and time at which statepoint was written entropy : numpy.ndarray Shannon entropy of fission source at each batch filters : dict @@ -59,8 +61,8 @@ class StatePoint(object): global_tallies : numpy.ndarray of compound datatype Global tallies for k-effective estimates and leakage. The compound datatype has fields 'name', 'sum', 'sum_sq', 'mean', and 'std_dev'. - k_combined : list - Combined estimator for k-effective and its uncertainty + k_combined : uncertainties.UFloat + Combined estimator for k-effective k_col_abs : float Cross-product of collision and absorption estimates of k-effective k_col_tra : float @@ -187,7 +189,8 @@ class StatePoint(object): @property def date_and_time(self): - return self._f.attrs['date_and_time'].decode() + s = self._f.attrs['date_and_time'].decode() + return datetime.strptime(s, '%Y-%m-%d %H:%M:%S') @property def entropy(self): @@ -255,7 +258,7 @@ class StatePoint(object): @property def k_combined(self): if self.run_mode == 'eigenvalue': - return self._f['k_combined'].value + return ufloat(*self._f['k_combined'].value) else: return None @@ -457,7 +460,7 @@ class StatePoint(object): @property def version(self): - return tuple(self._f.attrs['version']) + return tuple(self._f.attrs['openmc_version']) @property def summary(self): diff --git a/tests/regression_tests/entropy/test.py b/tests/regression_tests/entropy/test.py index 0f1052b6b..10a11e300 100644 --- a/tests/regression_tests/entropy/test.py +++ b/tests/regression_tests/entropy/test.py @@ -14,11 +14,11 @@ class EntropyTestHarness(TestHarness): with StatePoint(statepoint) as sp: # Write out k-combined. outstr = 'k-combined:\n' - outstr += '{0:12.6E} {1:12.6E}\n'.format(*sp.k_combined) + outstr += '{:12.6E} {:12.6E}\n'.format(sp.k_combined.n, sp.k_combined.s) # Write out entropy data. outstr += 'entropy:\n' - results = ['{0:12.6E}'.format(x) for x in sp.entropy] + results = ['{:12.6E}'.format(x) for x in sp.entropy] outstr += '\n'.join(results) + '\n' return outstr diff --git a/tests/regression_tests/mg_convert/test.py b/tests/regression_tests/mg_convert/test.py index 5b816a1cd..1ace10c80 100755 --- a/tests/regression_tests/mg_convert/test.py +++ b/tests/regression_tests/mg_convert/test.py @@ -144,8 +144,8 @@ class MGXSTestHarness(PyAPITestHarness): with openmc.StatePoint('statepoint.{}.h5'.format(batches)) as sp: # Write out k-combined. outstr += 'k-combined:\n' - form = '{0:12.6E} {1:12.6E}\n' - outstr += form.format(sp.k_combined[0], sp.k_combined[1]) + form = '{:12.6E} {:12.6E}\n' + outstr += form.format(sp.k_combined.n, sp.k_combined.s) return outstr diff --git a/tests/testing_harness.py b/tests/testing_harness.py index 92d477e23..fb07575ce 100644 --- a/tests/testing_harness.py +++ b/tests/testing_harness.py @@ -75,7 +75,7 @@ class TestHarness(object): # Write out k-combined. outstr = 'k-combined:\n' form = '{0:12.6E} {1:12.6E}\n' - outstr += form.format(sp.k_combined[0], sp.k_combined[1]) + outstr += form.format(sp.k_combined.n, sp.k_combined.s) # Write out tally data. for i, tally_ind in enumerate(sp.tallies): From ac28407aa2d54b96ff911f69fdb982f2f14728e0 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Sat, 3 Mar 2018 15:55:12 -0600 Subject: [PATCH 06/15] Don't have atomic_mass/atomic_weight return None for invalid --- openmc/data/data.py | 29 +++++++++++++++-------------- tests/unit_tests/test_data_misc.py | 13 +++++++++++++ 2 files changed, 28 insertions(+), 14 deletions(-) diff --git a/openmc/data/data.py b/openmc/data/data.py index 3a625b622..90d5903e7 100644 --- a/openmc/data/data.py +++ b/openmc/data/data.py @@ -1,10 +1,9 @@ import itertools +from math import sqrt import os import re from warnings import warn -from numpy import sqrt - # Isotopic abundances from Meija J, Coplen T B, et al, "Isotopic compositions # of the elements 2013 (IUPAC Technical Report)", Pure. Appl. Chem. 88 (3), @@ -142,19 +141,18 @@ _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. - Atomic mass data comes from the Atomic Mass Evaluation 2012, published in - Chinese Physics C 36 (2012), 1287--1602. + Atomic mass data comes from the `Atomic Mass Evaluation 2012 + `_. Parameters ---------- isotope : str - Name of isotope, e.g. 'Pu239' + Name of isotope, e.g., 'Pu239' Returns ------- - float or None - Atomic mass of isotope in atomic mass units. If the isotope listed does - not have a known atomic mass, None is returned. + float + Atomic mass of isotope in [amu] """ if not _ATOMIC_MASS: @@ -185,7 +183,7 @@ def atomic_mass(isotope): if '_' in isotope: isotope = isotope[:isotope.find('_')] - return _ATOMIC_MASS.get(isotope.lower()) + return _ATOMIC_MASS[isotope.lower()] def atomic_weight(element): @@ -201,16 +199,19 @@ def atomic_weight(element): Returns ------- - float or None - Atomic weight of element in atomic mass units. If the element listed does - not exist, None is returned. + float + Atomic weight of element in [amu] """ weight = 0. for nuclide, abundance in NATURAL_ABUNDANCE.items(): if re.match(r'{}\d+'.format(element), nuclide): weight += atomic_mass(nuclide) * abundance - return None if weight == 0. else weight + if weight > 0.: + return weight + else: + raise ValueError("No naturally-occurring isotopes for element '{}'." + .format(element)) def water_density(temperature, pressure=0.1013): @@ -236,7 +237,7 @@ def water_density(temperature, pressure=0.1013): Returns ------- float - Water density in units of [g / cm^3] + Water density in units of [g/cm^3] """ diff --git a/tests/unit_tests/test_data_misc.py b/tests/unit_tests/test_data_misc.py index 04ca0f103..34686b567 100644 --- a/tests/unit_tests/test_data_misc.py +++ b/tests/unit_tests/test_data_misc.py @@ -50,6 +50,19 @@ def test_thin(): assert f(1.0) == pytest.approx(np.sin(1.0), 0.001) +def test_atomic_mass(): + assert openmc.data.atomic_mass('H1') == 1.00782503223 + assert openmc.data.atomic_mass('U235') == 235.043930131 + with pytest.raises(KeyError): + openmc.data.atomic_mass('U100') + + +def test_atomic_weight(): + assert openmc.data.atomic_weight('C') == 12.011115164862904 + with pytest.raises(ValueError): + openmc.data.atomic_weight('Qt') + + def test_water_density(): dens = openmc.data.water_density # These test values are from IAPWS R7-97(2012). They are actually specific From 0efd0424204b0568ff6b48875b3618cd954a4dcd Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Sat, 3 Mar 2018 16:27:45 -0600 Subject: [PATCH 07/15] Fix display of version number and copyright year --- src/output.F90 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/output.F90 b/src/output.F90 index 1bf0c46d0..964289126 100644 --- a/src/output.F90 +++ b/src/output.F90 @@ -165,12 +165,12 @@ contains subroutine print_version() if (master) then - write(UNIT=OUTPUT_UNIT, FMT='(1X,A,1X,I1,".",I1,".",I1)') & + write(UNIT=OUTPUT_UNIT, FMT='(1X,A,1X,I1,".",I2,".",I1)') & "OpenMC version", VERSION_MAJOR, VERSION_MINOR, VERSION_RELEASE #ifdef GIT_SHA1 write(UNIT=OUTPUT_UNIT, FMT='(1X,A,A)') "Git SHA1: ", GIT_SHA1 #endif - write(UNIT=OUTPUT_UNIT, FMT=*) "Copyright (c) 2011-2015 & + write(UNIT=OUTPUT_UNIT, FMT=*) "Copyright (c) 2011-2018 & &Massachusetts Institute of Technology" write(UNIT=OUTPUT_UNIT, FMT=*) "MIT/X license at & &" From dca39f87e2730aba4152e7d51849b42916319ab0 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Mon, 5 Mar 2018 19:56:42 -0600 Subject: [PATCH 08/15] Use gnd_name in _get_metadata --- openmc/data/neutron.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/openmc/data/neutron.py b/openmc/data/neutron.py index 0aa1fe7d8..1cc0e3887 100644 --- a/openmc/data/neutron.py +++ b/openmc/data/neutron.py @@ -15,7 +15,7 @@ import h5py from . import HDF5_VERSION, HDF5_VERSION_MAJOR from .ace import Library, Table, get_table -from .data import ATOMIC_SYMBOL, K_BOLTZMANN, EV_PER_MEV +from .data import ATOMIC_SYMBOL, K_BOLTZMANN, EV_PER_MEV, gnd_name from .endf import Evaluation, SUM_RULES, get_head_record, get_tab1_record from .fission_energy import FissionEnergyRelease from .function import Tabulated1D, Sum, ResonancesWithBackground @@ -93,9 +93,7 @@ def _get_metadata(zaid, metastable_scheme='nndc'): # Determine name element = ATOMIC_SYMBOL[Z] - name = '{}{}'.format(element, mass_number) - if metastable > 0: - name += '_m{}'.format(metastable) + name = gnd_name(Z, mass_number, metastable) return (name, element, Z, mass_number, metastable) From 9904e64910eec94e63c071f1c5d8077be9b756e7 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Wed, 7 Mar 2018 06:31:27 -0600 Subject: [PATCH 09/15] Add three papers to list of publications --- docs/source/publications.rst | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/docs/source/publications.rst b/docs/source/publications.rst index 7578fee6b..b88bdc0f0 100644 --- a/docs/source/publications.rst +++ b/docs/source/publications.rst @@ -57,6 +57,11 @@ Benchmarking Coupling and Multi-physics -------------------------- +- Jun Chen, Liangzhi Cao, Chuanqi Zhao, and Zhouyu Liu, "`Development of + Subchannel Code SUBSC for high-fidelity multi-physics coupling application + `_", Energy Procedia, **127**, + 264-274 (2017). + - Tianliang Hu, Liangzhu Cao, Hongchun Wu, Xianan Du, and Mingtao He, "`Coupled neutrons and thermal-hydraulics simulation of molten salt reactors based on OpenMC/TANSY `_," @@ -98,6 +103,11 @@ Coupling and Multi-physics Geometry and Visualization -------------------------- +- Jin-Yang Li, Long Gu, Hu-Shan Xu, Nadezha Korepanova, Rui Yu, Yan-Lei Zhu, and + Chang-Ping Qin, "`CAD modeling study on FLUKA and OpenMC for accelerator + driven system simulation `_", + *Ann. Nucl. Energy*, **114**, 329-341 (2018). + - Logan Abel, William Boyd, Benoit Forget, and Kord Smith, "Interactive Visualization of Multi-Group Cross Sections on High-Fidelity Spatial Meshes," *Trans. Am. Nucl. Soc.*, **114**, 391-394 (2016). @@ -114,6 +124,11 @@ Geometry and Visualization Miscellaneous ------------- +- Bruno Merk, Dzianis Litskevich, R. Gregg, and A. R. Mount, "`Demand driven + salt clean-up in a molten salt fast reactor -- Defining a priority list + `_", *PLOS One*, **13**, + e0192020 (2018). + - Adam G. Nelson, Samuel Shaner, William Boyd, and Paul K. Romano, "Incorporation of a Multigroup Transport Capability in the OpenMC Monte Carlo Particle Transport Code," *Trans. Am. Nucl. Soc.*, **117**, 679-681 (2017). From 9e912a933dcadab2c240d928dd685088548d3193 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Thu, 15 Mar 2018 10:41:43 -0500 Subject: [PATCH 10/15] Support energyout filters in C API --- openmc/capi/filter.py | 2 +- src/tallies/tally_filter_energy.F90 | 9 +++++++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/openmc/capi/filter.py b/openmc/capi/filter.py index 79c19a624..5a5df4814 100644 --- a/openmc/capi/filter.py +++ b/openmc/capi/filter.py @@ -128,7 +128,7 @@ class EnergyFilter(Filter): self._index, len(energies), energies_p) -class EnergyoutFilter(Filter): +class EnergyoutFilter(EnergyFilter): filter_type = 'energyout' diff --git a/src/tallies/tally_filter_energy.F90 b/src/tallies/tally_filter_energy.F90 index 2a247cf35..caba6755d 100644 --- a/src/tallies/tally_filter_energy.F90 +++ b/src/tallies/tally_filter_energy.F90 @@ -211,6 +211,10 @@ contains energies = C_LOC(f % bins) n = size(f % bins) err = 0 + type is (EnergyoutFilter) + energies = C_LOC(f % bins) + n = size(f % bins) + err = 0 class default err = E_INVALID_TYPE call set_errmsg("Tried to get energy bins on a non-energy filter.") @@ -242,6 +246,11 @@ contains if (allocated(f % bins)) deallocate(f % bins) allocate(f % bins(n)) f % bins(:) = energies + type is (EnergyoutFilter) + f % n_bins = n - 1 + if (allocated(f % bins)) deallocate(f % bins) + allocate(f % bins(n)) + f % bins(:) = energies class default err = E_INVALID_TYPE call set_errmsg("Tried to get energy bins on a non-energy filter.") From bd5b7afc2d6e64bf03fb9e1400f6778baf3bbe81 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Fri, 16 Mar 2018 13:47:01 -0500 Subject: [PATCH 11/15] Fix bug related to bin ordering for mesh filters --- openmc/filter.py | 50 ++-- openmc/mesh.py | 18 ++ openmc/mgxs/mgxs.py | 16 +- openmc/tallies.py | 4 +- .../mgxs_library_mesh/results_true.dat | 256 +++++++++--------- .../tally_slice_merge/results_true.dat | 34 +-- .../tally_slice_merge/test.py | 8 +- 7 files changed, 200 insertions(+), 186 deletions(-) diff --git a/openmc/filter.py b/openmc/filter.py index 8763515f4..6cb81d97a 100644 --- a/openmc/filter.py +++ b/openmc/filter.py @@ -732,37 +732,40 @@ class MeshFilter(Filter): # Filter bins for a mesh are an (x,y,z) tuple. Convert (x,y,z) to a # single bin -- this is similar to subroutine mesh_indices_to_bin in # openmc/src/mesh.F90. - if len(self.mesh.dimension) == 3: + n_dim = len(self.mesh.dimension) + if n_dim == 3: + i, j, k = filter_bin nx, ny, nz = self.mesh.dimension - val = (filter_bin[0] - 1) * ny * nz + \ - (filter_bin[1] - 1) * nz + \ - (filter_bin[2] - 1) - else: + return (i - 1) + (j - 1)*nx + (k - 1)*nx*ny + elif n_dim == 2: + i, j, *_ = filter_bin nx, ny = self.mesh.dimension - val = (filter_bin[0] - 1) * ny + \ - (filter_bin[1] - 1) - - return val + return (i - 1) + (j - 1)*nx + else: + return filter_bin[0] - 1 def get_bin(self, bin_index): cv.check_type('bin_index', bin_index, Integral) cv.check_greater_than('bin_index', bin_index, 0, equality=True) cv.check_less_than('bin_index', bin_index, self.num_bins) - # Construct 3-tuple of x,y,z cell indices for a 3D mesh - if len(self.mesh.dimension) == 3: + n_dim = len(self.mesh.dimension) + if n_dim == 3: + # Construct 3-tuple of x,y,z cell indices for a 3D mesh nx, ny, nz = self.mesh.dimension - x = bin_index / (ny * nz) - y = (bin_index - (x * ny * nz)) / nz - z = bin_index - (x * ny * nz) - (y * nz) + x = bin_index % nx + 1 + y = (bin_index % (nx * ny)) // nx + 1 + z = bin_index // (nx * ny) + 1 return (x, y, z) - # Construct 2-tuple of x,y cell indices for a 2D mesh - else: + elif n_dim == 2: + # Construct 2-tuple of x,y cell indices for a 2D mesh nx, ny = self.mesh.dimension - x = bin_index / ny - y = bin_index - (x * ny) + x = bin_index % nx + 1 + y = bin_index // nx + 1 return (x, y) + else: + return (bin_index + 1,) def get_pandas_dataframe(self, data_size, stride, **kwargs): """Builds a Pandas DataFrame for the Filter's bins. @@ -802,9 +805,10 @@ class MeshFilter(Filter): mesh_key = 'mesh {0}'.format(self.mesh.id) # Find mesh dimensions - use 3D indices for simplicity - if len(self.mesh.dimension) == 3: + n_dim = len(self.mesh.dimension) + if n_dim == 3: nx, ny, nz = self.mesh.dimension - elif len(self.mesh.dimension) == 2: + elif n_dim == 2: nx, ny = self.mesh.dimension nz = 1 else: @@ -813,7 +817,7 @@ class MeshFilter(Filter): # Generate multi-index sub-column for x-axis filter_bins = np.arange(1, nx + 1) - repeat_factor = ny * nz * stride + repeat_factor = stride filter_bins = np.repeat(filter_bins, repeat_factor) tile_factor = data_size // len(filter_bins) filter_bins = np.tile(filter_bins, tile_factor) @@ -821,7 +825,7 @@ class MeshFilter(Filter): # Generate multi-index sub-column for y-axis filter_bins = np.arange(1, ny + 1) - repeat_factor = nz * stride + repeat_factor = nx * stride filter_bins = np.repeat(filter_bins, repeat_factor) tile_factor = data_size // len(filter_bins) filter_bins = np.tile(filter_bins, tile_factor) @@ -829,7 +833,7 @@ class MeshFilter(Filter): # Generate multi-index sub-column for z-axis filter_bins = np.arange(1, nz + 1) - repeat_factor = stride + repeat_factor = nx * ny * stride filter_bins = np.repeat(filter_bins, repeat_factor) tile_factor = data_size // len(filter_bins) filter_bins = np.tile(filter_bins, tile_factor) diff --git a/openmc/mesh.py b/openmc/mesh.py index d937e25ce..cd8eb3c5e 100644 --- a/openmc/mesh.py +++ b/openmc/mesh.py @@ -82,6 +82,24 @@ class Mesh(IDManagerMixin): def num_mesh_cells(self): return np.prod(self._dimension) + @property + def indices(self): + ndim = len(self._dimension) + if ndim == 3: + nx, ny, nz = self.dimension + return ((x, y, z) + for z in range(1, nz + 1) + for y in range(1, ny + 1) + for x in range(1, nx + 1)) + elif ndim == 2: + nx, ny = self.dimension + return ((x, y) + for y in range(1, ny + 1) + for x in range(1, nx + 1)) + else: + nx, = self.dimension + return ((x,) for x in range(1, nx + 1)) + @name.setter def name(self, name): if name is not None: diff --git a/openmc/mgxs/mgxs.py b/openmc/mgxs/mgxs.py index ecedc8e63..4932feff1 100644 --- a/openmc/mgxs/mgxs.py +++ b/openmc/mgxs/mgxs.py @@ -4,7 +4,6 @@ import warnings import os import copy from abc import ABCMeta -import itertools import numpy as np import h5py @@ -937,8 +936,7 @@ class MGXS(metaclass=ABCMeta): # NOTE: This is important if tally merging was used if self.domain_type == 'mesh': filters = [_DOMAIN_TO_FILTER[self.domain_type]] - xyz = [range(1, x + 1) for x in self.domain.dimension] - filter_bins = [tuple(itertools.product(*xyz))] + filter_bins = [tuple(self.domain.indices)] elif self.domain_type != 'distribcell': filters = [_DOMAIN_TO_FILTER[self.domain_type]] filter_bins = [(self.domain.id,)] @@ -1531,8 +1529,7 @@ class MGXS(metaclass=ABCMeta): elif self.domain_type == 'distribcell': subdomains = np.arange(self.num_subdomains, dtype=np.int) elif self.domain_type == 'mesh': - xyz = [range(1, x + 1) for x in self.domain.dimension] - subdomains = list(itertools.product(*xyz)) + subdomains = list(self.domain.indices) else: subdomains = [self.domain.id] @@ -1702,8 +1699,7 @@ class MGXS(metaclass=ABCMeta): domain_filter = self.xs_tally.find_filter('sum(distribcell)') subdomains = domain_filter.bins elif self.domain_type == 'mesh': - xyz = [range(1, x+1) for x in self.domain.dimension] - subdomains = list(itertools.product(*xyz)) + subdomains = list(self.domain.indices) else: subdomains = [self.domain.id] @@ -2342,8 +2338,7 @@ class MatrixMGXS(MGXS): elif self.domain_type == 'distribcell': subdomains = np.arange(self.num_subdomains, dtype=np.int) elif self.domain_type == 'mesh': - xyz = [range(1, x + 1) for x in self.domain.dimension] - subdomains = list(itertools.product(*xyz)) + subdomains = list(self.domain.indices) else: subdomains = [self.domain.id] @@ -4530,8 +4525,7 @@ class ScatterMatrixXS(MatrixMGXS): elif self.domain_type == 'distribcell': subdomains = np.arange(self.num_subdomains, dtype=np.int) elif self.domain_type == 'mesh': - xyz = [range(1, x + 1) for x in self.domain.dimension] - subdomains = list(itertools.product(*xyz)) + subdomains = list(self.domain.indices) else: subdomains = [self.domain.id] diff --git a/openmc/tallies.py b/openmc/tallies.py index d22cfdcb4..34424acb0 100644 --- a/openmc/tallies.py +++ b/openmc/tallies.py @@ -1164,9 +1164,7 @@ class Tally(IDManagerMixin): if not user_filter: # Create list of 2- or 3-tuples tuples for mesh cell bins if isinstance(self_filter, openmc.MeshFilter): - dimension = self_filter.mesh.dimension - xyz = [range(1, x+1) for x in dimension] - bins = list(product(*xyz)) + bins = list(self_filter.mesh.indices) # Create list of 2-tuples for energy boundary bins elif isinstance(self_filter, (openmc.EnergyFilter, diff --git a/tests/regression_tests/mgxs_library_mesh/results_true.dat b/tests/regression_tests/mgxs_library_mesh/results_true.dat index c167628bc..4b9303fbf 100644 --- a/tests/regression_tests/mgxs_library_mesh/results_true.dat +++ b/tests/regression_tests/mgxs_library_mesh/results_true.dat @@ -1,62 +1,62 @@ mesh 1 group in nuclide mean std. dev. x y z 0 1 1 1 1 total 0.762544 0.085298 -1 1 2 1 1 total 0.653375 0.153317 -2 2 1 1 1 total 0.644837 0.088457 +2 1 2 1 1 total 0.644837 0.088457 +1 2 1 1 1 total 0.653375 0.153317 3 2 2 1 1 total 0.676480 0.094215 mesh 1 group in nuclide mean std. dev. x y z 0 1 1 1 1 total 0.473988 0.088732 -1 1 2 1 1 total 0.379821 0.167092 -2 2 1 1 1 total 0.399254 0.091318 +2 1 2 1 1 total 0.399254 0.091318 +1 2 1 1 1 total 0.379821 0.167092 3 2 2 1 1 total 0.424265 0.099551 mesh 1 group in nuclide mean std. dev. x y z 0 1 1 1 1 total 0.473988 0.088732 -1 1 2 1 1 total 0.379821 0.167092 -2 2 1 1 1 total 0.399254 0.091318 +2 1 2 1 1 total 0.399254 0.091318 +1 2 1 1 1 total 0.379821 0.167092 3 2 2 1 1 total 0.424265 0.099551 mesh 1 group in nuclide mean std. dev. x y z 0 1 1 1 1 total 0.027288 0.005813 -1 1 2 1 1 total 0.019449 0.004420 -2 2 1 1 1 total 0.020262 0.003701 +2 1 2 1 1 total 0.020262 0.003701 +1 2 1 1 1 total 0.019449 0.004420 3 2 2 1 1 total 0.021266 0.002869 mesh 1 group in nuclide mean std. dev. x y z 0 1 1 1 1 total 0.016037 0.006339 -1 1 2 1 1 total 0.012153 0.003804 -2 2 1 1 1 total 0.013018 0.003521 +2 1 2 1 1 total 0.013018 0.003521 +1 2 1 1 1 total 0.012153 0.003804 3 2 2 1 1 total 0.012965 0.002454 mesh 1 group in nuclide mean std. dev. x y z 0 1 1 1 1 total 0.011251 0.003050 -1 1 2 1 1 total 0.007296 0.001795 -2 2 1 1 1 total 0.007243 0.001219 +2 1 2 1 1 total 0.007243 0.001219 +1 2 1 1 1 total 0.007296 0.001795 3 2 2 1 1 total 0.008301 0.001066 mesh 1 group in nuclide mean std. dev. x y z 0 1 1 1 1 total 0.027498 0.007445 -1 1 2 1 1 total 0.017912 0.004426 -2 2 1 1 1 total 0.017954 0.003077 +2 1 2 1 1 total 0.017954 0.003077 +1 2 1 1 1 total 0.017912 0.004426 3 2 2 1 1 total 0.020469 0.002617 mesh 1 group in nuclide mean std. dev. x y z 0 1 1 1 1 total 2.177345e+06 589804.299388 -1 1 2 1 1 total 1.413154e+06 347806.623417 -2 2 1 1 1 total 1.404096e+06 236476.851953 +2 1 2 1 1 total 1.404096e+06 236476.851953 +1 2 1 1 1 total 1.413154e+06 347806.623417 3 2 2 1 1 total 1.608259e+06 206502.707865 mesh 1 group in nuclide mean std. dev. x y z 0 1 1 1 1 total 0.735256 0.080216 -1 1 2 1 1 total 0.633925 0.149098 -2 2 1 1 1 total 0.624575 0.084974 +2 1 2 1 1 total 0.624575 0.084974 +1 2 1 1 1 total 0.633925 0.149098 3 2 2 1 1 total 0.655214 0.091422 mesh 1 group in nuclide mean std. dev. x y z 0 1 1 1 1 total 0.763779 0.070696 -1 1 2 1 1 total 0.640809 0.158369 -2 2 1 1 1 total 0.628158 0.064356 +2 1 2 1 1 total 0.628158 0.064356 +1 2 1 1 1 total 0.640809 0.158369 3 2 2 1 1 total 0.645171 0.080467 mesh 1 group in group out nuclide moment mean std. dev. x y z @@ -64,14 +64,14 @@ 1 1 1 1 1 1 total P1 0.288556 0.024446 2 1 1 1 1 1 total P2 0.082441 0.011443 3 1 1 1 1 1 total P3 -0.005627 0.012638 -4 1 2 1 1 1 total P0 0.640809 0.158369 -5 1 2 1 1 1 total P1 0.273553 0.066437 -6 1 2 1 1 1 total P2 0.108446 0.024435 -7 1 2 1 1 1 total P3 0.012229 0.003785 -8 2 1 1 1 1 total P0 0.628158 0.064356 -9 2 1 1 1 1 total P1 0.245583 0.022676 -10 2 1 1 1 1 total P2 0.086370 0.007833 -11 2 1 1 1 1 total P3 0.019590 0.005345 +8 1 2 1 1 1 total P0 0.628158 0.064356 +9 1 2 1 1 1 total P1 0.245583 0.022676 +10 1 2 1 1 1 total P2 0.086370 0.007833 +11 1 2 1 1 1 total P3 0.019590 0.005345 +4 2 1 1 1 1 total P0 0.640809 0.158369 +5 2 1 1 1 1 total P1 0.273553 0.066437 +6 2 1 1 1 1 total P2 0.108446 0.024435 +7 2 1 1 1 1 total P3 0.012229 0.003785 12 2 2 1 1 1 total P0 0.645171 0.080467 13 2 2 1 1 1 total P1 0.252215 0.032154 14 2 2 1 1 1 total P2 0.089251 0.009734 @@ -82,14 +82,14 @@ 1 1 1 1 1 1 total P1 0.288556 0.024446 2 1 1 1 1 1 total P2 0.082441 0.011443 3 1 1 1 1 1 total P3 -0.005627 0.012638 -4 1 2 1 1 1 total P0 0.640809 0.158369 -5 1 2 1 1 1 total P1 0.273553 0.066437 -6 1 2 1 1 1 total P2 0.108446 0.024435 -7 1 2 1 1 1 total P3 0.012229 0.003785 -8 2 1 1 1 1 total P0 0.628158 0.064356 -9 2 1 1 1 1 total P1 0.245583 0.022676 -10 2 1 1 1 1 total P2 0.086370 0.007833 -11 2 1 1 1 1 total P3 0.019590 0.005345 +8 1 2 1 1 1 total P0 0.628158 0.064356 +9 1 2 1 1 1 total P1 0.245583 0.022676 +10 1 2 1 1 1 total P2 0.086370 0.007833 +11 1 2 1 1 1 total P3 0.019590 0.005345 +4 2 1 1 1 1 total P0 0.640809 0.158369 +5 2 1 1 1 1 total P1 0.273553 0.066437 +6 2 1 1 1 1 total P2 0.108446 0.024435 +7 2 1 1 1 1 total P3 0.012229 0.003785 12 2 2 1 1 1 total P0 0.645171 0.080467 13 2 2 1 1 1 total P1 0.252215 0.032154 14 2 2 1 1 1 total P2 0.089251 0.009734 @@ -97,20 +97,20 @@ mesh 1 group in group out nuclide mean std. dev. x y z 0 1 1 1 1 1 total 1.0 0.108337 -1 1 2 1 1 1 total 1.0 0.238517 -2 2 1 1 1 1 total 1.0 0.113128 +2 1 2 1 1 1 total 1.0 0.113128 +1 2 1 1 1 1 total 1.0 0.238517 3 2 2 1 1 1 total 1.0 0.132597 mesh 1 group in group out nuclide mean std. dev. x y z 0 1 1 1 1 1 total 0.015584 0.003404 -1 1 2 1 1 1 total 0.014200 0.003676 -2 2 1 1 1 1 total 0.017684 0.002499 +2 1 2 1 1 1 total 0.017684 0.002499 +1 2 1 1 1 1 total 0.014200 0.003676 3 2 2 1 1 1 total 0.022409 0.002481 mesh 1 group in group out nuclide mean std. dev. x y z 0 1 1 1 1 1 total 1.0 0.108337 -1 1 2 1 1 1 total 1.0 0.238517 -2 2 1 1 1 1 total 1.0 0.113128 +2 1 2 1 1 1 total 1.0 0.113128 +1 2 1 1 1 1 total 1.0 0.238517 3 2 2 1 1 1 total 1.0 0.132597 mesh 1 group in group out nuclide moment mean std. dev. x y z @@ -118,14 +118,14 @@ 1 1 1 1 1 1 total P1 0.277780 0.041434 2 1 1 1 1 1 total P2 0.079362 0.014706 3 1 1 1 1 1 total P3 -0.005417 0.012184 -4 1 2 1 1 1 total P0 0.633925 0.212349 -5 1 2 1 1 1 total P1 0.270615 0.089799 -6 1 2 1 1 1 total P2 0.107281 0.034246 -7 1 2 1 1 1 total P3 0.012098 0.004637 -8 2 1 1 1 1 total P0 0.624575 0.110512 -9 2 1 1 1 1 total P1 0.244182 0.041824 -10 2 1 1 1 1 total P2 0.085877 0.014634 -11 2 1 1 1 1 total P3 0.019478 0.006012 +8 1 2 1 1 1 total P0 0.624575 0.110512 +9 1 2 1 1 1 total P1 0.244182 0.041824 +10 1 2 1 1 1 total P2 0.085877 0.014634 +11 1 2 1 1 1 total P3 0.019478 0.006012 +4 2 1 1 1 1 total P0 0.633925 0.212349 +5 2 1 1 1 1 total P1 0.270615 0.089799 +6 2 1 1 1 1 total P2 0.107281 0.034246 +7 2 1 1 1 1 total P3 0.012098 0.004637 12 2 2 1 1 1 total P0 0.655214 0.126119 13 2 2 1 1 1 total P1 0.256141 0.049765 14 2 2 1 1 1 total P2 0.090641 0.016563 @@ -136,14 +136,14 @@ 1 1 1 1 1 1 total P1 0.277780 0.051210 2 1 1 1 1 1 total P2 0.079362 0.017035 3 1 1 1 1 1 total P3 -0.005417 0.012198 -4 1 2 1 1 1 total P0 0.633925 0.260681 -5 1 2 1 1 1 total P1 0.270615 0.110590 -6 1 2 1 1 1 total P2 0.107281 0.042750 -7 1 2 1 1 1 total P3 0.012098 0.005462 -8 2 1 1 1 1 total P0 0.624575 0.131169 -9 2 1 1 1 1 total P1 0.244182 0.050123 -10 2 1 1 1 1 total P2 0.085877 0.017565 -11 2 1 1 1 1 total P3 0.019478 0.006403 +8 1 2 1 1 1 total P0 0.624575 0.131169 +9 1 2 1 1 1 total P1 0.244182 0.050123 +10 1 2 1 1 1 total P2 0.085877 0.017565 +11 1 2 1 1 1 total P3 0.019478 0.006403 +4 2 1 1 1 1 total P0 0.633925 0.260681 +5 2 1 1 1 1 total P1 0.270615 0.110590 +6 2 1 1 1 1 total P2 0.107281 0.042750 +7 2 1 1 1 1 total P3 0.012098 0.005462 12 2 2 1 1 1 total P0 0.655214 0.153147 13 2 2 1 1 1 total P1 0.256141 0.060250 14 2 2 1 1 1 total P2 0.090641 0.020464 @@ -151,32 +151,32 @@ mesh 1 group out nuclide mean std. dev. x y z 0 1 1 1 1 total 1.0 0.300047 -1 1 2 1 1 total 1.0 0.262180 -2 2 1 1 1 total 1.0 0.178169 +2 1 2 1 1 total 1.0 0.178169 +1 2 1 1 1 total 1.0 0.262180 3 2 2 1 1 total 1.0 0.104797 mesh 1 group out nuclide mean std. dev. x y z 0 1 1 1 1 total 1.0 0.300047 -1 1 2 1 1 total 1.0 0.262180 -2 2 1 1 1 total 1.0 0.178169 +2 1 2 1 1 total 1.0 0.178169 +1 2 1 1 1 total 1.0 0.262180 3 2 2 1 1 total 1.0 0.108931 mesh 1 group in nuclide mean std. dev. x y z 0 1 1 1 1 total 7.097008e-07 1.458546e-07 -1 1 2 1 1 total 3.984535e-07 1.157576e-07 -2 2 1 1 1 total 4.407745e-07 7.903907e-08 +2 1 2 1 1 total 4.407745e-07 7.903907e-08 +1 2 1 1 1 total 3.984535e-07 1.157576e-07 3 2 2 1 1 total 4.750476e-07 6.207437e-08 mesh 1 group in nuclide mean std. dev. x y z 0 1 1 1 1 total 0.027311 0.007397 -1 1 2 1 1 total 0.017783 0.004394 -2 2 1 1 1 total 0.017820 0.003054 +2 1 2 1 1 total 0.017820 0.003054 +1 2 1 1 1 total 0.017783 0.004394 3 2 2 1 1 total 0.020320 0.002598 mesh 1 group in group out nuclide mean std. dev. x y z 0 1 1 1 1 1 total 0.015584 0.003404 -1 1 2 1 1 1 total 0.014200 0.003676 -2 2 1 1 1 1 total 0.017684 0.002499 +2 1 2 1 1 1 total 0.017684 0.002499 +1 2 1 1 1 1 total 0.014200 0.003676 3 2 2 1 1 1 total 0.022259 0.002508 mesh 1 delayedgroup group in nuclide mean std. dev. x y z @@ -186,18 +186,18 @@ 3 1 1 1 4 1 total 0.000072 1.866015e-05 4 1 1 1 5 1 total 0.000031 7.654909e-06 5 1 1 1 6 1 total 0.000013 3.206343e-06 -6 1 2 1 1 1 total 0.000004 1.003100e-06 -7 1 2 1 2 1 total 0.000022 5.425275e-06 -8 1 2 1 3 1 total 0.000021 5.324236e-06 -9 1 2 1 4 1 total 0.000050 1.251572e-05 -10 1 2 1 5 1 total 0.000022 5.762184e-06 -11 1 2 1 6 1 total 0.000009 2.391676e-06 -12 2 1 1 1 1 total 0.000004 6.723192e-07 -13 2 1 1 2 1 total 0.000022 3.706235e-06 -14 2 1 1 3 1 total 0.000022 3.674263e-06 -15 2 1 1 4 1 total 0.000052 8.774048e-06 -16 2 1 1 5 1 total 0.000024 4.168024e-06 -17 2 1 1 6 1 total 0.000010 1.726268e-06 +12 1 2 1 1 1 total 0.000004 6.723192e-07 +13 1 2 1 2 1 total 0.000022 3.706235e-06 +14 1 2 1 3 1 total 0.000022 3.674263e-06 +15 1 2 1 4 1 total 0.000052 8.774048e-06 +16 1 2 1 5 1 total 0.000024 4.168024e-06 +17 1 2 1 6 1 total 0.000010 1.726268e-06 +6 2 1 1 1 1 total 0.000004 1.003100e-06 +7 2 1 1 2 1 total 0.000022 5.425275e-06 +8 2 1 1 3 1 total 0.000021 5.324236e-06 +9 2 1 1 4 1 total 0.000050 1.251572e-05 +10 2 1 1 5 1 total 0.000022 5.762184e-06 +11 2 1 1 6 1 total 0.000009 2.391676e-06 18 2 2 1 1 1 total 0.000005 5.962367e-07 19 2 2 1 2 1 total 0.000025 3.200900e-06 20 2 2 1 3 1 total 0.000025 3.127442e-06 @@ -212,18 +212,18 @@ 3 1 1 1 4 1 total 0.0 0.000000 4 1 1 1 5 1 total 0.0 0.000000 5 1 1 1 6 1 total 0.0 0.000000 -6 1 2 1 1 1 total 0.0 0.000000 -7 1 2 1 2 1 total 0.0 0.000000 -8 1 2 1 3 1 total 0.0 0.000000 -9 1 2 1 4 1 total 0.0 0.000000 -10 1 2 1 5 1 total 0.0 0.000000 -11 1 2 1 6 1 total 0.0 0.000000 -12 2 1 1 1 1 total 0.0 0.000000 -13 2 1 1 2 1 total 0.0 0.000000 -14 2 1 1 3 1 total 0.0 0.000000 -15 2 1 1 4 1 total 0.0 0.000000 -16 2 1 1 5 1 total 0.0 0.000000 -17 2 1 1 6 1 total 0.0 0.000000 +12 1 2 1 1 1 total 0.0 0.000000 +13 1 2 1 2 1 total 0.0 0.000000 +14 1 2 1 3 1 total 0.0 0.000000 +15 1 2 1 4 1 total 0.0 0.000000 +16 1 2 1 5 1 total 0.0 0.000000 +17 1 2 1 6 1 total 0.0 0.000000 +6 2 1 1 1 1 total 0.0 0.000000 +7 2 1 1 2 1 total 0.0 0.000000 +8 2 1 1 3 1 total 0.0 0.000000 +9 2 1 1 4 1 total 0.0 0.000000 +10 2 1 1 5 1 total 0.0 0.000000 +11 2 1 1 6 1 total 0.0 0.000000 18 2 2 1 1 1 total 0.0 0.000000 19 2 2 1 2 1 total 0.0 0.000000 20 2 2 1 3 1 total 1.0 1.414214 @@ -238,18 +238,18 @@ 3 1 1 1 4 1 total 0.002629 0.000950 4 1 1 1 5 1 total 0.001125 0.000398 5 1 1 1 6 1 total 0.000470 0.000166 -6 1 2 1 1 1 total 0.000228 0.000057 -7 1 2 1 2 1 total 0.001222 0.000309 -8 1 2 1 3 1 total 0.001193 0.000304 -9 1 2 1 4 1 total 0.002780 0.000713 -10 1 2 1 5 1 total 0.001250 0.000328 -11 1 2 1 6 1 total 0.000520 0.000136 -12 2 1 1 1 1 total 0.000225 0.000044 -13 2 1 1 2 1 total 0.001232 0.000242 -14 2 1 1 3 1 total 0.001216 0.000239 -15 2 1 1 4 1 total 0.002882 0.000570 -16 2 1 1 5 1 total 0.001345 0.000270 -17 2 1 1 6 1 total 0.000558 0.000112 +12 1 2 1 1 1 total 0.000225 0.000044 +13 1 2 1 2 1 total 0.001232 0.000242 +14 1 2 1 3 1 total 0.001216 0.000239 +15 1 2 1 4 1 total 0.002882 0.000570 +16 1 2 1 5 1 total 0.001345 0.000270 +17 1 2 1 6 1 total 0.000558 0.000112 +6 2 1 1 1 1 total 0.000228 0.000057 +7 2 1 1 2 1 total 0.001222 0.000309 +8 2 1 1 3 1 total 0.001193 0.000304 +9 2 1 1 4 1 total 0.002780 0.000713 +10 2 1 1 5 1 total 0.001250 0.000328 +11 2 1 1 6 1 total 0.000520 0.000136 18 2 2 1 1 1 total 0.000227 0.000027 19 2 2 1 2 1 total 0.001225 0.000143 20 2 2 1 3 1 total 0.001201 0.000140 @@ -264,18 +264,18 @@ 3 1 1 1 4 1 total 0.304289 0.106753 4 1 1 1 5 1 total 0.855760 0.286466 5 1 1 1 6 1 total 2.874120 0.965609 -6 1 2 1 1 1 total 0.013357 0.003345 -7 1 2 1 2 1 total 0.032590 0.008273 -8 1 2 1 3 1 total 0.121103 0.031074 -9 1 2 1 4 1 total 0.306111 0.080011 -10 1 2 1 5 1 total 0.862660 0.235694 -11 1 2 1 6 1 total 2.897534 0.788926 -12 2 1 1 1 1 total 0.013367 0.002548 -13 2 1 1 2 1 total 0.032520 0.006266 -14 2 1 1 3 1 total 0.121250 0.023544 -15 2 1 1 4 1 total 0.307552 0.060464 -16 2 1 1 5 1 total 0.867665 0.175131 -17 2 1 1 6 1 total 2.914635 0.587161 +12 1 2 1 1 1 total 0.013367 0.002548 +13 1 2 1 2 1 total 0.032520 0.006266 +14 1 2 1 3 1 total 0.121250 0.023544 +15 1 2 1 4 1 total 0.307552 0.060464 +16 1 2 1 5 1 total 0.867665 0.175131 +17 1 2 1 6 1 total 2.914635 0.587161 +6 2 1 1 1 1 total 0.013357 0.003345 +7 2 1 1 2 1 total 0.032590 0.008273 +8 2 1 1 3 1 total 0.121103 0.031074 +9 2 1 1 4 1 total 0.306111 0.080011 +10 2 1 1 5 1 total 0.862660 0.235694 +11 2 1 1 6 1 total 2.897534 0.788926 18 2 2 1 1 1 total 0.013360 0.001587 19 2 2 1 2 1 total 0.032564 0.003810 20 2 2 1 3 1 total 0.121158 0.014038 @@ -290,18 +290,18 @@ 3 1 1 1 4 1 1 total 0.00000 0.000000 4 1 1 1 5 1 1 total 0.00000 0.000000 5 1 1 1 6 1 1 total 0.00000 0.000000 -6 1 2 1 1 1 1 total 0.00000 0.000000 -7 1 2 1 2 1 1 total 0.00000 0.000000 -8 1 2 1 3 1 1 total 0.00000 0.000000 -9 1 2 1 4 1 1 total 0.00000 0.000000 -10 1 2 1 5 1 1 total 0.00000 0.000000 -11 1 2 1 6 1 1 total 0.00000 0.000000 -12 2 1 1 1 1 1 total 0.00000 0.000000 -13 2 1 1 2 1 1 total 0.00000 0.000000 -14 2 1 1 3 1 1 total 0.00000 0.000000 -15 2 1 1 4 1 1 total 0.00000 0.000000 -16 2 1 1 5 1 1 total 0.00000 0.000000 -17 2 1 1 6 1 1 total 0.00000 0.000000 +12 1 2 1 1 1 1 total 0.00000 0.000000 +13 1 2 1 2 1 1 total 0.00000 0.000000 +14 1 2 1 3 1 1 total 0.00000 0.000000 +15 1 2 1 4 1 1 total 0.00000 0.000000 +16 1 2 1 5 1 1 total 0.00000 0.000000 +17 1 2 1 6 1 1 total 0.00000 0.000000 +6 2 1 1 1 1 1 total 0.00000 0.000000 +7 2 1 1 2 1 1 total 0.00000 0.000000 +8 2 1 1 3 1 1 total 0.00000 0.000000 +9 2 1 1 4 1 1 total 0.00000 0.000000 +10 2 1 1 5 1 1 total 0.00000 0.000000 +11 2 1 1 6 1 1 total 0.00000 0.000000 18 2 2 1 1 1 1 total 0.00000 0.000000 19 2 2 1 2 1 1 total 0.00000 0.000000 20 2 2 1 3 1 1 total 0.00015 0.000151 diff --git a/tests/regression_tests/tally_slice_merge/results_true.dat b/tests/regression_tests/tally_slice_merge/results_true.dat index 4f1d6c6e2..461c4faa8 100644 --- a/tests/regression_tests/tally_slice_merge/results_true.dat +++ b/tests/regression_tests/tally_slice_merge/results_true.dat @@ -48,20 +48,20 @@ 13 (500, 5000, 50000) 6.25e-01 2.00e+07 U235 nu-fission 0.00e+00 0.00e+00 14 (500, 5000, 50000) 6.25e-01 2.00e+07 U238 fission 0.00e+00 0.00e+00 15 (500, 5000, 50000) 6.25e-01 2.00e+07 U238 nu-fission 0.00e+00 0.00e+00 - sum(mesh) energy low [eV] energy high [eV] nuclide score mean std. dev. -0 ((1, 1, 1), (1, 2, 1)) 0.00e+00 6.25e-01 U235 fission 1.48e-02 3.65e-03 -1 ((1, 1, 1), (1, 2, 1)) 0.00e+00 6.25e-01 U235 nu-fission 3.60e-02 8.90e-03 -2 ((1, 1, 1), (1, 2, 1)) 0.00e+00 6.25e-01 U238 fission 2.06e-08 4.98e-09 -3 ((1, 1, 1), (1, 2, 1)) 0.00e+00 6.25e-01 U238 nu-fission 5.14e-08 1.24e-08 -4 ((1, 1, 1), (1, 2, 1)) 6.25e-01 2.00e+07 U235 fission 2.23e-03 3.92e-04 -5 ((1, 1, 1), (1, 2, 1)) 6.25e-01 2.00e+07 U235 nu-fission 5.45e-03 9.56e-04 -6 ((1, 1, 1), (1, 2, 1)) 6.25e-01 2.00e+07 U238 fission 5.58e-04 2.08e-04 -7 ((1, 1, 1), (1, 2, 1)) 6.25e-01 2.00e+07 U238 nu-fission 1.50e-03 5.43e-04 -8 ((2, 1, 1), (2, 2, 1)) 0.00e+00 6.25e-01 U235 fission 2.56e-02 5.50e-03 -9 ((2, 1, 1), (2, 2, 1)) 0.00e+00 6.25e-01 U235 nu-fission 6.24e-02 1.34e-02 -10 ((2, 1, 1), (2, 2, 1)) 0.00e+00 6.25e-01 U238 fission 3.55e-08 7.70e-09 -11 ((2, 1, 1), (2, 2, 1)) 0.00e+00 6.25e-01 U238 nu-fission 8.85e-08 1.92e-08 -12 ((2, 1, 1), (2, 2, 1)) 6.25e-01 2.00e+07 U235 fission 5.01e-03 1.38e-03 -13 ((2, 1, 1), (2, 2, 1)) 6.25e-01 2.00e+07 U235 nu-fission 1.22e-02 3.37e-03 -14 ((2, 1, 1), (2, 2, 1)) 6.25e-01 2.00e+07 U238 fission 2.40e-03 2.69e-04 -15 ((2, 1, 1), (2, 2, 1)) 6.25e-01 2.00e+07 U238 nu-fission 6.60e-03 7.63e-04 + sum(mesh) energy low [eV] energy high [eV] nuclide score mean std. dev. +0 ((1, 1), (1, 2)) 0.00e+00 6.25e-01 U235 fission 0.00e+00 0.00e+00 +1 ((1, 1), (1, 2)) 0.00e+00 6.25e-01 U235 nu-fission 0.00e+00 0.00e+00 +2 ((1, 1), (1, 2)) 0.00e+00 6.25e-01 U238 fission 0.00e+00 0.00e+00 +3 ((1, 1), (1, 2)) 0.00e+00 6.25e-01 U238 nu-fission 0.00e+00 0.00e+00 +4 ((1, 1), (1, 2)) 6.25e-01 2.00e+07 U235 fission 1.60e-04 1.60e-04 +5 ((1, 1), (1, 2)) 6.25e-01 2.00e+07 U235 nu-fission 3.91e-04 3.91e-04 +6 ((1, 1), (1, 2)) 6.25e-01 2.00e+07 U238 fission 5.12e-05 5.12e-05 +7 ((1, 1), (1, 2)) 6.25e-01 2.00e+07 U238 nu-fission 1.36e-04 1.36e-04 +8 ((2, 1), (2, 2)) 0.00e+00 6.25e-01 U235 fission 4.04e-02 6.60e-03 +9 ((2, 1), (2, 2)) 0.00e+00 6.25e-01 U235 nu-fission 9.85e-02 1.61e-02 +10 ((2, 1), (2, 2)) 0.00e+00 6.25e-01 U238 fission 5.61e-08 9.18e-09 +11 ((2, 1), (2, 2)) 0.00e+00 6.25e-01 U238 nu-fission 1.40e-07 2.29e-08 +12 ((2, 1), (2, 2)) 6.25e-01 2.00e+07 U235 fission 7.08e-03 1.43e-03 +13 ((2, 1), (2, 2)) 6.25e-01 2.00e+07 U235 nu-fission 1.73e-02 3.48e-03 +14 ((2, 1), (2, 2)) 6.25e-01 2.00e+07 U238 fission 2.91e-03 3.36e-04 +15 ((2, 1), (2, 2)) 6.25e-01 2.00e+07 U238 nu-fission 7.96e-03 9.27e-04 diff --git a/tests/regression_tests/tally_slice_merge/test.py b/tests/regression_tests/tally_slice_merge/test.py index f79c8b268..e52d0fde4 100644 --- a/tests/regression_tests/tally_slice_merge/test.py +++ b/tests/regression_tests/tally_slice_merge/test.py @@ -126,10 +126,10 @@ class TallySliceMergeTestHarness(PyAPITestHarness): # Sum up a few subdomains from the distribcell tally sum1 = distribcell_tally.summation(filter_type=openmc.DistribcellFilter, - filter_bins=[0,100,2000,30000]) + filter_bins=[0, 100, 2000, 30000]) # Sum up a few subdomains from the distribcell tally sum2 = distribcell_tally.summation(filter_type=openmc.DistribcellFilter, - filter_bins=[500,5000,50000]) + filter_bins=[500, 5000, 50000]) # Merge the distribcell tally slices merge_tally = sum1.merge(sum2) @@ -143,10 +143,10 @@ class TallySliceMergeTestHarness(PyAPITestHarness): # Sum up a few subdomains from the mesh tally sum1 = mesh_tally.summation(filter_type=openmc.MeshFilter, - filter_bins=[(1,1,1), (1,2,1)]) + filter_bins=[(1, 1), (1, 2)]) # Sum up a few subdomains from the mesh tally sum2 = mesh_tally.summation(filter_type=openmc.MeshFilter, - filter_bins=[(2,1,1), (2,2,1)]) + filter_bins=[(2, 1), (2, 2)]) # Merge the mesh tally slices merge_tally = sum1.merge(sum2) From 0b6333810f7f73317f459a701a7d5cbd487f31ff Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Fri, 16 Mar 2018 14:07:38 -0500 Subject: [PATCH 12/15] Avoid divide-by-zero warnings in tally arithmetic --- openmc/tallies.py | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/openmc/tallies.py b/openmc/tallies.py index 34424acb0..d8bc2136a 100644 --- a/openmc/tallies.py +++ b/openmc/tallies.py @@ -1674,19 +1674,22 @@ class Tally(IDManagerMixin): new_tally._std_dev = np.sqrt(data['self']['std. dev.']**2 + data['other']['std. dev.']**2) elif binary_op == '*': - self_rel_err = data['self']['std. dev.'] / data['self']['mean'] - other_rel_err = data['other']['std. dev.'] / data['other']['mean'] + with np.errstate(divide='ignore', invalid='ignore'): + self_rel_err = data['self']['std. dev.'] / data['self']['mean'] + other_rel_err = data['other']['std. dev.'] / data['other']['mean'] new_tally._mean = data['self']['mean'] * data['other']['mean'] new_tally._std_dev = np.abs(new_tally.mean) * \ np.sqrt(self_rel_err**2 + other_rel_err**2) elif binary_op == '/': - self_rel_err = data['self']['std. dev.'] / data['self']['mean'] - other_rel_err = data['other']['std. dev.'] / data['other']['mean'] - new_tally._mean = data['self']['mean'] / data['other']['mean'] + with np.errstate(divide='ignore', invalid='ignore'): + self_rel_err = data['self']['std. dev.'] / data['self']['mean'] + other_rel_err = data['other']['std. dev.'] / data['other']['mean'] + new_tally._mean = data['self']['mean'] / data['other']['mean'] new_tally._std_dev = np.abs(new_tally.mean) * \ np.sqrt(self_rel_err**2 + other_rel_err**2) elif binary_op == '^': - mean_ratio = data['other']['mean'] / data['self']['mean'] + with np.errstate(divide='ignore', invalid='ignore'): + mean_ratio = data['other']['mean'] / data['self']['mean'] first_term = mean_ratio * data['self']['std. dev.'] second_term = \ np.log(data['self']['mean']) * data['other']['std. dev.'] From c83b89086912d2363778b609224c42b7acab7038 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Mon, 19 Mar 2018 10:13:51 -0500 Subject: [PATCH 13/15] Use ufloat for stochastic volume results --- openmc/cell.py | 4 +- openmc/data/decay.py | 5 +- openmc/material.py | 2 +- openmc/universe.py | 4 +- openmc/volume.py | 10 ++-- .../volume_calc/results_true.dat | 54 +++++++++---------- tests/regression_tests/volume_calc/test.py | 3 +- 7 files changed, 39 insertions(+), 43 deletions(-) diff --git a/openmc/cell.py b/openmc/cell.py index c7587e136..cbfd74b21 100644 --- a/openmc/cell.py +++ b/openmc/cell.py @@ -295,7 +295,7 @@ class Cell(IDManagerMixin): """ if volume_calc.domain_type == 'cell': if self.id in volume_calc.volumes: - self._volume = volume_calc.volumes[self.id][0] + self._volume = volume_calc.volumes[self.id].n self._atoms = volume_calc.atoms[self.id] else: raise ValueError('No volume information found for this cell.') @@ -335,7 +335,7 @@ class Cell(IDManagerMixin): volume = self.volume for name, atoms in self._atoms.items(): nuclide = openmc.Nuclide(name) - density = 1.0e-24 * atoms[0]/volume # density in atoms/b-cm + density = 1.0e-24 * atoms.n/volume # density in atoms/b-cm nuclides[name] = (nuclide, density) else: raise RuntimeError( diff --git a/openmc/data/decay.py b/openmc/data/decay.py index fa1875939..bbb059f4f 100644 --- a/openmc/data/decay.py +++ b/openmc/data/decay.py @@ -7,10 +7,7 @@ import re from warnings import warn import numpy as np -try: - from uncertainties import ufloat, unumpy, UFloat -except ImportError: - ufloat = UFloat = namedtuple('UFloat', ['nominal_value', 'std_dev']) +from uncertainties import ufloat, unumpy, UFloat import openmc.checkvalue as cv from openmc.mixin import EqualityMixin diff --git a/openmc/material.py b/openmc/material.py index 88479d8df..6bfe58f4a 100644 --- a/openmc/material.py +++ b/openmc/material.py @@ -313,7 +313,7 @@ class Material(IDManagerMixin): """ if volume_calc.domain_type == 'material': if self.id in volume_calc.volumes: - self._volume = volume_calc.volumes[self.id][0] + self._volume = volume_calc.volumes[self.id].n self._atoms = volume_calc.atoms[self.id] else: raise ValueError('No volume information found for this material.') diff --git a/openmc/universe.py b/openmc/universe.py index 77138adcc..294b114dd 100644 --- a/openmc/universe.py +++ b/openmc/universe.py @@ -145,7 +145,7 @@ class Universe(IDManagerMixin): """ if volume_calc.domain_type == 'universe': if self.id in volume_calc.volumes: - self._volume = volume_calc.volumes[self.id][0] + self._volume = volume_calc.volumes[self.id].n self._atoms = volume_calc.atoms[self.id] else: raise ValueError('No volume information found for this universe.') @@ -406,7 +406,7 @@ class Universe(IDManagerMixin): volume = self.volume for name, atoms in self._atoms.items(): nuclide = openmc.Nuclide(name) - density = 1.0e-24 * atoms[0]/volume # density in atoms/b-cm + density = 1.0e-24 * atoms.n/volume # density in atoms/b-cm nuclides[name] = (nuclide, density) else: raise RuntimeError( diff --git a/openmc/volume.py b/openmc/volume.py index d61093a17..af7c356ae 100644 --- a/openmc/volume.py +++ b/openmc/volume.py @@ -7,6 +7,7 @@ import warnings import numpy as np import pandas as pd import h5py +from uncertainties import ufloat import openmc import openmc.checkvalue as cv @@ -137,11 +138,10 @@ class VolumeCalculation(object): @property def atoms_dataframe(self): items = [] - columns = [self.domain_type.capitalize(), 'Nuclide', 'Atoms', - 'Uncertainty'] + columns = [self.domain_type.capitalize(), 'Nuclide', 'Atoms'] for uid, atoms_dict in self.atoms.items(): for name, atoms in atoms_dict.items(): - items.append((uid, name, atoms[0], atoms[1])) + items.append((uid, name, atoms)) return pd.DataFrame.from_records(items, columns=columns) @@ -211,13 +211,13 @@ class VolumeCalculation(object): domain_id = int(obj_name[7:]) ids.append(domain_id) group = f[obj_name] - volume = tuple(group['volume'].value) + volume = ufloat(*group['volume'].value) nucnames = group['nuclides'].value atoms_ = group['atoms'].value atom_dict = OrderedDict() for name_i, atoms_i in zip(nucnames, atoms_): - atom_dict[name_i.decode()] = tuple(atoms_i) + atom_dict[name_i.decode()] = ufloat(*atoms_i) volumes[domain_id] = volume atoms[domain_id] = atom_dict diff --git a/tests/regression_tests/volume_calc/results_true.dat b/tests/regression_tests/volume_calc/results_true.dat index 8eb2a61ac..466139cd6 100644 --- a/tests/regression_tests/volume_calc/results_true.dat +++ b/tests/regression_tests/volume_calc/results_true.dat @@ -1,30 +1,30 @@ Volume calculation 0 -Domain 1: 31.4693 +/- 0.0721 cm^3 -Domain 2: 2.0933 +/- 0.0310 cm^3 -Domain 3: 2.0486 +/- 0.0307 cm^3 - Cell Nuclide Atoms Uncertainty -0 1 U235 3.481769e+23 7.979991e+20 -1 1 Mo99 3.481769e+22 7.979991e+19 -2 2 H1 1.399770e+23 2.072914e+21 -3 2 O16 6.998852e+22 1.036457e+21 -4 2 B10 6.998852e+18 1.036457e+17 -5 3 H1 1.369920e+23 2.051689e+21 -6 3 O16 6.849599e+22 1.025844e+21 -7 3 B10 6.849599e+18 1.025844e+17 +Domain 1: 31.47+/-0.07 cm^3 +Domain 2: 2.093+/-0.031 cm^3 +Domain 3: 2.049+/-0.031 cm^3 + Cell Nuclide Atoms +0 1 U235 (3.482+/-0.008)e+23 +1 1 Mo99 (3.482+/-0.008)e+22 +2 2 H1 (1.400+/-0.021)e+23 +3 2 O16 (7.00+/-0.10)e+22 +4 2 B10 (7.00+/-0.10)e+18 +5 3 H1 (1.370+/-0.021)e+23 +6 3 O16 (6.85+/-0.10)e+22 +7 3 B10 (6.85+/-0.10)e+18 Volume calculation 1 -Domain 1: 4.1419 +/- 0.0426 cm^3 -Domain 2: 31.4693 +/- 0.0721 cm^3 - Material Nuclide Atoms Uncertainty -0 1 H1 2.769690e+23 2.850067e+21 -1 1 O16 1.384845e+23 1.425034e+21 -2 1 B10 1.384845e+19 1.425034e+17 -3 2 U235 3.481769e+23 7.979991e+20 -4 2 Mo99 3.481769e+22 7.979991e+19 +Domain 1: 4.14+/-0.04 cm^3 +Domain 2: 31.47+/-0.07 cm^3 + Material Nuclide Atoms +0 1 H1 (2.770+/-0.029)e+23 +1 1 O16 (1.385+/-0.014)e+23 +2 1 B10 (1.385+/-0.014)e+19 +3 2 U235 (3.482+/-0.008)e+23 +4 2 Mo99 (3.482+/-0.008)e+22 Volume calculation 2 -Domain 0: 35.6112 +/- 0.0664 cm^3 - Universe Nuclide Atoms Uncertainty -0 0 H1 2.769690e+23 2.850067e+21 -1 0 O16 1.384845e+23 1.425034e+21 -2 0 B10 1.384845e+19 1.425034e+17 -3 0 U235 3.481769e+23 7.979991e+20 -4 0 Mo99 3.481769e+22 7.979991e+19 +Domain 0: 35.61+/-0.07 cm^3 + Universe Nuclide Atoms +0 0 H1 (2.770+/-0.029)e+23 +1 0 O16 (1.385+/-0.014)e+23 +2 0 B10 (1.385+/-0.014)e+19 +3 0 U235 (3.482+/-0.008)e+23 +4 0 Mo99 (3.482+/-0.008)e+22 diff --git a/tests/regression_tests/volume_calc/test.py b/tests/regression_tests/volume_calc/test.py index a6b62b9be..fda4b3321 100644 --- a/tests/regression_tests/volume_calc/test.py +++ b/tests/regression_tests/volume_calc/test.py @@ -64,8 +64,7 @@ class VolumeTest(PyAPITestHarness): # Write cell volumes and total # of atoms for each nuclide for uid, volume in sorted(volume_calc.volumes.items()): - outstr += 'Domain {0}: {1[0]:.4f} +/- {1[1]:.4f} cm^3\n'.format( - uid, volume) + outstr += 'Domain {}: {} cm^3\n'.format(uid, volume) outstr += str(volume_calc.atoms_dataframe) + '\n' return outstr From 5dc25569f2b54d87e6c9cf7b263c06cdb1914094 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Mon, 19 Mar 2018 10:15:08 -0500 Subject: [PATCH 14/15] Use latest HDF5 format for openmc-get-jeff-data --- scripts/openmc-get-jeff-data | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/openmc-get-jeff-data b/scripts/openmc-get-jeff-data index 9f426a493..03b58163b 100755 --- a/scripts/openmc-get-jeff-data +++ b/scripts/openmc-get-jeff-data @@ -41,7 +41,7 @@ parser.add_argument('-b', '--batch', action='store_true', parser.add_argument('-d', '--destination', default='jeff-3.2-hdf5', help='Directory to create new library in') parser.add_argument('--libver', choices=['earliest', 'latest'], - default='earliest', help="Output HDF5 versioning. Use " + default='latest', help="Output HDF5 versioning. Use " "'earliest' for backwards compatibility or 'latest' for " "performance") args = parser.parse_args() From 85af75c459da55b3d77cf15e5b556b61ca97aa4b Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Mon, 19 Mar 2018 13:58:58 -0500 Subject: [PATCH 15/15] Address comments on #985 --- openmc/filter.py | 4 ++-- openmc/plots.py | 9 ++++++++- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/openmc/filter.py b/openmc/filter.py index 6cb81d97a..26629dafe 100644 --- a/openmc/filter.py +++ b/openmc/filter.py @@ -753,7 +753,7 @@ class MeshFilter(Filter): if n_dim == 3: # Construct 3-tuple of x,y,z cell indices for a 3D mesh nx, ny, nz = self.mesh.dimension - x = bin_index % nx + 1 + x = (bin_index % nx) + 1 y = (bin_index % (nx * ny)) // nx + 1 z = bin_index // (nx * ny) + 1 return (x, y, z) @@ -761,7 +761,7 @@ class MeshFilter(Filter): elif n_dim == 2: # Construct 2-tuple of x,y cell indices for a 2D mesh nx, ny = self.mesh.dimension - x = bin_index % nx + 1 + x = (bin_index % nx) + 1 y = bin_index // nx + 1 return (x, y) else: diff --git a/openmc/plots.py b/openmc/plots.py index a948c2a48..8eff78b1d 100644 --- a/openmc/plots.py +++ b/openmc/plots.py @@ -651,9 +651,16 @@ class Plot(IDManagerMixin): return element - def to_image(self, openmc_exec='openmc', cwd='.', convert_exec='convert'): + def to_ipython_image(self, openmc_exec='openmc', cwd='.', + convert_exec='convert'): """Render plot as an image + This method runs OpenMC in plotting mode to produce a bitmap image which + is then converted to a .png file and loaded in as an + :class:`IPython.display.Image` object. As such, it requires that your + model geometry, materials, and settings have already been exported to + XML. + Parameters ---------- openmc_exec : str