mirror of
https://github.com/openmc-dev/openmc.git
synced 2026-07-28 22:26:08 -04:00
Merge remote-tracking branch 'upstream/develop' into distribcell_mats
This commit is contained in:
commit
948fbdd73a
53 changed files with 1415 additions and 658 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']
|
||||
|
||||
|
|
@ -55,7 +74,7 @@ copyright = u'2011-2015, Massachusetts Institute of Technology'
|
|||
# The short X.Y version.
|
||||
version = "0.7"
|
||||
# The full version, including alpha/beta/rc tags.
|
||||
release = "0.7.0"
|
||||
release = "0.7.1"
|
||||
|
||||
# The language for content autogenerated by Sphinx. Refer to documentation
|
||||
# for a list of supported languages.
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -26,6 +26,10 @@ Overviews
|
|||
Benchmarking
|
||||
------------
|
||||
|
||||
- Khurrum S. Chaudri and Sikander M. Mirza, "Burnup dependent Monte Carlo
|
||||
neutron physics calculations of IAEA MTR benchmark," *Prog. Nucl. Energy*,
|
||||
**81**, 43-52 (2015). `<http://dx.doi.org/j.pnucene.2014.12.018>`_
|
||||
|
||||
- Daniel J. Kelly, Brian N. Aviles, Paul K. Romano, Bryan R. Herman,
|
||||
Nicholas E. Horelik, and Benoit Forget, "Analysis of select BEAVRS PWR
|
||||
benchmark cycle 1 results using MC21 and OpenMC," *Proc. PHYSOR*, Kyoto,
|
||||
|
|
@ -57,13 +61,8 @@ Coupling and Multi-physics
|
|||
|
||||
- Bryan R. Herman, Benoit Forget, and Kord Smith, "Progress toward Monte
|
||||
Carlo-thermal hydraulic coupling using low-order nonlinear diffusion
|
||||
acceleration methods." In press, *Ann. Nucl. Energy*,
|
||||
(2014). `<http://dx.doi.org/10.1016/j.anucene/2014.10.029>`_
|
||||
|
||||
- Adam G. Nelson and William R. Martin, "Improved Convergence of Monte Carlo
|
||||
Generated Multi-Group Scattering Moments," *Proc. Int. Conf. Mathematics and
|
||||
Computational Methods Applied to Nuclear Science and Engineering*, Sun Valley,
|
||||
Idaho, May 5--9 (2013).
|
||||
acceleration methods." *Ann. Nucl. Energy*, **84**, 63-72
|
||||
(2015). `<http://dx.doi.org/10.1016/j.anucene.2014.10.029>`_
|
||||
|
||||
- Bryan R. Herman, Benoit Forget, and Kord Smith, "Utilizing CMFD in OpenMC to
|
||||
Estimate Dominance Ratio and Adjoint," *Trans. Am. Nucl. Soc.*, **109**,
|
||||
|
|
@ -81,19 +80,65 @@ Geometry
|
|||
Miscellaneous
|
||||
-------------
|
||||
|
||||
- William Boyd, Sterling Harper, and Paul K. Romano, "Equipping OpenMC for the
|
||||
big data era," Accepted, *PHYSOR 2016*, Sun Valley, Idaho, May 1-5, 2016.
|
||||
|
||||
- Qicang Shen, William Boyd, Benoit Forget, and Kord Smith, "Tally precision
|
||||
triggers for the OpenMC Monte Carlo code," *Trans. Am. Nucl. Soc.*, **112**,
|
||||
637-640 (2015).
|
||||
|
||||
- Timothy P. Burke, Brian C. Kiedrowski, and William R. Martin, "Flux and
|
||||
Reaction Rate Kernel Density Estimators in OpenMC," *Trans. Am. Nucl. Soc.*,
|
||||
**109**, 683-686 (2013).
|
||||
|
||||
------------------------------------
|
||||
Multi-group Cross Section Generation
|
||||
------------------------------------
|
||||
|
||||
- Adam G. Nelson and William R. Martin, "Improved Monte Carlo tallying of
|
||||
multi-group scattering moments using the NDPP code," *Trans. Am. Nucl. Soc.*,
|
||||
**113**, 645-648 (2015)
|
||||
|
||||
- Adam G. Nelson and William R. Martin, "Improved Monte Carlo tallying of
|
||||
multi-group scattering moment matrices," *Trans. Am. Nucl. Soc.*, **110**,
|
||||
217-220 (2014).
|
||||
|
||||
- Adam G. Nelson and William R. Martin, "Improved Convergence of Monte Carlo
|
||||
Generated Multi-Group Scattering Moments," *Proc. Int. Conf. Mathematics and
|
||||
Computational Methods Applied to Nuclear Science and Engineering*, Sun Valley,
|
||||
Idaho, May 5--9 (2013).
|
||||
|
||||
------------
|
||||
Nuclear Data
|
||||
------------
|
||||
|
||||
- Colin Josey, Pablo Ducru, Benoit Forget, and Kord Smith, "Windowed multipole
|
||||
for cross section Doppler broadening," *J. Comput. Phys.*, In Press
|
||||
(2016). `<http://dx.doi.org/10.1016/jcp.2015.08.013>`_
|
||||
|
||||
- Colin Josey, Benoit Forget, and Kord Smith, "Windowed multipole sensitivity to
|
||||
target accuracy of the optimization procedure," *J. Nucl. Sci. Technol.*,
|
||||
**52**, 987-992 (2015). `<http://dx.doi.org/10.1080/00223131.2015.1035353>`_
|
||||
|
||||
- Jonathan A. Walsh, Paul K. Romano, Benoit Forget, and Kord S. Smith,
|
||||
"Optimizations of the energy grid search algorithm in continuous-energy Monte
|
||||
Carlo particle transport codes", *Comput. Phys. Commun.*, **196**, 134-142
|
||||
(2015). `<http://dx.doi.org/10.1016/j.cpc.2015.05.025>`_
|
||||
|
||||
- Jonathan A. Walsh, Benoit Forget, Kord S. Smith, Brian C. Kiedrowski, and
|
||||
Forrest B. Brown, "Direct, on-the-fly calculation of unresolved resonance
|
||||
region cross sections in Monte Carlo simulations," *Proc. Joint
|
||||
Int. Conf. M&C+SNA+MC*, Nashville, Tennessee, Apr. 19--23 (2015).
|
||||
|
||||
- Amanda L. Lund, Andrew R. Siegel, Benoit Forget, Colin Josey, and
|
||||
Paul K. Romano, "Using fractional cascading to accelerate cross section
|
||||
lookups in Monte Carlo particle transport calculations," *Proc. Joint
|
||||
Int. Conf. M&C+SNA+MC*, Nashville, Tennessee, Apr. 19--23 (2015).
|
||||
|
||||
- Ronald O. Rahaman, Andrew R. Siegel, and Paul K. Romano, "Monte Carlo
|
||||
performance analysis for varying cross section parameter regimes,"
|
||||
*Proc. Joint Int. Conf. M&C+SNA+MC*, Nashville, Tennessee, Apr. 19--23 (2015).
|
||||
|
||||
- Paul K. Romano and Timothy H. Trumbull, "Comparison of algorithms for Doppler
|
||||
broadening pointwise tabulated cross sections," *Ann. Nucl. Energy*, **75**,
|
||||
358--364 (2015). `<http://dx.doi.org/10.1016/j.anucene.2014.08.046>`_
|
||||
|
|
@ -114,6 +159,10 @@ Nuclear Data
|
|||
Parallelism
|
||||
-----------
|
||||
|
||||
- Paul K. Romano, John R. Tramm, and Andrew R. Siegel, "Efficacy of hardware
|
||||
threading for Monte Carlo particle transport calculations on multi- and
|
||||
many-core systems," Accepted, *PHYSOR 2016*, Sun Valley, Idaho, May 1-5, 2016.
|
||||
|
||||
- David Ozog, Allen D. Malony, and Andrew R. Siegel, "A performance analysis of
|
||||
SIMD algorithms for Monte Carlo simulations of nuclear reactor cores,"
|
||||
*Proc. IEEE Int. Parallel and Distributed Processing Symposium*, Hyderabad,
|
||||
|
|
|
|||
|
|
@ -1,9 +1,30 @@
|
|||
.. _releasenotes:
|
||||
|
||||
==============================
|
||||
Release Notes for OpenMC 0.7.0
|
||||
Release Notes for OpenMC 0.7.1
|
||||
==============================
|
||||
|
||||
This release of OpenMC provides some substantial improvements over version
|
||||
0.7.0. Non-simple cell regions can now be defined through the ``|`` (union) and
|
||||
``~`` (complement) operators. Similar changes in the Python API also allow
|
||||
complex cell regions to be defined. A true secondary particle bank now exists;
|
||||
this is crucial for photon transport (to be added in the next minor release). A
|
||||
rich API for multi-group cross section generation has been added via the
|
||||
``openmc.mgxs`` Python module.
|
||||
|
||||
Various improvements to tallies have also been made. It is now possible to
|
||||
explicitly specify that a collision estimator be used in a tally. A new
|
||||
``delayedgroup`` filter and ``delayed-nu-fission`` score allow a user to obtain
|
||||
delayed fission neutron production rates filtered by delayed group. Finally, the
|
||||
new ``inverse-velocity`` score may be useful for calculating kinetics
|
||||
parameters.
|
||||
|
||||
.. caution:: In previous versions, depending on how OpenMC was compiled binary
|
||||
output was either given in HDF5 or a flat binary format. With this
|
||||
version, all binary output is now HDF5 which means you **must**
|
||||
have HDF5 in order to install OpenMC. Please consult the user's
|
||||
guide for instructions on how to compile with HDF5.
|
||||
|
||||
-------------------
|
||||
System Requirements
|
||||
-------------------
|
||||
|
|
@ -17,36 +38,41 @@ the problem at hand (mostly on the number of nuclides in the problem).
|
|||
New Features
|
||||
------------
|
||||
|
||||
- Complete Python API
|
||||
- Python 3 compatability for all scripts
|
||||
- All scripts consistently named openmc-* and installed together
|
||||
- New 'distribcell' tally filter for repeated cells
|
||||
- Ability to specify outer lattice universe
|
||||
- XML input validation utility (openmc-validate-xml)
|
||||
- Support for hexagonal lattices
|
||||
- Material union energy grid method
|
||||
- Tally triggers
|
||||
- Remove dependence on PETSc
|
||||
- Significant OpenMP performance improvements
|
||||
- Support for Fortran 2008 MPI interface
|
||||
- Use of Travis CI for continuous integration
|
||||
- Simplifications and improvements to test suite
|
||||
- Support for complex cell regions (union and complement operators)
|
||||
- Generic quadric surface type
|
||||
- Improved handling of secondary particles
|
||||
- Binary output is now solely HDF5
|
||||
- ``openmc.mgxs`` Python module enabling multi-group cross section generation
|
||||
- Collision estimator for tallies
|
||||
- Delayed fission neutron production tallies with ability to filter by delayed
|
||||
group
|
||||
- Inverse velocity tally score
|
||||
- Performance improvements for binary search
|
||||
- Performance improvements for reaction rate tallies
|
||||
|
||||
---------
|
||||
Bug Fixes
|
||||
---------
|
||||
|
||||
- b5f712_: Fix bug in spherical harmonics tallies
|
||||
- e6675b_: Ensure all constants are double precision
|
||||
- 04e2c1_: Fix potential bug in sample_nuclide routine
|
||||
- 6121d9_: Fix bugs related to particle track files
|
||||
- 2f0e89_: Fixes for nuclide specification in tallies
|
||||
- 299322_: Bug with material filter when void material present
|
||||
- d74840_: Fix triggers on tallies with multiple filters
|
||||
- c29a81_: Correctly handle maximum transport energy
|
||||
- 3edc23_: Fixes in the nu-scatter score
|
||||
- 629e3b_: Assume unspecified surface coefficients are zero in Python API
|
||||
- 5dbe8b_: Fix energy filters for openmc-plot-mesh-tally
|
||||
- ff66f4_: Fixes in the openmc-plot-mesh-tally script
|
||||
- 441fd4_: Fix bug in kappa-fission score
|
||||
- 7e5974_: Allow fixed source simulations from Python API
|
||||
|
||||
.. _b5f712: https://github.com/mit-crpg/openmc/commit/b5f712
|
||||
.. _e6675b: https://github.com/mit-crpg/openmc/commit/e6675b
|
||||
.. _04e2c1: https://github.com/mit-crpg/openmc/commit/04e2c1
|
||||
.. _6121d9: https://github.com/mit-crpg/openmc/commit/6121d9
|
||||
.. _2f0e89: https://github.com/mit-crpg/openmc/commit/2f0e89
|
||||
.. _299322: https://github.com/mit-crpg/openmc/commit/299322
|
||||
.. _d74840: https://github.com/mit-crpg/openmc/commit/d74840
|
||||
.. _c29a81: https://github.com/mit-crpg/openmc/commit/c29a81
|
||||
.. _3edc23: https://github.com/mit-crpg/openmc/commit/3edc23
|
||||
.. _629e3b: https://github.com/mit-crpg/openmc/commit/629e3b
|
||||
.. _5dbe8b: https://github.com/mit-crpg/openmc/commit/5dbe8b
|
||||
.. _ff66f4: https://github.com/mit-crpg/openmc/commit/ff66f4
|
||||
.. _441fd4: https://github.com/mit-crpg/openmc/commit/441fd4
|
||||
.. _7e5974: https://github.com/mit-crpg/openmc/commit/7e5974
|
||||
|
||||
------------
|
||||
Contributors
|
||||
|
|
@ -55,13 +81,11 @@ Contributors
|
|||
This release contains new contributions from the following people:
|
||||
|
||||
- `Will Boyd <wbinventor@gmail.com>`_
|
||||
- `Matt Ellis <mellis13@mit.edu>`_
|
||||
- `Sterling Harper <sterlingmharper@mit.edu>`_
|
||||
- `Bryan Herman <bherman@mit.edu>`_
|
||||
- `Nicholas Horelik <nicholas.horelik@gmail.com>`_
|
||||
- `Bryan Herman <hermab53@gmail.com>`_
|
||||
- `Colin Josey <cjosey@mit.edu>`_
|
||||
- `William Lyu <PaleNeutron@users.noreply.github.com>`_
|
||||
- `Adam Nelson <nelsonag@umich.edu>`_
|
||||
- `Paul Romano <paul.k.romano@gmail.com>`_
|
||||
- `Anthony Scopatz <scopatz@gmail.com>`_
|
||||
- `Kelly Rowland <kellylynnerowland@gmail.com>`_
|
||||
- `Sam Shaner <samuelshaner@gmail.com>`_
|
||||
- `Jon Walsh <walshjon@mit.edu>`_
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ Installation and Configuration
|
|||
Installing on Ubuntu with PPA
|
||||
-----------------------------
|
||||
|
||||
For users with Ubuntu 11.10 or later, a binary package for OpenMC is available
|
||||
For users with Ubuntu 15.04 or later, a binary package for OpenMC is available
|
||||
through a Personal Package Archive (PPA) and can be installed through the APT
|
||||
package manager. First, add the following PPA to the repository sources:
|
||||
|
||||
|
|
@ -28,6 +28,9 @@ Now OpenMC should be recognized within the repository and can be installed:
|
|||
|
||||
sudo apt-get install openmc
|
||||
|
||||
Binary packages from this PPA may exist for earlier versions of Ubuntu, but they
|
||||
are no longer supported.
|
||||
|
||||
--------------------
|
||||
Building from Source
|
||||
--------------------
|
||||
|
|
@ -74,6 +77,12 @@ Prerequisites
|
|||
|
||||
You may omit ``--enable-parallel`` if you want to compile HDF5_ in serial.
|
||||
|
||||
.. important::
|
||||
|
||||
OpenMC uses various parts of the HDF5 Fortran 2003 API; as such you
|
||||
must include ``--enable-fortran2003`` or else OpenMC will not be able
|
||||
to compile.
|
||||
|
||||
On Debian derivatives, HDF5 and/or parallel HDF5 can be installed through
|
||||
the APT package manager:
|
||||
|
||||
|
|
|
|||
|
|
@ -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):
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
def sort_xml_elements(tree):
|
||||
|
||||
# Retrieve all children of the root XML node in the tree
|
||||
elements = tree.getchildren()
|
||||
elements = list(tree)
|
||||
|
||||
# Initialize empty lists for the sorted and comment elements
|
||||
sorted_elements = []
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -12,17 +12,13 @@ from openmc.checkvalue import check_type, check_value, check_greater_than
|
|||
from openmc.clean_xml import *
|
||||
|
||||
|
||||
# A list of all IDs for all Materials created
|
||||
MATERIAL_IDS = []
|
||||
|
||||
# A static variable for auto-generated Material IDs
|
||||
AUTO_MATERIAL_ID = 10000
|
||||
|
||||
|
||||
def reset_auto_material_id():
|
||||
global AUTO_MATERIAL_ID, MATERIAL_IDS
|
||||
global AUTO_MATERIAL_ID
|
||||
AUTO_MATERIAL_ID = 10000
|
||||
MATERIAL_IDS = []
|
||||
|
||||
|
||||
# Units for density supported by OpenMC
|
||||
|
|
@ -192,26 +188,15 @@ class Material(object):
|
|||
|
||||
@id.setter
|
||||
def id(self, material_id):
|
||||
global AUTO_MATERIAL_ID, MATERIAL_IDS
|
||||
|
||||
# If the Material already has an ID, remove it from global list
|
||||
if hasattr(self, '_id') and self._id is not None:
|
||||
MATERIAL_IDS.remove(self._id)
|
||||
|
||||
if material_id is None:
|
||||
global AUTO_MATERIAL_ID
|
||||
self._id = AUTO_MATERIAL_ID
|
||||
MATERIAL_IDS.append(AUTO_MATERIAL_ID)
|
||||
AUTO_MATERIAL_ID += 1
|
||||
else:
|
||||
check_type('material ID', material_id, Integral)
|
||||
if material_id in MATERIAL_IDS:
|
||||
msg = 'Unable to set Material ID to "{0}" since a Material with ' \
|
||||
'this ID was already initialized'.format(material_id)
|
||||
raise ValueError(msg)
|
||||
check_greater_than('material ID', material_id, 0, equality=True)
|
||||
|
||||
self._id = material_id
|
||||
MATERIAL_IDS.append(material_id)
|
||||
|
||||
@name.setter
|
||||
def name(self, name):
|
||||
|
|
|
|||
|
|
@ -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, :]
|
||||
|
|
|
|||
|
|
@ -355,6 +355,8 @@ class Complement(Region):
|
|||
temp_region = Intersection(*[~n for n in self.node.nodes])
|
||||
elif isinstance(self.node, Intersection):
|
||||
temp_region = Union(*[~n for n in self.node.nodes])
|
||||
elif isinstance(self.node, Complement):
|
||||
temp_region = self.node.node
|
||||
else:
|
||||
temp_region = ~n
|
||||
temp_region = ~self.node
|
||||
return temp_region.bounding_box
|
||||
|
|
|
|||
|
|
@ -1012,16 +1012,19 @@ class SettingsFile(object):
|
|||
|
||||
# Separate subelement
|
||||
if self._sourcepoint_separate is not None:
|
||||
element = ET.SubElement(self._settings_file, "source_point")
|
||||
subelement = ET.SubElement(element, "separate")
|
||||
subelement.text = str(self._sourcepoint_separate).lower()
|
||||
|
||||
# Write subelement
|
||||
if self._sourcepoint_write is not None:
|
||||
element = ET.SubElement(self._settings_file, "source_point")
|
||||
subelement = ET.SubElement(element, "write")
|
||||
subelement.text = str(self._sourcepoint_write).lower()
|
||||
|
||||
# Overwrite latest subelement
|
||||
if self._sourcepoint_overwrite is not None:
|
||||
element = ET.SubElement(self._settings_file, "source_point")
|
||||
subelement = ET.SubElement(element, "overwrite_latest")
|
||||
subelement.text = str(self._sourcepoint_overwrite).lower()
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -271,6 +272,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
|
||||
|
||||
|
|
@ -329,11 +335,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)
|
||||
|
|
@ -349,22 +352,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
|
||||
|
|
@ -520,12 +523,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
|
||||
|
|
@ -567,7 +576,7 @@ class Summary(object):
|
|||
"""
|
||||
|
||||
for index, material in self.materials.items():
|
||||
if material._id == material_id:
|
||||
if material.id == material_id:
|
||||
return material
|
||||
|
||||
return None
|
||||
|
|
@ -588,7 +597,7 @@ class Summary(object):
|
|||
"""
|
||||
|
||||
for index, surface in self.surfaces.items():
|
||||
if surface._id == surface_id:
|
||||
if surface.id == surface_id:
|
||||
return surface
|
||||
|
||||
return None
|
||||
|
|
@ -609,7 +618,7 @@ class Summary(object):
|
|||
"""
|
||||
|
||||
for index, cell in self.cells.items():
|
||||
if cell._id == cell_id:
|
||||
if cell.id == cell_id:
|
||||
return cell
|
||||
|
||||
return None
|
||||
|
|
@ -630,7 +639,7 @@ class Summary(object):
|
|||
"""
|
||||
|
||||
for index, universe in self.universes.items():
|
||||
if universe._id == universe_id:
|
||||
if universe.id == universe_id:
|
||||
return universe
|
||||
|
||||
return None
|
||||
|
|
@ -651,7 +660,7 @@ class Summary(object):
|
|||
"""
|
||||
|
||||
for index, lattice in self.lattices.items():
|
||||
if lattice._id == lattice_id:
|
||||
if lattice.id == lattice_id:
|
||||
return lattice
|
||||
|
||||
return None
|
||||
|
|
|
|||
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)
|
||||
|
|
|
|||
3
setup.py
3
setup.py
|
|
@ -10,7 +10,7 @@ except ImportError:
|
|||
have_setuptools = False
|
||||
|
||||
kwargs = {'name': 'openmc',
|
||||
'version': '0.7.0',
|
||||
'version': '0.7.1',
|
||||
'packages': ['openmc', 'openmc.mgxs'],
|
||||
'scripts': glob.glob('scripts/openmc-*'),
|
||||
|
||||
|
|
@ -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
|
||||
|
|
@ -308,6 +308,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)
|
||||
|
|
|
|||
|
|
@ -8,13 +8,13 @@ module constants
|
|||
! OpenMC major, minor, and release numbers
|
||||
integer, parameter :: VERSION_MAJOR = 0
|
||||
integer, parameter :: VERSION_MINOR = 7
|
||||
integer, parameter :: VERSION_RELEASE = 0
|
||||
integer, parameter :: VERSION_RELEASE = 1
|
||||
|
||||
! Revision numbers for binary files
|
||||
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.
|
||||
|
|
|
|||
|
|
@ -137,6 +137,8 @@ module geometry_header
|
|||
! 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
|
||||
|
||||
|
|
|
|||
|
|
@ -1053,12 +1053,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
|
||||
|
||||
|
|
@ -1077,8 +1077,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
|
||||
|
|
@ -1097,32 +1097,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
|
||||
|
|
@ -1130,26 +1112,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) % type /= CELL_NORMAL) then
|
||||
allocate(cells(i)%offset(n_maps))
|
||||
allocate(cells(i) % offset(n_maps))
|
||||
end if
|
||||
end do
|
||||
|
||||
|
|
|
|||
|
|
@ -994,7 +994,7 @@ contains
|
|||
character(MAX_LINE_LEN) :: filename
|
||||
character(MAX_WORD_LEN) :: word
|
||||
character(MAX_WORD_LEN), allocatable :: sarray(:)
|
||||
character(1000) :: region_spec
|
||||
character(REGION_SPEC_LEN) :: region_spec
|
||||
type(Cell), pointer :: c
|
||||
class(Surface), pointer :: s
|
||||
class(Lattice), pointer :: lat
|
||||
|
|
@ -1049,8 +1049,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)
|
||||
|
|
|
|||
|
|
@ -1378,8 +1378,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)
|
||||
|
|
@ -1413,15 +1412,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
|
||||
|
|
@ -1436,6 +1435,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
|
||||
|
|
@ -1447,17 +1449,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
|
||||
|
|
@ -1537,7 +1535,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
|
||||
|
||||
! ====================================================================
|
||||
|
|
@ -1577,7 +1575,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
|
||||
|
|
@ -1593,7 +1591,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
|
||||
|
||||
|
|
@ -1638,8 +1636,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
|
||||
|
|
@ -1656,7 +1653,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
|
||||
|
||||
|
|
|
|||
|
|
@ -268,7 +268,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. &
|
||||
|
|
@ -870,7 +869,6 @@ contains
|
|||
integer(HSIZE_T) :: dims(1)
|
||||
type(c_ptr) :: f_ptr
|
||||
#ifdef PHDF5
|
||||
integer :: data_xfer_mode
|
||||
integer(HID_T) :: plist ! property list
|
||||
#else
|
||||
integer :: i
|
||||
|
|
@ -989,7 +987,6 @@ contains
|
|||
integer(HSIZE_T) :: offset(1) ! offset of data
|
||||
type(c_ptr) :: f_ptr
|
||||
#ifdef PHDF5
|
||||
integer :: data_xfer_mode
|
||||
integer(HID_T) :: plist ! property list
|
||||
#endif
|
||||
|
||||
|
|
|
|||
|
|
@ -113,7 +113,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
|
||||
|
|
@ -196,6 +196,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
|
||||
|
||||
|
|
@ -355,16 +357,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
|
||||
|
|
@ -484,8 +492,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
|
||||
|
|
@ -540,7 +550,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
|
||||
|
|
@ -664,6 +673,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
|
||||
|
||||
|
|
|
|||
|
|
@ -1712,6 +1712,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
|
||||
|
|
@ -1756,12 +1757,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([&
|
||||
|
|
@ -1769,7 +1772,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