Merge branch 'develop' into collisionFilter

This commit is contained in:
Amelia J Trainer 2021-04-07 11:22:43 -04:00 committed by GitHub
commit ab32931870
105 changed files with 2976 additions and 1362 deletions

View file

@ -3,8 +3,8 @@ project(openmc C CXX)
# Set version numbers
set(OPENMC_VERSION_MAJOR 0)
set(OPENMC_VERSION_MINOR 12)
set(OPENMC_VERSION_RELEASE 1)
set(OPENMC_VERSION_MINOR 13)
set(OPENMC_VERSION_RELEASE 0)
set(OPENMC_VERSION ${OPENMC_VERSION_MAJOR}.${OPENMC_VERSION_MINOR}.${OPENMC_VERSION_RELEASE})
configure_file(include/openmc/version.h.in "${CMAKE_BINARY_DIR}/include/openmc/version.h" @ONLY)
@ -54,13 +54,13 @@ endif()
#===============================================================================
# If not found, we just pull appropriate versions from github and build them.
find_package(fmt QUIET)
find_package(fmt QUIET NO_SYSTEM_ENVIRONMENT_PATH)
if(fmt_FOUND)
message(STATUS "Found fmt: ${fmt_DIR} (version ${fmt_VERSION})")
else()
message(STATUS "Did not find fmt, will use submodule instead")
endif()
find_package(pugixml QUIET)
find_package(pugixml QUIET NO_SYSTEM_ENVIRONMENT_PATH)
if(pugixml_FOUND)
message(STATUS "Found pugixml: ${pugixml_DIR}")
else()
@ -87,7 +87,9 @@ endif()
find_package(HDF5 REQUIRED COMPONENTS C HL)
if(HDF5_IS_PARALLEL)
if(NOT MPI_ENABLED)
message(FATAL_ERROR "Parallel HDF5 must be used with MPI.")
message(FATAL_ERROR "Parallel HDF5 was detected, but the detected compiler,\
${CMAKE_CXX_COMPILER}, does not support MPI. An MPI-capable compiler must \
be used with parallel HDF5.")
endif()
message(STATUS "Using parallel HDF5")
endif()

View file

@ -65,7 +65,7 @@ RUN if [ "$include_dagmc" = "true" ] ; \
# Clone and install Embree
RUN if [ "$include_dagmc" = "true" ] ; \
then git clone --single-branch --branch master https://github.com/embree/embree.git ; \
then git clone --single-branch --branch v3.12.2 https://github.com/embree/embree.git ; \
cd embree ; \
mkdir build ; \
cd build ; \
@ -81,7 +81,7 @@ RUN if [ "$include_dagmc" = "true" ] ; \
mkdir MOAB ; \
cd MOAB ; \
mkdir build ; \
git clone --single-branch --branch master https://bitbucket.org/fathomteam/moab.git ; \
git clone --single-branch --branch 5.2.1 https://bitbucket.org/fathomteam/moab.git ; \
cd build ; \
cmake ../moab -DENABLE_HDF5=ON \
-DENABLE_NETCDF=ON \
@ -117,7 +117,7 @@ RUN if [ "$include_dagmc" = "true" ] ; \
RUN if [ "$include_dagmc" = "true" ] ; \
then mkdir DAGMC ; \
cd DAGMC ; \
git clone --single-branch --branch develop https://github.com/svalinn/DAGMC.git ; \
git clone --single-branch --branch 3.2.0 https://github.com/svalinn/DAGMC.git ; \
mkdir build ; \
cd build ; \
cmake ../DAGMC -DBUILD_TALLY=ON \

View file

@ -1,4 +1,4 @@
Copyright (c) 2011-2020 Massachusetts Institute of Technology and OpenMC contributors
Copyright (c) 2011-2021 Massachusetts Institute of Technology and OpenMC contributors
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in

View file

@ -63,16 +63,16 @@ master_doc = 'index'
# General information about the project.
project = 'OpenMC'
copyright = '2011-2020, Massachusetts Institute of Technology and OpenMC contributors'
copyright = '2011-2021, Massachusetts Institute of Technology and OpenMC contributors'
# The version info for the project you're documenting, acts as replacement for
# |version| and |release|, also used in various other places throughout the
# built documents.
#
# The short X.Y version.
version = "0.12"
version = "0.13"
# The full version, including alpha/beta/rc tags.
release = "0.12.1-dev"
release = "0.13.0-dev"
# The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages.
@ -215,6 +215,7 @@ latex_elements = {
\hypersetup{bookmarksdepth=3}
\setcounter{tocdepth}{2}
\numberwithin{equation}{section}
\DeclareUnicodeCharacter{03B1}{$\alpha$}
""",
'printindex': r""
}

View file

@ -215,7 +215,7 @@ Documentation
-------------
Classes, structs, and functions are to be annotated for the `Doxygen
<http://www.doxygen.nl/>`_ documentation generation tool. Use the ``\`` form of
<https://www.doxygen.nl/>`_ documentation generation tool. Use the ``\`` form of
Doxygen commands, e.g., ``\brief`` instead of ``@brief``.
------

View file

@ -14,7 +14,7 @@ functions/classes in the OpenMC Python API.
Prerequisites
-------------
- The test suite relies on the third-party `pytest <https://pytest.org>`_
- The test suite relies on the third-party `pytest <https://docs.pytest.org>`_
package. To run either or both the regression and unit test suites, it is
assumed that you have OpenMC fully installed, i.e., the :ref:`scripts_openmc`
executable is available on your :envvar:`PATH` and the :mod:`openmc` Python
@ -46,7 +46,7 @@ To execute the test suite, go to the ``tests/`` directory and run::
pytest
If you want to collect information about source line coverage in the Python API,
you must have the `pytest-cov <https://pypi.python.org/pypi/pytest-cov>`_ plugin
you must have the `pytest-cov <https://pypi.org/project/pytest-cov>`_ plugin
installed and run::
pytest --cov=../openmc --cov-report=html

View file

@ -65,7 +65,7 @@ developer or send a message to the `developers mailing list`_.
.. _property attribute: https://docs.python.org/3.6/library/functions.html#property
.. _XML Schema Part 2: http://www.w3.org/TR/xmlschema-2/
.. _boolean: http://www.w3.org/TR/xmlschema-2/#boolean
.. _RELAX NG: http://relaxng.org/
.. _compact syntax: http://relaxng.org/compact-tutorial-20030326.html
.. _trang: http://www.thaiopensource.com/relaxng/trang.html
.. _RELAX NG: https://relaxng.org/
.. _compact syntax: https://relaxng.org/compact-tutorial-20030326.html
.. _trang: https://relaxng.org/jclark/trang.html
.. _developers mailing list: https://groups.google.com/forum/?fromgroups=#!forum/openmc-dev

View file

@ -122,11 +122,11 @@ can interfere with virtual environments.
.. _git: http://git-scm.com/
.. _GitHub: https://github.com/
.. _git flow: http://nvie.com/git-model
.. _valgrind: http://valgrind.org/
.. _git flow: https://nvie.com/git-model
.. _valgrind: https://www.valgrind.org/
.. _style guide: https://docs.openmc.org/en/latest/devguide/styleguide.html
.. _pull request: https://help.github.com/articles/using-pull-requests
.. _pull request: https://docs.github.com/en/github/collaborating-with-issues-and-pull-requests/about-pull-requests
.. _openmc-dev/openmc: https://github.com/openmc-dev/openmc
.. _paid plan: https://github.com/plans
.. _paid plan: https://github.com/pricing
.. _Bitbucket: https://bitbucket.org
.. _pip: https://pip.pypa.io/en/stable/

View file

@ -0,0 +1 @@
../../../examples/jupyter/capi.ipynb

View file

@ -19,7 +19,7 @@ General Usage
post-processing
pandas-dataframes
tally-arithmetic
CAPI
capi
expansion-filters
search
nuclear-data

View file

@ -13,8 +13,8 @@ programming model.
OpenMC was originally developed by members of the `Computational Reactor Physics
Group <http://crpg.mit.edu>`_ at the `Massachusetts Institute of Technology
<http://web.mit.edu>`_ starting in 2011. Various universities, laboratories, and
other organizations now contribute to the development of OpenMC. For more
<https://web.mit.edu>`_ starting in 2011. Various universities, laboratories,
and other organizations now contribute to the development of OpenMC. For more
information on OpenMC, feel free to post a message on the `OpenMC Discourse
Forum <https://openmc.discourse.group/>`_.

View file

@ -49,4 +49,4 @@ Windowed Multipole Library Format
windows[i, 1] are, respectively, the indexes (1-based) of the first and
last pole in window i.
.. _h5py: http://docs.h5py.org/en/latest/
.. _h5py: https://docs.h5py.org/en/latest/

View file

@ -44,7 +44,6 @@ Output Files
statepoint
source
surface_source
summary
depletion_results
particle_restart

View file

@ -21,7 +21,7 @@ nuclides or materials.
The current version of the multi-group library file format is 1.0.
.. _HDF5: http://www.hdfgroup.org/HDF5/
.. _HDF5: https://www.hdfgroup.org/solutions/hdf5/
.. _mgxs_lib_spec:

View file

@ -162,5 +162,5 @@ All values are given in seconds and are measured on the master process.
source sites between processes for load balancing.
- **accumulating tallies** (*double*) -- Time spent communicating
tally results and evaluating their statistics.
- **writing statepoints** (*double*) -- Time spent writing statepoint
files
- **writing statepoints** (*double*) -- Time spent writing statepoint
files

View file

@ -4,7 +4,7 @@
License Agreement
=================
Copyright © 2011-2020 Massachusetts Institute of Technology and OpenMC contributors
Copyright © 2011-2021 Massachusetts Institute of Technology and OpenMC contributors
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in

View file

@ -186,10 +186,10 @@ The data governing the interaction of particles with various nuclei or materials
are represented using a multi-group library format specific to the OpenMC code.
The format is described in the :ref:`mgxs_lib_spec`. The data itself can be
prepared via traditional paths or directly from a continuous-energy OpenMC
calculation by use of the Python API as is shown in the
:ref:`notebook_mg_mode_part_i` example notebook. This multi-group library
consists of meta-data (such as the energy group structure) and multiple `xsdata`
objects which contains the required microscopic or macroscopic multi-group data.
calculation by use of the Python API as is shown in an `example notebook
<../examples/mg-mode-part-i.ipynb>`_. This multi-group library consists of
meta-data (such as the energy group structure) and multiple `xsdata` objects
which contains the required microscopic or macroscopic multi-group data.
At a minimum, the library must contain the absorption cross section
(:math:`\sigma_{a,g}`) and a scattering matrix. If the problem is an eigenvalue
@ -269,12 +269,12 @@ or even isotropic scattering.
.. _logarithmic mapping technique:
https://laws.lanl.gov/vhosts/mcnp.lanl.gov/pdf_files/la-ur-14-24530.pdf
.. _Hwang: http://www.ans.org/pubs/journals/nse/a_16381
.. _Hwang: https://doi.org/10.13182/NSE87-A16381
.. _Josey: https://doi.org/10.1016/j.jcp.2015.08.013
.. _WMP Library: https://github.com/mit-crpg/WMP_Library
.. _MCNP: http://mcnp.lanl.gov
.. _MCNP: https://mcnp.lanl.gov
.. _Serpent: http://montecarlo.vtt.fi
.. _NJOY: http://t2.lanl.gov/codes.shtml
.. _ENDF/B data: http://www.nndc.bnl.gov/endf
.. _NJOY: https://www.njoy21.io/NJOY21/
.. _ENDF/B data: https://www.nndc.bnl.gov/endf/b8.0/
.. _Leppanen: https://doi.org/10.1016/j.anucene.2009.03.019
.. _algorithms: http://ab-initio.mit.edu/wiki/index.php/Faddeeva_Package

View file

@ -962,6 +962,6 @@ surface is known as in :ref:`reflection`.
.. _constructive solid geometry: https://en.wikipedia.org/wiki/Constructive_solid_geometry
.. _surfaces: https://en.wikipedia.org/wiki/Surface
.. _MCNP: http://mcnp.lanl.gov
.. _MCNP: https://mcnp.lanl.gov
.. _Serpent: http://montecarlo.vtt.fi
.. _Monte Carlo Performance benchmark: https://github.com/mit-crpg/benchmarks/tree/master/mc-performance/openmc

View file

@ -76,10 +76,11 @@ absorption cross section (this includes fission), and :math:`\sigma_f` is the
total fission cross section. If this condition is met, then the neutron is
killed and we proceed to simulate the next neutron from the source bank.
No secondary particles from disappearance reactions such as photons or
alpha-particles are produced or tracked. To truly capture the affects of gamma
heating in a problem, it would be necessary to explicitly track photons
originating from :math:`(n,\gamma)` and other reactions.
Note that photons arising from :math:`(n,\gamma)` and other neutron reactions
are not produced in a microscopically correct manner. Instead, photons are
sampled probabilistically at each neutron collision, regardless of what reaction
actually takes place. This is described in more detail in
:ref:`photon_production`.
------------------
Elastic Scattering
@ -1694,7 +1695,7 @@ another.
.. _SIGMA1 method: https://doi.org/10.13182/NSE76-1
.. _scaled interpolation: http://www.ans.org/pubs/journals/nse/a_26575
.. _scaled interpolation: https://doi.org/10.13182/NSE73-A26575
.. _probability table method: https://doi.org/10.13182/NSE72-3
@ -1702,23 +1703,23 @@ another.
.. _Foderaro: http://hdl.handle.net/1721.1/1716
.. _OECD: http://www.oecd-nea.org/tools/abstract/detail/NEA-1792
.. _OECD: https://www.oecd-nea.org/tools/abstract/detail/NEA-1792
.. _NJOY: https://www.njoy21.io/NJOY2016/
.. _PREPRO: http://www-nds.iaea.org/ndspub/endf/prepro/
.. _PREPRO: https://www-nds.iaea.org/ndspub/endf/prepro/
.. _endf102: https://www.oecd-nea.org/dbdata/data/manual-endf/endf102.pdf
.. _Monte Carlo Sampler: https://laws.lanl.gov/vhosts/mcnp.lanl.gov/pdf_files/la-9721.pdf
.. _Monte Carlo Sampler: https://permalink.lanl.gov/object/tr?what=info:lanl-repo/lareport/LA-09721-MS
.. _LA-UR-14-27694: http://permalink.lanl.gov/object/tr?what=info:lanl-repo/lareport/LA-UR-14-27694
.. _LA-UR-14-27694: https://permalink.lanl.gov/object/tr?what=info:lanl-repo/lareport/LA-UR-14-27694
.. _MC21: http://www.osti.gov/bridge/servlets/purl/903083-HT5p1o/903083.pdf
.. _MC21: https://www.osti.gov/biblio/903083
.. _Romano: https://doi.org/10.1016/j.cpc.2014.11.001
.. _Sutton and Brown: http://www.osti.gov/bridge/product.biblio.jsp?osti_id=307911
.. _Sutton and Brown: https://www.osti.gov/biblio/307911
.. _lectures: https://laws.lanl.gov/vhosts/mcnp.lanl.gov/pdf_files/la-ur-05-4983.pdf

View file

@ -251,8 +251,8 @@ depending on how many nodes are communicating and the size of the message. Using
multiple algorithms allows one to minimize latency for small messages and
minimize bandwidth for long messages.
We will focus here on the implementation of broadcast in the MPICH2_
implementation. For short messages, MPICH2 uses a `binomial tree`_ algorithm. In
We will focus here on the implementation of broadcast in the MPICH_
implementation. For short messages, MPICH uses a `binomial tree`_ algorithm. In
this algorithm, the root process sends the data to one node in the first step,
and then in the subsequent, both the root and the other node can send the data
to other nodes. Thus, it takes a total of :math:`\lceil \log_2 p \rceil` steps
@ -266,7 +266,7 @@ to complete the communication. The time to complete the communication is
This algorithm works well for short messages since the latency term scales
logarithmically with the number of nodes. However, for long messages, an
algorithm that has lower bandwidth has been proposed by Barnett_ and implemented
in MPICH2. Rather than using a binomial tree, the broadcast is divided into a
in MPICH. Rather than using a binomial tree, the broadcast is divided into a
scatter and an allgather. The time to complete the scatter is :math:` \log_2 p
\: \alpha + \frac{p-1}{p} N\beta` using a binomial tree algorithm. The allgather
is performed using a ring algorithm that completes in :math:`p-1) \alpha +
@ -613,7 +613,7 @@ is actually independent of the number of nodes:
.. _Brissenden and Garlick: https://doi.org/10.1016/0306-4549(86)90095-2
.. _MPICH2: http://www.mcs.anl.gov/mpi/mpich
.. _MPICH: http://www.mpich.org
.. _binomial tree: https://www.mcs.anl.gov/~thakur/papers/ijhpca-coll.pdf
@ -629,19 +629,19 @@ is actually independent of the number of nodes:
.. _message-passing interface: https://en.wikipedia.org/wiki/Message_Passing_Interface
.. _PVM: http://www.csm.ornl.gov/pvm/pvm_home.html
.. _PVM: https://www.csm.ornl.gov/pvm/pvm_home.html
.. _MPI: http://www.mcs.anl.gov/research/projects/mpi/
.. _MPI: https://www.mcs.anl.gov/research/projects/mpi/
.. _embarrassingly parallel: https://en.wikipedia.org/wiki/Embarrassingly_parallel
.. _sends: http://www.mcs.anl.gov/research/projects/mpi/www/www3/MPI_Send.html
.. _sends: https://www.mpich.org//static/docs/latest/www3/MPI_Send.html
.. _broadcasts: http://www.mcs.anl.gov/research/projects/mpi/www/www3/MPI_Bcast.html
.. _broadcasts: https://www.mpich.org//static/docs/latest/www3/MPI_Bcast.html
.. _scatter: http://www.mcs.anl.gov/research/projects/mpi/www/www3/MPI_Scatter.html
.. _scatter: https://www.mpich.org//static/docs/latest/www3/MPI_Scatter.html
.. _allgather: http://www.mcs.anl.gov/research/projects/mpi/www/www3/MPI_Allgather.html
.. _allgather: https://www.mpich.org//static/docs/latest/www3/MPI_Allgather.html
.. _Cauchy distribution: https://en.wikipedia.org/wiki/Cauchy_distribution

View file

@ -1004,6 +1004,8 @@ direction of the incident charged particle, which is a reasonable approximation
at higher energies when the bremsstrahlung radiation is emitted at small
angles.
.. _photon_production:
-----------------
Photon Production
-----------------
@ -1067,6 +1069,6 @@ emitted photon.
.. _Kaltiaisenaho: https://aaltodoc.aalto.fi/bitstream/handle/123456789/21004/master_Kaltiaisenaho_Toni_2016.pdf
.. _Salvat: http://www.oecd-nea.org/globalsearch/download.php?doc=77434
.. _Salvat: https://www.oecd-nea.org/globalsearch/download.php?doc=77434
.. _Sternheimer: https://doi.org/10.1103/PhysRevB.26.6067

View file

@ -7,8 +7,8 @@ Python API
OpenMC includes a rich Python API that enables programmatic pre- and
post-processing. The easiest way to begin using the API is to take a look at the
:ref:`examples`. This assumes that you are already familiar with Python and
common third-party packages such as `NumPy <http://www.numpy.org/>`_. If you
have never used Python before, the prospect of learning a new code *and* a
common third-party packages such as `NumPy <https://numpy.org/>`_. If you have
never used Python before, the prospect of learning a new code *and* a
programming language might sound daunting. However, you should keep in mind that
there are many substantial benefits to using the Python API, including:
@ -28,7 +28,7 @@ there are many substantial benefits to using the Python API, including:
For those new to Python, there are many good tutorials available online. We
recommend going through the modules from `Codecademy
<https://www.codecademy.com/learn/learn-python-3>`_ and/or the `Scipy lectures
<https://scipy-lectures.github.io/>`_.
<https://scipy-lectures.org/>`_.
The full API documentation serves to provide more information on a given module
or class.

View file

@ -12,7 +12,7 @@ OpenMC, see :ref:`usersguide_install` in the User's Manual.
Installing on Linux/Mac with conda-forge
----------------------------------------
`Conda <http://conda.pydata.org/docs/>`_ is an open source package management
`Conda <https://conda.io/en/latest/>`_ is an open source package management
system and environment management system for installing multiple versions of
software packages and their dependencies and switching easily between them. If
you have `conda` installed on your system, OpenMC can be installed via the
@ -25,16 +25,16 @@ you have `conda` installed on your system, OpenMC can be installed via the
To list the versions of OpenMC that are available on the `conda-forge` channel,
in your terminal window or an Anaconda Prompt run:
.. code-block:: sh
.. code-block:: sh
conda search openmc
OpenMC can then be installed with:
.. code-block:: sh
conda create -n openmc-env openmc
This will install OpenMC in a conda environment called `openmc-env`. To activate
the environment, run:
@ -42,66 +42,61 @@ the environment, run:
conda activate openmc-env
--------------------------------
Installing on Ubuntu through PPA
--------------------------------
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:
.. code-block:: sh
sudo apt-add-repository ppa:paulromano/staging
Next, resynchronize the package index files:
.. code-block:: sh
sudo apt update
Now OpenMC should be recognized within the repository and can be installed:
.. code-block:: sh
sudo apt install openmc
Binary packages from this PPA may exist for earlier versions of Ubuntu, but they
are no longer supported.
.. _Personal Package Archive: https://launchpad.net/~paulromano/+archive/staging
.. _APT package manager: https://help.ubuntu.com/community/AptGet/Howto
-------------------------------------------
Installing on Linux/Mac/Windows with Docker
-------------------------------------------
OpenMC can be easily deployed using `Docker <https://www.docker.com/>`_ on any
Windows, Mac or Linux system. With Docker running, execute the following
command in the shell to download and run a `Docker image`_ with the most recent release of OpenMC from `DockerHub <https://hub.docker.com/>`_ called ``openmc/openmc:v0.10.0``:
Windows, Mac, or Linux system. With Docker running, execute the following command
in the shell to download and run a `Docker image`_ with the most recent release
of OpenMC from `DockerHub <https://hub.docker.com/>`_:
.. code-block:: sh
docker run openmc/openmc:v0.10.0
docker run openmc/openmc:latest
This will take several minutes to run depending on your internet download speed. The command will place you in an interactive shell running in a `Docker container`_ with OpenMC installed.
This will take several minutes to run depending on your internet download speed.
The command will place you in an interactive shell running in a `Docker
container`_ with OpenMC installed.
.. note:: The ``docker run`` command supports many `options`_ for spawning
containers -- including `mounting volumes`_ from the host
filesystem -- which many users will find useful.
containers including `mounting volumes`_ from the host filesystem,
which many users will find useful.
.. _Docker image: https://docs.docker.com/engine/reference/commandline/images/
.. _Docker container: https://www.docker.com/resources/what-container
.. _options: https://docs.docker.com/engine/reference/commandline/run/
.. _mounting volumes: https://docs.docker.com/storage/volumes/
---------------------------------------
Installing from Source on Ubuntu 15.04+
---------------------------------------
----------------------------------
Installing from Source using Spack
----------------------------------
Spack_ is a package management tool designed to support multiple versions and
configurations of software on a wide variety of platforms and environments.
Please follow Spack's `setup guide`_ to configure the Spack system.
To install the latest OpenMC with the Python API, use the following command:
.. code-block:: sh
spack install py-openmc
For more information about customizations including MPI, see the
:ref:`detailed installation instructions using Spack <install-spack>`.
Once installed, environment/lmod modules can be generated or Spack's `load` feature
can be used to access the installed packages.
.. _Spack: https://spack.readthedocs.io/en/latest/
.. _setup guide: https://spack.readthedocs.io/en/latest/getting_started.html
--------------------------------
Installing from Source on Ubuntu
--------------------------------
To build OpenMC from source, several :ref:`prerequisites <prerequisites>` are
needed. If you are using Ubuntu 15.04 or higher, all prerequisites can be
installed directly from the package manager.
needed. If you are using Ubuntu or higher, all prerequisites can be installed
directly from the package manager:
.. code-block:: sh
@ -117,9 +112,9 @@ Installing from Source on Linux or Mac OS X
All OpenMC source code is hosted on `GitHub
<https://github.com/openmc-dev/openmc>`_. If you have `git
<https://git-scm.com>`_, the `gcc <https://gcc.gnu.org/>`_ compiler suite,
`CMake <http://www.cmake.org>`_, and `HDF5 <https://www.hdfgroup.org/HDF5/>`_
installed, you can download and install OpenMC be entering the following
commands in a terminal:
`CMake <https://cmake.org>`_, and `HDF5
<https://www.hdfgroup.org/solutions/hdf5/>`_ installed, you can download and
install OpenMC be entering the following commands in a terminal:
.. code-block:: sh
@ -140,8 +135,8 @@ should specify an installation directory where you have write access, e.g.
The :mod:`openmc` Python package must be installed separately. The easiest way
to install it is using `pip <https://pip.pypa.io/en/stable/>`_, which is
included by default in Python 2.7 and Python 3.4+. From the root directory of
the OpenMC distribution/repository, run:
included by default in Python 3.4+. From the root directory of the OpenMC
distribution/repository, run:
.. code-block:: sh

View file

@ -0,0 +1,122 @@
====================
What's New in 0.12.1
====================
.. currentmodule:: openmc
-------
Summary
-------
This release of OpenMC includes an assortment of new features and many bug
fixes. The :mod:`openmc.deplete` module incorporates a number of improvements in
usability, accuracy, and performance. Other enhancements include generalized
rotational periodic boundary conditions, expanded source modeling capabilities,
and a capability to generate windowed multipole library files from ENDF files.
------------
New Features
------------
- Boundary conditions have been refactored and generalized. Rotational periodic
boundary conditions can now be applied to any N-fold symmetric geometry.
- External source distributions have been refactored and extended. Users writing
their own C++ custom sources need to write a class that derives from
``openmc::Source``. These changes have enabled new functionality, such as:
- Mixing more than one custom source library together
- Mixing a normal source with a custom source
- Using a file-based source for fixed source simulations
- Using a file-based source for eigenvalue simulations even when the number of
particles doesn't match
- New capability to read and write a source file based on particles that cross a
surface (known as a "surface source").
- Various improvements related to depletion:
- Reactions used in a depletion chain can now be configured through the
``reactions`` argument to :meth:`openmc.deplete.Chain.from_endf`.
- Specifying a power of zero during a depletion simulation no longer results
in an unnecessary transport solve.
- Reaction rates can be computed either directly or using multigroup flux
tallies that are used to collapse reaction rates afterward. This is enabled
through the ``reaction_rate_mode`` and ``reaction_rate_opts`` to
:class:`openmc.deplete.Operator`.
- Depletion results can be used to create a new :class:`openmc.Materials`
object using the :meth:`openmc.deplete.ResultsList.export_to_materials`
method.
- Multigroup current and diffusion cross sections can be generated through the
:class:`openmc.mgxs.Current` and :class:`openmc.mgxs.DiffusionCoefficient`
classes.
- Added :func:`openmc.data.isotopes` function that returns a list of naturally
occurring isotopes for a given element.
- Windowed multipole libraries can now be generated directly from the Python API
using :meth:`openmc.data.WindowedMultipole.from_endf`.
- The new :func:`openmc.write_source_file` function allows source files to be
generated programmatically.
---------
Bug Fixes
---------
- `Proper detection of MPI wrappers <https://github.com/openmc-dev/openmc/pull/1619>`_
- `Fix related to declaration order of maps/vectors <https://github.com/openmc-dev/openmc/pull/1622>`_
- `Check for existence of decay rate attribute <https://github.com/openmc-dev/openmc/pull/1629>`_
- `Small updates to deal with JEFF 3.3 data <https://github.com/openmc-dev/openmc/pull/1638>`_
- `Fix for depletion chain generation <https://github.com/openmc-dev/openmc/pull/1642>`_
- `Fix call to superclass constructor in MeshPlotter <https://github.com/openmc-dev/openmc/pull/1644>`_
- `Fix for data crossover in VTK files <https://github.com/openmc-dev/openmc/pull/1645>`_
- `Make sure reaction names are recognized as valid tally scores <https://github.com/openmc-dev/openmc/pull/1647>`_
- `Fix bug related to logging of particle restarts <https://github.com/openmc-dev/openmc/pull/1649>`_
- `Examine if region exists before removing redundant surfaces <https://github.com/openmc-dev/openmc/pull/1650>`_
- `Fix plotting of individual universe levels <https://github.com/openmc-dev/openmc/pull/1651>`_
- `Mixed materials should inherit depletable attribute <https://github.com/openmc-dev/openmc/pull/1657>`_
- `Fix typo in energy units in dose coefficients <https://github.com/openmc-dev/openmc/pull/1659/files>`_
- `Fixes for large tally cases <https://github.com/openmc-dev/openmc/pull/1666>`_
- `Fix verification of volume calculation results <https://github.com/openmc-dev/openmc/pull/1677>`_
- `Fix calculation of decay energy for depletion chains <https://github.com/openmc-dev/openmc/pull/1679>`_
- `Fix pointers in CartesianIndependent <https://github.com/openmc-dev/openmc/pull/1681>`_
- `Ensure correct initialization of members for RegularMesh <https://github.com/openmc-dev/openmc/pull/1683>`_
- `Add missing import in depletion module <https://github.com/openmc-dev/openmc/pull/1715>`_
- `Fixed several bugs related to decay-rate <https://github.com/openmc-dev/openmc/pull/1718>`_
- `Fix how depletion operator distributes burnable materials <https://github.com/openmc-dev/openmc/pull/1719>`_
- `Fix assignment of elemental carbon in JEFF 3.3 <https://github.com/openmc-dev/openmc/pull/1722>`_
- `Fix typo in RectangularParallelepiped.__pos__ <https://github.com/openmc-dev/openmc/pull/1724>`_
- `Fix temperature tolerance with S(a,b) data <https://github.com/openmc-dev/openmc/pull/1733>`_
- `Fix sampling or normal distribution <https://github.com/openmc-dev/openmc/pull/1739>`_
- `Fix for SharedArray relaxed memory ordering <https://github.com/openmc-dev/openmc/pull/1764>`_
- `Check for proper format of source files <https://github.com/openmc-dev/openmc/pull/1771>`_
- `Ensure (n,gamma) reaction rate tally uses sampled cross section <https://github.com/openmc-dev/openmc/pull/1776>`_
- `Fix for temperature range behavior <https://github.com/openmc-dev/openmc/pull/1777>`_
------------
Contributors
------------
This release contains new contributions from the following people:
- `Andrew Davis <https://github.com/makeclean>`_
- `Guillaume Giudicelli <https://github.com/GiudGiud>`_
- `Sterling Harper <https://github.com/smharper>`_
- `Bryan Herman <https://github.com/bryanherman>`_
- `Yue Jin <https://github.com/kingyue737>`_
- `Andrew Johnson <https://github.com/drewejohnson>`_
- `Miriam Kreher <https://github.com/mkreher13>`_
- `Shikhar Kumar <https://github.com/shikhar413>`_
- `Jingang Liang <https://github.com/liangjg>`_
- `Amanda Lund <https://github.com/amandalund>`_
- `Adam Nelson <https://github.com/nelsonag>`_
- `April Novak <https://github.com/aprilnovak>`_
- `YoungHui Park <https://github.com/ypark234>`_
- `Ariful Islam Pranto <https://github.com/AI-Pranto>`_
- `Ron Rahaman <https://github.com/RonRahaman>`_
- `Gavin Ridley <https://github.com/gridley>`_
- `Paul Romano <https://github.com/paulromano>`_
- `Jonathan Shimwell <https://github.com/Shimwell>`_
- `Dan Short <https://github.com/DanShort12>`_
- `Patrick Shriwise <https://github.com/pshriwise>`_
- `Roy Stogner <https://github.com/roystgnr>`_
- `John Tramm <https://github.com/jtramm>`_
- `Cyrus Wyett <https://github.com/cjwyett>`_
- `Jiankai Yu <https://github.com/rockfool>`_

View file

@ -7,6 +7,7 @@ Release Notes
.. toctree::
:maxdepth: 1
0.12.1
0.12.0
0.11.0
0.10.0

View file

@ -5,13 +5,13 @@ Basics of Using OpenMC
======================
----------------
Creating a Model
Running a Model
----------------
When you build and install OpenMC, you will have an :ref:`scripts_openmc`
executable on your system. When you run ``openmc``, the first thing it will do
is look for a set of XML_ files that describe the model you want to
simulation. Three of these files are required and another three are optional, as
simulate. Three of these files are required and another three are optional, as
described below.
.. admonition:: Required
@ -43,6 +43,10 @@ described below.
This file gives specifications for producing slice or voxel plots of the
geometry.
.. warning::
OpenMC models should be treated as code, and it is important to be careful with code from untrusted sources.
eXtensible Markup Language (XML)
--------------------------------

View file

@ -113,7 +113,7 @@ or Mac OS X (also Unix-derived), `this tutorial
commonly-used commands.
To reap the full benefits of OpenMC, you should also have basic proficiency in
the use of `Python <http://www.python.org/>`_, as OpenMC includes a rich Python
the use of `Python <https://www.python.org/>`_, as OpenMC includes a rich Python
API that offers many usability improvements over dealing with raw XML input
files.
@ -126,8 +126,9 @@ at the git documentation website. The `OpenMC source code`_ and documentation
are hosted at `GitHub`_. In order to receive updates to the code directly,
submit `bug reports`_, and perform other development tasks, you may want to sign
up for a free account on GitHub. Once you have an account, you can follow `these
instructions <https://help.github.com/articles/set-up-git/>`_ on how to set up
your computer for using GitHub.
instructions
<https://docs.github.com/en/github/getting-started-with-github/set-up-git>`_ on
how to set up your computer for using GitHub.
If you are new to nuclear engineering, you may want to review the NRC's `Reactor
Concepts Manual`_. This manual describes the basics of nuclear power for
@ -149,7 +150,7 @@ and `Volume II`_. You may also find it helpful to review the following terms:
.. _discretization: https://en.wikipedia.org/wiki/Discretization
.. _constructive solid geometry: https://en.wikipedia.org/wiki/Constructive_solid_geometry
.. _git: http://git-scm.com/
.. _git tutorials: http://git-scm.com/documentation
.. _git tutorials: https://git-scm.com/doc
.. _Reactor Concepts Manual: http://www.tayloredge.com/periodic/trivia/ReactorConcepts.pdf
.. _Volume I: https://www.standards.doe.gov/standards-documents/1000/1019-bhdbk-1993-v1
.. _Volume II: https://www.standards.doe.gov/standards-documents/1000/1019-bhdbk-1993-v2

View file

@ -124,7 +124,7 @@ OpenMC.
.. hint:: The :class:`IncidentNeutron` class allows you to view/modify cross
sections, secondary angle/energy distributions, probability tables,
etc. For a more thorough overview of the capabilities of this class,
see the :ref:`notebook_nuclear_data` example notebook.
see the `example notebook <../examples/nuclear-data.ipynb>`__.
Manually Creating a Library from ENDF files
-------------------------------------------
@ -252,15 +252,15 @@ However, if obtained or generated their own library, the user
should set the :envvar:`OPENMC_MG_CROSS_SECTIONS` environment variable
to the absolute path of the file library expected to used most frequently.
For an example of how to create a multi-group library, see
:ref:`notebook_mg_mode_part_i`.
For an example of how to create a multi-group library, see the `example notebook
<../examples/mg-mode-part-i.ipynb>`__.
.. _NJOY: http://www.njoy21.io/
.. _NNDC: https://www.nndc.bnl.gov/endf
.. _MCNP: https://mcnp.lanl.gov
.. _Serpent: http://montecarlo.vtt.fi
.. _ENDF/B: https://www.nndc.bnl.gov/endf/b7.1/acefiles.html
.. _JEFF: http://www.oecd-nea.org/dbdata/jeff/jeff33/
.. _JEFF: https://www.oecd-nea.org/dbdata/jeff/jeff33/
.. _TENDL: https://tendl.web.psi.ch/tendl_2017/tendl2017.html
.. _Seltzer and Berger: https://doi.org/10.1016/0092-640X(86)90014-8
.. _NIST ESTAR database: https://physics.nist.gov/PhysRefData/Star/Text/ESTAR.html

View file

@ -30,6 +30,12 @@ operator class requires a :class:`openmc.Geometry` instance and a
Any material that contains a fissionable nuclide is depleted by default, but
this can behavior can be changed with the :attr:`Material.depletable` attribute.
.. important:: The volume must be specified for each material that is depleted by
setting the :attr:`Material.volume` attribute. This is necessary
in order to calculate the proper normalization of tally results
based on the source rate.
:mod:`openmc.deplete` supports multiple time-integration methods for determining
material compositions over time. Each method appears as a different class.
For example, :class:`openmc.deplete.CECMIntegrator` runs a depletion calculation

View file

@ -261,7 +261,7 @@ lowest-level cell at that location::
As you are building a geometry, it is also possible to display a plot of single
universe using the :meth:`Universe.plot` method. This method requires that you
have `matplotlib <http://matplotlib.org/>`_ installed.
have `matplotlib <https://matplotlib.org/>`_ installed.
.. _usersguide_lattices:

View file

@ -12,11 +12,11 @@ Installation and Configuration
Installing on Linux/Mac with conda-forge
----------------------------------------
`Conda <http://conda.pydata.org/docs/>`_ is an open source package management
system and environment management system for installing multiple versions of
software packages and their dependencies and switching easily between them. If
you have `conda` installed on your system, OpenMC can be installed via the
`conda-forge` channel. First, add the `conda-forge` channel with:
Conda_ is an open source package management system and environment management
system for installing multiple versions of software packages and their
dependencies and switching easily between them. If you have `conda` installed on
your system, OpenMC can be installed via the `conda-forge` channel. First, add
the `conda-forge` channel with:
.. code-block:: sh
@ -25,16 +25,16 @@ you have `conda` installed on your system, OpenMC can be installed via the
To list the versions of OpenMC that are available on the `conda-forge` channel,
in your terminal window or an Anaconda Prompt run:
.. code-block:: sh
.. code-block:: sh
conda search openmc
OpenMC can then be installed with:
.. code-block:: sh
conda create -n openmc-env openmc
This will install OpenMC in a conda environment called `openmc-env`. To activate
the environment, run:
@ -42,37 +42,118 @@ the environment, run:
conda activate openmc-env
.. _install_ppa:
-------------------------------------------
Installing on Linux/Mac/Windows with Docker
-------------------------------------------
-----------------------------
Installing on Ubuntu with PPA
-----------------------------
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:
OpenMC can be easily deployed using `Docker <https://www.docker.com/>`_ on any
Windows, Mac, or Linux system. With Docker running, execute the following
command in the shell to download and run a `Docker image`_ with the most recent
release of OpenMC from `DockerHub <https://hub.docker.com/>`_:
.. code-block:: sh
sudo apt-add-repository ppa:paulromano/staging
docker run openmc/openmc:latest
Next, resynchronize the package index files:
This will take several minutes to run depending on your internet download speed.
The command will place you in an interactive shell running in a `Docker
container`_ with OpenMC installed.
.. note:: The ``docker run`` command supports many `options`_ for spawning
containers including `mounting volumes`_ from the host filesystem,
which many users will find useful.
.. _Docker image: https://docs.docker.com/engine/reference/commandline/images/
.. _Docker container: https://www.docker.com/resources/what-container
.. _options: https://docs.docker.com/engine/reference/commandline/run/
.. _mounting volumes: https://docs.docker.com/storage/volumes/
.. _install-spack:
----------------------------------
Installing from Source using Spack
----------------------------------
Spack_ is a package management tool designed to support multiple versions and
configurations of software on a wide variety of platforms and environments.
Please follow Spack's `setup guide`_ to configure the Spack system.
The OpenMC Spack recipe has been configured with variants that match most
options provided in the CMakeLists.txt file. To see a list of these variants and
other information use:
.. code-block:: sh
sudo apt update
spack info openmc
Now OpenMC should be recognized within the repository and can be installed:
.. note::
It should be noted that by default OpenMC builds with ``-O2 -g`` flags which
are equivalent to a CMake build type of `RelwithDebInfo`. In addition, MPI
is OFF while OpenMP is ON.
It is recommended to install OpenMC with the Python API. Information about this
Spack recipe can be found with the following command:
.. code-block:: sh
sudo apt install openmc
spack info py-openmc
Binary packages from this PPA may exist for earlier versions of Ubuntu, but they
are no longer supported.
.. note::
The only variant for the Python API is ``mpi``.
The most basic installation of OpenMC can be accomplished by entering the
following command:
.. code-block::
spack install py-openmc
.. caution::
When installing any Spack package, dependencies are assumed to be at
configured defaults unless otherwise specfied in the specification on the
command line. In the above example, assuming the default options weren't
changed in Spack's package configuration, py-openmc will link against a
non-optimized non-MPI openmc. Even if an optimized openmc was built
separately, it will rebuild openmc with optimization OFF. Thus, if you are
trying to link against dependencies that were configured different than
defaults, ``^openmc[variants]`` will have to be present in the command.
For a more performant build of OpenMC with optimization turned ON and MPI
provided by OpenMPI, the following command can be used:
.. code-block:: sh
spack install py-openmc+mpi ^openmc+optimize ^openmpi
.. note::
``+mpi`` is automatically forwarded to OpenMC.
.. tip::
When installing py-openmc, it will use Spack's preferred Python. For
example, assuming Spack's preferred Python is 3.8.7, to build py-openmc
against the latest Python 3.7 instead, ``^python@3.7.0:3.7.99`` should be
added to the specification on the command line. Additionally, a compiler
type and version can be specified at the end of the command using
``%gcc@<version>``, ``%intel@<version>``, etc.
A useful tool in Spack is to look at the dependency tree before installation.
This can be observed using Spack's ``spec`` tool:
.. code-block::
spack spec py-openmc+mpi ^openmc+optimize
Once installed, environment/lmod modules can be generated or Spack's ``load``
feature can be used to access the installed packages.
.. _Spack: https://spack.readthedocs.io/en/latest/
.. _setup guide: https://spack.readthedocs.io/en/latest/getting_started.html
.. _Personal Package Archive: https://launchpad.net/~paulromano/+archive/staging
.. _APT package manager: https://help.ubuntu.com/community/AptGet/Howto
.. _install_source:
@ -162,9 +243,9 @@ Prerequisites
.. _gcc: https://gcc.gnu.org/
.. _CMake: http://www.cmake.org
.. _OpenMPI: http://www.open-mpi.org
.. _MPICH: http://www.mpich.org
.. _CMake: https://cmake.org
.. _OpenMPI: https://www.open-mpi.org
.. _MPICH: https://www.mpich.org
.. _HDF5: https://www.hdfgroup.org/solutions/hdf5/
.. _DAGMC: https://svalinn.github.io/DAGMC/index.html
@ -176,10 +257,10 @@ directly from GitHub or, if you have the git_ version control software installed
on your computer, you can use git to obtain the source code. The latter method
has the benefit that it is easy to receive updates directly from the GitHub
repository. GitHub has a good set of `instructions
<http://help.github.com/set-up-git-redirect>`_ for how to set up git to work
with GitHub since this involves setting up ssh_ keys. With git installed and
setup, the following command will download the full source code from the GitHub
repository::
<https://docs.github.com/en/github/getting-started-with-github/set-up-git>`_ for
how to set up git to work with GitHub since this involves setting up ssh_ keys.
With git installed and setup, the following command will download the full
source code from the GitHub repository::
git clone --recurse-submodules https://github.com/openmc-dev/openmc.git
@ -328,36 +409,11 @@ Compiling on Windows 10
Recent versions of Windows 10 include a subsystem for Linux that allows one to
run Bash within Ubuntu running in Windows. First, follow the installation guide
`here <https://msdn.microsoft.com/en-us/commandline/wsl/install_guide>`_ to get
Bash on Ubuntu on Windows setup. Once you are within bash, obtain the necessary
`here <https://docs.microsoft.com/en-us/windows/wsl/install-win10>`_ to get Bash
on Ubuntu on Windows setup. Once you are within bash, obtain the necessary
:ref:`prerequisites <prerequisites>` via ``apt``. Finally, follow the
:ref:`instructions for compiling on linux <compile_linux>`.
Compiling for the Intel Xeon Phi
--------------------------------
For the second generation Knights Landing architecture, nothing special is
required to compile OpenMC. You may wish to experiment with compiler flags that
control generation of vector instructions to see what configuration gives
optimal performance for your target problem.
For the first generation Knights Corner architecture, it is necessary to
cross-compile OpenMC. If you are using the Intel compiler, it is necessary to
specify that all objects be compiled with the ``-mmic`` flag as follows:
.. code-block:: sh
mkdir build && cd build
CXX=icpc CXXFLAGS=-mmic cmake -Dopenmp=on ..
make
Note that unless an HDF5 build for the Intel Xeon Phi (Knights Corner) is
already on your target machine, you will need to cross-compile HDF5 for the Xeon
Phi. An `example script`_ to build zlib and HDF5 provides several necessary
workarounds.
.. _example script: https://github.com/paulromano/install-scripts/blob/master/install-hdf5-mic
Testing Build
-------------
@ -369,16 +425,16 @@ section library along with windowed multipole data. Please refer to our
Installing Python API
---------------------
If you installed OpenMC using :ref:`Conda <install_conda>` or :ref:`PPA
<install_ppa>`, no further steps are necessary in order to use OpenMC's
:ref:`Python API <pythonapi>`. However, if you are :ref:`installing from source
<install_source>`, the Python API is not installed by default when ``make
install`` is run because in many situations it doesn't make sense to install a
Python package in the same location as the ``openmc`` executable (for example,
if you are installing the package into a `virtual environment
<https://docs.python.org/3/tutorial/venv.html>`_). The easiest way to install
the :mod:`openmc` Python package is to use pip_, which is included by default in
Python 3.4+. From the root directory of the OpenMC distribution/repository, run:
If you installed OpenMC using :ref:`Conda <install_conda>`, no further steps are
necessary in order to use OpenMC's :ref:`Python API <pythonapi>`. However, if
you are :ref:`installing from source <install_source>`, the Python API is not
installed by default when ``make install`` is run because in many situations it
doesn't make sense to install a Python package in the same location as the
``openmc`` executable (for example, if you are installing the package into a
`virtual environment <https://docs.python.org/3/tutorial/venv.html>`_). The
easiest way to install the :mod:`openmc` Python package is to use pip_, which is
included by default in Python 3.4+. From the root directory of the OpenMC
distribution/repository, run:
.. code-block:: sh
@ -414,7 +470,7 @@ distributions.
.. admonition:: Required
:class: error
`NumPy <http://www.numpy.org/>`_
`NumPy <https://numpy.org/>`_
NumPy is used extensively within the Python API for its powerful
N-dimensional array.
@ -422,23 +478,23 @@ distributions.
SciPy's special functions, sparse matrices, and spatial data structures
are used for several optional features in the API.
`pandas <http://pandas.pydata.org/>`_
`pandas <https://pandas.pydata.org/>`_
Pandas is used to generate tally DataFrames as demonstrated in
:ref:`examples_pandas` example notebook.
an `example notebook <../examples/pandas-dataframes.ipynb>`_.
`h5py <http://www.h5py.org/>`_
h5py provides Python bindings to the HDF5 library. Since OpenMC outputs
various HDF5 files, h5py is needed to provide access to data within these
files from Python.
`Matplotlib <http://matplotlib.org/>`_
`Matplotlib <https://matplotlib.org/>`_
Matplotlib is used to providing plotting functionality in the API like the
:meth:`Universe.plot` method and the :func:`openmc.plot_xs` function.
`uncertainties <https://pythonhosted.org/uncertainties/>`_
Uncertainties are used for decay data in the :mod:`openmc.data` module.
`lxml <http://lxml.de/>`_
`lxml <https://lxml.de/>`_
lxml is used for the :ref:`scripts_validate` script and various other
parts of the Python API.
@ -450,11 +506,11 @@ distributions.
parallel runs. This package is needed if you plan on running depletion
simulations in parallel using MPI.
`Cython <http://cython.org/>`_
`Cython <https://cython.org/>`_
Cython is used for resonance reconstruction for ENDF data converted to
:class:`openmc.data.IncidentNeutron`.
`vtk <http://www.vtk.org/>`_
`vtk <https://vtk.org/>`_
The Python VTK bindings are needed to convert voxel and track files to VTK
format.
@ -508,8 +564,7 @@ schemas.xml file in your own OpenMC source directory.
.. _GNU Emacs: http://www.gnu.org/software/emacs/
.. _validation: https://en.wikipedia.org/wiki/XML_validation
.. _RELAX NG: http://relaxng.org/
.. _NNDC: http://www.nndc.bnl.gov/endf/b7.1/acefiles.html
.. _ctest: http://www.cmake.org/cmake/help/v2.8.12/ctest.html
.. _Conda: https://docs.conda.io/en/latest/
.. _RELAX NG: https://relaxng.org/
.. _ctest: https://cmake.org/cmake/help/latest/manual/ctest.1.html
.. _Conda: https://conda.io/en/latest/
.. _pip: https://pip.pypa.io/en/stable/

View file

@ -45,7 +45,7 @@ This method can also accept case-insensitive element names such as
::
mat.add_element('aluminium', 1.0)
Internally, OpenMC stores data on the atomic masses and natural abundances of
all known isotopes and then uses this data to determine what isotopes should be
added to the material. When the material is later exported to XML for use by the
@ -105,7 +105,7 @@ you would need to add hydrogen and oxygen to a material and then assign the
Naming Conventions
------------------
OpenMC uses the GND_ naming convention for nuclides, metastable states, and
OpenMC uses the GNDS_ naming convention for nuclides, metastable states, and
compounds:
:Nuclides: ``SymA`` where "A" is the mass number (e.g., ``Fe56``)
@ -122,7 +122,7 @@ compounds:
ENDF/B-VII.1! If you are adding an element via
:meth:`Material.add_element`, just use ``Sym``.
.. _GND: https://www.oecd-nea.org/science/wpec/sg38/Meetings/2016_May/tlh4gnd-main.pdf
.. _GNDS: https://www.oecd-nea.org/jcms/pl_39689/specifications-for-the-generalised-nuclear-database-structure-gnds
-----------
Temperature
@ -160,26 +160,26 @@ Material Mixtures
-----------------
In OpenMC it is possible to mix any number of materials to create a new material
with the correct nuclide composition and density. The
with the correct nuclide composition and density. The
:meth:`Material.mix_materials` method takes a list of materials and
a list of their mixing fractions. Mixing fractions can be provided as atomic
a list of their mixing fractions. Mixing fractions can be provided as atomic
fractions, weight fractions, or volume fractions. The fraction type
can be specified by passing 'ao', 'wo', or 'vo' as the third argument, respectively.
For example, assuming the required materials have already been defined, a MOX
can be specified by passing 'ao', 'wo', or 'vo' as the third argument, respectively.
For example, assuming the required materials have already been defined, a MOX
material with 3% plutonium oxide by weight could be created using the following:
::
mox = openmc.Material.mix_materials([uo2, puo2], [0.97, 0.03], 'wo')
It should be noted that, if mixing fractions are specifed as atomic or weight
It should be noted that, if mixing fractions are specifed as atomic or weight
fractions, the supplied fractions should sum to one. If the fractions are specified
as volume fractions, and the sum of the fractions is less than one, then the remaining
fraction is set as void material.
as volume fractions, and the sum of the fractions is less than one, then the remaining
fraction is set as void material.
.. warning:: Materials with :math:`S(\alpha,\beta)` thermal scattering data
cannot be used in :meth:`Material.mix_materials`. However, thermal
scattering data can be added to a material created by
scattering data can be added to a material created by
:meth:`Material.mix_materials`.
--------------------

View file

@ -8,8 +8,8 @@ If you are running a simulation on a computer with multiple cores, multiple
sockets, or multiple nodes (i.e., a cluster), you can benefit from the fact that
OpenMC is able to use all available hardware resources if configured
correctly. OpenMC is capable of using both distributed-memory (`MPI
<http://mpi-forum.org/>`_) and shared-memory (`OpenMP
<http://www.openmp.org/>`_) parallelism. If you are on a single-socket
<https://www.mpi-forum.org/>`_) and shared-memory (`OpenMP
<https://www.openmp.org/>`_) parallelism. If you are on a single-socket
workstation or a laptop, using shared-memory parallelism is likely
sufficient. On a multi-socket node, cluster, or supercomputer, chances are you
will need to use both distributed-memory (across nodes) and shared-memory
@ -49,7 +49,7 @@ Distributed-Memory Parallelism (MPI)
MPI defines a library specification for message-passing between processes. There
are two major implementations of MPI, `OpenMPI <https://www.open-mpi.org/>`_ and
`MPICH <http://www.mpich.org/>`_. Both implementations are known to work with
`MPICH <https://www.mpich.org/>`_. Both implementations are known to work with
OpenMC; there is no obvious reason to prefer one over the other. Building OpenMC
with support for MPI requires that you have one of these implementations
installed on your system. For instructions on obtaining MPI, see

View file

@ -97,7 +97,7 @@ derivatives: ``sudo apt install imagemagick``). Images are then converted like:
convert myplot.ppm myplot.png
Alternatively, if you're working within a `Jupyter <http://jupyter.org/>`_
Alternatively, if you're working within a `Jupyter <https://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.
@ -122,7 +122,7 @@ should be three items long, e.g.::
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
`ParaView <https://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 formats. Once

View file

@ -34,13 +34,13 @@ as requested; it is used in many of the provided plotting utilities, OpenMC's
regression test suite, and can be used in user-created scripts to carry out
manipulations of the data.
An :ref:`example IPython notebook <notebook_post_processing>` demonstrates how
to extract data from a statepoint using the Python API.
An `example notebook <../examples/post-processing.ipynb>`_ demonstrates how to
extract data from a statepoint using the Python API.
Plotting in 2D
--------------
The :ref:`IPython notebook example <notebook_post_processing>` also demonstrates
The `notebook example <../examples/post-processing.ipynb>`_ also demonstrates
how to plot a structured mesh tally in two dimensions using the Python API. One
can also use the :ref:`scripts_plot` script which provides an interactive GUI to
explore and plot structured mesh tallies for any scores and filter bins.
@ -54,7 +54,7 @@ Getting Data into MATLAB
There is currently no front-end utility to dump tally data to MATLAB files, but
the process is straightforward. First extract the data using the Python API via
``openmc.statepoint`` and then use the `Scipy MATLAB IO routines
<http://docs.scipy.org/doc/scipy/reference/tutorial/io.html>`_ to save to a MAT
<https://docs.scipy.org/doc/scipy/reference/tutorial/io.html>`_ to save to a MAT
file. Note that all arrays that are accessible in a statepoint are already in
NumPy arrays that can be reshaped and dumped to MATLAB in one step.
@ -101,5 +101,5 @@ For eigenvalue problems, OpenMC will store information on the fission source
sites in the statepoint file by default. For each source site, the weight,
position, sampled direction, and sampled energy are stored. To extract this data
from a statepoint file, the ``openmc.statepoint`` module can be used. An
:ref:`example IPython notebook <notebook_post_processing>` demontrates how to
`example notebook <../examples/post-processing.ipynb>`_ demontrates how to
analyze and plot source information.

View file

@ -13,7 +13,13 @@ Executables and Scripts
Once you have a model built (see :ref:`usersguide_basics`), you can either run
the openmc executable directly from the directory containing your XML input
files, or you can specify as a command-line argument the directory containing
the XML input files. For example, if your XML input files are in the directory
the XML input files.
.. warning::
OpenMC models should be treated as code, and it is important to be careful with code from untrusted sources.
For example, if your XML input files are in the directory
``/home/username/somemodel/``, one way to run the simulation would be:
.. code-block:: sh
@ -96,61 +102,6 @@ otherwise.
--fission_energy_release FISSION_ENERGY_RELEASE
HDF5 file containing fission energy release data
.. _scripts_compton:
-----------------------
``openmc-make-compton``
-----------------------
This script generates an HDF5 file called ``compton_profiles.h5`` that contains
Compton profile data using an existing data library from `Geant4
<http://geant4.cern.ch/>`_. Note that OpenMC includes this data file by default
so it should not be necessary in practice to generate it yourself.
.. _scripts_depletion_chain:
-------------------------------
``openmc-make-depletion-chain``
-------------------------------
This script generates a depletion chain file called ``chain_endfb71.xml``
using ENDF/B-VII.1 nuclear data. If the :envvar:`OPENMC_ENDF_DATA` variable
is not set, and ``"neutron"``, ``"decay"``, ``"nfy"`` directories
do not exist, then ENDF/B-VII.1 data will be downloaded.
.. _scripts_depletion_chain_casl:
------------------------------------
``openmc-make-depletion-chain-casl``
------------------------------------
This script generates a depletion chain called ``chain_casl.xml``
using ENDF/B-VII.1 nuclear data for a simplified chain.
The nuclides were chosen by CASL-ORIGEN, which can be found in
Appendix A of Kang Seog Kim, `"Specification for the VERA Depletion
Benchmark Suite" <https://doi.org/10.2172/1256820>`_,
CASL-U-2015-1014-000, Rev. 0, ORNL/TM-2016/53, 2016.
``Te129`` has been added into this chain due to its link to
``I129`` production.
If the :envvar:`OPENMC_ENDF_DATA` variable is not set,
and ``"neutron"``, ``"decay"``, ``"nfy"`` directories
to not exist, then ENDF/B-VII.1 data will be downloaded.
.. _scripts_stopping:
-------------------------------
``openmc-make-stopping-powers``
-------------------------------
This script generates an HDF5 file called ``stopping_power.h5`` that contains
radiative and collision stopping powers and mean excitation energy pulled from
the `NIST ESTAR database
<https://physics.nist.gov/PhysRefData/Star/Text/ESTAR.html>`_. Note that OpenMC
includes this data file by default so it should not be necessary in practice to
generate it yourself.
.. _scripts_plot:
--------------------------
@ -244,7 +195,7 @@ Message Description
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-vtk`` script converts a voxel HDF5 file to a `VTK
<http://www.vtk.org/>`_ file. To run this script, you will need to have the VTK
<https://vtk.org/>`_ file. To run this script, you will need to have the VTK
Python bindings installed. To convert a voxel file, simply provide the path to
the file:

View file

@ -54,9 +54,9 @@ If you don't specify a run mode, the default run mode is 'eigenvalue'.
.. _usersguide_particles:
-------------------
Number of Particles
-------------------
------------
Run Strategy
------------
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
@ -88,6 +88,79 @@ for accumulating tallies.
settings.batches = 150
settings.inactive = 5
.. _usersguide_batches:
Number of Batches
-----------------
In general, the stochastic uncertainty in your simulation results is directly
related to how many total active particles are simulated (the product of the
number of active batches, number of generations per batch, and number of
particles). At a minimum, you should use enough active batches so that the
central limit theorem is satisfied (about 30). Otherwise, reducing the overall
uncertainty in your simulation by a factor of 2 will require using 4 times as
many batches (since the standard deviation decreases as :math:`1/\sqrt{N}`).
Number of Inactive Batches
--------------------------
For :math:`k` eigenvalue simulations, the source distribution is not known a
priori. Thus, a "guess" of the source distribution is made and then iterated on,
with the source evolving closer to the true distribution at each iteration. Once
the source distribution has converged, it is then safe to start accumulating
tallies. Consequently, a preset number of inactive batches are run before the
active batches (where tallies are turned on) begin. The number of inactive
batches necessary to reach a converged source depends on the spatial extent of
the problem, its dominance ratio, what boundary conditions are used, and many
other factors. For small problems, using 50--100 inactive batches is likely
sufficient. For larger models, many hundreds of inactive batches may be
necessary. Users are recommended to use the :ref:`Shannon entropy
<usersguide_entropy>` diagnostic as a way of determining how many inactive
batches are necessary.
Specifying the initial source used for the very first batch is described in
:ref:`below <usersguide_source>`. Although the initial source is arbitrary in
the sense that any source will eventually converge to the correct distribution,
using a source guess that is closer to the actual converged source distribution
will translate into needing fewer inactive batches (and hence less simulation
time).
For fixed source simulations, the source distribution is known exactly, so no
inactive batches are needed. In this case the :attr:`Settings.inactive`
attribute can be omitted since it defaults to zero.
Number of Generations per Batch
-------------------------------
The standard deviation of tally results is calculated assuming that all
realizations (batches) are independent. However, in a :math:`k` eigenvalue
calculation, the source sites for each batch are produced from fissions in the
preceding batch, resulting in a correlation between successive batches. This
correlation can result in an underprediction of the variance. That is, the
variance reported is actually less than the true variance. To mitigate this
effect, OpenMC allows you to group together multiple fission generations into a
single batch for statistical purposes, rather than having each fission
generation be a separate batch, which is the default behavior.
Number of Particles per Generation
----------------------------------
There are several considerations for choosing the number of particles per
generation. As discussed in :ref:`usersguide_batches`, the total number of
active particles will determine the level of stochastic uncertainty in
simulation results, so using a higher number of particles will result in less
uncertainty. For parallel simulations that use OpenMP and/or MPI, the number of
particles per generation should be large enough to ensure good load balancing
between threads. For example, if you are running on a single processor with 32
cores, each core should have at least 100 particles or so (i.e., at least 3,200
particles per generation should be used). Using a larger number of particles per
generation can also help reduce the cost of synchronization and communication
between batches. For :math:`k` eigenvalue calculations, experts recommend_ at
least 10,000 particles per generation to avoid any bias in the estimate of
:math:`k` eigenvalue or tallies.
.. _recommend: https://permalink.lanl.gov/object/tr?what=info:lanl-repo/lareport/LA-UR-09-03136
.. _usersguide_source:
-----------------------------
@ -175,6 +248,32 @@ following would generate a photon source::
For a full list of all classes related to statistical distributions, see
:ref:`pythonapi_stats`.
File-based Sources
------------------
OpenMC can use a pregenerated HDF5 source file by specifying the ``filename``
argument to :class:`openmc.Source`::
settings.source = openmc.Source(filename='source.h5')
Statepoint and source files are generated automatically when a simulation is run
and can be used as the starting source in a new simulation. Alternatively, a
source file can be manually generated with the :func:`openmc.write_source_file`
function. This is particularly useful for coupling OpenMC with another program
that generates a source to be used in OpenMC.
A source file based on particles that cross one or more surfaces can be
generated during a simulation using the :attr:`Settings.surf_source_write`
attribute::
settings.surf_source_write = {
'surfaces_ids': [1, 2, 3],
'max_particles': 10000
}
In this example, at most 10,000 source particles are stored when particles cross
surfaces with IDs of 1, 2, or 3.
.. _custom_source:
Custom Sources
@ -301,6 +400,8 @@ the source class when it is created:
As with the basic custom source functionality, the custom source library
location must be provided in the :attr:`openmc.Source.library` attribute.
.. _usersguide_entropy:
---------------
Shannon Entropy
---------------

View file

@ -5,7 +5,7 @@
"metadata": {},
"source": [
"# Using CAD-Based Geometries\n",
"In this notebook we'll be exploring how to use CAD-based geometries in OpenMC via the [DagMC](https://svalinn.github.io/DAGMC/index.html) toolkit. The models we'll be using in this notebook have already been created using [Trelis](https://www.csimsoft.com/trelis) and faceted into a surface mesh represented as `.h5m` files in the [Mesh Oriented DatABase](https://press3.mcs.anl.gov/sigma/moab-library/) format. We'll be retrieving these files using the function below.\n",
"In this notebook we'll be exploring how to use CAD-based geometries in OpenMC via the [DagMC](https://svalinn.github.io/DAGMC/index.html) toolkit. The models we'll be using in this notebook have already been created using [Trelis](https://coreform.com/products/trelisnew/) and faceted into a surface mesh represented as `.h5m` files in the [Mesh Oriented DatABase](https://sigma.mcs.anl.gov/moab-library/) format. We'll be retrieving these files using the function below.\n",
"\n"
]
},
@ -93,7 +93,7 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"Let's download the DAGMC model. These models come in the form of triangle surface meshes stored using the the Mesh Oriented datABase ([MOAB](https://press3.mcs.anl.gov/sigma/moab-library/)) in an HDF5 file with the extension `.h5m`. An example of a coarse triangle mesh looks like:"
"Let's download the DAGMC model. These models come in the form of triangle surface meshes stored using the the Mesh Oriented datABase ([MOAB](https://sigma.mcs.anl.gov/moab-library/)) in an HDF5 file with the extension `.h5m`. An example of a coarse triangle mesh looks like:"
]
},
{
@ -234,7 +234,7 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"**Note:** Applying tally filters in DagMC models requires prior knowledge of the model. Here, we know that the fuel cell's volume ID in the CAD sofware is 1. To identify cells without use of CAD software, load them into the [OpenMC plotter](https://github.com/openmc/plotter) where cell, material, and volume IDs can be identified for native both OpenMC and DagMC geometries."
"**Note:** Applying tally filters in DagMC models requires prior knowledge of the model. Here, we know that the fuel cell's volume ID in the CAD sofware is 1. To identify cells without use of CAD software, load them into the [OpenMC plotter](https://github.com/openmc-dev/plotter) where cell, material, and volume IDs can be identified for native both OpenMC and DagMC geometries."
]
},
{

View file

@ -4,6 +4,7 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"# Using the C/C++ API\n",
"This notebook shows how to use the OpenMC C/C++ API through the openmc.lib module. This module is particularly useful for multiphysics coupling because it allows you to update the density of materials and the temperatures of cells in memory, without stopping the simulation.\n",
"\n",
"Warning: these bindings are still somewhat experimental and may be subject to change in future versions of OpenMC."
@ -466,7 +467,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.9.0"
"version": "3.8.3"
}
},
"nbformat": 4,

View file

@ -89,7 +89,7 @@
"\n",
"$$\\nu_d \\sigma_{n,x,k,g} = \\frac{\\int_{E_{g}}^{E_{g-1}}\\mathrm{d}E'\\int_{\\mathbf{r} \\in V_{k}}\\mathrm{d}\\mathbf{r} \\nu_d \\sigma_{f,x}(\\mathbf{r},E')\\Phi(\\mathbf{r},E')}{\\int_{E_{g}}^{E_{g-1}}\\mathrm{d}E'\\int_{\\mathbf{r} \\in V_{k}}\\mathrm{d}\\mathbf{r}\\Phi(\\mathbf{r},E')}$$\n",
"\n",
"This scalar flux-weighted average microscopic cross section is computed by `openmc.mgxs` for only the delayed-nu-fission and delayed neutron fraction reaction type at the moment. These double integrals are stochastically computed with OpenMC's tally system - in particular, [filters](https://docs.openmc.org/en/stable/usersguide/tallies.html#filters) on the energy range and spatial zone (material, cell, universe, or mesh) define the bounds of integration for both numerator and denominator."
"This scalar flux-weighted average microscopic cross section is computed by `openmc.mgxs` for only the delayed-nu-fission and delayed neutron fraction reaction type at the moment. These double integrals are stochastically computed with OpenMC's tally system - in particular, [filters](../usersguide/tallies.rst#filters) on the energy range and spatial zone (material, cell, universe, or mesh) define the bounds of integration for both numerator and denominator."
]
},
{
@ -702,7 +702,7 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"Since the `openmc.mgxs` module uses [tally arithmetic](https://mit-crpg.github.io/openmc/pythonapi/examples/tally-arithmetic.html) under-the-hood, the cross section is stored as a \"derived\" `Tally` object. This means that it can be queried and manipulated using all of the same methods supported for the `Tally` class in the OpenMC Python API. For example, we can construct a [Pandas](http://pandas.pydata.org/) `DataFrame` of the multi-group cross section data."
"Since the `openmc.mgxs` module uses [tally arithmetic](tally-arithmetic.ipynb) under-the-hood, the cross section is stored as a \"derived\" `Tally` object. This means that it can be queried and manipulated using all of the same methods supported for the `Tally` class in the OpenMC Python API. For example, we can construct a [Pandas](https://pandas.pydata.org/) `DataFrame` of the multi-group cross section data."
]
},
{
@ -1077,7 +1077,7 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"Finally, we illustrate how one can leverage OpenMC's [tally arithmetic](https://mit-crpg.github.io/openmc/pythonapi/examples/tally-arithmetic.html) data processing feature with `MGXS` objects. The `openmc.mgxs` module uses tally arithmetic to compute multi-group cross sections with automated uncertainty propagation. Each `MGXS` object includes an `xs_tally` attribute which is a \"derived\" `Tally` based on the tallies needed to compute the cross section type of interest. These derived tallies can be used in subsequent tally arithmetic operations. For example, we can use tally artithmetic to compute the delayed neutron precursor concentrations using the `Beta`, `DelayedNuFissionXS`, and `DecayRate` objects. The delayed neutron precursor concentrations are modeled using the following equations:\n",
"Finally, we illustrate how one can leverage OpenMC's [tally arithmetic](tally-arithmetic.ipynb) data processing feature with `MGXS` objects. The `openmc.mgxs` module uses tally arithmetic to compute multi-group cross sections with automated uncertainty propagation. Each `MGXS` object includes an `xs_tally` attribute which is a \"derived\" `Tally` based on the tallies needed to compute the cross section type of interest. These derived tallies can be used in subsequent tally arithmetic operations. For example, we can use tally artithmetic to compute the delayed neutron precursor concentrations using the `Beta`, `DelayedNuFissionXS`, and `DecayRate` objects. The delayed neutron precursor concentrations are modeled using the following equations:\n",
"\n",
"$$\\frac{\\partial}{\\partial t} C_{k,d} (t) = \\int_{0}^{\\infty}\\mathrm{d}E'\\int_{\\mathbf{r} \\in V_{k}}\\mathrm{d}\\mathbf{r} \\beta_{k,d} (t) \\nu_d \\sigma_{f,x}(\\mathbf{r},E',t)\\Phi(\\mathbf{r},E',t) - \\lambda_{d} C_{k,d} (t) $$\n",
"\n",

View file

@ -652,7 +652,7 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"Finally, we illustrate how one can leverage OpenMC's [tally arithmetic](https://mit-crpg.github.io/openmc/pythonapi/examples/tally-arithmetic.html) data processing feature with `MGXS` objects. The `openmc.mgxs` module uses tally arithmetic to compute multi-group cross sections with automated uncertainty propagation. Each `MGXS` object includes an `xs_tally` attribute which is a \"derived\" `Tally` based on the tallies needed to compute the cross section type of interest. These derived tallies can be used in subsequent tally arithmetic operations. For example, we can use tally artithmetic to compute the delayed neutron precursor concentrations using the `Beta` and `DelayedNuFissionXS` objects. The delayed neutron precursor concentrations are modeled using the following equations:\n",
"Finally, we illustrate how one can leverage OpenMC's [tally arithmetic](tally-arithmetic.ipynb) data processing feature with `MGXS` objects. The `openmc.mgxs` module uses tally arithmetic to compute multi-group cross sections with automated uncertainty propagation. Each `MGXS` object includes an `xs_tally` attribute which is a \"derived\" `Tally` based on the tallies needed to compute the cross section type of interest. These derived tallies can be used in subsequent tally arithmetic operations. For example, we can use tally artithmetic to compute the delayed neutron precursor concentrations using the `Beta` and `DelayedNuFissionXS` objects. The delayed neutron precursor concentrations are modeled using the following equations:\n",
"\n",
"$$\\frac{\\partial}{\\partial t} C_{k,d} (t) = \\int_{0}^{\\infty}\\mathrm{d}E'\\int_{\\mathbf{r} \\in V_{k}}\\mathrm{d}\\mathbf{r} \\beta_{k,d} (t) \\nu_d \\sigma_{f,x}(\\mathbf{r},E',t)\\Phi(\\mathbf{r},E',t) - \\lambda_{d} C_{k,d} (t) $$\n",
"\n",

View file

@ -5,7 +5,7 @@
"metadata": {},
"source": [
"# Multigroup Mode Part I: Introduction\n",
"This Notebook illustrates the usage of OpenMC's multi-group calculational mode with the Python API. This example notebook creates and executes the 2-D [C5G7](https://www.oecd-nea.org/science/docs/2003/nsc-doc2003-16.pdf) benchmark model using the `openmc.MGXSLibrary` class to create the supporting data library on the fly."
"This Notebook illustrates the usage of OpenMC's multi-group calculational mode with the Python API. This example notebook creates and executes the 2-D [C5G7](https://www.oecd-nea.org/jcms/pl_17882) benchmark model using the `openmc.MGXSLibrary` class to create the supporting data library on the fly."
]
},
{
@ -38,7 +38,7 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"We will now create the multi-group library using data directly from Appendix A of the [C5G7](https://www.oecd-nea.org/science/docs/2003/nsc-doc2003-16.pdf) benchmark documentation. All of the data below will be created at 294K, consistent with the benchmark.\n",
"We will now create the multi-group library using data directly from Appendix A of the [C5G7](https://www.oecd-nea.org/jcms/pl_17882) benchmark documentation. All of the data below will be created at 294K, consistent with the benchmark.\n",
"\n",
"This notebook will first begin by setting the group structure and building the groupwise data for UO2. As you can see, the cross sections are input in the order of increasing groups (or decreasing energy).\n",
"\n",

View file

@ -88,7 +88,7 @@
"\n",
"$$\\sigma_{n,x,k,g} = \\frac{\\int_{E_{g}}^{E_{g-1}}\\mathrm{d}E'\\int_{\\mathbf{r} \\in V_{k}}\\mathrm{d}\\mathbf{r}\\sigma_{n,x}(\\mathbf{r},E')\\Phi(\\mathbf{r},E')}{\\int_{E_{g}}^{E_{g-1}}\\mathrm{d}E'\\int_{\\mathbf{r} \\in V_{k}}\\mathrm{d}\\mathbf{r}\\Phi(\\mathbf{r},E')}$$\n",
"\n",
"This scalar flux-weighted average microscopic cross section is computed by `openmc.mgxs` for most multi-group cross sections, including total, absorption, and fission reaction types. These double integrals are stochastically computed with OpenMC's tally system - in particular, [filters](http://openmc.readthedocs.io/en/latest/usersguide/tallies.html#filters) on the energy range and spatial zone (material, cell or universe) define the bounds of integration for both numerator and denominator."
"This scalar flux-weighted average microscopic cross section is computed by `openmc.mgxs` for most multi-group cross sections, including total, absorption, and fission reaction types. These double integrals are stochastically computed with OpenMC's tally system - in particular, [filters](../usersguide/tallies.rst#filters) on the energy range and spatial zone (material, cell or universe) define the bounds of integration for both numerator and denominator."
]
},
{
@ -712,7 +712,7 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"Since the `openmc.mgxs` module uses [tally arithmetic](http://openmc.readthedocs.io/en/latest/examples/tally-arithmetic.html) under-the-hood, the cross section is stored as a \"derived\" `Tally` object. This means that it can be queried and manipulated using all of the same methods supported for the `Tally` class in the OpenMC Python API. For example, we can construct a [Pandas](http://pandas.pydata.org/) `DataFrame` of the multi-group cross section data."
"Since the `openmc.mgxs` module uses [tally arithmetic](../examples/tally-arithmetic.rst) under-the-hood, the cross section is stored as a \"derived\" `Tally` object. This means that it can be queried and manipulated using all of the same methods supported for the `Tally` class in the OpenMC Python API. For example, we can construct a [Pandas](https://pandas.pydata.org/) `DataFrame` of the multi-group cross section data."
]
},
{
@ -817,7 +817,7 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"Finally, we illustrate how one can leverage OpenMC's [tally arithmetic](http://openmc.readthedocs.io/en/latest/examples/tally-arithmetic.html) data processing feature with `MGXS` objects. The `openmc.mgxs` module uses tally arithmetic to compute multi-group cross sections with automated uncertainty propagation. Each `MGXS` object includes an `xs_tally` attribute which is a \"derived\" `Tally` based on the tallies needed to compute the cross section type of interest. These derived tallies can be used in subsequent tally arithmetic operations. For example, we can use tally artithmetic to confirm that the `TotalXS` is equal to the sum of the `AbsorptionXS` and `ScatterXS` objects."
"Finally, we illustrate how one can leverage OpenMC's [tally arithmetic](../examples/tally-arithmetic.rst) data processing feature with `MGXS` objects. The `openmc.mgxs` module uses tally arithmetic to compute multi-group cross sections with automated uncertainty propagation. Each `MGXS` object includes an `xs_tally` attribute which is a \"derived\" `Tally` based on the tallies needed to compute the cross section type of interest. These derived tallies can be used in subsequent tally arithmetic operations. For example, we can use tally artithmetic to confirm that the `TotalXS` is equal to the sum of the `AbsorptionXS` and `ScatterXS` objects."
]
},
{

View file

@ -9,12 +9,12 @@
"\n",
"* Creation of multi-group cross sections on a **heterogeneous geometry**\n",
"* Calculation of cross sections on a **nuclide-by-nuclide basis**\n",
"* The use of **[tally precision triggers](http://docs.openmc.org/en/latest/io_formats/settings.html#trigger-element)** with multi-group cross sections\n",
"* The use of **[tally precision triggers](../io_formats/settings.rst#trigger-element)** with multi-group cross sections\n",
"* Built-in features for **energy condensation** in downstream data processing\n",
"* The use of the **`openmc.data`** module to plot continuous-energy vs. multi-group cross sections\n",
"* **Validation** of multi-group cross sections with **[OpenMOC](https://mit-crpg.github.io/OpenMOC/)**\n",
"\n",
"**Note:** This Notebook was created using [OpenMOC](https://mit-crpg.github.io/OpenMOC/) to verify the multi-group cross-sections generated by OpenMC. You must install [OpenMOC](https://mit-crpg.github.io/OpenMOC/) on your system in order to run this Notebook in its entirety. In addition, this Notebook illustrates the use of [Pandas](http://pandas.pydata.org/) `DataFrames` to containerize multi-group cross section data."
"**Note:** This Notebook was created using [OpenMOC](https://mit-crpg.github.io/OpenMOC/) to verify the multi-group cross-sections generated by OpenMC. You must install [OpenMOC](https://mit-crpg.github.io/OpenMOC/) on your system in order to run this Notebook in its entirety. In addition, this Notebook illustrates the use of [Pandas](https://pandas.pydata.org/) `DataFrames` to containerize multi-group cross section data."
]
},
{
@ -264,7 +264,7 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"Next, we showcase the use of OpenMC's [tally precision trigger](http://openmc.readthedocs.io/en/latest/io_formats/settings.html#trigger-element) feature in conjunction with the `openmc.mgxs` module. In particular, we will assign a tally trigger of 1E-2 on the standard deviation for each of the tallies used to compute multi-group cross sections."
"Next, we showcase the use of OpenMC's [tally precision trigger](../io_formats/settings.rst#trigger-element) feature in conjunction with the `openmc.mgxs` module. In particular, we will assign a tally trigger of 1E-2 on the standard deviation for each of the tallies used to compute multi-group cross sections."
]
},
{
@ -745,7 +745,7 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"Although a printed report is nice, it is not scalable or flexible. Let's extract the microscopic cross section data for the moderator as a [Pandas](http://pandas.pydata.org/) `DataFrame` ."
"Although a printed report is nice, it is not scalable or flexible. Let's extract the microscopic cross section data for the moderator as a [Pandas](https://pandas.pydata.org/) `DataFrame` ."
]
},
{

View file

@ -12,7 +12,7 @@
"* **Validation** of multi-group cross sections with **[OpenMOC](https://mit-crpg.github.io/OpenMOC/)**\n",
"* Steady-state pin-by-pin **fission rates comparison** between OpenMC and [OpenMOC](https://mit-crpg.github.io/OpenMOC/)\n",
"\n",
"**Note:** This Notebook was created using [OpenMOC](https://mit-crpg.github.io/OpenMOC/) to verify the multi-group cross-sections generated by OpenMC. You must install [OpenMOC](https://mit-crpg.github.io/OpenMOC/) on your system to run this Notebook in its entirety. In addition, this Notebook illustrates the use of [Pandas](http://pandas.pydata.org/) `DataFrames` to containerize multi-group cross section data."
"**Note:** This Notebook was created using [OpenMOC](https://mit-crpg.github.io/OpenMOC/) to verify the multi-group cross-sections generated by OpenMC. You must install [OpenMOC](https://mit-crpg.github.io/OpenMOC/) on your system to run this Notebook in its entirety. In addition, this Notebook illustrates the use of [Pandas](https://pandas.pydata.org/) `DataFrames` to containerize multi-group cross section data."
]
},
{
@ -811,7 +811,7 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"The `NuFissionXS` object supports all of the methods described previously in the `openmc.mgxs` tutorials, such as [Pandas](http://pandas.pydata.org/) `DataFrames`:\n",
"The `NuFissionXS` object supports all of the methods described previously in the `openmc.mgxs` tutorials, such as [Pandas](https://pandas.pydata.org/) `DataFrames`:\n",
"Note that since so few histories were simulated, we should expect a few division-by-error errors as some tallies have not yet scored any results."
]
},
@ -994,7 +994,7 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"The HDF5 store will contain the numerical multi-group cross section data indexed by domain, nuclide and cross section type. Some data workflows may be optimized by storing and retrieving binary representations of the `MGXS` objects in the `Library`. This feature is supported through the `Library.dump_to_file(...)` and `Library.load_from_file(...)` routines which use Python's [`pickle`](https://docs.python.org/2/library/pickle.html) module. This is illustrated as follows."
"The HDF5 store will contain the numerical multi-group cross section data indexed by domain, nuclide and cross section type. Some data workflows may be optimized by storing and retrieving binary representations of the `MGXS` objects in the `Library`. This feature is supported through the `Library.dump_to_file(...)` and `Library.load_from_file(...)` routines which use Python's [`pickle`](https://docs.python.org/3/library/pickle.html) module. This is illustrated as follows."
]
},
{

View file

@ -900,7 +900,7 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"If had [Cython](http://cython.org/) installed when you built/installed OpenMC, you should be able to evaluate resonant cross sections from ENDF data directly, i.e., OpenMC will reconstruct resonances behind the scenes for you."
"If you had [Cython](https://cython.org/) installed when you built/installed OpenMC, you should be able to evaluate resonant cross sections from ENDF data directly, i.e., OpenMC will reconstruct resonances behind the scenes for you."
]
},
{

View file

@ -567,7 +567,7 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"The statepoint file actually stores the sum and sum-of-squares for each tally bin from which the mean and variance can be calculated as described [here](http://openmc.readthedocs.io/en/latest/methods/tallies.html#variance). The sum and sum-of-squares can be accessed using the ``sum`` and ``sum_sq`` properties:"
"The statepoint file actually stores the sum and sum-of-squares for each tally bin from which the mean and variance can be calculated as described [here](../methods/tallies.rst#variance). The sum and sum-of-squares can be accessed using the ``sum`` and ``sum_sq`` properties:"
]
},
{

View file

@ -36,7 +36,7 @@
"\n",
"To perform the search we will use the `openmc.search_for_keff` function. This function requires a different function be defined which creates an parametrized model to analyze. This model is required to be stored in an `openmc.model.Model` object. The first parameter of this function will be modified during the search process for our critical eigenvalue.\n",
"\n",
"Our model will be a pin-cell from the [Multi-Group Mode Part II](http://docs.openmc.org/en/latest/examples/mg-mode-part-ii.html) assembly, except this time the entire model building process will be contained within a function, and the Boron concentration will be parametrized."
"Our model will be a pin-cell from the [Multi-Group Mode Part II](mg-mode-part-ii.ipynb) assembly, except this time the entire model building process will be contained within a function, and the Boron concentration will be parametrized."
]
},
{

View file

@ -28,7 +28,8 @@ extern "C" {
int openmc_extend_cells(int32_t n, int32_t* index_start, int32_t* index_end);
int openmc_extend_filters(int32_t n, int32_t* index_start, int32_t* index_end);
int openmc_extend_materials(int32_t n, int32_t* index_start, int32_t* index_end);
int openmc_extend_meshes(int32_t n, int32_t* index_start, int32_t* index_end);
int openmc_extend_meshes(int32_t n, const char* type, int32_t* index_start,
int32_t* index_end);
int openmc_extend_tallies(int32_t n, int32_t* index_start, int32_t* index_end);
int openmc_filter_get_id(int32_t index, int32_t* id);
int openmc_filter_get_type(int32_t index, char* type);
@ -73,11 +74,7 @@ extern "C" {
int openmc_mesh_filter_get_mesh(int32_t index, int32_t* index_mesh);
int openmc_mesh_filter_set_mesh(int32_t index, int32_t index_mesh);
int openmc_mesh_get_id(int32_t index, int32_t* id);
int openmc_mesh_get_dimension(int32_t index, int** id, int* n);
int openmc_mesh_get_params(int32_t index, double** ll, double** ur, double** width, int* n);
int openmc_mesh_set_id(int32_t index, int32_t id);
int openmc_mesh_set_dimension(int32_t index, int n, const int* dims);
int openmc_mesh_set_params(int32_t index, int n, const double* ll, const double* ur, const double* width);
int openmc_meshsurface_filter_get_mesh(int32_t index, int32_t* index_mesh);
int openmc_meshsurface_filter_set_mesh(int32_t index, int32_t index_mesh);
int openmc_new_filter(const char* type, int32_t* index);
@ -86,6 +83,15 @@ extern "C" {
int openmc_plot_geometry();
int openmc_id_map(const void* slice, int32_t* data_out);
int openmc_property_map(const void* slice, double* data_out);
int openmc_rectilinear_mesh_get_grid(int32_t index, double** grid_x, int* nx,
double** grid_y, int* ny, double** grid_z, int* nz);
int openmc_rectilinear_mesh_set_grid(int32_t index, const double* grid_x,
const int nx, const double* grid_y, const int ny,
const double* grid_z, const int nz);
int openmc_regular_mesh_get_dimension(int32_t index, int** id, int* n);
int openmc_regular_mesh_get_params(int32_t index, double** ll, double** ur, double** width, int* n);
int openmc_regular_mesh_set_dimension(int32_t index, int n, const int* dims);
int openmc_regular_mesh_set_params(int32_t index, int n, const double* ll, const double* ur, const double* width);
int openmc_reset();
int openmc_reset_timers();
int openmc_run();

View file

@ -10,7 +10,7 @@
#include "openmc/capi.h"
#include "openmc/settings.h"
#ifdef __GNUC__
#if defined(__GNUC__) || defined(__clang__)
#define UNREACHABLE() __builtin_unreachable()
#else
#define UNREACHABLE() (void)0

View file

@ -43,14 +43,11 @@ bool check_cell_overlap(Particle& p, bool error=true);
//!
//! \param p A particle to be located. This function will populate the
//! geometry-dependent data fields of the particle.
//! \param use_neighbor_lists If true, neighbor lists will be used to accelerate
//! the geometry search, but this only works if the cell attribute of the
//! particle's lowest coordinate level is valid and meaningful.
//! \return True if the particle's location could be found and ascribed to a
//! valid geometry coordinate stack.
//==============================================================================
bool find_cell(Particle& p, bool use_neighbor_lists);
bool exhaustive_find_cell(Particle& p);
bool neighbor_list_find_cell(Particle& p); // Only usable on surface crossings
//==============================================================================
//! Move a particle into a new lattice tile.

View file

@ -114,6 +114,14 @@ public:
void bins_crossed(const Particle& p, std::vector<int>& bins,
std::vector<double>& lengths) const override;
//! Count number of bank sites in each mesh bin / energy bin
//
//! \param[in] Pointer to bank sites
//! \param[in] Number of bank sites
//! \param[out] Whether any bank sites are outside the mesh
xt::xtensor<double, 1> count_sites(const Particle::Bank* bank,
int64_t length, bool* outside) const;
//! Get bin given mesh indices
//
//! \param[in] Array of mesh indices
@ -200,16 +208,6 @@ public:
void to_hdf5(hid_t group) const override;
// New methods
//! Count number of bank sites in each mesh bin / energy bin
//
//! \param[in] bank Array of bank sites
//! \param[out] Whether any bank sites are outside the mesh
//! \return Array indicating number of sites in each mesh/energy bin
xt::xtensor<double, 1> count_sites(const Particle::Bank* bank, int64_t length,
bool* outside) const;
// Data members
double volume_frac_; //!< Volume fraction of each mesh element
@ -221,6 +219,7 @@ class RectilinearMesh : public StructuredMesh
{
public:
// Constructors
RectilinearMesh() = default;
RectilinearMesh(pugi::xml_node node);
// Overriden methods
@ -239,8 +238,9 @@ public:
void to_hdf5(hid_t group) const override;
private:
std::vector<std::vector<double>> grid_;
int set_grid();
};
#ifdef DAGMC
@ -424,8 +424,6 @@ void read_meshes(pugi::xml_node root);
//! \param[in] group HDF5 group
void meshes_to_hdf5(hid_t group);
RegularMesh* get_regular_mesh(int32_t index);
void free_memory_mesh();
} // namespace openmc

View file

@ -182,7 +182,7 @@ T PlotBase::get_map() const {
p.r()[in_i] = xyz[in_i] + in_pixel * x;
p.n_coord_ = 1;
// local variables
bool found_cell = find_cell(p, 0);
bool found_cell = exhaustive_find_cell(p);
j = p.n_coord_ - 1;
if (level >= 0) { j = level; }
if (found_cell) {

View file

@ -51,6 +51,18 @@ struct Position {
}
}
// Access to x, y, or z by compile time known index (specializations below)
template<int i>
const double& get() const
{
throw std::out_of_range {"Index in Position must be between 0 and 2."};
}
template<int i>
double& get()
{
throw std::out_of_range {"Index in Position must be between 0 and 2."};
}
// Other member functions
//! Dot product of two vectors
@ -77,6 +89,38 @@ struct Position {
double z = 0.;
};
// Compile-time known member index access functions
template<>
inline const double& Position::get<0>() const
{
return x;
}
template<>
inline const double& Position::get<1>() const
{
return y;
}
template<>
inline const double& Position::get<2>() const
{
return z;
}
template<>
inline double& Position::get<0>()
{
return x;
}
template<>
inline double& Position::get<1>()
{
return y;
}
template<>
inline double& Position::get<2>()
{
return z;
}
// Binary operators
inline Position operator+(Position a, Position b) { return a += b; }
inline Position operator+(Position a, double b) { return a += b; }

View file

@ -88,7 +88,7 @@ extern RunMode run_mode; //!< Run mode (eigenvalue, fixed src, e
extern std::unordered_set<int> sourcepoint_batch; //!< Batches when source should be written
extern std::unordered_set<int> statepoint_batch; //!< Batches when state should be written
extern std::unordered_set<int> source_write_surf_id; //!< Surface ids where sources will be written
extern int64_t max_particles; //!< maximum number of particles to be banked on surfaces per process
extern int64_t max_surface_particles; //!< maximum number of particles to be banked on surfaces per process
extern TemperatureMethod temperature_method; //!< method for choosing temperatures
extern double temperature_tolerance; //!< Tolerance in [K] on choosing temperatures
extern double temperature_default; //!< Default T in [K]

View file

@ -73,12 +73,12 @@ public:
{
// Atomically capture the index we want to write to
int64_t idx;
#pragma omp atomic capture
#pragma omp atomic capture seq_cst
idx = size_++;
// Check that we haven't written off the end of the array
if (idx >= capacity_) {
#pragma omp atomic write
#pragma omp atomic write seq_cst
size_ = capacity_;
return -1;
}

View file

@ -57,7 +57,7 @@ Indicates the default path to an HDF5 file that contains multi-group cross
section libraries if the user has not specified the <cross_sections> tag in
.I materials.xml\fP.
.SH LICENSE
Copyright \(co 2011-2020 Massachusetts Institute of Technology and OpenMC
Copyright \(co 2011-2021 Massachusetts Institute of Technology and OpenMC
contributors.
.PP
Permission is hereby granted, free of charge, to any person obtaining a copy of

View file

@ -34,4 +34,4 @@ from . import examples
# Import a few convencience functions that used to be here
from openmc.model import rectangular_prism, hexagonal_prism
__version__ = '0.12.1-dev'
__version__ = '0.13.0-dev'

View file

@ -60,15 +60,17 @@ class CMFDMesh:
Attributes
----------
lower_left : Iterable of float
The lower-left corner of the structured mesh. If only two coordinates
are given, it is assumed that the mesh is an x-y mesh.
The lower-left corner of a regular structured mesh. If only two
coordinates are given, it is assumed that the mesh is an x-y mesh.
upper_right : Iterable of float
The upper-right corner of the structured mesh. If only two coordinates
are given, it is assumed that the mesh is an x-y mesh.
The upper-right corner of a regular structured mesh. If only two
coordinates are given, it is assumed that the mesh is an x-y mesh.
dimension : Iterable of int
The number of mesh cells in each direction.
The number of mesh cells in each direction for a regular structured
mesh.
width : Iterable of float
The width of mesh cells in each direction.
The width of mesh cells in each direction for a regular structured
mesh
energy : Iterable of float
Energy bins in eV, listed in ascending order (e.g. [0.0, 0.625e-1,
20.0e6]) for CMFD tallies and acceleration. If no energy bins are
@ -96,6 +98,14 @@ class CMFDMesh:
is extremely important to use in reflectors as neutrons will not
contribute to any tallies far away from fission source neutron regions.
A ``1`` must be used to identify any fission source region.
mesh_type : str
Type of structured mesh to use. Acceptable values are:
* "regular" - Use RegularMesh to define CMFD mesh
* "rectilinear" - Use RectilinearMesh to define CMFD
grid : Iterable of Iterable of float
Grid used to define RectilinearMesh. First dimension must have length
3 where grid[0], grid[1], and grid[2] correspond to the x-, y-, and
z-grids respectively
"""
@ -107,6 +117,28 @@ class CMFDMesh:
self._energy = None
self._albedo = None
self._map = None
self._mesh_type = 'regular'
self._grid = None
def __repr__(self):
outstr = type(self).__name__ + '\n'
if self._mesh_type == 'regular':
outstr += (self._get_repr(self._lower_left, "Lower left") + "\n" +
self._get_repr(self._upper_right, "Upper right") + "\n" +
self._get_repr(self._dimension, "Dimension") + "\n" +
self._get_repr(self._width, "Width") + "\n" +
self._get_repr(self._albedo, "Albedo"))
elif self._mesh_type == 'rectilinear':
outstr += (self._get_repr(self._grid[0], "X-grid") + "\n" +
self._get_repr(self._grid[1], "Y-grid") + "\n" +
self._get_repr(self._grid[2], "Z-grid"))
return outstr
def _get_repr(self, list_var, label):
outstr = "\t{:<11} = ".format(label)
if list(list_var):
outstr += ", ".join(str(i) for i in list_var)
return outstr
@property
def lower_left(self):
@ -136,17 +168,27 @@ class CMFDMesh:
def map(self):
return self._map
@property
def mesh_type(self):
return self._mesh_type
@property
def grid(self):
return self._grid
@lower_left.setter
def lower_left(self, lower_left):
check_type('CMFD mesh lower_left', lower_left, Iterable, Real)
check_length('CMFD mesh lower_left', lower_left, 2, 3)
self._lower_left = lower_left
self._display_mesh_warning('regular', 'CMFD mesh lower_left')
@upper_right.setter
def upper_right(self, upper_right):
check_type('CMFD mesh upper_right', upper_right, Iterable, Real)
check_length('CMFD mesh upper_right', upper_right, 2, 3)
self._upper_right = upper_right
self._display_mesh_warning('regular', 'CMFD mesh upper_right')
@dimension.setter
def dimension(self, dimension):
@ -163,6 +205,7 @@ class CMFDMesh:
for w in width:
check_greater_than('CMFD mesh width', w, 0)
self._width = width
self._display_mesh_warning('regular', 'CMFD mesh width')
@energy.setter
def energy(self, energy):
@ -187,6 +230,31 @@ class CMFDMesh:
check_value('CMFD mesh map', m, [0, 1])
self._map = mesh_map
@mesh_type.setter
def mesh_type(self, mesh_type):
check_value('CMFD mesh type', mesh_type, ['regular', 'rectilinear'])
self._mesh_type = mesh_type
@grid.setter
def grid(self, grid):
grid_length = 3
dims = ['x', 'y', 'z']
check_length('CMFD mesh grid', grid, grid_length)
for i in range(grid_length):
check_type('CMFD mesh {}-grid'.format(dims[i]), grid[i], Iterable,
Real)
check_greater_than('CMFD mesh {}-grid length'.format(dims[i]),
len(grid[i]), 1)
self._grid = np.array(grid)
self._display_mesh_warning('rectilinear', 'CMFD mesh grid')
def _display_mesh_warning(self, mesh_type, variable_label):
if self._mesh_type != mesh_type:
warn_msg = 'Setting {} if mesh type is not set to {} ' \
'will have no effect'.format(variable_label, mesh_type)
warnings.warn(warn_msg, RuntimeWarning)
class CMFDRun:
r"""Class for running CMFD acceleration through the C API.
@ -566,48 +634,56 @@ class CMFDRun:
def mesh(self, cmfd_mesh):
check_type('CMFD mesh', cmfd_mesh, CMFDMesh)
# Check dimension defined
if cmfd_mesh.dimension is None:
raise ValueError('CMFD mesh requires spatial '
'dimensions to be specified')
if cmfd_mesh.mesh_type == 'regular':
# Check dimension defined
if cmfd_mesh.dimension is None:
raise ValueError('CMFD regular mesh requires spatial '
'dimensions to be specified')
# Check lower left defined
if cmfd_mesh.lower_left is None:
raise ValueError('CMFD mesh requires lower left coordinates '
'to be specified')
# Check lower left defined
if cmfd_mesh.lower_left is None:
raise ValueError('CMFD regular mesh requires lower left '
'coordinates to be specified')
# Check that both upper right and width both not defined
if cmfd_mesh.upper_right is not None and cmfd_mesh.width is not None:
raise ValueError('Both upper right coordinates and width '
'cannot be specified for CMFD mesh')
# Check that both upper right and width both not defined
if cmfd_mesh.upper_right is not None and cmfd_mesh.width is not None:
raise ValueError('Both upper right coordinates and width '
'cannot be specified for CMFD regular mesh')
# Check that at least one of width or upper right is defined
if cmfd_mesh.upper_right is None and cmfd_mesh.width is None:
raise ValueError('CMFD mesh requires either upper right '
'coordinates or width to be specified')
# Check that at least one of width or upper right is defined
if cmfd_mesh.upper_right is None and cmfd_mesh.width is None:
raise ValueError('CMFD regular mesh requires either upper right '
'coordinates or width to be specified')
# Check width and lower length are same dimension and define
# upper_right
if cmfd_mesh.width is not None:
check_length('CMFD mesh width', cmfd_mesh.width,
len(cmfd_mesh.lower_left))
cmfd_mesh.upper_right = np.array(cmfd_mesh.lower_left) + \
np.array(cmfd_mesh.width) * np.array(cmfd_mesh.dimension)
# Check width and lower length are same dimension and define
# upper_right
if cmfd_mesh.width is not None:
check_length('CMFD mesh width', cmfd_mesh.width,
len(cmfd_mesh.lower_left))
cmfd_mesh.upper_right = np.array(cmfd_mesh.lower_left) + \
np.array(cmfd_mesh.width) * np.array(cmfd_mesh.dimension)
# Check upper_right and lower length are same dimension and define
# width
elif cmfd_mesh.upper_right is not None:
check_length('CMFD mesh upper right', cmfd_mesh.upper_right,
len(cmfd_mesh.lower_left))
# Check upper right coordinates are greater than lower left
if np.any(np.array(cmfd_mesh.upper_right) <=
np.array(cmfd_mesh.lower_left)):
raise ValueError('CMFD regular mesh requires upper right '
'coordinates to be greater than lower '
'left coordinates')
cmfd_mesh.width = np.true_divide((np.array(cmfd_mesh.upper_right) -
np.array(cmfd_mesh.lower_left)),
np.array(cmfd_mesh.dimension))
elif cmfd_mesh.mesh_type == 'rectilinear':
# Check dimension defined
if cmfd_mesh.grid is None:
raise ValueError('CMFD rectilinear mesh requires spatial '
'grid to be specified')
cmfd_mesh.dimension = [len(cmfd_mesh.grid[i]) - 1 for i in range(3)]
# Check upper_right and lower length are same dimension and define
# width
elif cmfd_mesh.upper_right is not None:
check_length('CMFD mesh upper right', cmfd_mesh.upper_right,
len(cmfd_mesh.lower_left))
# Check upper right coordinates are greater than lower left
if np.any(np.array(cmfd_mesh.upper_right) <=
np.array(cmfd_mesh.lower_left)):
raise ValueError('CMFD mesh requires upper right '
'coordinates to be greater than lower '
'left coordinates')
cmfd_mesh.width = np.true_divide((np.array(cmfd_mesh.upper_right) -
np.array(cmfd_mesh.lower_left)),
np.array(cmfd_mesh.dimension))
self._mesh = cmfd_mesh
@norm.setter
@ -1014,6 +1090,12 @@ class CMFDRun:
# Initialize parameters for CMFD tally windows
self._set_tally_window()
# Extract spatial and energy indices
nx, ny, nz, ng = self._indices
# Initialize CMFD source to all ones
self._cmfd_src = np.ones((nx, ny, nz, ng))
# Define all variables that will exist only on master process
if openmc.lib.master():
# Set global albedo
@ -1025,9 +1107,6 @@ class CMFDRun:
# Set up CMFD coremap
self._set_coremap()
# Extract spatial and energy indices
nx, ny, nz, ng = self._indices
# Allocate parameters that need to be stored for tally window
self._openmc_src_rate = np.zeros((nx, ny, nz, ng, 0))
self._flux_rate = np.zeros((nx, ny, nz, ng, 0))
@ -1088,10 +1167,17 @@ class CMFDRun:
# Overwrite CMFD mesh properties
cmfd_mesh_name = 'mesh ' + str(cmfd_group.attrs['mesh_id'])
cmfd_mesh = f['tallies']['meshes'][cmfd_mesh_name]
self._mesh.dimension = cmfd_mesh['dimension'][()]
self._mesh.lower_left = cmfd_mesh['lower_left'][()]
self._mesh.upper_right = cmfd_mesh['upper_right'][()]
self._mesh.width = cmfd_mesh['width'][()]
self._mesh.mesh_type = cmfd_mesh['type'][()].decode()
if self._mesh.mesh_type == 'regular':
self._mesh.dimension = cmfd_mesh['dimension'][()]
self._mesh.lower_left = cmfd_mesh['lower_left'][()]
self._mesh.upper_right = cmfd_mesh['upper_right'][()]
self._mesh.width = cmfd_mesh['width'][()]
elif self._mesh.mesh_type == 'rectilinear':
x_grid = cmfd_mesh['x_grid'][()]
y_grid = cmfd_mesh['y_grid'][()]
z_grid = cmfd_mesh['z_grid'][()]
self._mesh.grid = [x_grid, y_grid, z_grid]
# Define variables that exist only on master process
if openmc.lib.master():
@ -1370,8 +1456,7 @@ class CMFDRun:
# Compute fission source
cmfd_src = (np.sum(self._nfissxs[:,:,:,:,:] *
cmfd_flux[:,:,:,:,np.newaxis], axis=3) *
vol[:,:,:,np.newaxis])
cmfd_flux[:,:,:,:,np.newaxis], axis=3))
# Normalize source such that it sums to 1.0
self._cmfd_src = cmfd_src / np.sum(cmfd_src)
@ -2804,15 +2889,22 @@ class CMFDRun:
def _create_cmfd_tally(self):
"""Creates all tallies in-memory that are used to solve CMFD problem"""
# Create Mesh object based on CMFDMesh, stored internally
cmfd_mesh = openmc.lib.RegularMesh()
# Create Mesh object based on CMFDMesh mesh_type, stored internally
if self._mesh.mesh_type == 'regular':
cmfd_mesh = openmc.lib.RegularMesh()
# Set dimension and parameters of mesh object
cmfd_mesh.dimension = self._mesh.dimension
cmfd_mesh.set_parameters(lower_left=self._mesh.lower_left,
upper_right=self._mesh.upper_right,
width=self._mesh.width)
elif self._mesh.mesh_type == 'rectilinear':
cmfd_mesh = openmc.lib.RectilinearMesh()
# Set grid of mesh object
x_grid, y_grid, z_grid = self._mesh.grid
cmfd_mesh.set_grid(x_grid, y_grid, z_grid)
# Store id of mesh object
self._mesh_id = cmfd_mesh.id
# Set dimension and parameters of mesh object
cmfd_mesh.dimension = self._mesh.dimension
cmfd_mesh.set_parameters(lower_left=self._mesh.lower_left,
upper_right=self._mesh.upper_right,
width=self._mesh.width)
# Create mesh Filter object, stored internally
mesh_filter = openmc.lib.MeshFilter()

View file

@ -402,7 +402,9 @@ def gnd_name(Z, A, m=0):
def isotopes(element):
"""Return naturally-occurring isotopes and their abundances
"""Return naturally occurring isotopes and their abundances
.. versionadded:: 0.12.1
Parameters
----------

View file

@ -22,7 +22,8 @@ double cfloat_endf(const char* buffer, int n)
// limit n to 11 characters
n = n > 11 ? 11 : n;
for (int i = 0; i < n; ++i) {
int i;
for (i = 0; i < n; ++i) {
char c = buffer[i];
// Skip whitespace characters

View file

@ -1018,6 +1018,8 @@ class WindowedMultipole(EqualityMixin):
def from_endf(cls, endf_file, log=False, vf_options=None, wmp_options=None):
"""Generate windowed multipole neutron data from an ENDF evaluation.
.. versionadded:: 0.12.1
Parameters
----------
endf_file : str

View file

@ -326,6 +326,8 @@ class Chain:
`["(n,2n)", "(n,gamma)"]`. Note that fission is always included if
it is present. A complete listing of transmutation reactions can be
found in :data:`openmc.deplete.chain.REACTIONS`.
.. versionadded:: 0.12.1
progress : bool, optional
Flag to print status messages during processing. Does not
effect warning messages

View file

@ -302,6 +302,8 @@ class ResultsList(list):
def export_to_materials(self, burnup_index, nuc_with_data=None) -> Materials:
"""Return openmc.Materials object based on results at a given step
.. versionadded:: 0.12.1
Parameters
----------
burn_index : int

View file

@ -25,8 +25,17 @@ def _run(args, output, cwd):
# Raise an exception if return status is non-zero
if p.returncode != 0:
raise subprocess.CalledProcessError(p.returncode, ' '.join(args),
''.join(lines))
# Get error message from output and simplify whitespace
output = ''.join(lines)
if 'ERROR: ' in output:
_, _, error_msg = output.partition('ERROR: ')
elif 'what()' in output:
_, _, error_msg = output.partition('what(): ')
else:
error_msg = 'OpenMC aborted unexpectedly.'
error_msg = ' '.join(error_msg.split())
raise RuntimeError(error_msg)
def plot_geometry(output=True, openmc_exec='openmc', cwd='.'):
@ -43,7 +52,7 @@ def plot_geometry(output=True, openmc_exec='openmc', cwd='.'):
Raises
------
subprocess.CalledProcessError
RuntimeError
If the `openmc` executable returns a non-zero status
"""
@ -70,7 +79,7 @@ def plot_inline(plots, openmc_exec='openmc', cwd='.', convert_exec='convert'):
Raises
------
subprocess.CalledProcessError
RuntimeError
If the `openmc` executable returns a non-zero status
"""
@ -133,7 +142,7 @@ def calculate_volumes(threads=None, output=True, cwd='.',
Raises
------
subprocess.CalledProcessError
RuntimeError
If the `openmc` executable returns a non-zero status
See Also
@ -188,7 +197,7 @@ def run(particles=None, threads=None, geometry_debug=False,
Raises
------
subprocess.CalledProcessError
RuntimeError
If the `openmc` executable returns a non-zero status
"""

View file

@ -11,7 +11,7 @@ from . import _dll
from .core import _FortranObjectWithID
from .error import _error_handler
from .material import Material
from .mesh import RegularMesh
from .mesh import _get_mesh
__all__ = [
@ -319,7 +319,7 @@ class MeshFilter(Filter):
def mesh(self):
index_mesh = c_int32()
_dll.openmc_mesh_filter_get_mesh(self._index, index_mesh)
return RegularMesh(index=index_mesh.value)
return _get_mesh(index_mesh.value)
@mesh.setter
def mesh(self, mesh):
@ -338,7 +338,7 @@ class MeshSurfaceFilter(Filter):
def mesh(self):
index_mesh = c_int32()
_dll.openmc_meshsurface_filter_get_mesh(self._index, index_mesh)
return RegularMesh(index=index_mesh.value)
return _get_mesh(index_mesh.value)
@mesh.setter
def mesh(self, mesh):

View file

@ -1,7 +1,9 @@
from collections.abc import Mapping
from ctypes import c_int, c_int32, c_double, POINTER
from ctypes import (c_int, c_int32, c_char_p, c_double, POINTER,
create_string_buffer)
from weakref import WeakValueDictionary
import numpy as np
from numpy.ctypeslib import as_array
from ..exceptions import AllocationError, InvalidIDError
@ -9,41 +11,100 @@ from . import _dll
from .core import _FortranObjectWithID
from .error import _error_handler
__all__ = ['RegularMesh', 'meshes']
__all__ = ['RegularMesh', 'RectilinearMesh', 'meshes']
# Mesh functions
_dll.openmc_extend_meshes.argtypes = [c_int32, POINTER(c_int32), POINTER(c_int32)]
_dll.openmc_extend_meshes.argtypes = [c_int32, c_char_p, POINTER(c_int32),
POINTER(c_int32)]
_dll.openmc_extend_meshes.restype = c_int
_dll.openmc_extend_meshes.errcheck = _error_handler
_dll.openmc_mesh_get_id.argtypes = [c_int32, POINTER(c_int32)]
_dll.openmc_mesh_get_id.restype = c_int
_dll.openmc_mesh_get_id.errcheck = _error_handler
_dll.openmc_mesh_get_dimension.argtypes = [c_int32, POINTER(POINTER(c_int)), POINTER(c_int)]
_dll.openmc_mesh_get_dimension.restype = c_int
_dll.openmc_mesh_get_dimension.errcheck = _error_handler
_dll.openmc_mesh_get_params.argtypes = [
c_int32, POINTER(POINTER(c_double)), POINTER(POINTER(c_double)),
POINTER(POINTER(c_double)), POINTER(c_int)]
_dll.openmc_mesh_get_params.restype = c_int
_dll.openmc_mesh_get_params.errcheck = _error_handler
_dll.openmc_mesh_set_id.argtypes = [c_int32, c_int32]
_dll.openmc_mesh_set_id.restype = c_int
_dll.openmc_mesh_set_id.errcheck = _error_handler
_dll.openmc_mesh_set_dimension.argtypes = [c_int32, c_int, POINTER(c_int)]
_dll.openmc_mesh_set_dimension.restype = c_int
_dll.openmc_mesh_set_dimension.errcheck = _error_handler
_dll.openmc_mesh_set_params.argtypes = [
c_int32, c_int, POINTER(c_double), POINTER(c_double), POINTER(c_double)]
_dll.openmc_mesh_set_params.restype = c_int
_dll.openmc_mesh_set_params.errcheck = _error_handler
_dll.openmc_get_mesh_index.argtypes = [c_int32, POINTER(c_int32)]
_dll.openmc_get_mesh_index.restype = c_int
_dll.openmc_get_mesh_index.errcheck = _error_handler
_dll.n_meshes.argtypes = []
_dll.n_meshes.restype = c_int
_dll.openmc_rectilinear_mesh_get_grid.argtypes = [c_int32,
POINTER(POINTER(c_double)), POINTER(c_int), POINTER(POINTER(c_double)),
POINTER(c_int), POINTER(POINTER(c_double)), POINTER(c_int)]
_dll.openmc_rectilinear_mesh_get_grid.restype = c_int
_dll.openmc_rectilinear_mesh_get_grid.errcheck = _error_handler
_dll.openmc_rectilinear_mesh_set_grid.argtypes = [c_int32, POINTER(c_double),
c_int, POINTER(c_double), c_int, POINTER(c_double), c_int]
_dll.openmc_rectilinear_mesh_set_grid.restype = c_int
_dll.openmc_rectilinear_mesh_set_grid.errcheck = _error_handler
_dll.openmc_regular_mesh_get_dimension.argtypes = [c_int32,
POINTER(POINTER(c_int)), POINTER(c_int)]
_dll.openmc_regular_mesh_get_dimension.restype = c_int
_dll.openmc_regular_mesh_get_dimension.errcheck = _error_handler
_dll.openmc_regular_mesh_get_params.argtypes = [
c_int32, POINTER(POINTER(c_double)), POINTER(POINTER(c_double)),
POINTER(POINTER(c_double)), POINTER(c_int)]
_dll.openmc_regular_mesh_get_params.restype = c_int
_dll.openmc_regular_mesh_get_params.errcheck = _error_handler
_dll.openmc_regular_mesh_set_dimension.argtypes = [c_int32, c_int,
POINTER(c_int)]
_dll.openmc_regular_mesh_set_dimension.restype = c_int
_dll.openmc_regular_mesh_set_dimension.errcheck = _error_handler
_dll.openmc_regular_mesh_set_params.argtypes = [
c_int32, c_int, POINTER(c_double), POINTER(c_double), POINTER(c_double)]
_dll.openmc_regular_mesh_set_params.restype = c_int
_dll.openmc_regular_mesh_set_params.errcheck = _error_handler
class RegularMesh(_FortranObjectWithID):
class Mesh(_FortranObjectWithID):
"""Base class to represent mesh objects
"""
__instances = WeakValueDictionary()
def __new__(cls, uid=None, new=True, index=None):
mapping = meshes
if index is None:
if new:
# Determine ID to assign
if uid is None:
uid = max(mapping, default=0) + 1
else:
if uid in mapping:
raise AllocationError('A mesh with ID={} has already '
'been allocated.'.format(uid))
# Set the mesh type -- note that mesh type attribute only
# exists on subclasses!
index = c_int32()
_dll.openmc_extend_meshes(1, cls.mesh_type.encode(), index,
None)
index = index.value
else:
index = mapping[uid]._index
if index not in cls.__instances:
instance = super().__new__(cls)
instance._index = index
if uid is not None:
instance.id = uid
cls.__instances[index] = instance
return cls.__instances[index]
@property
def id(self):
mesh_id = c_int32()
_dll.openmc_mesh_get_id(self._index, mesh_id)
return mesh_id.value
@id.setter
def id(self, mesh_id):
_dll.openmc_mesh_set_id(self._index, mesh_id)
class RegularMesh(Mesh):
"""RegularMesh stored internally.
This class exposes a mesh that is stored internally in the OpenMC
@ -71,57 +132,24 @@ class RegularMesh(_FortranObjectWithID):
The width of mesh cells in each direction.
"""
__instances = WeakValueDictionary()
mesh_type = 'regular'
def __new__(cls, uid=None, new=True, index=None):
mapping = meshes
if index is None:
if new:
# Determine ID to assign
if uid is None:
uid = max(mapping, default=0) + 1
else:
if uid in mapping:
raise AllocationError('A mesh with ID={} has already '
'been allocated.'.format(uid))
index = c_int32()
_dll.openmc_extend_meshes(1, index, None)
index = index.value
else:
index = mapping[uid]._index
if index not in cls.__instances:
instance = super().__new__(cls)
instance._index = index
if uid is not None:
instance.id = uid
cls.__instances[index] = instance
return cls.__instances[index]
@property
def id(self):
mesh_id = c_int32()
_dll.openmc_mesh_get_id(self._index, mesh_id)
return mesh_id.value
@id.setter
def id(self, mesh_id):
_dll.openmc_mesh_set_id(self._index, mesh_id)
def __init__(self, uid=None, new=True, index=None):
super().__init__(uid, new, index)
@property
def dimension(self):
dims = POINTER(c_int)()
n = c_int()
_dll.openmc_mesh_get_dimension(self._index, dims, n)
_dll.openmc_regular_mesh_get_dimension(self._index, dims, n)
return tuple(as_array(dims, (n.value,)))
@dimension.setter
def dimension(self, dimension):
n = len(dimension)
dimension = (c_int*n)(*dimension)
_dll.openmc_mesh_set_dimension(self._index, n, dimension)
_dll.openmc_regular_mesh_set_dimension(self._index, n, dimension)
@property
def lower_left(self):
@ -140,7 +168,7 @@ class RegularMesh(_FortranObjectWithID):
ur = POINTER(c_double)()
w = POINTER(c_double)()
n = c_int()
_dll.openmc_mesh_get_params(self._index, ll, ur, w, n)
_dll.openmc_regular_mesh_get_params(self._index, ll, ur, w, n)
return (
as_array(ll, (n.value,)),
as_array(ur, (n.value,)),
@ -157,7 +185,107 @@ class RegularMesh(_FortranObjectWithID):
if width is not None:
n = len(width)
width = (c_double*n)(*width)
_dll.openmc_mesh_set_params(self._index, n, lower_left, upper_right, width)
_dll.openmc_regular_mesh_set_params(self._index, n, lower_left, upper_right, width)
class RectilinearMesh(Mesh):
"""RectilinearMesh stored internally.
This class exposes a mesh that is stored internally in the OpenMC
library. To obtain a view of a mesh with a given ID, use the
:data:`openmc.lib.meshes` mapping.
Parameters
----------
index : int
Index in the `meshes` array.
Attributes
----------
id : int
ID of the mesh
dimension : iterable of int
The number of mesh cells in each direction.
lower_left : numpy.ndarray
The lower-left corner of the structured mesh.
upper_right : numpy.ndarray
The upper-right corner of the structrued mesh.
width : numpy.ndarray
The width of mesh cells in each direction.
"""
mesh_type = 'rectilinear'
def __init__(self, uid=None, new=True, index=None):
super().__init__(uid, new, index)
@property
def lower_left(self):
return self._get_parameters()[0]
@property
def upper_right(self):
return self._get_parameters()[1]
@property
def dimension(self):
return self._get_parameters()[2]
@property
def width(self):
return self._get_parameters()[3]
def _get_parameters(self):
gx = POINTER(c_double)()
nx = c_int()
gy = POINTER(c_double)()
ny = c_int()
gz = POINTER(c_double)()
nz = c_int()
# Call C API to get grid parameters
_dll.openmc_rectilinear_mesh_get_grid(self._index, gx, nx, gy, ny, gz,
nz)
# Convert grid parameters to Numpy arrays
grid_x = as_array(gx, (nx.value,))
grid_y = as_array(gy, (ny.value,))
grid_z = as_array(gz, (nz.value,))
# Calculate lower_left, upper_right, width, and dimension from grid
lower_left = np.array((grid_x[0], grid_y[0], grid_z[0]))
upper_right = np.array((grid_x[-1], grid_y[-1], grid_z[-1]))
dimension = np.array((nx.value - 1, ny.value - 1, nz.value - 1))
width = np.zeros(list(dimension) + [3])
for i, diff_x in enumerate(np.diff(grid_x)):
for j, diff_y in enumerate(np.diff(grid_y)):
for k, diff_z in enumerate(np.diff(grid_z)):
width[i, j, k, :] = diff_x, diff_y, diff_z
return (lower_left, upper_right, dimension, width)
def set_grid(self, x_grid, y_grid, z_grid):
nx = len(x_grid)
x_grid = (c_double*nx)(*x_grid)
ny = len(y_grid)
y_grid = (c_double*ny)(*y_grid)
nz = len(z_grid)
z_grid = (c_double*nz)(*z_grid)
_dll.openmc_rectilinear_mesh_set_grid(self._index, x_grid, nx, y_grid,
ny, z_grid, nz)
_MESH_TYPE_MAP = {
'regular': RegularMesh,
'rectilinear': RectilinearMesh
}
def _get_mesh(index):
mesh_type = create_string_buffer(20)
_dll.openmc_mesh_get_type(index, mesh_type)
mesh_type = mesh_type.value.decode()
return _MESH_TYPE_MAP[mesh_type](index=index)
class _MeshMapping(Mapping):
@ -168,11 +296,12 @@ class _MeshMapping(Mapping):
except (AllocationError, InvalidIDError) as e:
# __contains__ expects a KeyError to work correctly
raise KeyError(str(e))
return RegularMesh(index=index.value)
return _get_mesh(index.value)
def __iter__(self):
for i in range(len(self)):
yield RegularMesh(index=i).id
yield _get_mesh(i).id
def __len__(self):
return _dll.n_meshes()

View file

@ -13,13 +13,14 @@ GROUP_STRUCTURES = {}
- "XMAS-172_" designed for LWR analysis ([SAR1990]_, [SAN2004]_)
- "SHEM-361_" designed for LWR analysis to eliminate self-shielding calculations
of thermal resonances ([HFA2005]_, [SAN2007]_, [HEB2008]_)
- activation_ energy group structures "VITAMIN-J-175", "TRIPOLI-315",
"CCFE-709_" and "UKAEA-1102_"
- activation_ energy group structures "VITAMIN-J-42", "VITAMIN-J-175",
"TRIPOLI-315", "CCFE-709_" and "UKAEA-1102_"
.. _CASMO: https://www.studsvik.com/SharepointFiles/CASMO-5%20Development%20and%20Applications.pdf
.. _XMAS-172: https://www-nds.iaea.org/wimsd/energy.htm
.. _SHEM-361: https://www.polymtl.ca/merlin/downloads/FP214.pdf
.. _activation: https://fispact.ukaea.uk/wiki/Keyword:GETXS
.. _VITAMIN-J-42: https://www.oecd-nea.org/dbdata/nds_jefreports/jefreport-10.pdf
.. _CCFE-709: https://fispact.ukaea.uk/wiki/CCFE-709_group_structure
.. _UKAEA-1102: https://fispact.ukaea.uk/wiki/UKAEA-1102_group_structure
.. [SAR1990] Sartori, E., OECD/NEA Data Bank: Standard Energy Group Structures
@ -61,6 +62,12 @@ GROUP_STRUCTURES['CASMO-40'] = np.array([
9.72e-1, 1.02, 1.097, 1.15, 1.3, 1.5, 1.855, 2.1, 2.6, 3.3, 4.,
9.877, 1.5968e1, 2.77e1, 4.8052e1, 1.4873e2, 5.53e3, 9.118e3,
1.11e5, 5.e5, 8.21e5, 1.353e6, 2.231e6, 3.679e6, 6.0655e6, 2.e7])
GROUP_STRUCTURES['VITAMIN-J-42'] = np.array([
1.e3, 10.e3, 20.e3, 30.e3, 45.e3, 60.e3, 70.e3, 75.e3, 0.1e6, 0.15e6,
0.2e6, 0.3e6, 0.4e6, 0.45e6, 0.51e6, 0.512e6, 0.6e6, 0.7e6, 0.8e6, 1.e6,
1.33e6, 1.34e6, 1.5e6, 1.66e6, 2.e6, 2.5e6, 3.e6, 3.5e6, 4.e6, 4.5e6, 5.e6,
5.5e6, 6.e6, 6.5e6, 7.e6, 7.5e6, 8.e6, 10.e6, 12.e6, 14.e6, 20.e6, 30.e6,
50.e6])
GROUP_STRUCTURES['CASMO-70'] = np.array([
0., 5.e-3, 1.e-2, 1.5e-2, 2.e-2, 2.5e-2, 3.e-2, 3.5e-2, 4.2e-2,
5.e-2, 5.8e-2, 6.7e-2, 8.e-2, 1.e-1, 1.4e-1, 1.8e-1, 2.2e-1,

View file

@ -3020,6 +3020,8 @@ class DiffusionCoefficient(TransportXS):
To incorporate the effect of scattering multiplication in the above
relation, the `nu` parameter can be set to `True`.
.. versionadded:: 0.12.1
Parameters
----------
domain : openmc.Material or openmc.Cell or openmc.Universe or openmc.RegularMesh
@ -6610,6 +6612,8 @@ class MeshSurfaceMGXS(MGXS):
.. note:: Users should instantiate the subclasses of this abstract class.
.. versionadded:: 0.12.1
Parameters
----------
domain : openmc.RegularMesh
@ -6992,6 +6996,8 @@ class Current(MeshSurfaceMGXS):
\frac{\int_{r \in S} dS \int_{E_g}^{E_{g-1}} dE \;
J(r, E)}{\int_{r \in S} dS \int_{E_g}^{E_{g-1}} dE}.
.. versionadded:: 0.12.1
Parameters
----------
domain : openmc.RegularMesh

View file

@ -152,8 +152,8 @@ class Settings:
:surface_ids: List of surface ids at which crossing particles are to be
banked (int)
:max_particles: Maximum number of particles to be banked on surfaces
per process (int)
:max_particles: Maximum number of particles to be banked on
surfaces per process (int)
survival_biasing : bool
Indicate whether survival biasing is to be used
tabular_legendre : dict

View file

@ -298,6 +298,10 @@ def write_source_file(source_particles, filename, **kwargs):
**kwargs
Keyword arguments to pass to :class:`h5py.File`
See Also
--------
openmc.SourceParticle
"""
# Create compound datatype for source particles
pos_dtype = np.dtype([('x', '<f8'), ('y', '<f8'), ('z', '<f8')])

View file

@ -40,7 +40,7 @@ xt::xtensor<int, 2> indexmap;
int use_all_threads;
RegularMesh* mesh;
StructuredMesh* mesh;
std::vector<double> egrid;
@ -222,7 +222,7 @@ void openmc_initialize_mesh_egrid(const int meshtally_id, const int* cmfd_indice
openmc_mesh_filter_get_mesh(meshfilter_index, &mesh_index);
// Get mesh from mesh index
cmfd::mesh = get_regular_mesh(mesh_index);
cmfd::mesh = dynamic_cast<StructuredMesh*>(model::meshes[mesh_index].get());
// Get energy bins from energy index, otherwise use default
if (energy_index != -1) {

View file

@ -72,7 +72,7 @@ find_cell_inner(Particle& p, const NeighborList* neighbor_list)
// Find which cell of this universe the particle is in. Use the neighbor list
// to shorten the search if one was provided.
bool found = false;
int32_t i_cell;
int32_t i_cell = C_NONE;
if (neighbor_list) {
for (auto it = neighbor_list->cbegin(); it != neighbor_list->cend(); ++it) {
i_cell = *it;
@ -91,45 +91,51 @@ find_cell_inner(Particle& p, const NeighborList* neighbor_list)
break;
}
}
}
} else {
int i_universe = p.coord_[p.n_coord_-1].universe;
const auto& univ {*model::universes[i_universe]};
const auto& cells {
!univ.partitioner_
? model::universes[i_universe]->cells_
: univ.partitioner_->get_cells(p.r_local(), p.u_local())
};
for (auto it = cells.cbegin(); it != cells.cend(); it++) {
i_cell = *it;
// Make sure the search cell is in the same universe.
// Check successively lower coordinate levels until finding material fill
for (;;++p.n_coord_) {
// If neighbor lists did not find a cell, must do exhaustive search
if (i_cell == C_NONE) {
int i_universe = p.coord_[p.n_coord_-1].universe;
if (model::cells[i_cell]->universe_ != i_universe) continue;
const auto& univ {*model::universes[i_universe]};
const auto& cells {
!univ.partitioner_
? model::universes[i_universe]->cells_
: univ.partitioner_->get_cells(p.r_local(), p.u_local())
};
// Check if this cell contains the particle.
Position r {p.r_local()};
Direction u {p.u_local()};
auto surf = p.surface_;
if (model::cells[i_cell]->contains(r, u, surf)) {
p.coord_[p.n_coord_-1].cell = i_cell;
found = true;
break;
for (auto it = cells.cbegin(); it != cells.cend(); it++) {
i_cell = *it;
// Make sure the search cell is in the same universe.
int i_universe = p.coord_[p.n_coord_-1].universe;
if (model::cells[i_cell]->universe_ != i_universe) continue;
// Check if this cell contains the particle.
Position r {p.r_local()};
Direction u {p.u_local()};
auto surf = p.surface_;
if (model::cells[i_cell]->contains(r, u, surf)) {
p.coord_[p.n_coord_-1].cell = i_cell;
found = true;
break;
}
}
}
}
if (!found) {
return found;
}
// Announce the cell that the particle is entering.
if (found && (settings::verbosity >= 10 || p.trace_)) {
auto msg = fmt::format(" Entering cell {}", model::cells[i_cell]->id_);
write_message(msg, 1);
}
// Announce the cell that the particle is entering.
if (found && (settings::verbosity >= 10 || p.trace_)) {
auto msg = fmt::format(" Entering cell {}", model::cells[i_cell]->id_);
write_message(msg, 1);
}
if (found) {
Cell& c {*model::cells[i_cell]};
if (c.type_ == Fill::MATERIAL) {
//=======================================================================
//! Found a material cell which means this is the lowest coord level.
// Found a material cell which means this is the lowest coord level.
// Find the distribcell instance number.
int offset = 0;
@ -139,10 +145,9 @@ find_cell_inner(Particle& p, const NeighborList* neighbor_list)
if (c_i.type_ == Fill::UNIVERSE) {
offset += c_i.offset_[c.distribcell_index_];
} else if (c_i.type_ == Fill::LATTICE) {
auto& lat {*model::lattices[p.coord_[i+1].lattice]};
int i_xyz[3] {p.coord_[i+1].lattice_x,
p.coord_[i+1].lattice_y,
p.coord_[i+1].lattice_z};
auto& lat {*model::lattices[p.coord_[i + 1].lattice]};
int i_xyz[3] {p.coord_[i + 1].lattice_x, p.coord_[i + 1].lattice_y,
p.coord_[i + 1].lattice_z};
if (lat.are_valid_indices(i_xyz)) {
offset += lat.offset(c.distribcell_index_, i_xyz);
}
@ -187,10 +192,6 @@ find_cell_inner(Particle& p, const NeighborList* neighbor_list)
coord.rotate(c.rotation_);
}
// Update the coordinate level and recurse.
++p.n_coord_;
return find_cell_inner(p, nullptr);
} else if (c.type_ == Fill::LATTICE) {
//========================================================================
//! Found a lower lattice, update this coord level then search the next.
@ -230,15 +231,13 @@ find_cell_inner(Particle& p, const NeighborList* neighbor_list)
coord.universe = lat.outer_;
} else {
warning(fmt::format("Particle {} is outside lattice {} but the "
"lattice has no defined outer universe.", p.id_, lat.id_));
"lattice has no defined outer universe.",
p.id_, lat.id_));
return false;
}
}
// Update the coordinate level and recurse.
++p.n_coord_;
return find_cell_inner(p, nullptr);
}
i_cell = C_NONE; // trip non-neighbor cell search at next iteration
}
return found;
@ -246,44 +245,47 @@ find_cell_inner(Particle& p, const NeighborList* neighbor_list)
//==============================================================================
bool
find_cell(Particle& p, bool use_neighbor_lists)
bool neighbor_list_find_cell(Particle& p)
{
// Determine universe (if not yet set, use root universe).
int i_universe = p.coord_[p.n_coord_-1].universe;
if (i_universe == C_NONE) {
p.coord_[0].universe = model::root_universe;
p.n_coord_ = 1;
i_universe = model::root_universe;
}
// Reset all the deeper coordinate levels.
for (int i = p.n_coord_; i < p.coord_.size(); i++) {
p.coord_[i].reset();
}
if (use_neighbor_lists) {
// Get the cell this particle was in previously.
auto coord_lvl = p.n_coord_ - 1;
auto i_cell = p.coord_[coord_lvl].cell;
Cell& c {*model::cells[i_cell]};
// Get the cell this particle was in previously.
auto coord_lvl = p.n_coord_ - 1;
auto i_cell = p.coord_[coord_lvl].cell;
Cell& c {*model::cells[i_cell]};
// Search for the particle in that cell's neighbor list. Return if we
// found the particle.
bool found = find_cell_inner(p, &c.neighbors_);
if (found) return found;
// The particle could not be found in the neighbor list. Try searching all
// cells in this universe, and update the neighbor list if we find a new
// neighboring cell.
found = find_cell_inner(p, nullptr);
if (found) c.neighbors_.push_back(p.coord_[coord_lvl].cell);
// Search for the particle in that cell's neighbor list. Return if we
// found the particle.
bool found = find_cell_inner(p, &c.neighbors_);
if (found)
return found;
} else {
// Search all cells in this universe for the particle.
return find_cell_inner(p, nullptr);
// The particle could not be found in the neighbor list. Try searching all
// cells in this universe, and update the neighbor list if we find a new
// neighboring cell.
found = find_cell_inner(p, nullptr);
if (found)
c.neighbors_.push_back(p.coord_[coord_lvl].cell);
return found;
}
bool exhaustive_find_cell(Particle& p)
{
int i_universe = p.coord_[p.n_coord_-1].universe;
if (i_universe == C_NONE) {
p.coord_[0].universe = model::root_universe;
p.n_coord_ = 1;
i_universe = model::root_universe;
}
// Reset all the deeper coordinate levels.
for (int i = p.n_coord_; i < p.coord_.size(); i++) {
p.coord_[i].reset();
}
return find_cell_inner(p, nullptr);
}
//==============================================================================
@ -319,7 +321,7 @@ cross_lattice(Particle& p, const BoundaryInfo& boundary)
if (!lat.are_valid_indices(i_xyz)) {
// The particle is outside the lattice. Search for it from the base coords.
p.n_coord_ = 1;
bool found = find_cell(p, 0);
bool found = exhaustive_find_cell(p);
if (!found && p.alive_) {
p.mark_as_lost(fmt::format("Could not locate particle {} after "
"crossing a lattice boundary", p.id_));
@ -328,13 +330,13 @@ cross_lattice(Particle& p, const BoundaryInfo& boundary)
} else {
// Find cell in next lattice element.
p.coord_[p.n_coord_-1].universe = lat[i_xyz];
bool found = find_cell(p, 0);
bool found = exhaustive_find_cell(p);
if (!found) {
// A particle crossing the corner of a lattice tile may not be found. In
// this case, search for it from the base coords.
p.n_coord_ = 1;
bool found = find_cell(p, 0);
bool found = exhaustive_find_cell(p);
if (!found && p.alive_) {
p.mark_as_lost(fmt::format("Could not locate particle {} after "
"crossing a lattice boundary", p.id_));
@ -450,7 +452,7 @@ openmc_find_cell(const double* xyz, int32_t* index, int32_t* instance)
p.r() = Position{xyz};
p.u() = {0.0, 0.0, 1.0};
if (!find_cell(p, false)) {
if (!exhaustive_find_cell(p)) {
set_errmsg(fmt::format("Could not find cell at position {}.", p.r()));
return OPENMC_E_GEOMETRY;
}

View file

@ -162,6 +162,62 @@ int StructuredMesh::n_surface_bins() const
return 4 * n_dimension_ * n_bins();
}
xt::xtensor<double, 1>
StructuredMesh::count_sites(const Particle::Bank* bank,
int64_t length,
bool* outside) const
{
// Determine shape of array for counts
std::size_t m = this->n_bins();
std::vector<std::size_t> shape = {m};
// Create array of zeros
xt::xarray<double> cnt {shape, 0.0};
bool outside_ = false;
for (int64_t i = 0; i < length; i++) {
const auto& site = bank[i];
// determine scoring bin for entropy mesh
int mesh_bin = get_bin(site.r);
// if outside mesh, skip particle
if (mesh_bin < 0) {
outside_ = true;
continue;
}
// Add to appropriate bin
cnt(mesh_bin) += site.wgt;
}
// Create copy of count data. Since ownership will be acquired by xtensor,
// std::allocator must be used to avoid Valgrind mismatched free() / delete
// warnings.
int total = cnt.size();
double* cnt_reduced = std::allocator<double>{}.allocate(total);
#ifdef OPENMC_MPI
// collect values from all processors
MPI_Reduce(cnt.data(), cnt_reduced, total, MPI_DOUBLE, MPI_SUM, 0,
mpi::intracomm);
// Check if there were sites outside the mesh for any processor
if (outside) {
MPI_Reduce(&outside_, outside, 1, MPI_C_BOOL, MPI_LOR, 0, mpi::intracomm);
}
#else
std::copy(cnt.data(), cnt.data() + total, cnt_reduced);
if (outside) *outside = outside_;
#endif
// Adapt reduced values in array back into an xarray
auto arr = xt::adapt(cnt_reduced, total, xt::acquire_ownership(), shape);
xt::xarray<double> counts = arr;
return counts;
}
bool StructuredMesh::intersects(Position& r0, Position r1, int* ijk) const
{
switch(n_dimension_) {
@ -818,62 +874,6 @@ void RegularMesh::to_hdf5(hid_t group) const
close_group(mesh_group);
}
xt::xtensor<double, 1>
RegularMesh::count_sites(const Particle::Bank* bank,
int64_t length,
bool* outside) const
{
// Determine shape of array for counts
std::size_t m = this->n_bins();
std::vector<std::size_t> shape = {m};
// Create array of zeros
xt::xarray<double> cnt {shape, 0.0};
bool outside_ = false;
for (int64_t i = 0; i < length; i++) {
const auto& site = bank[i];
// determine scoring bin for entropy mesh
int mesh_bin = get_bin(site.r);
// if outside mesh, skip particle
if (mesh_bin < 0) {
outside_ = true;
continue;
}
// Add to appropriate bin
cnt(mesh_bin) += site.wgt;
}
// Create copy of count data. Since ownership will be acquired by xtensor,
// std::allocator must be used to avoid Valgrind mismatched free() / delete
// warnings.
int total = cnt.size();
double* cnt_reduced = std::allocator<double>{}.allocate(total);
#ifdef OPENMC_MPI
// collect values from all processors
MPI_Reduce(cnt.data(), cnt_reduced, total, MPI_DOUBLE, MPI_SUM, 0,
mpi::intracomm);
// Check if there were sites outside the mesh for any processor
if (outside) {
MPI_Reduce(&outside_, outside, 1, MPI_C_BOOL, MPI_LOR, 0, mpi::intracomm);
}
#else
std::copy(cnt.data(), cnt.data() + total, cnt_reduced);
if (outside) *outside = outside_;
#endif
// Adapt reduced values in array back into an xarray
auto arr = xt::adapt(cnt_reduced, total, xt::acquire_ownership(), shape);
xt::xarray<double> counts = arr;
return counts;
}
//==============================================================================
// RectilinearMesh implementation
//==============================================================================
@ -883,26 +883,14 @@ RectilinearMesh::RectilinearMesh(pugi::xml_node node)
{
n_dimension_ = 3;
grid_.resize(3);
grid_.resize(n_dimension_);
grid_[0] = get_node_array<double>(node, "x_grid");
grid_[1] = get_node_array<double>(node, "y_grid");
grid_[2] = get_node_array<double>(node, "z_grid");
shape_ = {static_cast<int>(grid_[0].size()) - 1,
static_cast<int>(grid_[1].size()) - 1,
static_cast<int>(grid_[2].size()) - 1};
for (const auto& g : grid_) {
if (g.size() < 2) fatal_error("x-, y-, and z- grids for rectilinear meshes "
"must each have at least 2 points");
for (int i = 1; i < g.size(); ++i) {
if (g[i] <= g[i-1]) fatal_error("Values in for x-, y-, and z- grids for "
"rectilinear meshes must be sorted and unique.");
}
if (int err = set_grid()) {
fatal_error(openmc_err_msg);
}
lower_left_ = {grid_[0].front(), grid_[1].front(), grid_[2].front()};
upper_right_ = {grid_[0].back(), grid_[1].back(), grid_[2].back()};
}
double RectilinearMesh::positive_grid_boundary(int* ijk, int i) const
@ -915,6 +903,33 @@ double RectilinearMesh::negative_grid_boundary(int* ijk, int i) const
return grid_[i][ijk[i] - 1];
}
int RectilinearMesh::set_grid()
{
shape_ = {static_cast<int>(grid_[0].size()) - 1,
static_cast<int>(grid_[1].size()) - 1,
static_cast<int>(grid_[2].size()) - 1};
for (const auto& g : grid_) {
if (g.size() < 2) {
set_errmsg("x-, y-, and z- grids for rectilinear meshes "
"must each have at least 2 points");
return OPENMC_E_INVALID_ARGUMENT;
}
for (int i = 1; i < g.size(); ++i) {
if (g[i] <= g[i-1]) {
set_errmsg("Values in for x-, y-, and z- grids for "
"rectilinear meshes must be sorted and unique.");
return OPENMC_E_INVALID_ARGUMENT;
}
}
}
lower_left_ = {grid_[0].front(), grid_[1].front(), grid_[2].front()};
upper_right_ = {grid_[0].back(), grid_[1].back(), grid_[2].back()};
return 0;
}
void RectilinearMesh::surface_bins_crossed(const Particle& p,
std::vector<int>& bins) const
{
@ -1144,13 +1159,15 @@ check_mesh(int32_t index)
return 0;
}
template <class T>
int
check_regular_mesh(int32_t index, RegularMesh** mesh)
check_mesh_type(int32_t index)
{
if (int err = check_mesh(index)) return err;
*mesh = dynamic_cast<RegularMesh*>(model::meshes[index].get());
if (!*mesh) {
set_errmsg("This function is only valid for regular meshes.");
T* mesh = dynamic_cast<T*>(model::meshes[index].get());
if (!mesh) {
set_errmsg("This function is not valid for input mesh.");
return OPENMC_E_INVALID_TYPE;
}
return 0;
@ -1160,17 +1177,40 @@ check_regular_mesh(int32_t index, RegularMesh** mesh)
// C API functions
//==============================================================================
RegularMesh* get_regular_mesh(int32_t index) {
return dynamic_cast<RegularMesh*>(model::meshes[index].get());
// Return the type of mesh as a C string
extern "C" int
openmc_mesh_get_type(int32_t index, char* type)
{
if (int err = check_mesh(index)) return err;
RegularMesh* mesh = dynamic_cast<RegularMesh*>(model::meshes[index].get());
if (mesh) {
std::strcpy(type, "regular");
} else {
RectilinearMesh* mesh = dynamic_cast<RectilinearMesh*>(model::meshes[index].get());
if (mesh) {
std::strcpy(type, "rectilinear");
}
}
return 0;
}
//! Extend the meshes array by n elements
extern "C" int
openmc_extend_meshes(int32_t n, int32_t* index_start, int32_t* index_end)
openmc_extend_meshes(int32_t n, const char* type, int32_t* index_start,
int32_t* index_end)
{
if (index_start) *index_start = model::meshes.size();
std::string mesh_type;
for (int i = 0; i < n; ++i) {
model::meshes.push_back(std::make_unique<RegularMesh>());
if (std::strcmp(type, "regular") == 0) {
model::meshes.push_back(std::make_unique<RegularMesh>());
} else if (std::strcmp(type, "rectilinear") == 0) {
model::meshes.push_back(std::make_unique<RectilinearMesh>());
} else {
throw std::runtime_error{"Unknown mesh type: " + std::string(type)};
}
}
if (index_end) *index_end = model::meshes.size() - 1;
@ -1209,23 +1249,23 @@ openmc_mesh_set_id(int32_t index, int32_t id)
return 0;
}
//! Get the dimension of a mesh
//! Get the dimension of a regular mesh
extern "C" int
openmc_mesh_get_dimension(int32_t index, int** dims, int* n)
openmc_regular_mesh_get_dimension(int32_t index, int** dims, int* n)
{
RegularMesh* mesh;
if (int err = check_regular_mesh(index, &mesh)) return err;
if (int err = check_mesh_type<RegularMesh>(index)) return err;
RegularMesh* mesh = dynamic_cast<RegularMesh*>(model::meshes[index].get());
*dims = mesh->shape_.data();
*n = mesh->n_dimension_;
return 0;
}
//! Set the dimension of a mesh
//! Set the dimension of a regular mesh
extern "C" int
openmc_mesh_set_dimension(int32_t index, int n, const int* dims)
openmc_regular_mesh_set_dimension(int32_t index, int n, const int* dims)
{
RegularMesh* mesh;
if (int err = check_regular_mesh(index, &mesh)) return err;
if (int err = check_mesh_type<RegularMesh>(index)) return err;
RegularMesh* mesh = dynamic_cast<RegularMesh*>(model::meshes[index].get());
// Copy dimension
std::vector<std::size_t> shape = {static_cast<std::size_t>(n)};
@ -1234,12 +1274,13 @@ openmc_mesh_set_dimension(int32_t index, int n, const int* dims)
return 0;
}
//! Get the mesh parameters
//! Get the regular mesh parameters
extern "C" int
openmc_mesh_get_params(int32_t index, double** ll, double** ur, double** width, int* n)
openmc_regular_mesh_get_params(int32_t index, double** ll, double** ur,
double** width, int* n)
{
RegularMesh* m;
if (int err = check_regular_mesh(index, &m)) return err;
if (int err = check_mesh_type<RegularMesh>(index)) return err;
RegularMesh* m = dynamic_cast<RegularMesh*>(model::meshes[index].get());
if (m->lower_left_.dimension() == 0) {
set_errmsg("Mesh parameters have not been set.");
@ -1253,13 +1294,13 @@ openmc_mesh_get_params(int32_t index, double** ll, double** ur, double** width,
return 0;
}
//! Set the mesh parameters
//! Set the regular mesh parameters
extern "C" int
openmc_mesh_set_params(int32_t index, int n, const double* ll, const double* ur,
const double* width)
openmc_regular_mesh_set_params(int32_t index, int n, const double* ll,
const double* ur, const double* width)
{
RegularMesh* m;
if (int err = check_regular_mesh(index, &m)) return err;
if (int err = check_mesh_type<RegularMesh>(index)) return err;
RegularMesh* m = dynamic_cast<RegularMesh*>(model::meshes[index].get());
std::vector<std::size_t> shape = {static_cast<std::size_t>(n)};
if (ll && ur) {
@ -1282,6 +1323,55 @@ openmc_mesh_set_params(int32_t index, int n, const double* ll, const double* ur,
return 0;
}
//! Get the rectilinear mesh grid
extern "C" int
openmc_rectilinear_mesh_get_grid(int32_t index, double** grid_x, int* nx,
double** grid_y, int* ny, double** grid_z, int* nz)
{
if (int err = check_mesh_type<RectilinearMesh>(index)) return err;
RectilinearMesh* m = dynamic_cast<RectilinearMesh*>(model::meshes[index].get());
if (m->lower_left_.dimension() == 0) {
set_errmsg("Mesh parameters have not been set.");
return OPENMC_E_ALLOCATE;
}
*grid_x = m->grid_[0].data();
*nx = m->grid_[0].size();
*grid_y = m->grid_[1].data();
*ny = m->grid_[1].size();
*grid_z = m->grid_[2].data();
*nz = m->grid_[2].size();
return 0;
}
//! Set the rectilienar mesh parameters
extern "C" int
openmc_rectilinear_mesh_set_grid(int32_t index, const double* grid_x,
const int nx, const double* grid_y, const int ny,
const double* grid_z, const int nz)
{
if (int err = check_mesh_type<RectilinearMesh>(index)) return err;
RectilinearMesh* m = dynamic_cast<RectilinearMesh*>(model::meshes[index].get());
m->n_dimension_ = 3;
m->grid_.resize(m->n_dimension_);
for (int i = 0; i < nx; i++) {
m->grid_[0].push_back(grid_x[i]);
}
for (int i = 0; i < ny; i++) {
m->grid_[1].push_back(grid_y[i]);
}
for (int i = 0; i < nz; i++) {
m->grid_[2].push_back(grid_z[i]);
}
int err = m->set_grid();
return err;
}
#ifdef DAGMC
UnstructuredMesh::UnstructuredMesh(pugi::xml_node node) : Mesh(node)

View file

@ -32,8 +32,8 @@ namespace openmc {
namespace data {
std::array<double, 2> energy_min {0.0, 0.0};
std::array<double, 2> energy_max {INFTY, INFTY};
double temperature_min {0.0};
double temperature_max {INFTY};
double temperature_min {INFTY};
double temperature_max {0.0};
std::unordered_map<std::string, int> nuclide_map;
std::vector<std::unique_ptr<Nuclide>> nuclides;
} // namespace data
@ -83,17 +83,25 @@ Nuclide::Nuclide(hid_t group, const std::vector<double>& temperature)
}
// Determine actual temperatures to read -- start by checking whether a
// temperature range was given, in which case all temperatures in the range
// are loaded irrespective of what temperatures actually appear in the model
// temperature range was given (indicated by T_max > 0), in which case all
// temperatures in the range are loaded irrespective of what temperatures
// actually appear in the model
std::vector<int> temps_to_read;
int n = temperature.size();
double T_min = n > 0 ? settings::temperature_range[0] : 0.0;
double T_max = n > 0 ? settings::temperature_range[1] : INFTY;
if (T_max > 0.0) {
for (auto T : temps_available) {
if (T_min <= T && T <= T_max) {
temps_to_read.push_back(std::round(T));
}
// Determine first available temperature below or equal to T_min
auto T_min_it = std::upper_bound(temps_available.begin(), temps_available.end(), T_min);
if (T_min_it != temps_available.begin()) --T_min_it;
// Determine first available temperature above or equal to T_max
auto T_max_it = std::lower_bound(temps_available.begin(), temps_available.end(), T_max);
if (T_max_it != temps_available.end()) ++T_max_it;
// Add corresponding temperatures to vector
for (auto it = T_min_it; it != T_max_it; ++it) {
temps_to_read.push_back(std::round(*it));
}
}
@ -161,11 +169,10 @@ Nuclide::Nuclide(hid_t group, const std::vector<double>& temperature)
// Sort temperatures to read
std::sort(temps_to_read.begin(), temps_to_read.end());
double T_min_read = *std::min_element(temps_to_read.cbegin(), temps_to_read.cend());
double T_max_read = *std::max_element(temps_to_read.cbegin(), temps_to_read.cend());
data::temperature_min = std::max(data::temperature_min, T_min_read);
data::temperature_max = std::min(data::temperature_max, T_max_read);
data::temperature_min =
std::min(data::temperature_min, static_cast<double>(temps_to_read.front()));
data::temperature_max =
std::max(data::temperature_max, static_cast<double>(temps_to_read.back()));
hid_t energy_group = open_group(group, "energy");
for (const auto& T : temps_to_read) {
@ -896,18 +903,21 @@ void Nuclide::calculate_urr_xs(int i_temp, Particle& p) const
if (fission < 0.) {fission = 0.;}
if (capture < 0.) {capture = 0.;}
// Set elastic, absorption, fission, and total x/s. Note that the total x/s
// is calculated as a sum of partials instead of the table-provided value
// Set elastic, absorption, fission, total, and capture x/s. Note that the
// total x/s is calculated as a sum of partials instead of the table-provided
// value
micro.elastic = elastic;
micro.absorption = capture + fission;
micro.fission = fission;
micro.total = elastic + inelastic + capture + fission;
if (simulation::need_depletion_rx) {
micro.reaction[0] = capture;
}
// Determine nu-fission cross-section
if (fissionable_) {
micro.nu_fission = nu(p.E_, EmissionMode::total) * micro.fission;
}
}
std::pair<gsl::index, double> Nuclide::find_temperature(double T) const

View file

@ -74,7 +74,7 @@ void title()
// Write version information
fmt::print(
" | The OpenMC Monte Carlo Code\n"
" Copyright | 2011-2020 MIT and OpenMC contributors\n"
" Copyright | 2011-2021 MIT and OpenMC contributors\n"
" License | https://docs.openmc.org/en/latest/license.html\n"
" Version | {}.{}.{}{}\n", VERSION_MAJOR, VERSION_MINOR,
VERSION_RELEASE, VERSION_DEV ? "-dev" : "");
@ -328,7 +328,7 @@ void print_version()
#ifdef GIT_SHA1
fmt::print("Git SHA1: {}\n", GIT_SHA1);
#endif
fmt::print("Copyright (c) 2011-2020 Massachusetts Institute of "
fmt::print("Copyright (c) 2011-2021 Massachusetts Institute of "
"Technology and OpenMC contributors\nMIT/X license at "
"<https://docs.openmc.org/en/latest/license.html>\n");
}

View file

@ -156,7 +156,7 @@ Particle::event_calculate_xs()
// initiate a search for the current cell. This generally happens at the
// beginning of the history and again for any secondary particles
if (coord_[n_coord_ - 1].cell == C_NONE) {
if (!find_cell(*this, false)) {
if (!exhaustive_find_cell(*this)) {
this->mark_as_lost("Could not find the cell containing particle "
+ std::to_string(id_));
return;
@ -454,7 +454,8 @@ Particle::cross_surface()
}
#endif
if (find_cell(*this, true)) return;
if (neighbor_list_find_cell(*this))
return;
// ==========================================================================
// COULDN'T FIND PARTICLE IN NEIGHBORING CELLS, SEARCH ALL CELLS
@ -462,7 +463,7 @@ Particle::cross_surface()
// Remove lower coordinate levels and assignment of surface
surface_ = 0;
n_coord_ = 1;
bool found = find_cell(*this, false);
bool found = exhaustive_find_cell(*this);
if (settings::run_mode != RunMode::PLOTTING && (!found)) {
// If a cell is still not found, there are two possible causes: 1) there is
@ -476,7 +477,7 @@ Particle::cross_surface()
// Couldn't find next cell anywhere! This probably means there is an actual
// undefined region in the geometry.
if (!find_cell(*this, false)) {
if (!exhaustive_find_cell(*this)) {
this->mark_as_lost("After particle " + std::to_string(id_) +
" crossed surface " + std::to_string(surf->id_) +
" it could not be located in any cell and it did not leak.");
@ -553,7 +554,7 @@ Particle::cross_reflective_bc(const Surface& surf, Direction new_u)
// (unless we're using a dagmc model, which has exactly one universe)
if (!settings::dagmc) {
n_coord_ = 1;
if (!find_cell(*this, true)) {
if (!neighbor_list_find_cell(*this)) {
this->mark_as_lost("Couldn't find particle after reflecting from surface "
+ std::to_string(surf.id_) + ".");
return;
@ -601,7 +602,7 @@ Particle::cross_periodic_bc(const Surface& surf, Position new_r,
// Figure out what cell particle is in now
n_coord_ = 1;
if (!find_cell(*this, true)) {
if (!neighbor_list_find_cell(*this)) {
this->mark_as_lost("Couldn't find particle after hitting periodic "
"boundary on surface " + std::to_string(surf.id_) + ". The normal vector "
"of one periodic surface may need to be reversed.");

View file

@ -101,7 +101,7 @@ RunMode run_mode {RunMode::UNSET};
std::unordered_set<int> sourcepoint_batch;
std::unordered_set<int> statepoint_batch;
std::unordered_set<int> source_write_surf_id;
int64_t max_particles;
int64_t max_surface_particles;
TemperatureMethod temperature_method {TemperatureMethod::NEAREST};
double temperature_tolerance {10.0};
double temperature_default {293.6};
@ -656,7 +656,7 @@ void read_settings_xml()
// Get maximum number of particles to be banked per surface
if (check_for_node(node_ssw, "max_particles")) {
max_particles = std::stoi(get_node_value(node_ssw, "max_particles"));
max_surface_particles = std::stoll(get_node_value(node_ssw, "max_particles"));
}
}

View file

@ -289,7 +289,7 @@ void allocate_banks()
if (settings::surf_source_write) {
// Allocate surface source bank
simulation::surf_source_bank.reserve(settings::max_particles);
simulation::surf_source_bank.reserve(settings::max_surface_particles);
}
}

View file

@ -474,8 +474,8 @@ template<int i1, int i2> double
axis_aligned_cylinder_evaluate(Position r, double offset1,
double offset2, double radius)
{
const double r1 = r[i1] - offset1;
const double r2 = r[i2] - offset2;
const double r1 = r.get<i1>() - offset1;
const double r2 = r.get<i2>() - offset2;
return r1*r1 + r2*r2 - radius*radius;
}
@ -486,12 +486,12 @@ template<int i1, int i2, int i3> double
axis_aligned_cylinder_distance(Position r, Direction u,
bool coincident, double offset1, double offset2, double radius)
{
const double a = 1.0 - u[i1]*u[i1]; // u^2 + v^2
const double a = 1.0 - u.get<i1>() * u.get<i1>(); // u^2 + v^2
if (a == 0.0) return INFTY;
const double r2 = r[i2] - offset1;
const double r3 = r[i3] - offset2;
const double k = r2 * u[i2] + r3 * u[i3];
const double r2 = r.get<i2>() - offset1;
const double r3 = r.get<i3>() - offset2;
const double k = r2 * u.get<i2>() + r3 * u.get<i3>();
const double c = r2*r2 + r3*r3 - radius*radius;
const double quad = k*k - a*c;
@ -532,9 +532,9 @@ template<int i1, int i2, int i3> Direction
axis_aligned_cylinder_normal(Position r, double offset1, double offset2)
{
Direction u;
u[i2] = 2.0 * (r[i2] - offset1);
u[i3] = 2.0 * (r[i3] - offset2);
u[i1] = 0.0;
u.get<i2>() = 2.0 * (r.get<i2>() - offset1);
u.get<i3>() = 2.0 * (r.get<i3>() - offset2);
u.get<i1>() = 0.0;
return u;
}
@ -750,9 +750,9 @@ template<int i1, int i2, int i3> double
axis_aligned_cone_evaluate(Position r, double offset1,
double offset2, double offset3, double radius_sq)
{
const double r1 = r[i1] - offset1;
const double r2 = r[i2] - offset2;
const double r3 = r[i3] - offset3;
const double r1 = r.get<i1>() - offset1;
const double r2 = r.get<i2>() - offset2;
const double r3 = r.get<i3>() - offset3;
return r2*r2 + r3*r3 - radius_sq*r1*r1;
}
@ -764,12 +764,13 @@ axis_aligned_cone_distance(Position r, Direction u,
bool coincident, double offset1, double offset2, double offset3,
double radius_sq)
{
const double r1 = r[i1] - offset1;
const double r2 = r[i2] - offset2;
const double r3 = r[i3] - offset3;
const double a = u[i2]*u[i2] + u[i3]*u[i3]
- radius_sq*u[i1]*u[i1];
const double k = r2*u[i2] + r3*u[i3] - radius_sq*r1*u[i1];
const double r1 = r.get<i1>() - offset1;
const double r2 = r.get<i2>() - offset2;
const double r3 = r.get<i3>() - offset3;
const double a = u.get<i2>() * u.get<i2>() + u.get<i3>() * u.get<i3>() -
radius_sq * u.get<i1>() * u.get<i1>();
const double k =
r2 * u.get<i2>() + r3 * u.get<i3>() - radius_sq * r1 * u.get<i1>();
const double c = r2*r2 + r3*r3 - radius_sq*r1*r1;
double quad = k*k - a*c;
@ -818,9 +819,9 @@ axis_aligned_cone_normal(Position r, double offset1, double offset2,
double offset3, double radius_sq)
{
Direction u;
u[i1] = -2.0 * radius_sq * (r[i1] - offset1);
u[i2] = 2.0 * (r[i2] - offset2);
u[i3] = 2.0 * (r[i3] - offset3);
u.get<i1>() = -2.0 * radius_sq * (r.get<i1>() - offset1);
u.get<i2>() = 2.0 * (r.get<i2>() - offset2);
u.get<i3>() = 2.0 * (r.get<i3>() - offset3);
return u;
}

View file

@ -479,6 +479,13 @@ double get_nuclide_xs(const Particle& p, int i_nuclide, int score_bin) {
const auto& rxn {*nuc.reactions_[m]};
const auto& micro {p.neutron_xs_[i_nuclide]};
// In the URR, the (n,gamma) cross section is sampled randomly from
// probability tables. Make sure we use the sampled value (which is equal to
// absorption - fission) rather than the dilute average value
if (micro.use_ptable && score_bin == N_GAMMA) {
return micro.absorption - micro.fission;
}
auto i_temp = micro.index_temp;
if (i_temp >= 0) { // Can be false due to multipole
// Get index on energy grid and interpolation factor

View file

@ -87,6 +87,8 @@ check_tally_triggers(double& ratio, int& tally_id, int& score)
case TriggerMetric::relative_error:
uncertainty = rel_err;
break;
case TriggerMetric::not_active:
UNREACHABLE();
}
// Compute the uncertainty / threshold ratio.

View file

@ -135,7 +135,8 @@ std::vector<VolumeCalculation::Result> VolumeCalculation::execute() const
p.u() = {0.5, 0.5, 0.5};
// If this location is not in the geometry at all, move on to next block
if (!find_cell(p, false)) continue;
if (!exhaustive_find_cell(p))
continue;
if (domain_type_ == TallyDomain::MATERIAL) {
if (p.material_ != MATERIAL_VOID) {

View file

@ -0,0 +1,38 @@
<?xml version='1.0' encoding='utf-8'?>
<geometry>
<cell id="1" material="1" region="-1" universe="1" />
<cell id="2" material="2" region="1" universe="1" />
<cell fill="1" id="3" region="2 -3 4 -5 6 -8" rotation="10 20 30" universe="2" />
<cell fill="1" id="4" region="2 -3 4 -5 8 -7" translation="0 0 15" universe="2" />
<surface coeffs="1.0 0.0 0.0 5.0" id="1" type="sphere" />
<surface boundary="vacuum" coeffs="-7.5" id="2" name="minimum x" type="x-plane" />
<surface boundary="vacuum" coeffs="7.5" id="3" name="maximum x" type="x-plane" />
<surface boundary="vacuum" coeffs="-7.5" id="4" name="minimum y" type="y-plane" />
<surface boundary="vacuum" coeffs="7.5" id="5" name="maximum y" type="y-plane" />
<surface boundary="vacuum" coeffs="-7.5" id="6" type="z-plane" />
<surface boundary="vacuum" coeffs="22.5" id="7" type="z-plane" />
<surface coeffs="7.5" id="8" type="z-plane" />
</geometry>
<?xml version='1.0' encoding='utf-8'?>
<materials>
<material depletable="true" id="1">
<density units="g/cc" value="10.0" />
<nuclide ao="1.0" name="U235" />
</material>
<material id="2">
<density units="g/cc" value="0.1" />
<nuclide ao="0.1" name="H1" />
</material>
</materials>
<?xml version='1.0' encoding='utf-8'?>
<settings>
<run_mode>eigenvalue</run_mode>
<particles>10000</particles>
<batches>10</batches>
<inactive>5</inactive>
<source strength="1.0">
<space type="box">
<parameters>-4.0 -4.0 -4.0 4.0 4.0 4.0</parameters>
</space>
</source>
</settings>

View file

@ -0,0 +1,2 @@
k-combined:
4.453328E-01 5.918369E-03

View file

@ -0,0 +1,50 @@
import pytest
import openmc
from tests.testing_harness import PyAPITestHarness
@pytest.fixture
def model():
model = openmc.model.Model()
fuel = openmc.Material()
fuel.set_density('g/cc', 10.0)
fuel.add_nuclide('U235', 1.0)
h1 = openmc.Material()
h1.set_density('g/cc', 0.1)
h1.add_nuclide('H1', 0.1)
inner_sphere = openmc.Sphere(x0=1.0, r=5.0)
fuel_cell = openmc.Cell(fill=fuel, region=-inner_sphere)
hydrogen_cell = openmc.Cell(fill=h1, region=+inner_sphere)
univ = openmc.Universe(cells=[fuel_cell, hydrogen_cell])
# Create one cell on top of the other. Only one
# has a rotation
box = openmc.rectangular_prism(15., 15., 'z', boundary_type='vacuum')
lower_z = openmc.ZPlane(-7.5, boundary_type='vacuum')
upper_z = openmc.ZPlane(22.5, boundary_type='vacuum')
middle_z = openmc.ZPlane(7.5)
lower_cell = openmc.Cell(fill=univ, region=box & +lower_z & -middle_z)
lower_cell.rotation = (10, 20, 30)
upper_cell = openmc.Cell(fill=univ, region=box & +middle_z & -upper_z)
upper_cell.translation = (0, 0, 15)
model.geometry = openmc.Geometry(root=[lower_cell, upper_cell])
model.settings.particles = 10000
model.settings.inactive = 5
model.settings.batches = 10
source_box = openmc.stats.Box((-4., -4., -4.), (4., 4., 4.))
model.settings.source = openmc.Source(space=source_box)
return model
def test_rotation(model):
harness = PyAPITestHarness('statepoint.10.h5', model)
harness.main()

View file

@ -141,6 +141,31 @@ def test_cmfd_feed():
harness = CMFDTestHarness('statepoint.20.h5', cmfd_run)
harness.main()
def test_cmfd_feed_rectlin():
"""Test 1 group CMFD solver with CMFD feedback"""
# Initialize and set CMFD mesh
cmfd_mesh = cmfd.CMFDMesh()
cmfd_mesh.mesh_type = 'rectilinear'
x_grid = np.linspace(-10, 10, 11)
y_grid = [-1., 1.]
z_grid = [-1., 1.]
cmfd_mesh.grid = [x_grid, y_grid, z_grid]
cmfd_mesh.albedo = (0.0, 0.0, 1.0, 1.0, 1.0, 1.0)
# Initialize and run CMFDRun object
cmfd_run = cmfd.CMFDRun()
cmfd_run.mesh = cmfd_mesh
cmfd_run.tally_begin = 5
cmfd_run.solver_begin = 5
cmfd_run.display = {'dominance': True}
cmfd_run.feedback = True
cmfd_run.gauss_seidel_tolerance = [1.e-15, 1.e-20]
cmfd_run.run()
# Initialize and run CMFD test harness
harness = CMFDTestHarness('statepoint.20.h5', cmfd_run)
harness.main()
def test_cmfd_multithread():
"""Test 1 group CMFD solver with all available threads"""
# Initialize and set CMFD mesh

View file

@ -0,0 +1,43 @@
<?xml version="1.0" encoding="UTF-8"?>
<geometry>
<!-- Definition of Cells -->
<cell id="1">
<universe>0</universe>
<region>-1 2 -3 4 -5 6</region>
<material>1</material>
</cell>
<!-- Defition of Surfaces -->
<surface id="1">
<type>x-plane</type>
<coeffs>10</coeffs>
<boundary> vacuum </boundary>
</surface>
<surface id="2">
<type>x-plane</type>
<coeffs>-10</coeffs>
<boundary> vacuum </boundary>
</surface>
<surface id="3">
<type>y-plane</type>
<coeffs>1</coeffs>
<boundary>reflective</boundary>
</surface>
<surface id="4">
<type>y-plane</type>
<coeffs>-1</coeffs>
<boundary>reflective</boundary>
</surface>
<surface id="5">
<type>z-plane</type>
<coeffs>1</coeffs>
<boundary>reflective</boundary>
</surface>
<surface id="6">
<type>z-plane</type>
<coeffs>-1</coeffs>
<boundary>reflective</boundary>
</surface>
</geometry>

View file

@ -0,0 +1,12 @@
<?xml version="1.0"?>
<materials>
<!-- Definition of materials -->
<material id="1">
<density value="19" units="g/cc" />
<nuclide name="U235" wo="0.21" />
<nuclide name="U238" wo="0.68" />
<nuclide name="O16" wo="0.11" />
</material>
</materials>

View file

@ -0,0 +1,636 @@
k-combined:
1.157187E+00 1.636299E-02
tally 1:
1.105119E+01
1.225764E+01
2.005562E+01
4.044077E+01
2.763651E+01
7.659204E+01
3.350385E+01
1.124748E+02
3.708973E+01
1.378980E+02
3.819687E+01
1.461904E+02
3.563815E+01
1.272689E+02
2.951618E+01
8.720253E+01
2.110567E+01
4.462562E+01
1.177125E+01
1.391704E+01
tally 2:
8.413458E+00
3.600701E+00
5.811221E+00
1.720423E+00
3.152237E+01
4.997128E+01
2.209153E+01
2.455911E+01
2.181469E+01
2.395139E+01
1.541498E+01
1.196916E+01
5.445894E+01
1.490652E+02
3.866629E+01
7.523403E+01
3.282600E+01
5.400949E+01
2.342806E+01
2.753117E+01
7.081101E+01
2.514150E+02
5.036626E+01
1.272409E+02
3.737870E+01
7.016018E+01
2.659096E+01
3.553255E+01
3.782640E+01
7.182993E+01
2.699064E+01
3.660686E+01
7.361578E+01
2.717788E+02
5.234377E+01
1.374393E+02
3.428621E+01
5.895928E+01
2.449124E+01
3.009739E+01
5.922017E+01
1.756748E+02
4.200257E+01
8.838800E+01
2.336382E+01
2.740967E+01
1.658498E+01
1.382335E+01
3.297049E+01
5.456989E+01
2.339783E+01
2.749345E+01
8.828373E+00
3.943974E+00
6.102413E+00
1.883966E+00
tally 3:
5.596852E+00
1.598537E+00
3.522058E-01
6.713731E-03
2.126148E+01
2.274990E+01
1.422059E+00
1.023184E-01
1.486366E+01
1.113118E+01
9.672994E-01
4.841756E-02
3.718151E+01
6.959813E+01
2.434965E+00
2.992672E-01
2.255899E+01
2.552453E+01
1.400193E+00
9.974367E-02
4.850275E+01
1.180150E+02
3.030061E+00
4.650085E-01
2.561202E+01
3.297554E+01
1.660808E+00
1.399354E-01
2.603551E+01
3.406292E+01
1.644980E+00
1.378019E-01
5.041383E+01
1.274936E+02
3.230209E+00
5.274516E-01
2.357275E+01
2.788910E+01
1.519553E+00
1.172908E-01
4.043162E+01
8.190810E+01
2.584619E+00
3.376865E-01
1.598070E+01
1.283439E+01
1.032328E+00
5.432257E-02
2.254607E+01
2.553039E+01
1.449211E+00
1.061279E-01
5.871759E+00
1.744573E+00
3.943129E-01
8.103936E-03
tally 4:
3.066217E+00
4.730450E-01
0.000000E+00
0.000000E+00
1.360953E+00
9.533513E-02
4.308283E+00
9.334136E-01
0.000000E+00
0.000000E+00
0.000000E+00
0.000000E+00
0.000000E+00
0.000000E+00
0.000000E+00
0.000000E+00
0.000000E+00
0.000000E+00
0.000000E+00
0.000000E+00
0.000000E+00
0.000000E+00
0.000000E+00
0.000000E+00
4.308283E+00
9.334136E-01
1.360953E+00
9.533513E-02
3.783652E+00
7.238359E-01
6.291955E+00
1.990579E+00
0.000000E+00
0.000000E+00
0.000000E+00
0.000000E+00
0.000000E+00
0.000000E+00
0.000000E+00
0.000000E+00
0.000000E+00
0.000000E+00
0.000000E+00
0.000000E+00
0.000000E+00
0.000000E+00
0.000000E+00
0.000000E+00
6.291955E+00
1.990579E+00
3.783652E+00
7.238359E-01
4.885573E+00
1.200082E+00
7.106830E+00
2.535661E+00
0.000000E+00
0.000000E+00
0.000000E+00
0.000000E+00
0.000000E+00
0.000000E+00
0.000000E+00
0.000000E+00
0.000000E+00
0.000000E+00
0.000000E+00
0.000000E+00
0.000000E+00
0.000000E+00
0.000000E+00
0.000000E+00
7.106830E+00
2.535661E+00
4.885573E+00
1.200082E+00
6.866283E+00
2.371554E+00
8.503237E+00
3.630917E+00
0.000000E+00
0.000000E+00
0.000000E+00
0.000000E+00
0.000000E+00
0.000000E+00
0.000000E+00
0.000000E+00
0.000000E+00
0.000000E+00
0.000000E+00
0.000000E+00
0.000000E+00
0.000000E+00
0.000000E+00
0.000000E+00
8.503237E+00
3.630917E+00
6.866283E+00
2.371554E+00
7.768902E+00
3.027583E+00
9.082457E+00
4.135990E+00
0.000000E+00
0.000000E+00
0.000000E+00
0.000000E+00
0.000000E+00
0.000000E+00
0.000000E+00
0.000000E+00
0.000000E+00
0.000000E+00
0.000000E+00
0.000000E+00
0.000000E+00
0.000000E+00
0.000000E+00
0.000000E+00
9.082457E+00
4.135990E+00
7.768902E+00
3.027583E+00
8.769969E+00
3.865147E+00
9.319943E+00
4.358847E+00
0.000000E+00
0.000000E+00
0.000000E+00
0.000000E+00
0.000000E+00
0.000000E+00
0.000000E+00
0.000000E+00
0.000000E+00
0.000000E+00
0.000000E+00
0.000000E+00
0.000000E+00
0.000000E+00
0.000000E+00
0.000000E+00
9.319943E+00
4.358847E+00
8.769969E+00
3.865147E+00
9.325939E+00
4.366610E+00
9.435739E+00
4.466600E+00
0.000000E+00
0.000000E+00
0.000000E+00
0.000000E+00
0.000000E+00
0.000000E+00
0.000000E+00
0.000000E+00
0.000000E+00
0.000000E+00
0.000000E+00
0.000000E+00
0.000000E+00
0.000000E+00
0.000000E+00
0.000000E+00
9.435739E+00
4.466600E+00
9.325939E+00
4.366610E+00
9.542810E+00
4.573627E+00
9.199847E+00
4.247714E+00
0.000000E+00
0.000000E+00
0.000000E+00
0.000000E+00
0.000000E+00
0.000000E+00
0.000000E+00
0.000000E+00
0.000000E+00
0.000000E+00
0.000000E+00
0.000000E+00
0.000000E+00
0.000000E+00
0.000000E+00
0.000000E+00
9.199847E+00
4.247714E+00
9.542810E+00
4.573627E+00
9.374166E+00
4.404055E+00
8.192575E+00
3.370018E+00
0.000000E+00
0.000000E+00
0.000000E+00
0.000000E+00
0.000000E+00
0.000000E+00
0.000000E+00
0.000000E+00
0.000000E+00
0.000000E+00
0.000000E+00
0.000000E+00
0.000000E+00
0.000000E+00
0.000000E+00
0.000000E+00
8.192575E+00
3.370018E+00
9.374166E+00
4.404055E+00
8.889272E+00
3.956143E+00
7.298067E+00
2.671190E+00
0.000000E+00
0.000000E+00
0.000000E+00
0.000000E+00
0.000000E+00
0.000000E+00
0.000000E+00
0.000000E+00
0.000000E+00
0.000000E+00
0.000000E+00
0.000000E+00
0.000000E+00
0.000000E+00
0.000000E+00
0.000000E+00
7.298067E+00
2.671190E+00
8.889272E+00
3.956143E+00
7.459052E+00
2.787818E+00
5.208762E+00
1.362339E+00
0.000000E+00
0.000000E+00
0.000000E+00
0.000000E+00
0.000000E+00
0.000000E+00
0.000000E+00
0.000000E+00
0.000000E+00
0.000000E+00
0.000000E+00
0.000000E+00
0.000000E+00
0.000000E+00
0.000000E+00
0.000000E+00
5.208762E+00
1.362339E+00
7.459052E+00
2.787818E+00
6.514105E+00
2.127726E+00
3.935834E+00
7.791845E-01
0.000000E+00
0.000000E+00
0.000000E+00
0.000000E+00
0.000000E+00
0.000000E+00
0.000000E+00
0.000000E+00
0.000000E+00
0.000000E+00
0.000000E+00
0.000000E+00
0.000000E+00
0.000000E+00
0.000000E+00
0.000000E+00
3.935834E+00
7.791845E-01
6.514105E+00
2.127726E+00
4.382888E+00
9.637493E-01
1.398986E+00
9.904821E-02
0.000000E+00
0.000000E+00
0.000000E+00
0.000000E+00
0.000000E+00
0.000000E+00
0.000000E+00
0.000000E+00
0.000000E+00
0.000000E+00
0.000000E+00
0.000000E+00
0.000000E+00
0.000000E+00
0.000000E+00
0.000000E+00
1.398986E+00
9.904821E-02
4.382888E+00
9.637493E-01
3.080536E+00
4.769864E-01
0.000000E+00
0.000000E+00
0.000000E+00
0.000000E+00
0.000000E+00
0.000000E+00
0.000000E+00
0.000000E+00
0.000000E+00
0.000000E+00
0.000000E+00
0.000000E+00
0.000000E+00
0.000000E+00
0.000000E+00
0.000000E+00
0.000000E+00
0.000000E+00
tally 5:
5.593947E+00
1.596885E+00
8.106566E-01
3.664721E-02
2.125531E+01
2.273647E+01
3.065490E+00
4.787394E-01
1.486069E+01
1.112690E+01
1.949973E+00
1.949146E-01
3.717221E+01
6.956205E+01
5.001200E+00
1.267587E+00
2.255049E+01
2.550506E+01
2.899016E+00
4.325940E-01
4.849423E+01
1.179738E+02
6.528348E+00
2.152826E+00
2.561091E+01
3.297274E+01
3.488550E+00
6.229290E-01
2.603063E+01
3.405034E+01
3.601295E+00
6.558219E-01
5.040479E+01
1.274480E+02
6.786233E+00
2.323774E+00
2.357068E+01
2.788373E+01
2.889115E+00
4.258034E-01
4.042343E+01
8.187501E+01
5.332998E+00
1.439867E+00
1.597773E+01
1.282957E+01
1.942949E+00
1.954364E-01
2.254116E+01
2.551921E+01
3.104316E+00
4.901972E-01
5.869140E+00
1.742897E+00
9.010904E-01
4.316080E-02
cmfd indices
1.400000E+01
1.000000E+00
1.000000E+00
1.000000E+00
k cmfd
1.175888E+00
1.173169E+00
1.178686E+00
1.169259E+00
1.159624E+00
1.161905E+00
1.150366E+00
1.156936E+00
1.152230E+00
1.158120E+00
1.151832E+00
1.156090E+00
1.156076E+00
1.159749E+00
1.159483E+00
1.159617E+00
cmfd entropy
3.585755E+00
3.588829E+00
3.591601E+00
3.596486E+00
3.598552E+00
3.600536E+00
3.606024E+00
3.602025E+00
3.603625E+00
3.601073E+00
3.602144E+00
3.601031E+00
3.603146E+00
3.603878E+00
3.602530E+00
3.603442E+00
cmfd balance
5.69096E-03
5.82028E-03
5.54245E-03
3.56776E-03
2.86949E-03
2.55946E-03
2.27787E-03
2.58567E-03
1.98573E-03
2.01270E-03
2.15386E-03
1.88029E-03
1.65172E-03
1.50711E-03
1.28653E-03
1.19687E-03
cmfd dominance ratio
6.039E-01
6.045E-01
6.026E-01
6.050E-01
6.067E-01
6.071E-01
6.097E-01
6.060E-01
6.067E-01
6.060E-01
6.069E-01
6.056E-01
6.064E-01
6.066E-01
6.050E-01
6.052E-01
cmfd openmc source comparison
6.220816E-03
6.181852E-03
4.920765E-03
5.006176E-03
4.717371E-03
5.049855E-03
2.182449E-03
3.301480E-03
3.408666E-03
2.012317E-03
1.751563E-03
1.934989E-03
1.827288E-03
1.055350E-03
1.321006E-03
1.220975E-03
cmfd source
1.501950E-02
6.088975E-02
4.178034E-02
1.057740E-01
6.080482E-02
1.314338E-01
7.208400E-02
7.138769E-02
1.400772E-01
6.569802E-02
1.114779E-01
4.436863E-02
6.224041E-02
1.696388E-02

View file

@ -0,0 +1,26 @@
<?xml version="1.0" encoding="UTF-8"?>
<settings>
<!-- Parameters for criticality calculation -->
<run_mode>eigenvalue</run_mode>
<batches>20</batches>
<inactive>10</inactive>
<particles>1000</particles>
<!-- Starting source -->
<source>
<space>
<type>box</type>
<parameters>-10 -1 -1 10 1 1</parameters>
</space>
</source>
<!-- Shannon Entropy -->
<mesh id="10">
<dimension> 10 1 1 </dimension>
<lower_left> -10.0 -1.0 -1.0 </lower_left>
<upper_right> 10.0 1.0 1.0 </upper_right>
</mesh>
<entropy_mesh>10</entropy_mesh>
</settings>

View file

@ -0,0 +1,21 @@
<?xml version="1.0"?>
<tallies>
<mesh id="1">
<type>regular</type>
<lower_left>-10 -1 -1 </lower_left>
<upper_right>10 1 1</upper_right>
<dimension>10 1 1</dimension>
</mesh>
<filter id="1">
<type>mesh</type>
<bins>1</bins>
</filter>
<tally id="1">
<filters>1</filters>
<scores>flux</scores>
</tally>
</tallies>

View file

@ -0,0 +1,30 @@
from tests.testing_harness import CMFDTestHarness
from openmc import cmfd
import numpy as np
import scipy.sparse
def test_cmfd_feed_rectlin():
"""Test 1 group CMFD solver with CMFD feedback"""
# Initialize and set CMFD mesh
cmfd_mesh = cmfd.CMFDMesh()
cmfd_mesh.mesh_type = 'rectilinear'
x_grid = [-10., -9., -7., -6., -4., -3., -1., 0., 1., 3., 4., 6., 7., 9., 10.]
y_grid = [-1., 1.]
z_grid = [-1., 1.]
cmfd_mesh.grid = [x_grid, y_grid, z_grid]
cmfd_mesh.albedo = (0.0, 0.0, 1.0, 1.0, 1.0, 1.0)
# Initialize and run CMFDRun object
cmfd_run = cmfd.CMFDRun()
cmfd_run.mesh = cmfd_mesh
cmfd_run.tally_begin = 5
cmfd_run.solver_begin = 5
cmfd_run.display = {'dominance': True}
cmfd_run.feedback = True
cmfd_run.gauss_seidel_tolerance = [1.e-15, 1.e-20]
cmfd_run.run()
# Initialize and run CMFD test harness
harness = CMFDTestHarness('statepoint.20.h5', cmfd_run)
harness.main()

View file

@ -1,2 +1,2 @@
energyfunction nuclide score mean std. dev.
0 d2effa26cb3cf2 Am241 ((n,gamma) / (n,gamma)) 1.74e-01 3.55e-03
0 d2effa26cb3cf2 Am241 ((n,gamma) / (n,gamma)) 1.74e-01 3.52e-03

View file

@ -184,7 +184,7 @@ nu-diffusion-coefficient
0 1 2 total 0.000000 0.000000
(n,gamma)
material group in nuclide mean std. dev.
1 1 1 total 0.019727 0.002262
1 1 1 total 0.019720 0.002260
0 1 2 total 0.071719 0.006262
(n,a)
material group in nuclide mean std. dev.
@ -490,7 +490,7 @@ nu-diffusion-coefficient
0 2 2 total 0.000000 0.000000
(n,gamma)
material group in nuclide mean std. dev.
1 2 1 total 0.001569 0.000322
1 2 1 total 0.001571 0.000323
0 2 2 total 0.005400 0.000618
(n,a)
material group in nuclide mean std. dev.

View file

@ -1 +1 @@
a9999488e2aa2ad0f1d694afedb71fbb56f1d0c8e8abdb6616698505a9d85302bf90586866fdb58eac96f76712a2dfbc884cc03087df7b5d148fb29d14dd2bbb
54a6351f3444c5ea85f972ed05f48c81da2de27a6295a660c321e7c595ec3865e5882fb7fa1f2e4a3bfd616e4b637482e2a16930dd59c3968d04c59d4b1c08b1

Some files were not shown because too many files have changed in this diff Show more