Keep working on documentation. Allow default source.

Also merge Settings.output_path into Settings.output
This commit is contained in:
Paul Romano 2017-03-31 14:10:48 -05:00
parent df786664a8
commit a7da8096f7
12 changed files with 441 additions and 94 deletions

View file

@ -220,11 +220,6 @@ The ``<output>`` element determines what output files should be written to disk
during the run. The sub-elements are described below, where "true" will write
out the file and "false" will not.
:cross_sections:
Writes out an ASCII summary file of the cross sections that were read in.
*Default*: false
:summary:
Writes out an HDF5 summary file describing all of the user input files that
were read in.
@ -239,15 +234,11 @@ out the file and "false" will not.
.. note:: The tally results will always be written to a binary/HDF5 state
point file.
-------------------------
``<output_path>`` Element
-------------------------
:path:
Absolute or relative path where all output files should be written to. The
specified path must exist or else OpenMC will abort.
The ``<output_path>`` element specifies an absolute or relative path where all
output files should be written to. The specified path must exist or else OpenMC
will abort.
*Default*: Current working directory
*Default*: Current working directory
-----------------------
``<particles>`` Element

View file

@ -200,6 +200,8 @@ Various classes may be created when performing tally slicing and/or arithmetic:
openmc.arithmetic.AggregateNuclide
openmc.arithmetic.AggregateFilter
.. _pythonapi_stats:
---------------------------------
:mod:`openmc.stats` -- Statistics
---------------------------------

View file

@ -156,6 +156,8 @@ Serpent. In the Python API, integer IDs can be assigned but it is not strictly
required. When IDs are not explicitly assigned to instances of the OpenMC Python
classes, they will be automatically assigned.
.. _result_files:
-----------------------------
Viewing and Analyzing Results
-----------------------------

View file

@ -18,6 +18,7 @@ essential aspects of using OpenMC to perform simulations.
geometry
settings
tallies
plots
scripts
processing
troubleshoot

View file

@ -0,0 +1,125 @@
.. _usersguide_plots:
======================
Geometry Visualization
======================
OpenMC is capable of producing two-dimensional slice plots of a geometry as well
as three-dimensional voxel plots using the geometry plotting :ref:`run mode
<usersguide_run_modes>` is a geometry plotting mode. The geometry plotting mode
relies on the presence of a :ref:`plots.xml <io_plots>` file that indicates what
plots should be created. To create this file, one needs to create one or more
:class:`openmc.Plot` instances, add them to a :class:`openmc.Plots` collection,
and then use the :class:`Plots.export_to_xml` method to write the ``plots.xml``
file.
-----------
Slice Plots
-----------
.. image:: ../_images/atr.png
:width: 300px
By default, when an instance of :class:`openmc.Plot` is created, it indicates
that a 2D slice plot should be made. You can specify the origin of the plot
(:attr:`Plot.origin`), the width of the plot in each direction
(:attr:`Plot.width`), the number of pixels to use in each direction
(:attr:`Plot.pixels`), and the basis directions for the plot. For example, to
create a x-z plot centered at (5.0, 2.0, 3.0) with a width of (50., 50.) and
400x400 pixels::
plot = openmc.Plot()
plot.basis = 'yz'
plot.origin = (5.0, 2.0, 3.0)
plot.width = (50., 50.)
plot.pixels = (400, 400)
By default, a unique color will be assigned to each cell in the geometry. If you
want your plot to be colored by material instead, change the
:attr:`Plot.color_by` attribute::
plot.color_by = 'material'
If you don't like the random colors assigned, you can also indicate that
particular cells/materials should be given colors of your choosing::
plot.colors = {
water: 'blue',
clad: 'black'
}
# ..or..
plot.colors = {
water: (0, 0, 255),
clad: (0, 0, 0)
}
Note that colors can be given as RGB tuples or by a string indicating a valid
`SVG color <https://www.w3.org/TR/SVG/types.html#ColorKeywords>`_.
When you're done creating your :class:`openmc.Plot` instances, you need to then
assign them to a :class:`openmc.Plots` collection and export it to XML::
plots = openmc.Plots([plot1, plot2, plot3])
plots.export_to_xml()
# ..or..
plots = openmc.Plots()
plots.append(plot1)
plots += [plot2, plot3]
plots.export_to_xml()
To actually generate the plots, run the :func:`openmc.plot_geometry`
function. Alternatively, run the :ref:`scripts_openmc` executable with the
``--plot`` command-line flag. When that has finished, you will have one or more
``.ppm`` files, i.e., `portable pixmap
<http://netpbm.sourceforge.net/doc/ppm.html>`_ files. On some Linux
distributions, these ``.ppm`` files are natively viewable. If you find that
you're unable to open them on your system (or you don't like the fact that they
are not compressed), you may want to consider converting them to another format.
This is easily accomplished with the ``convert`` command available on most Linux
distributions as part of the `ImageMagick
<http://www.imagemagick.org/script/convert.php>`_ package. (On Debian
derivatives: ``sudo apt install imagemagick``). Images are then converted like:
.. code-block:: sh
convert myplot.ppm myplot.png
Alternatively, if you're working with in a `Jupyter <http://jupyter.org/>`_
Notebook or QtConsole, you can use the :func:`openmc.plot_inline` to run OpenMC
in plotting mode and display the resulting plot within the notebook.
.. _usersguide_voxel:
-----------
Voxel Plots
-----------
.. image:: ../_images/3dba.png
:width: 200px
The :class:`openmc.Plot` class can also be told to generate a 3D voxel plot
instead of a 2D slice plot. Simply change the :attr:`Plot.type` attribute to
'voxel'. In this case, the :attr:`Plot.width` and :attr:`Plot.pixels` attributes
should be three items long, e.g.::
vox_plot = openmc.Plot()
vox_plot.type = 'voxel'
vox_plot.width = (100., 100., 50.)
vox_plot.pixels = (400, 400, 200)
The voxel plot data is written to an :ref:`HDF5 file <io_voxel>`. The voxel file
can subsequently be converted into a standard mesh format that can be viewed in
`ParaView <http://www.paraview.org/>`_, `VisIt
<https://wci.llnl.gov/simulation/computer-codes/visit>`_, etc. This typically
will compress the size of the file significantly. The provided
:ref:`scripts_voxel` script can convert the HDF5 voxel file to VTK or SILO
formats. Once processed into a standard 3D file format, colors and masks can be
defined using the stored ID numbers to better explore the geometry. The process
for doing this will depend on the 3D viewer, but should be straightforward.
.. note:: 3D voxel plotting can be very computer intensive for the viewing
program (Visit, ParaView, etc.) if the number of voxels is large (>10
million or so). Thus if you want an accurate picture that renders
smoothly, consider using only one voxel in a certain direction.

View file

@ -34,7 +34,7 @@ Geometry Visualization
Geometry plotting is carried out by creating a plots.xml, specifying plots, and
running OpenMC with the --plot or -p command-line option (See
:ref:`usersguide_plotting`).
:ref:`scripts_openmc`).
Plotting in 2D
--------------

View file

@ -30,7 +30,7 @@ Alternatively, you could run from any directory:
Note that in the latter case, any output files will be placed in the present
working directory which may be different from ``/home/username/somemodel``. If
you're using the Python API, :func:`openmc.run` is equivalent to running
``openmc`` from the command line. OpenMC accepts the following command line
``openmc`` from the command line. ``openmc`` accepts the following command line
flags:
-c, --volume Run in stochastic volume calculation mode
@ -95,10 +95,8 @@ Input files can be checked before executing OpenMC using the
``openmc-validate-xml`` script which is installed alongside the Python API. Two
command line arguments can be set when running ``openmc-validate-xml``:
* ``-i``, ``--input-path`` - Location of OpenMC input files.
*Default*: current working directory
* ``-r``, ``--relaxng-path`` - Location of OpenMC RelaxNG files.
*Default*: None
-i, --input-path Location of OpenMC input files.
-r, --relaxng-path Location of OpenMC RelaxNG files
If the RelaxNG path is not set, the script will search for these files because
it expects that the user is either running the script located in the install
@ -120,3 +118,22 @@ Message Description
---------------------------
``openmc-voxel-to-silovtk``
---------------------------
When OpenMC generates :ref:`voxel plots <usersguide_voxel>`, they are in an
:ref:`HDF5 format <io_voxel>` that is not terribly useful by itself. The
``openmc-voxel-to-silovtk`` script converts a voxel HDF5 file to `VTK
<http://www.vtk.org/>`_ or `SILO
<https://wci.llnl.gov/simulation/computer-codes/silo>`_ file. For VTK, you need
to have the VTK Python bindings installed. For SILO, you need to have `silomesh
<https://github.com/nhorelik/silomesh>`_ installed. To convert a voxel file,
simply provide the path to the file:
.. code-block:: sh
openmc-voxel-to-silovtk voxel_1.h5
The ``openmc-voxel-to-silovtk`` script also takes the following optional
command-line arguments:
-o, --output Path to output VTK or SILO file
-s, --silo Flag to convert to SILO instead of VTK

View file

@ -3,3 +3,221 @@
==================
Execution Settings
==================
.. currentmodule:: openmc
Once you have created the materials and geometry for your simulation, the last
step to have a complete model is to specify execution settings through the
:class:`openmc.Settings` class. At a minimum, you need to specify a :ref:`source
distribution <usersguide_source>` and :ref:`how many particles to run
<usersguide_particles>`. Many other execution settings can be set using the
:class:`openmc.Settings` object, but they are generally optional.
.. _usersguide_run_modes:
---------
Run Modes
---------
The :attr:`Settings.run_mode` attribute controls what run mode is used when
:ref:`scripts_openmc` is executed. There are five different run modes that can
be specified:
'eigenvalue'
Runs a :math:`k` eigenvalue simulation. See :ref:`methods_eigenvalue` for a
full description of eigenvalue calculations. In this mode, the
:attr:`Settings.source` specifies a starting source that is only used for the
first fission generation.
'fixed source'
Runs a fixed-source calculation with a specified external source, specified in
the :attr:`Settings.source` attribute.
'volume'
Runs a stochastic volume calculation.
'plot'
Generates slice or voxel plots (see :ref:`usersguide_plots`).
'particle_restart'
Simulate a single source particle using a particle restart file.
So, for example, to specify that OpenMC should be run in fixed source mode, you
would need to instantiate a :class:`openmc.Settings` object and assign the
:attr:`Settings.run_mode` attribute::
settings = openmc.Settings()
settings.run_mode = 'fixed source'
.. _usersguide_particles:
-------------------
Number of Particles
-------------------
For a fixed source simulation, the total number of source particle histories
simulated is broken up into a number of *batches*, each corresponding to a
:ref:`realization <methods_tallies>` of the tally random variables. Thus, you
need to specify both the number of batches (:attr:`Settings.batches`) as well as
the number of particles per batch (:attr:`Settings.particles`).
For a :math:`k` eigenvalue simulation, particles are grouped into *fission
generations*, as described in :ref:`methods_eigenvalue`. Successive fission
generations can be combined into a batch for statistical purposes. By default, a
batch will consist of only a single fission generation, but this can be changed
with the :attr:`Settings.generations_per_batch` attribute. For problems with a
high dominance ratio, using multiple generations per batch can help reduce
underprediction of variance, thereby leading to more accurate confidence
intervals. Tallies should not be scored to until the source distribution
converges, as described in :ref:`method-successive-generations`, which may take
many generations. To specify the number of batches that should be discarded
before tallies begin to accumulate, use the :attr:`Settings.inactive` attribute.
The following example shows how one would simulate 10000 particles per
generation, using 10 generations per batch, 150 total batches, and discarding 5
batches. Thus, a total of 145 active batches (or 1450 generations) will be used
for accumulating tallies.
::
settings.particles = 10000
settings.generations_per_batch = 10
settings.batches = 150
settings.inactive = 5
.. _usersguide_source:
-----------------------------
External Source Distributions
-----------------------------
External source distributions can be specified through the
:attr:`Settings.source` attribute. If you have a single external source, you can
create an instance of :class:`openmc.Source` and use it to set the
:attr:`Settings.source` attribute. If you have multiple external sources with
varying source strengths, :attr:`Settings.source` should be set to a list of
:class:`openmc.Source` objects.
The :class:`openmc.Source` class has three main attributes that one can set:
:attr:`Source.space`, which defines the spatial distribution,
:attr:`Source.angle`, which defines the angular distribution, and
:attr:`Source.energy`, which defines the energy distribution.
The spatial distribution can be set equal to a sub-class of
:class:`openmc.stats.Spatial`; common choices are :class:`openmc.stats.Point` or
:class:`openmc.stats.Box`. To independently specify distributions in the x, y,
and z coordinates, you can use :class:`openmc.stats.CartesianIndependent`.
The angular distribution can be set equal to a sub-class of
:class:`openmc.stats.UnitSphere` such as :class:`openmc.stats.Isotropic`,
:class:`openmc.stats.Monodirectional`, or
:class:`openmc.stats.PolarAzimuthal`. By default, if no angular distribution is
specified, an isotropic angular distribution is used.
The energy distribution can be set equal to any univariate probability
distribution. This could be a probability mass function
(:class:`openmc.stats.Discrete`), a Watt fission spectrum
(:class:`openmc.stats.Watt`), or a tabular distribution
(:class:`openmc.stats.Tabular`). By default, if no energy distribution is
specified, a Watt fission spectrum with :math:`a` = 0.988 MeV and :math:`b` =
2.249 MeV :sup:`-1` is used.
As an example, to create an isotropic, 10 MeV monoenergetic source uniformly
distributed over a cube centered at the origin with an edge length of 10 cm, one
would run::
source = openmc.Source()
source.space = openmc.stats.Box((-5, -5, -5), (5, 5, 5))
source.angle = openmc.stats.Isotropic()
source.energy = openmc.stats.Discrete([10.0e6], [1.0])
settings.source = source
The :class:`openmc.Source` class also has a :attr:`Source.strength` attribute
that indicates the relative strength of a source distribution if multiple are
used. For example, to create two sources, one that should be sampled 70% of the
time and another that should be sampled 30% of the time::
src1 = openmc.Source()
src1.strength = 0.7
...
src2 = openmc.Source()
src2.strength = 0.3
...
settings.source = [src1, src2]
For a full list of all classes related to statistical distributions, see
:ref:`pythonapi_stats`.
---------------
Shannon Entropy
---------------
To assess convergence of the source distribution, the scalar Shannon entropy
metric is often used in Monte Carlo codes. OpenMC also allows you to calculate
Shannon entropy at each generation over a specified mesh, created using the
:class:`openmc.Mesh` class. After instantiating a :class:`Mesh`, you need to
specify the lower-left coordinates of the mesh (:attr:`Mesh.lower_left`), the
number of mesh cells in each direction (:attr:`Mesh.dimension`) and either the
upper-right coordinates of the mesh (:attr:`Mesh.upper_right`) or the width of
each mesh cell (:attr:`Mesh.width`). Once you have a mesh, simply assign it to
the :attr:`Settings.entropy_mesh` attribute.
::
entropy_mesh = openmc.Mesh()
entropy_mesh.lower_left = (-50, -50, -25)
entropy_mesh.upper_right = (50, 50, 25)
entropy_mesh.dimension = (8, 8, 8)
settings.entropy_mesh = entropy_mesh
If you're unsure of what bounds to use for the entropy mesh, you can try getting
a bounding box for the entire geometry using the :attr:`Geometry.bounding_box`
property::
geom = openmc.Geometry()
...
m = openmc.Mesh()
m.lower_left, m.upper_right = geom.bounding_box
m.dimension = (8, 8, 8)
settings.entropy_mesh = m
--------------------------
Generation of Output Files
--------------------------
A number of attributes of the :class:`openmc.Settings` class can be used to
control what files are output and how often. First, there is the
:attr:`Settings.output` attribute which takes a dictionary having keys
'summary', 'tallies', and 'path'. The first two keys controls whether a
``summary.h5`` and ``tallies.out`` file are written, respectively (see
:ref:`result_files` for a description of those files). By default, output files
are written to the current working directory; this can be changed by setting the
'path' key. For example, if you want to disable the ``tallies.out`` file and
write the ``summary.h5`` to a directory called 'results', you'd specify the
:attr:`Settings.output` dictionary as::
settings.output = {
'tallies': False,
'path': 'results'
}
Generation of statepoint and source files is handled separately through the
:attr:`Settings.statepoint` and :attr:`Settings.sourcepoint` attributes. Both of
those attributes expect dictionaries and have a 'batches' key which indicates at
which batches statepoints and source files should be written. Note that by
default, the source is written as part of the statepoint file; this behavior can
be changed by the 'separate' and 'write' keys of the
:attr:`Settings.sourcepoint` dictionary, the first of which indicates whether
the source should be written to a separate file and the second of which
indicates whether the source should be written at all.
As an example, to write a statepoint file every five batches::
settings.batches = n
settings.statepoint = {'batches': range(5, n + 5, 5)}

View file

@ -71,11 +71,12 @@ class Settings(object):
Indicate that all user-defined and global tallies should not be reduced
across processes in a parallel calculation.
output : dict
Dictionary indicating what files to output. Valid keys are 'summary',
'cross_sections', 'tallies', and 'distribmats'. Values corresponding to
each key should be given as a boolean value.
output_path : str
Path to write output to
Dictionary indicating what files to output. Acceptable keys are:
:path: String indicating a directory where output files should be
written
:summary: Whether the 'summary.h5' file should be written (bool)
:tallies: Whether the 'tallies.out' file should be written (bool)
particles : int
Number of particles per generation
ptables : bool
@ -193,7 +194,6 @@ class Settings(object):
self._trigger_batch_interval = None
self._output = None
self._output_path = None
# Output options
self._statepoint = {}
@ -315,10 +315,6 @@ class Settings(object):
def output(self):
return self._output
@property
def output_path(self):
return self._output_path
@property
def sourcepoint(self):
return self._sourcepoint
@ -479,30 +475,15 @@ class Settings(object):
@output.setter
def output(self, output):
if not isinstance(output, dict):
msg = 'Unable to set output to "{0}" which is not a Python ' \
'dictionary of string keys and boolean values'.format(output)
raise ValueError(msg)
for element in output:
keys = ['summary', 'cross_sections', 'tallies', 'distribmats']
if element not in keys:
msg = 'Unable to set output to "{0}" which is unsupported by ' \
'OpenMC'.format(element)
raise ValueError(msg)
if not isinstance(output[element], (bool, np.bool)):
msg = 'Unable to set output for "{0}" to a non-boolean ' \
'value "{1}"'.format(element, output[element])
raise ValueError(msg)
cv.check_type('output', output, Mapping)
for key, value in output.items():
cv.check_value('output key', key, ('summary', 'tallies', 'path'))
if key in ('summary', 'tallies'):
cv.check_type("output['{}']".format(key), value, bool)
else:
cv.check_type("output['path']", value, string_types)
self._output = output
@output_path.setter
def output_path(self, output_path):
cv.check_type('output path', output_path, string_types)
self._output_path = output_path
@verbosity.setter
def verbosity(self, verbosity):
cv.check_type('verbosity', verbosity, Integral)
@ -876,13 +857,12 @@ class Settings(object):
if self._output is not None:
element = ET.SubElement(root, "output")
for key in self._output:
for key, value in self._output.items():
subelement = ET.SubElement(element, key)
subelement.text = str(self._output[key]).lower()
if self._output_path is not None:
element = ET.SubElement(root, "output_path")
element.text = self._output_path
if key in ('summary', 'tallies'):
subelement.text = str(value).lower()
else:
subelement.text = value
def _create_verbosity_subelement(self, root):
if self._verbosity is not None:

View file

@ -183,14 +183,6 @@ contains
max_order = 0
end if
! Set output directory if a path has been specified on the <output_path>
! element
if (check_for_node(root, "output_path")) then
call get_node_value(root, "output_path", path_output)
if (.not. ends_with(path_output, "/")) &
path_output = trim(path_output) // "/"
end if
! Check for a trigger node and get trigger information
if (check_for_node(root, "trigger")) then
node_trigger = root % child("trigger")
@ -308,12 +300,30 @@ contains
call get_node_list(root, "source", node_source_list)
n = size(node_source_list)
if (run_mode == MODE_EIGENVALUE .or. run_mode == MODE_FIXEDSOURCE) then
if (n == 0) call fatal_error("No source specified in settings XML file.")
end if
if (n == 0) then
! Default source is isotropic point source at origin with Watt spectrum
allocate(external_source(1))
external_source % strength = ONE
! Allocate array for sources
allocate(external_source(n))
allocate(SpatialPoint :: external_source(1) % space)
select type (space => external_source(1) % space)
type is (SpatialPoint)
space % xyz(:) = [ZERO, ZERO, ZERO]
end select
allocate(Isotropic :: external_source(1) % angle)
external_source(1) % angle % reference_uvw(:) = [ZERO, ZERO, ONE]
allocate(Watt :: external_source(1) % energy)
select type(energy => external_source(1) % energy)
type is (Watt)
energy % a = 0.988e6_8
energy % b = 2.249e-6_8
end select
else
! Allocate array for sources
allocate(external_source(n))
end if
! Read each source
do i = 1, n
@ -451,8 +461,12 @@ contains
end select
else
call fatal_error("No spatial distribution specified for external &
&source.")
! If no spatial distribution specified, make it a point source
allocate(SpatialPoint :: external_source(i) % space)
select type (space => external_source(i) % space)
type is (SpatialPoint)
space % xyz(:) = [ZERO, ZERO, ZERO]
end select
end if
! Determine external source angular distribution
@ -839,6 +853,13 @@ contains
if (check_for_node(node_output, "tallies")) then
call get_node_value(node_output, "tallies", output_tallies)
end if
! Set output directory if a path has been specified
if (check_for_node(node_output, "path")) then
call get_node_value(node_output, "path", path_output)
if (.not. ends_with(path_output, "/")) &
path_output = trim(path_output) // "/"
end if
end if
! Check for cmfd run

View file

@ -38,13 +38,10 @@ element settings {
element output {
(element summary { xsd:boolean } | attribute summary { xsd:boolean })? &
(element cross_sections { xsd:boolean } |
attribute cross_sections { xsd:boolean })? &
(element tallies { xsd:boolean } | attribute tallies { xsd:boolean })?
(element tallies { xsd:boolean } | attribute tallies { xsd:boolean })? &
(element path { xsd:string } | attribute path { xsd:string })?
}? &
element output_path { xsd:string { maxLength = "255" } }? &
element particles { xsd:positiveInteger }? &
element ptables { xsd:boolean }? &

View file

@ -177,16 +177,6 @@
</attribute>
</choice>
</optional>
<optional>
<choice>
<element name="cross_sections">
<data type="boolean"/>
</element>
<attribute name="cross_sections">
<data type="boolean"/>
</attribute>
</choice>
</optional>
<optional>
<choice>
<element name="tallies">
@ -197,16 +187,19 @@
</attribute>
</choice>
</optional>
<optional>
<choice>
<element name="path">
<data type="string"/>
</element>
<attribute name="path">
<data type="string"/>
</attribute>
</choice>
</optional>
</interleave>
</element>
</optional>
<optional>
<element name="output_path">
<data type="string">
<param name="maxLength">255</param>
</data>
</element>
</optional>
<optional>
<element name="particles">
<data type="positiveInteger"/>