Merge remote-tracking branch 'upstream/develop' into mg

This commit is contained in:
Adam Nelson 2016-01-07 20:05:01 -05:00
commit ff27852c51
46 changed files with 1283 additions and 595 deletions

1
.gitignore vendored
View file

@ -24,6 +24,7 @@ examples/python/**/*.xml
# Documentation builds
docs/build
docs/source/_images/*.pdf
docs/source/_images/*.aux
# Source build
build

View file

@ -17,6 +17,8 @@ ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) sou
SVG2PDF = inkscape
PDFS = $(patsubst %.svg,%.pdf,$(wildcard $(IMAGEDIR)/*.svg))
# Tikz to PNG conversion
PNGS = $(patsubst %.tex,%.png,$(wildcard $(IMAGEDIR)/*.tex))
.PHONY: help images clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest
@ -43,8 +45,13 @@ help:
%.pdf: %.svg
$(SVG2PDF) -f $< -A $@
%.png: %.tex
pdflatex --interaction=nonstopmode --output-directory=$(IMAGEDIR) $<
pdftoppm -r 120 -singlefile $(patsubst %.tex,%.pdf, $<) $(basename $<)
convert -trim -fuzz 2% -transparent white $(patsubst %.tex,%.ppm,$<) $@
# Rule to build PDFs
images: $(PDFS)
images: $(PDFS) $(PNGS)
clean:
-rm -rf $(BUILDDIR)/*

View file

@ -0,0 +1,2 @@
sphinx-numfig
jupyter

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

View file

@ -1,3 +1,12 @@
\documentclass{standalone}
\usepackage[utf8]{inputenc}
\usepackage{amsmath}
\usepackage{tikz}
\usepackage{pgfplots}
\pgfplotsset{compat=1.11}
\usetikzlibrary{shapes,snakes,shadows,arrows,calc,decorations.markings,patterns,fit,matrix,spy}
\pagestyle{empty}
\begin{document}
\begin{tikzpicture}
\matrix[every node/.style={draw, thick, minimum width=3cm, minimum height=1cm, align=center}, column sep=2cm, row sep=1cm] (m) {
\node[draw, fill=red!40] (start) {Batch $i$ \\ tally NDA}; & \\
@ -16,4 +25,5 @@
\draw (modify.north) -- (end.south);
\end{scope}
\end{tikzpicture}
\end{tikzpicture}
\end{document}

Binary file not shown.

After

Width:  |  Height:  |  Size: 46 KiB

View file

@ -1,10 +1,20 @@
\documentclass[tikz]{standalone}
\usepackage[utf8]{inputenc}
\usepackage{amsmath}
\usepackage{tikz}
\usepackage{pgfplots}
\pgfplotsset{compat=1.11}
\usetikzlibrary{shapes,snakes,shadows,arrows,calc,decorations.markings,patterns,fit,matrix,spy}
\usepackage{fixltx2e}
\pagestyle{empty}
\begin{document}
% these dimensions are determined in arrow_dimms.ods
\def\scale{1.0}
\def\latWidth{0.2808363589*\scale}
\def\RPVOR{3*\scale}
\def\rectW{0.75*\scale}
\def\RPVIR{2.8694005485*\scale}
@ -20,7 +30,7 @@
\def\bafMIRy{1.5445999739*\scale}
\def\bafMORx{1.8544620609*\scale}
\def\bafMORy{1.573625702*\scale}
\tikzset{Assembly/.style={
inner sep=0pt,
text width=\latWidth in,
@ -29,13 +39,13 @@
align=center
}
}
\def\tkzRPV{(0,0) circle (\RPVIR) (0,0) circle (\RPVOR)}
\def\tkzBarrel{(0,0) circle (\BarrelIR) (0,0) circle (\BarrelOR)}
\def\tkzShields{(0,0) circle (\BarrelOR) (0,0) circle (\ShieldOR)}
\def\tkzBaffCOR{(-\bafCORx, -\bafCORy) rectangle (\bafCORx, \bafCORy)}
\def\tkzBaffCIR{(-\bafCIRx, -\bafCIRy) rectangle (\bafCIRx, \bafCIRy)}
\def\tkzBaffCIR{(-\bafCIRx, -\bafCIRy) rectangle (\bafCIRx, \bafCIRy)}
\def\tkzBaffMOR{(-\bafMORx, -\bafMORy) rectangle (\bafMORx, \bafMORy)}
\def\tkzBaffMIR{(-\bafMIRx, -\bafMIRy) rectangle (\bafMIRx, \bafMIRy) }
\def\tkzBaffleC{ \tkzBaffCIR \tkzBaffCOR }
@ -53,7 +63,7 @@
\begin{tikzpicture}[x=1in,y=1in, xshift=3in]
\scalebox{0.6}{
% draw RPV, barrel, and shield panels
\path[fill=black,even odd rule] \tkzRPV;
\path[fill=black,even odd rule] \tkzBarrel;
\begin{scope}
@ -61,9 +71,9 @@
\path[fill=black,even odd rule] \tkzShields;
\end{scope}
% draw assembly row/column headers
\draw[red, thick] ($(-7*\latWidth,\RPVOR/\latWidth*\latWidth)$) node[above, anchor=south] {R} -- ($(-7*\latWidth,4*\latWidth)$);
\draw[red, thick] ($(-6*\latWidth,\RPVOR/\latWidth*\latWidth)$) node[above, anchor=south] {P} -- ($(-6*\latWidth,6*\latWidth)$);
\draw[red, thick] ($(-5*\latWidth,\RPVOR/\latWidth*\latWidth)$) node[above, anchor=south] {N} -- ($(-5*\latWidth,7*\latWidth)$);
@ -79,7 +89,7 @@
\draw[red, thick] ($(5*\latWidth,\RPVOR/\latWidth*\latWidth)$) node[above, anchor=south] {C} -- ($(5*\latWidth,7*\latWidth)$);
\draw[red, thick] ($(6*\latWidth,\RPVOR/\latWidth*\latWidth)$) node[above, anchor=south] {B} -- ($(6*\latWidth,6*\latWidth)$);
\draw[red, thick] ($(7*\latWidth,\RPVOR/\latWidth*\latWidth)$) node[above, anchor=south] {A} -- ($(7*\latWidth,4*\latWidth)$);
\begin{scope}[rotate=90]
\draw[red, thick] ($(-7*\latWidth,\RPVOR/\latWidth*\latWidth)$) node[left, anchor=east] {15} -- ($(-7*\latWidth,4*\latWidth)$);
\draw[red, thick] ($(-6*\latWidth,\RPVOR/\latWidth*\latWidth)$) node[left, anchor=east] {14} -- ($(-6*\latWidth,6*\latWidth)$);
@ -97,7 +107,7 @@
\draw[red, thick] ($(6*\latWidth,\RPVOR/\latWidth*\latWidth)$) node[left, anchor=east] {2} -- ($(6*\latWidth,6*\latWidth)$);
\draw[red, thick] ($(7*\latWidth,\RPVOR/\latWidth*\latWidth)$) node[left, anchor=east] {1} -- ($(7*\latWidth,4*\latWidth)$);
\end{scope}
% draw fuel assembly nodes
\node [Assembly, fill=\lightgray, opacity=0.3] at ($(-8*\latWidth,8*\latWidth)$) {};
\node [Assembly, fill=\lightgray, opacity=0.3] at ($(-7*\latWidth,8*\latWidth)$) {};
@ -116,7 +126,7 @@
\node [Assembly, fill=\lightgray, opacity=0.3] at ($( 6*\latWidth,8*\latWidth)$) {};
\node [Assembly, fill=\lightgray, opacity=0.3] at ($( 7*\latWidth,8*\latWidth)$) {};
\node [Assembly, fill=\lightgray, opacity=0.3] at ($( 8*\latWidth,8*\latWidth)$) {};
\node [Assembly, fill=\lightgray, opacity=0.3] at ($(-8*\latWidth,7*\latWidth)$) {};
\node [Assembly, fill=\lightgray, opacity=0.3] at ($(-7*\latWidth,7*\latWidth)$) {};
\node [Assembly, fill=\lightgray, opacity=0.3] at ($(-6*\latWidth,7*\latWidth)$) {};
@ -581,7 +591,7 @@
\node [Assembly, fill=\lightgray, opacity=0.3] at ($( 6*\latWidth,-7*\latWidth)$) {};
\node [Assembly, fill=\lightgray, opacity=0.3] at ($( 7*\latWidth,-7*\latWidth)$) {};
\node [Assembly, fill=\lightgray, opacity=0.3] at ($( 8*\latWidth,-7*\latWidth)$) {};
\node [Assembly, fill=\lightgray, opacity=0.3] at ($(-8*\latWidth,-8*\latWidth)$) {};
\node [Assembly, fill=\lightgray, opacity=0.3] at ($(-7*\latWidth,-8*\latWidth)$) {};
\node [Assembly, fill=\lightgray, opacity=0.3] at ($(-6*\latWidth,-8*\latWidth)$) {};
@ -601,7 +611,7 @@
\node [Assembly, fill=\lightgray, opacity=0.3] at ($( 8*\latWidth,-8*\latWidth)$) {};
% draw baffle north/south
\begin{scope}[even odd rule]
\clip[rotate=90] \tkzBaffMClip;
\path[fill=black] \tkzBaffleC;
@ -611,9 +621,9 @@
\clip \tkzBaffMClip;
\path[fill=black, rotate=90] \tkzBaffleM;
\end{scope}
% draw baffle east/west
\begin{scope}[rotate=90]
\begin{scope}[even odd rule]
\clip[rotate=90] \tkzBaffMClip;
@ -626,3 +636,4 @@
\end{scope}
\end{scope}}
\end{tikzpicture}
\end{document}

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.8 KiB

View file

@ -13,6 +13,26 @@
import sys, os
# Determine if we're on Read the Docs server
on_rtd = os.environ.get('READTHEDOCS', None) == 'True'
# On Read the Docs, we need to mock a few third-party modules so we don't get
# ImportErrors when building documentation
try:
from unittest.mock import MagicMock
except ImportError:
from mock import Mock as MagicMock
class Mock(MagicMock):
@classmethod
def __getattr__(cls, name):
return Mock()
MOCK_MODULES = ['numpy', 'h5py', 'pandas', 'opencg']
sys.modules.update((mod_name, Mock()) for mod_name in MOCK_MODULES)
# If extensions (or modules to document with autodoc) are in another directory,
# add these directories to sys.path here. If the directory is relative to the
# documentation root, use os.path.abspath to make it absolute, like shown here.
@ -26,9 +46,8 @@ sys.path.insert(0, os.path.abspath('../..'))
# coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
extensions = ['sphinx.ext.autodoc',
'sphinx.ext.napoleon',
'sphinx.ext.pngmath',
'sphinx.ext.mathjax',
'sphinx.ext.autosummary',
'sphinxcontrib.tikz',
'sphinx_numfig',
'notebook_sphinxext']
@ -105,16 +124,15 @@ pygments_style = 'tango'
# The theme to use for HTML and HTML Help pages. Major themes that come with
# Sphinx are currently 'default' and 'sphinxdoc'.
html_theme = 'haiku'
#html_theme = 'altered_nature'
#html_theme = 'sphinxdoc'
# Theme options are theme-specific and customize the look and feel of a theme
# further. For a list of options available for each theme, see the
# documentation.
html_theme_options = {'full_logo': True,
'linkcolor': '#0c3762',
'visitedlinkcolor': '#0c3762'}
if on_rtd:
html_theme = 'default'
html_logo = '_images/openmc200px.png'
else:
html_theme = 'haiku'
html_theme_options = {'full_logo': True,
'linkcolor': '#0c3762',
'visitedlinkcolor': '#0c3762'}
html_logo = '_images/openmc.png'
# Add any paths that contain custom themes here, relative to this directory.
#html_theme_path = ["_theme"]
@ -126,10 +144,6 @@ html_title = "OpenMC Documentation"
# A shorter title for the navigation bar. Default is the same as html_title.
#html_short_title = None
# The name of an image file (relative to this directory) to place at the top
# of the sidebar.
html_logo = '_images/openmc.png'
# The name of an image file (within the static path) to use as favicon of the
# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32
# pixels large.

View file

@ -12,15 +12,8 @@ is via pip:
sudo pip install sphinx
Additionally, you will also need two Sphinx extensions for TikZ support and
numbering figures. The sphinxcontrib-tikz_ package should be installed directly
from the git repository as such:
.. code-block:: sh
sudo pip install https://bitbucket.org/philexander/tikz/get/HEAD.tar.gz
The Numfig_ package can be installed directly with pip:
Additionally, you will also need a Sphinx extension for numbering figures. The
Numfig_ package can be installed directly with pip:
.. code-block:: sh

View file

@ -110,10 +110,12 @@ illustrated as a flow chart below. After a batch of neutrons
is simulated, NDA can take place. Each of the steps described above is described
in detail in the following sections.
.. tikz:: Flow chart of NDA process. Note "XS" is used for cross section and
"DC" is used for diffusion coefficient.
:libs: shapes, snakes, shadows, arrows, calc, decorations.markings, patterns, fit, matrix, spy
:include: cmfd_tikz/cmfd_flow.tikz
.. figure:: ../_images/cmfd_flow.png
:align: center
:figclass: align-center
Flow chart of NDA process. Note "XS" is used for cross section and "DC" is
used for diffusion coefficient.
Calculation of Macroscopic Cross Sections
-----------------------------------------
@ -422,9 +424,11 @@ during the MC simulation with incoming and outgoing partial currents. This
allows the user to not have to worry about neutrons producing adequate tallies
in mesh cells far away from the core.
.. tikz:: Diagram of CMFD acceleration mesh
:libs: shapes, snakes, shadows, arrows, calc, decorations.markings, patterns, fit, matrix, spy
:include: cmfd_tikz/meshfig.tikz
.. figure:: ../_images/meshfig.png
:align: center
:figclass: align-center
Diagram of CMFD acceleration mesh
During an MC simulation, CMFD tallies are accumulated. The basic tallies needed
are listed in Table :ref:`tab_tally`. Each tally is performed on a spatial and

View file

@ -1626,7 +1626,7 @@ another.
.. _ENDF-6 Format: http://www-nds.iaea.org/ndspub/documents/endf/endf102/endf102.pdf
.. _Monte Carlo Sampler: https://laws.lanl.gov/vhosts/mcnp.lanl.gov/pdf_files/la-9721_3rdmcsampler.pdf
.. _Monte Carlo Sampler: https://laws.lanl.gov/vhosts/mcnp.lanl.gov/pdf_files/la-9721.pdf
.. _LA-UR-14-27694: http://permalink.lanl.gov/object/tr?what=info:lanl-repo/lareport/LA-UR-14-27694
@ -1636,4 +1636,4 @@ another.
.. _lectures: https://laws.lanl.gov/vhosts/mcnp.lanl.gov/pdf_files/la-ur-05-4983.pdf
.. _MCNP Manual: https://laws.lanl.gov/vhosts/mcnp.lanl.gov/pdf_files/MCNP5_Manual_Volume_I_LA-UR-03-1987.pdf
.. _MCNP Manual: https://laws.lanl.gov/vhosts/mcnp.lanl.gov/pdf_files/la-ur-03-1987.pdf

View file

@ -70,5 +70,5 @@ the idea is to determine the new multiplicative and additive constants in
Different Sizes and Good Lattice Structures," *Math. Comput.*, **68**, 249
(1999).
.. _Brown: https://laws.lanl.gov/vhosts/mcnp.lanl.gov/pdf_files/anl_rn_arb-strides_1994.pdf
.. _Brown: https://laws.lanl.gov/vhosts/mcnp.lanl.gov/pdf_files/anl-rn-arb-stride.pdf
.. _linear congruential generator: http://en.wikipedia.org/wiki/Linear_congruential_generator

View file

@ -507,6 +507,6 @@ improve the estimate of the percentile.
.. _Cauchy distribution: http://en.wikipedia.org/wiki/Cauchy_distribution
.. _unpublished rational approximation: http://home.online.no/~pjacklam/notes/invnorm/
.. _unpublished rational approximation: https://web.archive.org/web/20150926021742/http://home.online.no/~pjacklam/notes/invnorm/
.. _MC21: http://www.osti.gov/bridge/servlets/purl/903083-HT5p1o/903083.pdf

View file

@ -185,10 +185,6 @@ if run_mode == 'k-eigenvalue':
Type of the j-th filter. Can be 'universe', 'material', 'cell', 'cellborn',
'surface', 'mesh', 'energy', 'energyout', or 'distribcell'.
**/tallies/tally <uid>/filter <j>/offset** (*int*)
Filter offset (used for distribcell filter).
**/tallies/tally <uid>/filter <j>/n_bins** (*int*)
Number of bins for the j-th filter.

View file

@ -121,6 +121,10 @@ The current revision of the summary file format is 1.
Region specification for the cell.
**/geometry/cells/cell <uid>/distribcell_index** (*int*)
Index of this cell in distribcell filter arrays.
**/geometry/surfaces/surface <uid>/index** (*int*)
Index in surfaces array used internally in OpenMC.
@ -306,6 +310,11 @@ The current revision of the summary file format is 1.
than the number of user-specified scores since each score might have
multiple scoring bins, e.g., scatter-PN.
**/tallies/tally <uid>/moment_orders** (*char[][]*)
Tallying moment orders for Legendre and spherical harmonic tally expansions
(*e.g.*, 'P2', 'Y1,2', etc.).
**/tallies/tally <uid>/score_bins** (*char[][]*)
Scoring bins for the tally.

View file

@ -12,10 +12,7 @@ from docutils.parsers.rst import directives, roles, states
from docutils.parsers.rst.roles import set_classes
from docutils.transforms import misc
try:
from IPython.nbconver.exporters import html
except ImportError:
from IPython.nbconvert import html
from nbconvert import html
class Notebook(Directive):

View file

@ -42,8 +42,6 @@ class Filter(object):
The number of filter bins
mesh : Mesh or None
A Mesh object for 'mesh' type filters.
offset : Integral
A value used to index tally bins for 'distribcell' tallies.
stride : Integral
The number of filter, nuclide and score bins within each of this
filter's bins.
@ -57,7 +55,6 @@ class Filter(object):
self._num_bins = 0
self._bins = None
self._mesh = None
self._offset = -1
self._stride = None
if type is not None:
@ -93,7 +90,6 @@ class Filter(object):
clone._bins = copy.deepcopy(self.bins, memo)
clone._num_bins = self.num_bins
clone._mesh = copy.deepcopy(self.mesh, memo)
clone._offset = self.offset
clone._stride = self.stride
memo[id(self)] = clone
@ -108,7 +104,6 @@ class Filter(object):
string = 'Filter\n'
string += '{0: <16}{1}{2}\n'.format('\tType', '=\t', self.type)
string += '{0: <16}{1}{2}\n'.format('\tBins', '=\t', self.bins)
string += '{0: <16}{1}{2}\n'.format('\tOffset', '=\t', self.offset)
return string
@property
@ -134,10 +129,6 @@ class Filter(object):
def mesh(self):
return self._mesh
@property
def offset(self):
return self._offset
@property
def stride(self):
return self._stride
@ -226,11 +217,6 @@ class Filter(object):
self.type = 'mesh'
self.bins = self.mesh.id
@offset.setter
def offset(self, offset):
cv.check_type('filter offset', offset, Integral)
self._offset = offset
@stride.setter
def stride(self, stride):
cv.check_type('filter stride', stride, Integral)
@ -623,7 +609,7 @@ class Filter(object):
# If this region is in Cell corresponding to the
# distribcell filter bin, store it in dictionary
if cell_id == self.bins[0]:
offset = openmc_geometry.get_offset(path, self.offset)
offset = openmc_geometry.get_cell_instance(path)
offsets_to_coords[offset] = coords
# Each distribcell offset is a DataFrame bin

View file

@ -42,10 +42,10 @@ class Geometry(object):
self._root_universe = root_universe
def get_offset(self, path, filter_offset):
"""Returns the corresponding location in the results array for a given path and
filter number. This is primarily intended to post-processing result when
a distribcell filter is used.
def get_cell_instance(self, path):
"""Return the instance number for the final cell in a geometry path.
The instance is an index into tally distribcell filter arrays.
Parameters
----------
@ -55,24 +55,31 @@ class Geometry(object):
lattice passed through. For the case of the lattice, a tuple should
be provided to indicate which coordinates in the lattice should be
entered. This should be in the form: (lat_id, i_x, i_y, i_z)
filter_offset : int
An integer that specifies which offset map the filter is using
Returns
-------
offset : int
Location in the results array for the path and filter
instance : int
Index in tally results array for distribcell filters
"""
# Find the distribcell index of the cell.
cells = self.get_all_cells()
if path[-1] in cells:
distribcell_index = cells[path[-1]].distribcell_index
else:
raise RuntimeError('Could not find cell {} specified in a \
distribcell filter'.format(path[-1]))
# Return memoize'd offset if possible
if (path, filter_offset) in self._offsets:
offset = self._offsets[(path, filter_offset)]
if (path, distribcell_index) in self._offsets:
offset = self._offsets[(path, distribcell_index)]
# Begin recursive call to compute offset starting with the base Universe
else:
offset = self._root_universe.get_offset(path, filter_offset)
self._offsets[(path, filter_offset)] = offset
offset = self._root_universe.get_cell_instance(path,
distribcell_index)
self._offsets[(path, distribcell_index)] = offset
# Return the final offset
return offset

View file

@ -73,6 +73,9 @@ class Library(object):
name : str, optional
Name of the multi-group cross section library. Used as a label to
identify tallies in OpenMC 'tallies.xml' file.
sparse : bool
Whether or not the Library's tallies use SciPy's LIL sparse matrix
format for compressed data storage
"""
@ -92,6 +95,7 @@ class Library(object):
self._all_mgxs = OrderedDict()
self._sp_filename = None
self._keff = None
self._sparse = False
self.name = name
self.openmc_geometry = openmc_geometry
@ -119,6 +123,7 @@ class Library(object):
clone._all_mgxs = self.all_mgxs
clone._sp_filename = self._sp_filename
clone._keff = self._keff
clone._sparse = self.sparse
clone._all_mgxs = OrderedDict()
for domain in self.domains:
@ -208,6 +213,10 @@ class Library(object):
def keff(self):
return self._keff
@property
def sparse(self):
return self._sparse
@openmc_geometry.setter
def openmc_geometry(self, openmc_geometry):
cv.check_type('openmc_geometry', openmc_geometry, openmc.Geometry)
@ -286,6 +295,28 @@ class Library(object):
cv.check_type('tally trigger', tally_trigger, openmc.Trigger)
self._tally_trigger = tally_trigger
@sparse.setter
def sparse(self, sparse):
"""Convert tally data from NumPy arrays to SciPy list of lists (LIL)
sparse matrices, and vice versa.
This property may be used to reduce the amount of data in memory during
tally data processing. The tally data will be stored as SciPy LIL
matrices internally within the Tally object. All tally data access
properties and methods will return data as a dense NumPy array.
"""
cv.check_type('sparse', sparse, bool)
# Sparsify or densify each MGXS in the Library
for domain in self.domains:
for mgxs_type in self.mgxs_types:
mgxs = self.get_mgxs(domain, mgxs_type)
mgxs.sparse = self.sparse
self._sparse = sparse
def build_library(self):
"""Initialize MGXS objects in each domain and for each reaction type
in the library.
@ -381,6 +412,7 @@ class Library(object):
for mgxs_type in self.mgxs_types:
mgxs = self.get_mgxs(domain, mgxs_type)
mgxs.load_from_statepoint(statepoint)
mgxs.sparse = self.sparse
def get_mgxs(self, domain, mgxs_type):
"""Return the MGXS object for some domain and reaction rate type.

View file

@ -47,7 +47,7 @@ _DOMAINS = [openmc.Cell,
class MGXS(object):
"""An abstract multi-group cross section for some energy group structure
"""An abstract multi-group cross section for some energy group structure
within some spatial domain.
This class can be used for both OpenMC input generation and tally data
@ -92,10 +92,10 @@ class MGXS(object):
xs_tally : Tally
Derived tally for the multi-group cross section. This attribute
is None unless the multi-group cross section has been computed.
num_sumbdomains : Integral
num_subdomains : Integral
The number of subdomains is unity for 'material', 'cell' and 'universe'
domain types. When the This is equal to the number of cell instances
for 'distribcell' domain types (it is equal to unity prior to loading
for 'distribcell' domain types (it is equal to unity prior to loading
tally data from a statepoint file).
num_nuclides : Integral
The number of nuclides for which the multi-group cross section is
@ -103,6 +103,9 @@ class MGXS(object):
nuclides : list of str or 'sum'
A list of nuclide string names (e.g., 'U-238', 'O-16') when by_nuclide
is True and 'sum' when by_nuclide is False.
sparse : bool
Whether or not the MGXS' tallies use SciPy's LIL sparse matrix format
for compressed data storage
"""
@ -121,6 +124,7 @@ class MGXS(object):
self._tally_trigger = None
self._tallies = None
self._xs_tally = None
self._sparse = False
self.name = name
self.by_nuclide = by_nuclide
@ -146,6 +150,7 @@ class MGXS(object):
clone._energy_groups = copy.deepcopy(self.energy_groups, memo)
clone._tally_trigger = copy.deepcopy(self.tally_trigger, memo)
clone._xs_tally = copy.deepcopy(self.xs_tally, memo)
clone._sparse = self.sparse
clone._tallies = OrderedDict()
for tally_type, tally in self.tallies.items():
@ -199,6 +204,10 @@ class MGXS(object):
def xs_tally(self):
return self._xs_tally
@property
def sparse(self):
return self._sparse
@property
def num_subdomains(self):
tally = list(self.tallies.values())[0]
@ -249,6 +258,29 @@ class MGXS(object):
cv.check_type('tally trigger', tally_trigger, openmc.Trigger)
self._tally_trigger = tally_trigger
@sparse.setter
def sparse(self, sparse):
"""Convert tally data from NumPy arrays to SciPy list of lists (LIL)
sparse matrices, and vice versa.
This property may be used to reduce the amount of data in memory during
tally data processing. The tally data will be stored as SciPy LIL
matrices internally within the Tally object. All tally data access
properties and methods will return data as a dense NumPy array.
"""
cv.check_type('sparse', sparse, bool)
# Sparsify or densify the derived MGXS tally and its base tallies
if self.xs_tally:
self.xs_tally.sparse = sparse
for tally_name in self.tallies:
self.tallies[tally_name].sparse = sparse
self._sparse = sparse
@staticmethod
def get_mgxs(mgxs_type, domain=None, domain_type=None,
energy_groups=None, by_nuclide=False, name=''):
@ -503,6 +535,7 @@ class MGXS(object):
# Remove NaNs which may have resulted from divide-by-zero operations
self._xs_tally._mean = np.nan_to_num(self.xs_tally.mean)
self._xs_tally._std_dev = np.nan_to_num(self.xs_tally.std_dev)
self.xs_tally.sparse = self.sparse
def load_from_statepoint(self, statepoint):
"""Extracts tallies in an OpenMC StatePoint with the data needed to
@ -565,6 +598,7 @@ class MGXS(object):
estimator=tally.estimator)
sp_tally = sp_tally.get_slice(tally.scores, filters,
filter_bins, tally.nuclides)
sp_tally.sparse = self.sparse
self.tallies[tally_type] = sp_tally
# Compute the cross section from the tallies
@ -716,6 +750,7 @@ class MGXS(object):
# Clone this MGXS to initialize the condensed version
condensed_xs = copy.deepcopy(self)
condensed_xs.sparse = False
condensed_xs.energy_groups = coarse_groups
# Build energy indices to sum across
@ -754,10 +789,8 @@ class MGXS(object):
std_dev = np.sqrt(std_dev)
# Reshape condensed data arrays with one dimension for all filters
new_shape = \
(tally.num_filter_bins, tally.num_nuclides, tally.num_score_bins,)
mean = np.reshape(mean, new_shape)
std_dev = np.reshape(std_dev, new_shape)
mean = np.reshape(mean, tally.shape)
std_dev = np.reshape(std_dev, tally.shape)
# Override tally's data with the new condensed data
tally._mean = mean
@ -765,6 +798,7 @@ class MGXS(object):
# Compute the energy condensed multi-group cross section
condensed_xs.compute_xs()
condensed_xs.sparse = self.sparse
return condensed_xs
def get_subdomain_avg_xs(self, subdomains='all'):
@ -807,8 +841,9 @@ class MGXS(object):
# Clone this MGXS to initialize the subdomain-averaged version
avg_xs = copy.deepcopy(self)
avg_xs.sparse = False
# If domain is distribcell, make the new domain 'cell'
# If domain is distribcell, make the new domain 'cell'
if self.domain_type == 'distribcell':
avg_xs.domain_type = 'cell'
@ -836,10 +871,8 @@ class MGXS(object):
domain_filter.num_bins = 1
# Reshape averaged data arrays with one dimension for all filters
new_shape = \
(tally.num_filter_bins, tally.num_nuclides, tally.num_score_bins,)
mean = np.reshape(mean, new_shape)
std_dev = np.reshape(std_dev, new_shape)
mean = np.reshape(mean, tally.shape)
std_dev = np.reshape(std_dev, tally.shape)
# Override tally's data with the new condensed data
tally._mean = mean
@ -847,7 +880,7 @@ class MGXS(object):
# Compute the subdomain-averaged multi-group cross section
avg_xs.compute_xs()
avg_xs.sparse = self.sparse
return avg_xs
def print_xs(self, subdomains='all', nuclides='all', xs_type='macro'):
@ -1420,8 +1453,8 @@ class AbsorptionXS(MGXS):
class CaptureXS(MGXS):
"""A capture multi-group cross section.
The Neutron capture reaction rate is defined as the difference between
The neutron capture reaction rate is defined as the difference between
OpenMC's 'absorption' and 'fission' reaction rate score types. This includes
not only radiative capture, but all forms of neutron disappearance aside
from fission (e.g., MT > 100).
@ -1723,8 +1756,8 @@ class ScatterMatrixXS(MGXS):
if self.correction == 'P0':
scatter_p1 = self.tallies['scatter-P1']
scatter_p1 = scatter_p1.get_slice(scores=['scatter-P1'])
energy_filter = openmc.Filter(type='energy')
energy_filter.bins = self.energy_groups.group_edges
energy_filter = self.tallies['scatter'].find_filter('energy')
energy_filter = copy.deepcopy(energy_filter)
scatter_p1 = scatter_p1.diagonalize_filter(energy_filter)
rxn_tally = self.tallies['scatter'] - scatter_p1
else:

View file

@ -725,11 +725,11 @@ def get_openmc_cell(opencg_cell):
else:
openmc_cell.fill = get_openmc_material(fill)
if opencg_cell.rotation:
if opencg_cell.rotation is not None:
rotation = np.asarray(opencg_cell.rotation, dtype=np.float64)
openmc_cell.rotation = rotation
if opencg_cell.translation:
if opencg_cell.translation is not None:
translation = np.asarray(opencg_cell.translation, dtype=np.float64)
openmc_cell.translation = translation
@ -881,16 +881,30 @@ def get_opencg_lattice(openmc_lattice):
universes = openmc_lattice.universes
outer = openmc_lattice.outer
# Convert 2D dimension to 3D for OpenCG
if len(dimension) == 2:
new_dimension = np.ones(3, dtype=np.int)
new_dimension[:2] = dimension
dimension = new_dimension
# Convert 2D pitch to 3D for OpenCG
if len(pitch) == 2:
new_pitch = np.ones(3, dtype=np.float64) * np.inf
new_pitch = np.ones(3, dtype=np.float64) * np.finfo(np.float64).max
new_pitch[:2] = pitch
pitch = new_pitch
# Convert 2D lower left to 3D for OpenCG
if len(lower_left) == 2:
new_lower_left = np.ones(3, dtype=np.float64)
new_lower_left = np.ones(3, dtype=np.float64) * np.finfo(np.float64).min
new_lower_left[:2] = lower_left
lower_left = new_lower_left
# Convert 2D universes array to 3D for OpenCG
if len(universes.shape) == 2:
new_universes = universes.copy()
new_universes.shape = (1,) + universes.shape
universes = new_universes
# Initialize an empty array for the OpenCG nested Universes in this Lattice
universe_array = np.ndarray(tuple(np.array(dimension)[::-1]),
dtype=opencg.Universe)
@ -905,7 +919,7 @@ def get_opencg_lattice(openmc_lattice):
for z in range(dimension[2]):
for y in range(dimension[1]):
for x in range(dimension[0]):
universe_id = universes[x][dimension[1]-y-1][z].id
universe_id = universes[z][y][x].id
universe_array[z][y][x] = unique_universes[universe_id]
opencg_lattice = opencg.Lattice(lattice_id, name)
@ -963,7 +977,7 @@ def get_openmc_lattice(opencg_lattice):
outer = opencg_lattice.outside
# Initialize an empty array for the OpenMC nested Universes in this Lattice
universe_array = np.ndarray(tuple(np.array(dimension)),
universe_array = np.ndarray(tuple(np.array(dimension)[::-1]),
dtype=openmc.Universe)
# Create OpenMC Universes for each unique nested Universe in this Lattice
@ -977,7 +991,7 @@ def get_openmc_lattice(opencg_lattice):
for y in range(dimension[1]):
for x in range(dimension[0]):
universe_id = universes[z][y][x].id
universe_array[x][y][z] = unique_universes[universe_id]
universe_array[z][y][x] = unique_universes[universe_id]
# Reverse y-dimension in array to match ordering in OpenCG
universe_array = universe_array[:, ::-1, :]

View file

@ -9,9 +9,9 @@ if sys.version > '3':
class StatePoint(object):
"""State information on a simulation at a certain point in time (at the end of a
given batch). Statepoints can be used to analyze tally results as well as
restart a simulation.
"""State information on a simulation at a certain point in time (at the end
of a given batch). Statepoints can be used to analyze tally results as well
as restart a simulation.
Attributes
----------
@ -75,6 +75,9 @@ class StatePoint(object):
energy of the source site.
source_present : bool
Indicate whether source sites are present
sparse : bool
Whether or not the tallies uses SciPy's LIL sparse matrix format for
compressed data storage
tallies : dict
Dictionary whose keys are tally IDs and whose values are Tally objects
tallies_present : bool
@ -110,6 +113,7 @@ class StatePoint(object):
self._tallies_read = False
self._summary = False
self._global_tallies = None
self._sparse = False
def close(self):
self._f.close()
@ -318,6 +322,10 @@ class StatePoint(object):
def source_present(self):
return self._f['source_present'].value > 0
@property
def sparse(self):
return self._sparse
@property
def tallies(self):
if not self._tallies_read:
@ -340,7 +348,8 @@ class StatePoint(object):
for tally_key in tally_keys:
# Read the Tally size specifications
n_realizations = self._f['{0}{1}/n_realizations'.format(base, tally_key)].value
n_realizations = \
self._f['{0}{1}/n_realizations'.format(base, tally_key)].value
# Create Tally object and assign basic properties
tally = openmc.Tally(tally_id=tally_key)
@ -350,7 +359,8 @@ class StatePoint(object):
tally.num_realizations = n_realizations
# Read the number of Filters
n_filters = self._f['{0}{1}/n_filters'.format(base, tally_key)].value
n_filters = \
self._f['{0}{1}/n_filters'.format(base, tally_key)].value
subbase = '{0}{1}/filter '.format(base, tally_key)
@ -358,10 +368,8 @@ class StatePoint(object):
for j in range(1, n_filters+1):
# Read the Filter type
filter_type = self._f['{0}{1}/type'.format(subbase, j)].value.decode()
# Read the Filter offset
offset = self._f['{0}{1}/offset'.format(subbase, j)].value
filter_type = \
self._f['{0}{1}/type'.format(subbase, j)].value.decode()
n_bins = self._f['{0}{1}/n_bins'.format(subbase, j)].value
@ -370,7 +378,6 @@ class StatePoint(object):
# Create Filter object
filter = openmc.Filter(filter_type, bins)
filter.offset = offset
filter.num_bins = n_bins
if filter_type == 'mesh':
@ -384,22 +391,18 @@ class StatePoint(object):
tally.add_filter(filter)
# Read Nuclide bins
nuclide_names = self._f['{0}{1}/nuclides'.format(base, tally_key)].value
nuclide_names = \
self._f['{0}{1}/nuclides'.format(base, tally_key)].value
# Add all Nuclides to the Tally
for name in nuclide_names:
nuclide = openmc.Nuclide(name.decode().strip())
tally.add_nuclide(nuclide)
# Read score bins
n_score_bins = self._f['{0}{1}/n_score_bins'.format(base, tally_key)].value
tally.num_score_bins = n_score_bins
scores = self._f['{0}{1}/score_bins'.format(
base, tally_key)].value
n_user_scores = self._f['{0}{1}/n_user_score_bins'
.format(base, tally_key)].value
n_score_bins = self._f['{0}{1}/n_score_bins'
.format(base, tally_key)].value
# Compute and set the filter strides
for i in range(n_filters):
@ -409,7 +412,7 @@ class StatePoint(object):
for j in range(i+1, n_filters):
filter.stride *= tally.filters[j].num_bins
# Read scattering moment order strings (e.g., P3, Y-1,2, etc.)
# Read scattering moment order strings (e.g., P3, Y1,2, etc.)
moments = self._f['{0}{1}/moment_orders'.format(
base, tally_key)].value
@ -424,6 +427,7 @@ class StatePoint(object):
tally.add_score(score)
# Add Tally to the global dictionary of all Tallies
tally.sparse = self.sparse
self._tallies[tally_key] = tally
self._tallies_read = True
@ -448,6 +452,26 @@ class StatePoint(object):
def with_summary(self):
return False if self.summary is None else True
@sparse.setter
def sparse(self, sparse):
"""Convert tally data from NumPy arrays to SciPy list of lists (LIL)
sparse matrices, and vice versa.
This property may be used to reduce the amount of data in memory during
tally data processing. The tally data will be stored as SciPy LIL
matrices internally within each Tally object. All tally data access
properties and methods will return data as a dense NumPy array.
"""
cv.check_type('sparse', sparse, bool)
self._sparse = sparse
# Update tally sparsities
if self._tallies_read:
for tally_id in self.tallies:
self.tallies[tally_id].sparse = self.sparse
def get_tally(self, scores=[], filters=[], nuclides=[],
name=None, id=None, estimator=None):
"""Finds and returns a Tally object with certain properties.

View file

@ -1,4 +1,5 @@
import numpy as np
import re
import openmc
from openmc.region import Region
@ -274,6 +275,11 @@ class Summary(object):
cell.region = Region.from_expression(
region, {s.id: s for s in self.surfaces.values()})
# Get the distribcell index
ind = self._f['geometry/cells'][key]['distribcell_index'].value
if ind != 0:
cell.distribcell_index = ind
# Add the Cell to the global dictionary of all Cells
self.cells[index] = cell
@ -332,11 +338,8 @@ class Summary(object):
self._f['geometry/lattices'][key]['lower_left'][...]
pitch = self._f['geometry/lattices'][key]['pitch'][...]
outer = self._f['geometry/lattices'][key]['outer'].value
universe_ids = \
self._f['geometry/lattices'][key]['universes'][...]
universe_ids = np.swapaxes(universe_ids, 0, 1)
universe_ids = np.swapaxes(universe_ids, 1, 2)
self._f['geometry/lattices'][key]['universes'][...]
# Create the Lattice
lattice = openmc.RectLattice(lattice_id=lattice_id, name=name)
@ -352,22 +355,22 @@ class Summary(object):
universes = \
np.ndarray(tuple(universe_ids.shape), dtype=openmc.Universe)
for x in range(universe_ids.shape[0]):
for z in range(universe_ids.shape[0]):
for y in range(universe_ids.shape[1]):
for z in range(universe_ids.shape[2]):
universes[x, y, z] = \
self.get_universe_by_id(universe_ids[x, y, z])
for x in range(universe_ids.shape[2]):
universes[z, y, x] = \
self.get_universe_by_id(universe_ids[z, y, x])
# Transpose, reverse y-dimension for appropriate ordering
shape = universes.shape
universes = np.transpose(universes, (1, 0, 2))
universes.shape = shape
universes = universes[:, ::-1, :]
# Use 2D NumPy array to store lattice universes for 2D lattices
if len(dimension) == 2:
universes = np.squeeze(universes)
universes = np.atleast_2d(universes)
# Set the universes for the lattice
lattice.universes = universes
if offsets is not None:
offsets = np.swapaxes(offsets, 0, 1)
offsets = np.swapaxes(offsets, 1, 2)
offsets = np.swapaxes(offsets, 0, 2)
lattice.offsets = offsets
# Add the Lattice to the global dictionary of all Lattices
@ -523,12 +526,18 @@ class Summary(object):
# Create Tally object and assign basic properties
tally = openmc.Tally(tally_id, tally_name)
# Read scattering moment order strings (e.g., P3, Y1,2, etc.)
moments = self._f['{0}/moment_orders'.format(subbase)].value
# Read score metadata
scores = self._f['{0}/score_bins'.format(subbase)].value
for score in scores:
tally.add_score(score.decode())
num_score_bins = self._f['{0}/n_score_bins'.format(subbase)][...]
tally.num_score_bins = num_score_bins
for j, score in enumerate(scores):
score = score.decode()
# If this is a moment, use generic moment order
pattern = r'-n$|-pn$|-yn$'
score = re.sub(pattern, '-' + moments[j].decode(), score)
tally.add_score(score)
# Read filter metadata
num_filters = self._f['{0}/n_filters'.format(subbase)].value

File diff suppressed because it is too large Load diff

View file

@ -63,6 +63,8 @@ class Cell(object):
that is used to translate (shift) the universe.
offsets : ndarray
Array of offsets used for distributed cell searches
distribcell_index : int
Index of this cell in distribcell arrays
"""
@ -76,6 +78,7 @@ class Cell(object):
self._rotation = None
self._translation = None
self._offsets = None
self._distribcell_index = None
def __eq__(self, other):
if not isinstance(other, Cell):
@ -122,6 +125,8 @@ class Cell(object):
string += '{0: <16}{1}{2}\n'.format('\tTranslation', '=\t',
self._translation)
string += '{0: <16}{1}{2}\n'.format('\tOffset', '=\t', self._offsets)
string += '{0: <16}{1}{2}\n'.format('\tDistribcell index', '=\t',
self._distribcell_index)
return string
@ -164,6 +169,10 @@ class Cell(object):
def offsets(self):
return self._offsets
@property
def distribcell_index(self):
return self._distribcell_index
@id.setter
def id(self, cell_id):
if cell_id is None:
@ -231,6 +240,11 @@ class Cell(object):
cv.check_type('cell region', region, Region)
self._region = region
@distribcell_index.setter
def distribcell_index(self, ind):
cv.check_type('distribcell index', ind, Integral)
self._distribcell_index = ind
def add_surface(self, surface, halfspace):
"""Add a half-space to the list of half-spaces whose intersection defines the
cell.
@ -271,7 +285,7 @@ class Cell(object):
else:
self.region = Intersection(self.region, region)
def get_offset(self, path, filter_offset):
def get_cell_instance(self, path, distribcell_index):
# Get the current element and remove it from the list
cell_id = path[0]
path = path[1:]
@ -282,12 +296,12 @@ class Cell(object):
# If the Cell is filled by a Universe
elif self._type == 'fill':
offset = self._offsets[filter_offset-1]
offset += self._fill.get_offset(path, filter_offset)
offset = self.offsets[distribcell_index-1]
offset += self.fill.get_cell_instance(path, distribcell_index)
# If the Cell is filled by a Lattice
else:
offset = self._fill.get_offset(path, filter_offset)
offset = self.fill.get_cell_instance(path, distribcell_index)
return offset
@ -591,7 +605,7 @@ class Universe(object):
self._cells.clear()
def get_offset(self, path, filter_offset):
def get_cell_instance(self, path, distribcell_index):
# Get the current element and remove it from the list
path = path[1:]
@ -599,7 +613,7 @@ class Universe(object):
cell_id = path[0]
# Make a recursive call to the Cell within this Universe
offset = self._cells[cell_id].get_offset(path, filter_offset)
offset = self.cells[cell_id].get_cell_instance(path, distribcell_index)
# Return the offset computed at all nested Universe levels
return offset
@ -807,7 +821,7 @@ class Lattice(object):
def universes(self, universes):
cv.check_iterable_type('lattice universes', universes, Universe,
min_depth=2, max_depth=3)
self._universes = universes
self._universes = np.asarray(universes)
def get_unique_universes(self):
"""Determine all unique universes in the lattice
@ -1059,21 +1073,22 @@ class RectLattice(Lattice):
cv.check_greater_than('lattice pitch', dim, 0.0)
self._pitch = pitch
def get_offset(self, path, filter_offset):
def get_cell_instance(self, path, distribcell_index):
# Get the current element and remove it from the list
i = path[0]
path = path[1:]
# For 2D Lattices
if len(self._dimension) == 2:
offset = self._offsets[i[1]-1, i[2]-1, 0, filter_offset-1]
offset += self._universes[i[1]][i[2]].get_offset(path, filter_offset)
offset = self._offsets[i[1]-1, i[2]-1, 0, distribcell_index-1]
offset += self._universes[i[1]-1][i[2]-1].get_cell_instance(path,
distribcell_index)
# For 3D Lattices
else:
offset = self._offsets[i[1]-1, i[2]-1, i[3]-1, filter_offset-1]
offset += self._universes[i[1]-1][i[2]-1][i[3]-1].get_offset(path,
filter_offset)
offset = self._offsets[i[1]-1, i[2]-1, i[3]-1, distribcell_index-1]
offset += self._universes[i[1]-1][i[2]-1][i[3]-1].get_cell_instance(
path, distribcell_index)
return offset
@ -1119,7 +1134,7 @@ class RectLattice(Lattice):
for z in range(self._dimension[2]):
for y in range(self._dimension[1]):
for x in range(self._dimension[0]):
universe = self._universes[x][y][z]
universe = self._universes[z][y][x]
# Append Universe ID to the Lattice XML subelement
universe_ids += '{0} '.format(universe._id)
@ -1137,7 +1152,7 @@ class RectLattice(Lattice):
else:
for y in range(self._dimension[1]):
for x in range(self._dimension[0]):
universe = self._universes[x][y]
universe = self._universes[y][x]
# Append Universe ID to Lattice XML subelement
universe_ids += '{0} '.format(universe._id)

View file

@ -37,6 +37,7 @@ if have_setuptools:
# Optional dependencies
'extras_require': {
'pandas': ['pandas'],
'sparse' : ['scipy'],
'vtk': ['vtk', 'silomesh'],
'validate': ['lxml']
}})

View file

@ -48,7 +48,7 @@ module ace_header
integer :: MT ! ENDF MT value
real(8) :: Q_value ! Reaction Q value
integer :: multiplicity ! Number of secondary particles released
type(Tab1), allocatable :: multiplicity_E ! Energy-dependent neutron yield
type(Tab1), pointer :: multiplicity_E => null() ! Energy-dependent neutron yield
integer :: threshold ! Energy grid index of threshold
logical :: scatter_in_cm ! scattering system in center-of-mass?
logical :: multiplicity_with_E = .false. ! Flag to indicate E-dependent multiplicity
@ -104,6 +104,8 @@ module ace_header
class(Reaction), intent(inout) :: this ! The Reaction object to clear
if (associated(this % multiplicity_E)) deallocate(this % multiplicity_E)
if (associated(this % edist)) then
call this % edist % clear()
deallocate(this % edist)

View file

@ -14,7 +14,7 @@ module constants
integer, parameter :: REVISION_STATEPOINT = 14
integer, parameter :: REVISION_PARTICLE_RESTART = 1
integer, parameter :: REVISION_TRACK = 1
integer, parameter :: REVISION_SUMMARY = 1
integer, parameter :: REVISION_SUMMARY = 2
! ============================================================================
! ADJUSTABLE PARAMETERS
@ -45,10 +45,11 @@ module constants
! Maximum number of words in a single line, length of line, and length of
! single word
integer, parameter :: MAX_WORDS = 500
integer, parameter :: MAX_LINE_LEN = 250
integer, parameter :: MAX_WORD_LEN = 150
integer, parameter :: MAX_FILE_LEN = 255
integer, parameter :: MAX_WORDS = 500
integer, parameter :: MAX_LINE_LEN = 250
integer, parameter :: MAX_WORD_LEN = 150
integer, parameter :: MAX_FILE_LEN = 255
integer, parameter :: REGION_SPEC_LEN = 1000
! Maximum number of external source spatial resamples to encounter before an
! error is thrown.

View file

@ -131,10 +131,13 @@ module geometry_header
integer, allocatable :: offset (:) ! Distribcell offset for tally
! counter
integer, allocatable :: region(:) ! Definition of spatial region as
! Boolean expression of half-spaces
! Boolean expression of half-spaces
integer, allocatable :: rpn(:) ! Reverse Polish notation for region
! expression
logical :: simple ! Is the region simple (intersections only)
! expression
logical :: simple ! Is the region simple (intersections
! only)
integer :: distribcell_index ! Index corresponding to this cell in
! distribcell arrays
! Rotation matrix and translation vector
real(8), allocatable :: translation(:)

View file

@ -1898,7 +1898,7 @@ contains
logical :: mpio
integer :: hdf5_err
integer :: driver
integer(HID_T) :: driver
integer(HID_T) :: file_id
integer(HID_T) :: fapl_id

View file

@ -1073,12 +1073,12 @@ contains
do i = 1, n_tallies
t => tallies(i)
do j = 1, t%n_filters
filter => t%filters(j)
do j = 1, t % n_filters
filter => t % filters(j)
if (filter%type == FILTER_DISTRIBCELL) then
if (.not. cell_list%contains(filter%int_bins(1))) then
call cell_list%add(filter%int_bins(1))
if (filter % type == FILTER_DISTRIBCELL) then
if (.not. cell_list % contains(filter % int_bins(1))) then
call cell_list % add(filter % int_bins(1))
end if
end if
@ -1089,8 +1089,8 @@ contains
! to determine the number of offset tables to allocate
do i = 1, n_universes
univ => universes(i)
do j = 1, univ%n_cells
if (cell_list%contains(univ%cells(j))) then
do j = 1, univ % n_cells
if (cell_list % contains(univ % cells(j))) then
n_maps = n_maps + 1
end if
end do
@ -1109,32 +1109,14 @@ contains
found(:,:) = .false.
k = 1
! Search through universes for distributed cells and assign each one a
! unique distribcell array index.
do i = 1, n_universes
univ => universes(i)
do j = 1, univ%n_cells
if (cell_list%contains(univ%cells(j))) then
! Loop over all tallies
do l = 1, n_tallies
t => tallies(l)
do m = 1, t%n_filters
filter => t%filters(m)
! Loop over only distribcell filters
! If filter points to cell we just found, set offset index
if (filter%type == FILTER_DISTRIBCELL) then
if (filter%int_bins(1) == univ%cells(j)) then
filter%offset = k
end if
end if
end do
end do
univ_list(k) = univ%id
do j = 1, univ % n_cells
if (cell_list % contains(univ % cells(j))) then
cells(univ % cells(j)) % distribcell_index = k
univ_list(k) = univ % id
k = k + 1
end if
end do
@ -1142,26 +1124,26 @@ contains
! Allocate the offset tables for lattices
do i = 1, n_lattices
lat => lattices(i)%obj
lat => lattices(i) % obj
select type(lat)
type is (RectLattice)
allocate(lat%offset(n_maps, lat%n_cells(1), lat%n_cells(2), &
lat%n_cells(3)))
allocate(lat % offset(n_maps, lat % n_cells(1), lat % n_cells(2), &
lat % n_cells(3)))
type is (HexLattice)
allocate(lat%offset(n_maps, 2 * lat%n_rings - 1, &
2 * lat%n_rings - 1, lat%n_axial))
allocate(lat % offset(n_maps, 2 * lat % n_rings - 1, &
2 * lat % n_rings - 1, lat % n_axial))
end select
lat%offset(:, :, :, :) = 0
lat % offset(:, :, :, :) = 0
end do
! Allocate offset table for fill cells
do i = 1, n_cells
if (cells(i)%material == NONE) then
allocate(cells(i)%offset(n_maps))
if (cells(i) % material == NONE) then
allocate(cells(i) % offset(n_maps))
end if
end do

View file

@ -1037,7 +1037,7 @@ contains
logical :: boundary_exists
character(MAX_LINE_LEN) :: filename
character(MAX_WORD_LEN) :: word
character(1000) :: region_spec
character(REGION_SPEC_LEN) :: region_spec
type(Cell), pointer :: c
class(Surface), pointer :: s
class(Lattice), pointer :: lat
@ -1092,8 +1092,9 @@ contains
do i = 1, n_cells
c => cells(i)
! Initialize the number of cell instances - this is a base case for distribcells
! Initialize distribcell instances and distribcell index
c % instances = 0
c % distribcell_index = NONE
! Get pointer to i-th cell node
call get_list_item(node_cell_list, i, node_cell)

View file

@ -1186,8 +1186,7 @@ contains
label = ''
univ => universes(BASE_UNIVERSE)
offset = 0
call find_offset(t % filters(i_filter) % offset, &
t % filters(i_filter) % int_bins(1), &
call find_offset(t % filters(i_filter) % int_bins(1), &
univ, bin-1, offset, label)
case (FILTER_SURFACE)
i = t % filters(i_filter) % int_bins(bin)
@ -1221,15 +1220,15 @@ contains
! with the given offset
!===============================================================================
recursive subroutine find_offset(map, goal, univ, final, offset, path)
recursive subroutine find_offset(goal, univ, final, offset, path)
integer, intent(in) :: map ! Index in maps vector
integer, intent(in) :: goal ! The target cell ID
integer, intent(in) :: goal ! The target cell index
type(Universe), intent(in) :: univ ! Universe to begin search
integer, intent(in) :: final ! Target offset
integer, intent(inout) :: offset ! Current offset
character(*), intent(inout) :: path ! Path to offset
integer :: map ! Index in maps vector
integer :: i, j ! Index over cells
integer :: k, l, m ! Indices in lattice
integer :: old_k, old_l, old_m ! Previous indices in lattice
@ -1244,6 +1243,9 @@ contains
type(Universe), pointer :: next_univ ! Next universe to loop through
class(Lattice), pointer :: lat ! Pointer to current lattice
! Get the distribcell index for this cell
map = cells(goal) % distribcell_index
n = univ % n_cells
! Write to the geometry stack
@ -1255,17 +1257,13 @@ contains
! Look through all cells in this universe
do i = 1, n
cell_index = univ % cells(i)
c => cells(cell_index)
! If the cell ID matches the goal and the offset matches final,
! write to the geometry stack
if (cell_dict % get_key(c % id) == goal .AND. offset == final) then
path = trim(path) // "->" // to_str(c%id)
! If the cell matches the goal and the offset matches final, write to the
! geometry stack
if (univ % cells(i) == goal .AND. offset == final) then
c => cells(univ % cells(i))
path = trim(path) // "->" // to_str(c % id)
return
end if
end do
! Find the fill cell or lattice cell that we need to enter
@ -1345,7 +1343,7 @@ contains
offset = c % offset(map) + offset
next_univ => universes(c % fill)
call find_offset(map, goal, next_univ, final, offset, path)
call find_offset(goal, next_univ, final, offset, path)
return
! ====================================================================
@ -1385,7 +1383,7 @@ contains
path = trim(path) // "(" // trim(to_str(k)) // &
"," // trim(to_str(l)) // "," // &
trim(to_str(m)) // ")"
call find_offset(map, goal, next_univ, final, offset, path)
call find_offset(goal, next_univ, final, offset, path)
return
else
old_m = m
@ -1401,7 +1399,7 @@ contains
path = trim(path) // "(" // trim(to_str(old_k)) // &
"," // trim(to_str(old_l)) // "," // &
trim(to_str(old_m)) // ")"
call find_offset(map, goal, next_univ, final, offset, path)
call find_offset(goal, next_univ, final, offset, path)
return
end if
@ -1446,8 +1444,7 @@ contains
trim(to_str(k - lat % n_rings)) // "," // &
trim(to_str(l - lat % n_rings)) // "," // &
trim(to_str(m)) // ")"
call find_offset(map, goal, next_univ, final, offset, &
path)
call find_offset(goal, next_univ, final, offset, path)
return
else
old_m = m
@ -1464,7 +1461,7 @@ contains
trim(to_str(old_k - lat % n_rings)) // "," // &
trim(to_str(old_l - lat % n_rings)) // "," // &
trim(to_str(old_m)) // ")"
call find_offset(map, goal, next_univ, final, offset, path)
call find_offset(goal, next_univ, final, offset, path)
return
end if

View file

@ -274,7 +274,6 @@ contains
call write_dataset(filter_group, "type", "delayedgroup")
end select
call write_dataset(filter_group, "offset", tally%filters(j)%offset)
call write_dataset(filter_group, "n_bins", tally%filters(j)%n_bins)
if (tally % filters(j) % type == FILTER_ENERGYIN .or. &
tally % filters(j) % type == FILTER_ENERGYOUT .or. &

View file

@ -120,7 +120,7 @@ contains
integer(HID_T) :: universes_group, univ_group
integer(HID_T) :: lattices_group, lattice_group
real(8), allocatable :: coeffs(:)
character(MAX_LINE_LEN) :: region_spec
character(REGION_SPEC_LEN) :: region_spec
type(Cell), pointer :: c
class(Surface), pointer :: s
type(Universe), pointer :: u
@ -203,6 +203,8 @@ contains
end do
call write_dataset(cell_group, "region", adjustl(region_spec))
call write_dataset(cell_group, "distribcell_index", c % distribcell_index)
call close_group(cell_group)
end do CELL_LOOP
@ -362,16 +364,22 @@ contains
call write_dataset(lattice_group, "type", "rectangular")
! Write lattice dimensions, lower left corner, and pitch
call write_dataset(lattice_group, "dimension", lat%n_cells)
call write_dataset(lattice_group, "lower_left", lat%lower_left)
if (lat % is_3d) then
call write_dataset(lattice_group, "dimension", lat % n_cells)
call write_dataset(lattice_group, "lower_left", lat % lower_left)
else
call write_dataset(lattice_group, "dimension", lat % n_cells(1:2))
call write_dataset(lattice_group, "lower_left", lat % lower_left)
end if
! Write lattice universes.
allocate(lattice_universes(lat%n_cells(1), lat%n_cells(2), &
&lat%n_cells(3)))
do j = 1, lat%n_cells(1)
do k = 1, lat%n_cells(2)
do k = 0, lat%n_cells(2) - 1
do m = 1, lat%n_cells(3)
lattice_universes(j,k,m) = universes(lat%universes(j,k,m))%id
lattice_universes(j, k+1, m) = &
universes(lat%universes(j, lat%n_cells(2) - k, m))%id
end do
end do
end do
@ -495,8 +503,10 @@ contains
subroutine write_tallies(file_id)
integer(HID_T), intent(in) :: file_id
integer :: i, j
integer :: i, j, k
integer :: i_list, i_xs
integer :: n_order ! loop index for moment orders
integer :: nm_order ! loop index for Ynm moment orders
integer(HID_T) :: tallies_group
integer(HID_T) :: mesh_group
integer(HID_T) :: tally_group
@ -551,7 +561,6 @@ contains
filter_group = create_group(tally_group, "filter " // trim(to_str(j)))
! Write number of bins for this filter
call write_dataset(filter_group, "offset", t%filters(j)%offset)
call write_dataset(filter_group, "n_bins", t%filters(j)%n_bins)
! Write filter bins
@ -675,6 +684,37 @@ contains
deallocate(str_array)
! Write explicit moment order strings for each score bin
k = 1
allocate(str_array(t%n_score_bins))
MOMENT_LOOP: do j = 1, t%n_user_score_bins
select case(t%score_bins(k))
case (SCORE_SCATTER_N, SCORE_NU_SCATTER_N)
str_array(k) = 'P' // trim(to_str(t%moment_order(k)))
k = k + 1
case (SCORE_SCATTER_PN, SCORE_NU_SCATTER_PN)
do n_order = 0, t%moment_order(k)
str_array(k) = 'P' // trim(to_str(n_order))
k = k + 1
end do
case (SCORE_SCATTER_YN, SCORE_NU_SCATTER_YN, SCORE_FLUX_YN, &
SCORE_TOTAL_YN)
do n_order = 0, t%moment_order(k)
do nm_order = -n_order, n_order
str_array(k) = 'Y' // trim(to_str(n_order)) // ',' // &
trim(to_str(nm_order))
k = k + 1
end do
end do
case default
str_array(k) = ''
k = k + 1
end select
end do MOMENT_LOOP
call write_dataset(tally_group, "moment_orders", str_array)
deallocate(str_array)
call close_group(tally_group)
end do TALLY_METADATA

View file

@ -2276,6 +2276,7 @@ contains
integer :: j
integer :: n ! number of bins for single filter
integer :: offset ! offset for distribcell
integer :: distribcell_index ! index in distribcell arrays
real(8) :: E ! particle energy
real(8) :: theta, phi ! Polar and Azimuthal Angles, respectively
type(TallyObject), pointer :: t
@ -2320,12 +2321,14 @@ contains
case (FILTER_DISTRIBCELL)
! determine next distribcell bin
distribcell_index = cells(t % filters(i) % int_bins(1)) &
% distribcell_index
matching_bins(i) = NO_BIN_FOUND
offset = 0
do j = 1, p % n_coord
if (cells(p % coord(j) % cell) % type == CELL_FILL) then
offset = offset + cells(p % coord(j) % cell) % &
offset(t % filters(i) % offset)
offset(distribcell_index)
elseif(cells(p % coord(j) % cell) % type == CELL_LATTICE) then
if (lattices(p % coord(j + 1) % lattice) % obj &
% are_valid_indices([&
@ -2333,7 +2336,7 @@ contains
p % coord(j + 1) % lattice_y, &
p % coord(j + 1) % lattice_z])) then
offset = offset + lattices(p % coord(j + 1) % lattice) % obj % &
offset(t % filters(i) % offset, &
offset(distribcell_index, &
p % coord(j + 1) % lattice_x, &
p % coord(j + 1) % lattice_y, &
p % coord(j + 1) % lattice_z)

View file

@ -55,7 +55,6 @@ module tally_header
type TallyFilter
integer :: type = NONE
integer :: n_bins = 0
integer :: offset = 0 ! Only used for distribcell filters
integer, allocatable :: int_bins(:)
real(8), allocatable :: real_bins(:) ! Only used for energy filters
end type TallyFilter

View file

@ -11,18 +11,6 @@ tally 1:
2.483728E+01
5.102293E-01
8.710841E-02
8.628000E+00
2.481430E+01
9.329009E-01
2.902534E-01
5.102293E-01
8.710841E-02
5.087118E-01
8.657086E-02
8.632000E+00
2.483728E+01
9.328366E-01
2.902108E-01
5.087118E-01
8.657086E-02
9.212024E+00

View file

@ -4,9 +4,9 @@
<tally id="1">
<filter type="cell" bins="21" />
<scores>
flux total scatter nu-scatter scatter-2 scatter-p2 nu-scatter-2
nu-scatter-p2 transport n1n absorption nu-fission kappa-fission
flux-y2 total-y2 scatter-y2 nu-scatter-y2 events delayed-nu-fission
flux total scatter nu-scatter scatter-2 nu-scatter-2 transport n1n
absorption nu-fission kappa-fission flux-y2 total-y2 scatter-y2
nu-scatter-y2 events delayed-nu-fission
</scores>
</tally>

View file

@ -1 +1 @@
63295b9d510370e65e63a3db627d47d286f5479e53c8eabeda9a5cb25ffe35becb636835aadad11691e34c23292fe11b5f688daee76d76ceac4b5dfd2f9ede4c
7270299e4a4dde19d250825b0124fa36b60df847f046e058ccdfc74d4690beaaaaf387e050f596cb3445caf793d6a390ddb2d19650a3dccd4eb60056ae3b1477

View file

@ -7,10 +7,6 @@ tally 1:
0.000000E+00
0.000000E+00
0.000000E+00
0.000000E+00
0.000000E+00
1.538090E-03
1.381456E-06
1.538090E-03
1.381456E-06
3.974412E-01
@ -19,16 +15,12 @@ tally 1:
3.796357E-01
5.252455E-06
2.290531E-11
5.252455E-06
2.290531E-11
3.359792E-02
2.267331E-04
2.459115E-02
1.233078E-04
0.000000E+00
0.000000E+00
0.000000E+00
0.000000E+00
7.004005E-05
1.748739E-09
8.104946E-02
@ -42,18 +34,12 @@ tally 2:
0.000000E+00
0.000000E+00
0.000000E+00
0.000000E+00
0.000000E+00
0.000000E+00
0.000000E+00
2.000000E-01
9.000000E-03
0.000000E+00
0.000000E+00
0.000000E+00
0.000000E+00
0.000000E+00
0.000000E+00
2.000000E-02
2.000000E-04
0.000000E+00
@ -64,8 +50,6 @@ tally 2:
0.000000E+00
0.000000E+00
0.000000E+00
0.000000E+00
0.000000E+00
tally 3:
0.000000E+00
0.000000E+00
@ -73,10 +57,6 @@ tally 3:
0.000000E+00
0.000000E+00
0.000000E+00
0.000000E+00
0.000000E+00
1.408027E-03
1.849607E-06
1.408027E-03
1.849607E-06
3.946436E-01
@ -85,16 +65,12 @@ tally 3:
3.382059E-01
2.179241E-05
4.749090E-10
2.179241E-05
4.749090E-10
3.146594E-02
2.159308E-04
4.278352E-02
4.094478E-04
0.000000E+00
0.000000E+00
0.000000E+00
0.000000E+00
1.736514E-04
1.245171E-08
7.989710E-02

View file

@ -12,7 +12,6 @@ class ScoreMTTestHarness(PyAPITestHarness):
filt = openmc.Filter(type='cell', bins=(10, 21, 22, 23))
tallies = [openmc.Tally(tally_id=i) for i in range(1, 4)]
[t.add_filter(filt) for t in tallies]
[t.add_score('n2n') for t in tallies]
[t.add_score('16') for t in tallies]
[t.add_score('51') for t in tallies]
[t.add_score('102') for t in tallies]

View file

@ -0,0 +1 @@
df6318b76cd37a29ef9dd09da48a70c191ed07c1a2ceb75eb502ab35086c31250872406f22c2587edfcee16f67dd95c81db012ccd728710ed2509084438aea56

View file

@ -0,0 +1,134 @@
[[[ 8.90240785e-05 8.31464209e-11 4.41507090e-05 4.12357364e-11]
[ 7.29618709e-05 5.98879928e-05 3.61847984e-05 2.97009235e-05]
[ 4.69276830e-05 4.38293656e-11 2.35903380e-05 2.20328275e-11]
[ 3.84607356e-05 3.15690405e-05 1.93340411e-05 1.58696166e-05]]
[[ 8.90240785e-05 8.31464209e-11 4.41507090e-05 4.12357364e-11]
[ 7.29618709e-05 5.98879928e-05 3.61847984e-05 2.97009235e-05]
[ 4.69276830e-05 4.38293656e-11 2.35903380e-05 2.20328275e-11]
[ 3.84607356e-05 3.15690405e-05 1.93340411e-05 1.58696166e-05]]
[[ 8.90240785e-05 8.31464209e-11 4.41507090e-05 4.12357364e-11]
[ 7.29618709e-05 5.98879928e-05 3.61847984e-05 2.97009235e-05]
[ 4.69276830e-05 4.38293656e-11 2.35903380e-05 2.20328275e-11]
[ 3.84607356e-05 3.15690405e-05 1.93340411e-05 1.58696166e-05]]
...,
[[ 0.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00]
[ 0.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00]
[ 0.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00]
[ 0.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00]]
[[ 0.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00]
[ 0.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00]
[ 0.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00]
[ 0.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00]]
[[ 0.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00]
[ 0.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00]
[ 0.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00]
[ 0.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00]]][[[ 8.90240785e-05 8.31464209e-11 4.41507090e-05 4.12357364e-11]
[ 7.29618709e-05 5.98879928e-05 3.61847984e-05 2.97009235e-05]
[ 4.69276830e-05 4.38293656e-11 2.35903380e-05 2.20328275e-11]
[ 3.84607356e-05 3.15690405e-05 1.93340411e-05 1.58696166e-05]]
[[ 8.90240785e-05 8.31464209e-11 4.41507090e-05 4.12357364e-11]
[ 7.29618709e-05 5.98879928e-05 3.61847984e-05 2.97009235e-05]
[ 4.69276830e-05 4.38293656e-11 2.35903380e-05 2.20328275e-11]
[ 3.84607356e-05 3.15690405e-05 1.93340411e-05 1.58696166e-05]]
[[ 8.90240785e-05 8.31464209e-11 4.41507090e-05 4.12357364e-11]
[ 7.29618709e-05 5.98879928e-05 3.61847984e-05 2.97009235e-05]
[ 4.69276830e-05 4.38293656e-11 2.35903380e-05 2.20328275e-11]
[ 3.84607356e-05 3.15690405e-05 1.93340411e-05 1.58696166e-05]]
...,
[[ 0.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00]
[ 0.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00]
[ 0.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00]
[ 0.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00]]
[[ 0.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00]
[ 0.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00]
[ 0.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00]
[ 0.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00]]
[[ 0.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00]
[ 0.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00]
[ 0.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00]
[ 0.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00]]][[[ 7.29618709e-05 5.98879928e-05 3.61847984e-05 2.97009235e-05]
[ 0.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00]
[ 0.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00]]
[[ 7.29618709e-05 5.98879928e-05 3.61847984e-05 2.97009235e-05]
[ 0.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00]
[ 0.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00]]
[[ 7.29618709e-05 5.98879928e-05 3.61847984e-05 2.97009235e-05]
[ 0.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00]
[ 0.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00]]
...,
[[ 0.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00]
[ 0.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00]
[ 0.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00]]
[[ 0.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00]
[ 0.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00]
[ 0.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00]]
[[ 0.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00]
[ 0.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00]
[ 0.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00]]][[[ 0.00000000e+00 4.41507090e-05 0.00000000e+00]
[ 0.00000000e+00 3.61847984e-05 0.00000000e+00]
[ 0.00000000e+00 2.35903380e-05 0.00000000e+00]
[ 0.00000000e+00 1.93340411e-05 0.00000000e+00]]
[[ 0.00000000e+00 4.41507090e-05 0.00000000e+00]
[ 0.00000000e+00 3.61847984e-05 0.00000000e+00]
[ 0.00000000e+00 2.35903380e-05 0.00000000e+00]
[ 0.00000000e+00 1.93340411e-05 0.00000000e+00]]
[[ 0.00000000e+00 4.41507090e-05 0.00000000e+00]
[ 0.00000000e+00 3.61847984e-05 0.00000000e+00]
[ 0.00000000e+00 2.35903380e-05 0.00000000e+00]
[ 0.00000000e+00 1.93340411e-05 0.00000000e+00]]
...,
[[ 0.00000000e+00 0.00000000e+00 0.00000000e+00]
[ 0.00000000e+00 0.00000000e+00 0.00000000e+00]
[ 0.00000000e+00 0.00000000e+00 0.00000000e+00]
[ 0.00000000e+00 0.00000000e+00 0.00000000e+00]]
[[ 0.00000000e+00 0.00000000e+00 0.00000000e+00]
[ 0.00000000e+00 0.00000000e+00 0.00000000e+00]
[ 0.00000000e+00 0.00000000e+00 0.00000000e+00]
[ 0.00000000e+00 0.00000000e+00 0.00000000e+00]]
[[ 0.00000000e+00 0.00000000e+00 0.00000000e+00]
[ 0.00000000e+00 0.00000000e+00 0.00000000e+00]
[ 0.00000000e+00 0.00000000e+00 0.00000000e+00]
[ 0.00000000e+00 0.00000000e+00 0.00000000e+00]]][[[ 0.00000000e+00 3.61847984e-05 0.00000000e+00]
[ 0.00000000e+00 0.00000000e+00 0.00000000e+00]
[ 0.00000000e+00 0.00000000e+00 0.00000000e+00]]
[[ 0.00000000e+00 3.61847984e-05 0.00000000e+00]
[ 0.00000000e+00 0.00000000e+00 0.00000000e+00]
[ 0.00000000e+00 0.00000000e+00 0.00000000e+00]]
[[ 0.00000000e+00 3.61847984e-05 0.00000000e+00]
[ 0.00000000e+00 0.00000000e+00 0.00000000e+00]
[ 0.00000000e+00 0.00000000e+00 0.00000000e+00]]
...,
[[ 0.00000000e+00 0.00000000e+00 0.00000000e+00]
[ 0.00000000e+00 0.00000000e+00 0.00000000e+00]
[ 0.00000000e+00 0.00000000e+00 0.00000000e+00]]
[[ 0.00000000e+00 0.00000000e+00 0.00000000e+00]
[ 0.00000000e+00 0.00000000e+00 0.00000000e+00]
[ 0.00000000e+00 0.00000000e+00 0.00000000e+00]]
[[ 0.00000000e+00 0.00000000e+00 0.00000000e+00]
[ 0.00000000e+00 0.00000000e+00 0.00000000e+00]
[ 0.00000000e+00 0.00000000e+00 0.00000000e+00]]]

View file

@ -0,0 +1,120 @@
#!/usr/bin/env python
import os
import sys
import glob
import hashlib
sys.path.insert(0, os.pardir)
from testing_harness import PyAPITestHarness
import openmc
class TallyArithmeticTestHarness(PyAPITestHarness):
def _build_inputs(self):
# The summary.h5 file needs to be created to read in the tallies
self._input_set.settings.output = {'summary': True}
# Initialize the tallies file
tallies_file = openmc.TalliesFile()
# Initialize the nuclides
u235 = openmc.Nuclide('U-235')
u238 = openmc.Nuclide('U-238')
pu239 = openmc.Nuclide('Pu-239')
# Initialize Mesh
mesh = openmc.Mesh(mesh_id=1)
mesh.type = 'regular'
mesh.dimension = [2, 2, 2]
mesh.lower_left = [-160.0, -160.0, -183.0]
mesh.upper_right = [160.0, 160.0, 183.0]
# Initialize the filters
energy_filter = openmc.Filter(type='energy', bins=(0.0, 0.253e-6,
1.0e-3, 1.0, 20.0))
material_filter = openmc.Filter(type='material', bins=(1, 3))
distrib_filter = openmc.Filter(type='distribcell', bins=(60))
mesh_filter = openmc.Filter(type='mesh')
mesh_filter.mesh = mesh
# Initialized the tallies
tally = openmc.Tally(name='tally 1')
tally.add_filter(material_filter)
tally.add_filter(energy_filter)
tally.add_filter(distrib_filter)
tally.add_score('nu-fission')
tally.add_score('total')
tally.add_nuclide(u235)
tally.add_nuclide(pu239)
tallies_file.add_tally(tally)
tally = openmc.Tally(name='tally 2')
tally.add_filter(energy_filter)
tally.add_filter(mesh_filter)
tally.add_score('total')
tally.add_score('fission')
tally.add_nuclide(u238)
tally.add_nuclide(u235)
tallies_file.add_tally(tally)
tallies_file.add_mesh(mesh)
# Export tallies to file
self._input_set.tallies = tallies_file
super(TallyArithmeticTestHarness, self)._build_inputs()
def _get_results(self, hash_output=False):
"""Digest info in the statepoint and return as a string."""
# Read the statepoint file.
statepoint = glob.glob(os.path.join(os.getcwd(), self._sp_name))[0]
sp = openmc.StatePoint(statepoint)
# Read the summary file.
summary = glob.glob(os.path.join(os.getcwd(), 'summary.h5'))[0]
su = openmc.Summary(summary)
sp.link_with_summary(su)
# Load the tallies
tally_1 = sp.get_tally(name='tally 1')
tally_2 = sp.get_tally(name='tally 2')
# Perform all the tally arithmetic operations and output results
outstr = ''
tally_3 = tally_1 * tally_2
outstr += str(tally_3.mean)
tally_3 = tally_1.hybrid_product(tally_2, '*', 'entrywise', 'tensor',
'tensor')
outstr += str(tally_3.mean)
tally_3 = tally_1.hybrid_product(tally_2, '*', 'entrywise', 'entrywise',
'tensor')
outstr += str(tally_3.mean)
tally_3 = tally_1.hybrid_product(tally_2, '*', 'entrywise', 'tensor',
'entrywise')
outstr += str(tally_3.mean)
tally_3 = tally_1.hybrid_product(tally_2, '*', 'entrywise', 'entrywise',
'entrywise')
outstr += str(tally_3.mean)
print(outstr)
# Hash the results if necessary
if hash_output:
sha512 = hashlib.sha512()
sha512.update(outstr.encode('utf-8'))
outstr = sha512.hexdigest()
return outstr
def _cleanup(self):
super(TallyArithmeticTestHarness, self)._cleanup()
f = os.path.join(os.getcwd(), 'tallies.xml')
if os.path.exists(f): os.remove(f)
if __name__ == '__main__':
harness = TallyArithmeticTestHarness('statepoint.10.h5', True)
harness.main()