mirror of
https://github.com/openmc-dev/openmc.git
synced 2026-07-28 06:05:58 -04:00
Merge remote-tracking branch 'upstream/develop' into mg
This commit is contained in:
commit
ff27852c51
46 changed files with 1283 additions and 595 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
|
@ -24,6 +24,7 @@ examples/python/**/*.xml
|
|||
# Documentation builds
|
||||
docs/build
|
||||
docs/source/_images/*.pdf
|
||||
docs/source/_images/*.aux
|
||||
|
||||
# Source build
|
||||
build
|
||||
|
|
|
|||
|
|
@ -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)/*
|
||||
|
|
|
|||
2
docs/requirements-rtd.txt
Normal file
2
docs/requirements-rtd.txt
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
sphinx-numfig
|
||||
jupyter
|
||||
BIN
docs/source/_images/cmfd_flow.png
Normal file
BIN
docs/source/_images/cmfd_flow.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 25 KiB |
|
|
@ -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}
|
||||
BIN
docs/source/_images/meshfig.png
Normal file
BIN
docs/source/_images/meshfig.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 46 KiB |
|
|
@ -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}
|
||||
BIN
docs/source/_images/openmc200px.png
Normal file
BIN
docs/source/_images/openmc200px.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 6.8 KiB |
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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):
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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, :]
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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
|
|
@ -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)
|
||||
|
|
|
|||
1
setup.py
1
setup.py
|
|
@ -37,6 +37,7 @@ if have_setuptools:
|
|||
# Optional dependencies
|
||||
'extras_require': {
|
||||
'pandas': ['pandas'],
|
||||
'sparse' : ['scipy'],
|
||||
'vtk': ['vtk', 'silomesh'],
|
||||
'validate': ['lxml']
|
||||
}})
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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(:)
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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. &
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
63295b9d510370e65e63a3db627d47d286f5479e53c8eabeda9a5cb25ffe35becb636835aadad11691e34c23292fe11b5f688daee76d76ceac4b5dfd2f9ede4c
|
||||
7270299e4a4dde19d250825b0124fa36b60df847f046e058ccdfc74d4690beaaaaf387e050f596cb3445caf793d6a390ddb2d19650a3dccd4eb60056ae3b1477
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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]
|
||||
|
|
|
|||
1
tests/test_tally_arithmetic/inputs_true.dat
Normal file
1
tests/test_tally_arithmetic/inputs_true.dat
Normal file
|
|
@ -0,0 +1 @@
|
|||
df6318b76cd37a29ef9dd09da48a70c191ed07c1a2ceb75eb502ab35086c31250872406f22c2587edfcee16f67dd95c81db012ccd728710ed2509084438aea56
|
||||
134
tests/test_tally_arithmetic/results_true.dat
Normal file
134
tests/test_tally_arithmetic/results_true.dat
Normal 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]]]
|
||||
120
tests/test_tally_arithmetic/test_tally_arithmetic.py
Normal file
120
tests/test_tally_arithmetic/test_tally_arithmetic.py
Normal 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()
|
||||
Loading…
Add table
Add a link
Reference in a new issue