diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000000..f8ab9235ef --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,122 @@ +name: CI + +on: + # allows us to run workflows manually + workflow_dispatch: + + pull_request: + branches: + - develop + - master + push: + branches: + - develop + - master + +env: + MPI_DIR: /usr + HDF5_ROOT: /usr + OMP_NUM_THREADS: 2 + COVERALLS_PARALLEL: true + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + +jobs: + main: + runs-on: ubuntu-16.04 + strategy: + matrix: + python-version: [3.8] + mpi: [n, y] + omp: [n, y] + dagmc: [n] + event: [n] + vectfit: [n] + + include: + - python-version: 3.6 + omp: n + mpi: n + - python-version: 3.7 + omp: n + mpi: n + - dagmc: y + python-version: 3.8 + mpi: y + omp: y + - event: y + python-version: 3.8 + omp: y + mpi: n + - vectfit: y + python-version: 3.8 + omp: n + mpi: y + + env: + MPI: ${{ matrix.mpi }} + PHDF5: ${{ matrix.mpi }} + OMP: ${{ matrix.omp }} + DAGMC: ${{ matrix.dagmc }} + EVENT: ${{ matrix.event }} + VECTFIT: ${{ matrix.vectfit }} + + steps: + - + uses: actions/checkout@v2 + + - + name: Set up Python ${{ matrix.python-version }} + uses: actions/setup-python@v2 + with: + python-version: ${{ matrix.python-version }} + + - + name: Environment Variables + run: | + echo "DAGMC_ROOT=$HOME/DAGMC" + echo "OPENMC_CROSS_SECTIONS=$HOME/nndc_hdf5/cross_sections.xml" >> $GITHUB_ENV + echo "OPENMC_ENDF_DATA=$HOME/endf-b-vii.1" >> $GITHUB_ENV + + - + name: Apt dependencies + shell: bash + run: | + sudo apt -y update + sudo apt install -y mpich \ + libmpich-dev \ + libhdf5-serial-dev \ + libhdf5-mpich-dev \ + libeigen3-dev + - + name: install + shell: bash + run: | + echo "$HOME/NJOY2016/build" >> $GITHUB_PATH + $GITHUB_WORKSPACE/tools/ci/gha-install.sh + - + name: before + shell: bash + run: $GITHUB_WORKSPACE/tools/ci/gha-before-script.sh + + - + name: test + shell: bash + run: $GITHUB_WORKSPACE/tools/ci/gha-script.sh + + - + name: after_success + shell: bash + run: | + cpp-coveralls -i src -i include --exclude-pattern "/usr/*" --dump cpp_cov.json + coveralls --merge=cpp_cov.json + + finish: + needs: main + runs-on: ubuntu-latest + steps: + - name: Coveralls Finished + uses: coverallsapp/github-action@master + with: + github-token: ${{ secrets.github_token }} + parallel-finished: true \ No newline at end of file diff --git a/.github/workflows/dockerhub-publish-dev.yml b/.github/workflows/dockerhub-publish-dev.yml new file mode 100644 index 0000000000..00fab4129a --- /dev/null +++ b/.github/workflows/dockerhub-publish-dev.yml @@ -0,0 +1,32 @@ +name: dockerhub-publish-develop + +on: + push: + branches: develop + +jobs: + main: + runs-on: ubuntu-latest + steps: + - + name: Set up QEMU + uses: docker/setup-qemu-action@v1 + - + name: Set up Docker Buildx + uses: docker/setup-buildx-action@v1 + - + name: Login to DockerHub + uses: docker/login-action@v1 + with: + username: ${{ secrets.DOCKERHUB_USERNAME }} + password: ${{ secrets.DOCKERHUB_TOKEN }} + - + name: Build and push + id: docker_build + uses: docker/build-push-action@v2 + with: + push: true + tags: openmc/openmc:develop + - + name: Image digest + run: echo ${{ steps.docker_build.outputs.digest }} diff --git a/.github/workflows/dockerhub-publish-release.yml b/.github/workflows/dockerhub-publish-release.yml new file mode 100644 index 0000000000..d8de72618d --- /dev/null +++ b/.github/workflows/dockerhub-publish-release.yml @@ -0,0 +1,35 @@ +name: dockerhub-publish-release + +on: + push: + tags: 'v*.*.*' + +jobs: + main: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - name: Set env + run: echo "RELEASE_VERSION=${GITHUB_REF#refs/*/}" >> $GITHUB_ENV + - + name: Set up QEMU + uses: docker/setup-qemu-action@v1 + - + name: Set up Docker Buildx + uses: docker/setup-buildx-action@v1 + - + name: Login to DockerHub + uses: docker/login-action@v1 + with: + username: ${{ secrets.DOCKERHUB_USERNAME }} + password: ${{ secrets.DOCKERHUB_TOKEN }} + - + name: Build and push + id: docker_build + uses: docker/build-push-action@v2 + with: + push: true + tags: openmc/openmc:${{ env.RELEASE_VERSION }} + - + name: Image digest + run: echo ${{ steps.docker_build.outputs.digest }} diff --git a/.github/workflows/dockerhub-publish.yml b/.github/workflows/dockerhub-publish.yml new file mode 100644 index 0000000000..0737849e93 --- /dev/null +++ b/.github/workflows/dockerhub-publish.yml @@ -0,0 +1,32 @@ +name: dockerhub-publish-latest + +on: + push: + branches: master + +jobs: + main: + runs-on: ubuntu-latest + steps: + - + name: Set up QEMU + uses: docker/setup-qemu-action@v1 + - + name: Set up Docker Buildx + uses: docker/setup-buildx-action@v1 + - + name: Login to DockerHub + uses: docker/login-action@v1 + with: + username: ${{ secrets.DOCKERHUB_USERNAME }} + password: ${{ secrets.DOCKERHUB_TOKEN }} + - + name: Build and push + id: docker_build + uses: docker/build-push-action@v2 + with: + push: true + tags: openmc/openmc:latest + - + name: Image digest + run: echo ${{ steps.docker_build.outputs.digest }} diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 6eee7f7429..0000000000 --- a/.travis.yml +++ /dev/null @@ -1,60 +0,0 @@ - -sudo: required -dist: xenial -language: python -addons: - apt: - packages: - - mpich - - libmpich-dev - - libhdf5-serial-dev - - libhdf5-mpich-dev - - libeigen3-dev - config: - retries: true -services: - - xvfb -cache: - directories: - - $HOME/nndc_hdf5 - - $HOME/endf-b-vii.1 -env: - global: - - MPI_DIR=/usr - - DAGMC_ROOT=$HOME/DAGMC - - HDF5_ROOT=/usr - - OMP_NUM_THREADS=2 - - OPENMC_CROSS_SECTIONS=$HOME/nndc_hdf5/cross_sections.xml - - OPENMC_ENDF_DATA=$HOME/endf-b-vii.1 - - PATH=$PATH:$HOME/NJOY2016/build - - COVERALLS_PARALLEL=true - - NUMPY_EXPERIMENTAL_ARRAY_FUNCTION=0 -matrix: - include: - - python: "3.6" - env: OMP=n MPI=n PHDF5=n - - python: "3.7" - env: OMP=n MPI=n PHDF5=n - - python: "3.8" - env: OMP=n MPI=n PHDF5=n - - python: "3.8" - env: OMP=y MPI=n PHDF5=n - - python: "3.8" - env: OMP=n MPI=y PHDF5=n VECTFIT=y - - python: "3.8" - env: OMP=n MPI=y PHDF5=y - - python: "3.8" - env: OMP=y MPI=y PHDF5=y DAGMC=y - - python: "3.8" - env: OMP=y MPI=n PHDF5=n EVENT=y -notifications: - webhooks: https://coveralls.io/webhook?repo_token=$COVERALLS_REPO_TOKEN -install: - - ./tools/ci/travis-install.sh -before_script: - - ./tools/ci/travis-before-script.sh -script: - - ./tools/ci/travis-script.sh -after_success: - - cpp-coveralls -i src -i include --exclude-pattern "/usr/*" --dump cpp_cov.json - - coveralls --merge=cpp_cov.json diff --git a/README.md b/README.md index f0bb67989d..a905a501c0 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ # OpenMC Monte Carlo Particle Transport Code [![License](https://img.shields.io/github/license/openmc-dev/openmc.svg)](http://openmc.readthedocs.io/en/latest/license.html) -[![Travis CI build status (Linux)](https://travis-ci.org/openmc-dev/openmc.svg?branch=develop)](https://travis-ci.org/openmc-dev/openmc) +[![GitHub Actions build status (Linux)](https://github.com/openmc-dev/openmc/workflows/CI/badge.svg?branch=develop)](https://github.com/openmc-dev/openmc/actions) [![Code Coverage](https://coveralls.io/repos/github/openmc-dev/openmc/badge.svg?branch=develop)](https://coveralls.io/github/openmc-dev/openmc?branch=develop) The OpenMC project aims to provide a fully-featured Monte Carlo particle diff --git a/docs/requirements-rtd.txt b/docs/requirements-rtd.txt index 7801c670f8..fd76dfffb9 100644 --- a/docs/requirements-rtd.txt +++ b/docs/requirements-rtd.txt @@ -2,3 +2,10 @@ sphinx-numfig jupyter sphinxcontrib-katex sphinxcontrib-svg2pdfconverter +nbsphinx +numpy +scipy +h5py +pandas +uncertainties +matplotlib diff --git a/docs/source/conf.py b/docs/source/conf.py index 2410a887db..dea3440a76 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -20,26 +20,15 @@ on_rtd = os.environ.get('READTHEDOCS', None) == 'True' # ImportErrors when building documentation from unittest.mock import MagicMock - MOCK_MODULES = [ - 'numpy', 'numpy.polynomial', 'numpy.polynomial.polynomial', - 'numpy.ctypeslib', 'scipy', 'scipy.sparse', 'scipy.sparse.linalg', - 'scipy.interpolate', 'scipy.integrate', 'scipy.optimize', 'scipy.special', - 'scipy.stats', 'scipy.spatial', 'h5py', 'pandas', 'uncertainties', - 'matplotlib', 'matplotlib.pyplot', 'openmoc', - 'openmc.data.reconstruct', 'openmc.checkvalue' + 'openmoc', 'openmc.data.reconstruct', ] sys.modules.update((mod_name, MagicMock()) for mod_name in MOCK_MODULES) -import numpy as np -np.ndarray = MagicMock -np.polynomial.Polynomial = MagicMock - # If extensions (or modules to document with autodoc) are in another directory, # add these directories to sys.path here. If the directory is relative to the # documentation root, use os.path.abspath to make it absolute, like shown here. -sys.path.insert(0, os.path.abspath('../sphinxext')) sys.path.insert(0, os.path.abspath('../..')) @@ -47,14 +36,16 @@ sys.path.insert(0, os.path.abspath('../..')) # Add any Sphinx extension module names here, as strings. They can be extensions # coming with Sphinx (named 'sphinx.ext.*') or your custom ones. -extensions = ['sphinx.ext.autodoc', - 'sphinx.ext.napoleon', - 'sphinx.ext.autosummary', - 'sphinx.ext.intersphinx', - 'sphinx.ext.viewcode', - 'sphinxcontrib.katex', - 'sphinx_numfig', - 'notebook_sphinxext'] +extensions = [ + 'sphinx.ext.autodoc', + 'sphinx.ext.napoleon', + 'sphinx.ext.autosummary', + 'sphinx.ext.intersphinx', + 'sphinx.ext.viewcode', + 'sphinxcontrib.katex', + 'sphinx_numfig', + 'nbsphinx' +] if not on_rtd: extensions.append('sphinxcontrib.rsvgconverter') diff --git a/docs/source/examples/cad-based-geometry.ipynb b/docs/source/examples/cad-based-geometry.ipynb new file mode 120000 index 0000000000..ee3727e672 --- /dev/null +++ b/docs/source/examples/cad-based-geometry.ipynb @@ -0,0 +1 @@ +../../../examples/jupyter/cad-based-geometry.ipynb \ No newline at end of file diff --git a/docs/source/examples/cad-geom.rst b/docs/source/examples/cad-geom.rst deleted file mode 100644 index c5251c7ca1..0000000000 --- a/docs/source/examples/cad-geom.rst +++ /dev/null @@ -1,13 +0,0 @@ -.. _notebook_cad-geom: - -========================== -Using CAD-Based Geometries -========================== - -.. only:: html - - .. notebook:: ../../../examples/jupyter/cad-based-geometry.ipynb - -.. only:: latex - - IPython notebooks must be viewed in the online HTML documentation. diff --git a/docs/source/examples/candu.ipynb b/docs/source/examples/candu.ipynb new file mode 120000 index 0000000000..480d99fb16 --- /dev/null +++ b/docs/source/examples/candu.ipynb @@ -0,0 +1 @@ +../../../examples/jupyter/candu.ipynb \ No newline at end of file diff --git a/docs/source/examples/candu.rst b/docs/source/examples/candu.rst deleted file mode 100644 index 463a3c76e6..0000000000 --- a/docs/source/examples/candu.rst +++ /dev/null @@ -1,13 +0,0 @@ -.. _notebook_candu: - -======================= -Modeling a CANDU Bundle -======================= - -.. only:: html - - .. notebook:: ../../../examples/jupyter/candu.ipynb - -.. only:: latex - - IPython notebooks must be viewed in the online HTML documentation. diff --git a/docs/source/examples/expansion-filters.ipynb b/docs/source/examples/expansion-filters.ipynb new file mode 120000 index 0000000000..e757341359 --- /dev/null +++ b/docs/source/examples/expansion-filters.ipynb @@ -0,0 +1 @@ +../../../examples/jupyter/expansion-filters.ipynb \ No newline at end of file diff --git a/docs/source/examples/expansion-filters.rst b/docs/source/examples/expansion-filters.rst deleted file mode 100644 index f06d2bde6b..0000000000 --- a/docs/source/examples/expansion-filters.rst +++ /dev/null @@ -1,13 +0,0 @@ -.. _notebook_expansion: - -===================== -Functional Expansions -===================== - -.. only:: html - - .. notebook:: ../../../examples/jupyter/expansion-filters.ipynb - -.. only:: latex - - IPython notebooks must be viewed in the online HTML documentation. diff --git a/docs/source/examples/hexagonal-lattice.ipynb b/docs/source/examples/hexagonal-lattice.ipynb new file mode 120000 index 0000000000..e2b63d2437 --- /dev/null +++ b/docs/source/examples/hexagonal-lattice.ipynb @@ -0,0 +1 @@ +../../../examples/jupyter/hexagonal-lattice.ipynb \ No newline at end of file diff --git a/docs/source/examples/hexagonal.rst b/docs/source/examples/hexagonal.rst deleted file mode 100644 index 8955fdb3fe..0000000000 --- a/docs/source/examples/hexagonal.rst +++ /dev/null @@ -1,13 +0,0 @@ -.. _notebook_hexagonal: - -=========================== -Modeling Hexagonal Lattices -=========================== - -.. only:: html - - .. notebook:: ../../../examples/jupyter/hexagonal-lattice.ipynb - -.. only:: latex - - IPython notebooks must be viewed in the online HTML documentation. diff --git a/docs/source/examples/index.rst b/docs/source/examples/index.rst index 14565e64af..304137bcbc 100644 --- a/docs/source/examples/index.rst +++ b/docs/source/examples/index.rst @@ -23,7 +23,7 @@ General Usage search nuclear-data nuclear-data-resonance-covariance - pincell-depletion + pincell_depletion -------- Geometry @@ -32,14 +32,14 @@ Geometry .. toctree:: :maxdepth: 1 - hexagonal + hexagonal-lattice triso candu - cad-geom + cad-based-geometry ------------------------------------- -Multi-Group Cross Section Generation ------------------------------------- +----------------------------------- +Multigroup Cross Section Generation +----------------------------------- .. toctree:: :maxdepth: 1 @@ -50,9 +50,9 @@ Multi-Group Cross Section Generation mdgxs-part-i mdgxs-part-ii ----------------- -Multi-Group Mode ----------------- +--------------- +Multigroup Mode +--------------- .. toctree:: :maxdepth: 1 diff --git a/docs/source/examples/mdgxs-part-i.ipynb b/docs/source/examples/mdgxs-part-i.ipynb new file mode 120000 index 0000000000..01eb1172d4 --- /dev/null +++ b/docs/source/examples/mdgxs-part-i.ipynb @@ -0,0 +1 @@ +../../../examples/jupyter/mdgxs-part-i.ipynb \ No newline at end of file diff --git a/docs/source/examples/mdgxs-part-i.rst b/docs/source/examples/mdgxs-part-i.rst deleted file mode 100644 index 2899f126bd..0000000000 --- a/docs/source/examples/mdgxs-part-i.rst +++ /dev/null @@ -1,13 +0,0 @@ -.. _notebook_mdgxs_part_i: - -=================================================================== -Multi-Group (Delayed) Cross Section Generation Part I: Introduction -=================================================================== - -.. only:: html - - .. notebook:: ../../../examples/jupyter/mdgxs-part-i.ipynb - -.. only:: latex - - IPython notebooks must be viewed in the online HTML documentation. diff --git a/docs/source/examples/mdgxs-part-ii.ipynb b/docs/source/examples/mdgxs-part-ii.ipynb new file mode 120000 index 0000000000..2d9d339074 --- /dev/null +++ b/docs/source/examples/mdgxs-part-ii.ipynb @@ -0,0 +1 @@ +../../../examples/jupyter/mdgxs-part-ii.ipynb \ No newline at end of file diff --git a/docs/source/examples/mdgxs-part-ii.rst b/docs/source/examples/mdgxs-part-ii.rst deleted file mode 100644 index c5d52df629..0000000000 --- a/docs/source/examples/mdgxs-part-ii.rst +++ /dev/null @@ -1,13 +0,0 @@ -.. _notebook_mdgxs_part_ii: - -========================================================================= -Multi-Group (Delayed) Cross Section Generation Part II: Advanced Features -========================================================================= - -.. only:: html - - .. notebook:: ../../../examples/jupyter/mdgxs-part-ii.ipynb - -.. only:: latex - - IPython notebooks must be viewed in the online HTML documentation. diff --git a/docs/source/examples/mg-mode-part-i.ipynb b/docs/source/examples/mg-mode-part-i.ipynb new file mode 120000 index 0000000000..d1577f7000 --- /dev/null +++ b/docs/source/examples/mg-mode-part-i.ipynb @@ -0,0 +1 @@ +../../../examples/jupyter/mg-mode-part-i.ipynb \ No newline at end of file diff --git a/docs/source/examples/mg-mode-part-i.rst b/docs/source/examples/mg-mode-part-i.rst deleted file mode 100644 index e54c21c2fd..0000000000 --- a/docs/source/examples/mg-mode-part-i.rst +++ /dev/null @@ -1,13 +0,0 @@ -.. _notebook_mg_mode_part_i: - -===================================== -Multi-Group Mode Part I: Introduction -===================================== - -.. only:: html - - .. notebook:: ../../../examples/jupyter/mg-mode-part-i.ipynb - -.. only:: latex - - IPython notebooks must be viewed in the online HTML documentation. diff --git a/docs/source/examples/mg-mode-part-ii.ipynb b/docs/source/examples/mg-mode-part-ii.ipynb new file mode 120000 index 0000000000..a093063761 --- /dev/null +++ b/docs/source/examples/mg-mode-part-ii.ipynb @@ -0,0 +1 @@ +../../../examples/jupyter/mg-mode-part-ii.ipynb \ No newline at end of file diff --git a/docs/source/examples/mg-mode-part-ii.rst b/docs/source/examples/mg-mode-part-ii.rst deleted file mode 100644 index 9b4e574ae3..0000000000 --- a/docs/source/examples/mg-mode-part-ii.rst +++ /dev/null @@ -1,13 +0,0 @@ -.. _notebook_mg_mode_part_ii: - -============================================================= -Multi-Group Mode Part II: MGXS Library Generation With OpenMC -============================================================= - -.. only:: html - - .. notebook:: ../../../examples/jupyter/mg-mode-part-ii.ipynb - -.. only:: latex - - IPython notebooks must be viewed in the online HTML documentation. diff --git a/docs/source/examples/mg-mode-part-iii.ipynb b/docs/source/examples/mg-mode-part-iii.ipynb new file mode 120000 index 0000000000..6fa0d180e4 --- /dev/null +++ b/docs/source/examples/mg-mode-part-iii.ipynb @@ -0,0 +1 @@ +../../../examples/jupyter/mg-mode-part-iii.ipynb \ No newline at end of file diff --git a/docs/source/examples/mg-mode-part-iii.rst b/docs/source/examples/mg-mode-part-iii.rst deleted file mode 100644 index 86657c9675..0000000000 --- a/docs/source/examples/mg-mode-part-iii.rst +++ /dev/null @@ -1,13 +0,0 @@ -.. _notebook_mg_mode_part_iii: - -==================================================== -Multi-Group Mode Part III: Advanced Feature Showcase -==================================================== - -.. only:: html - - .. notebook:: ../../../examples/jupyter/mg-mode-part-iii.ipynb - -.. only:: latex - - IPython notebooks must be viewed in the online HTML documentation. diff --git a/docs/source/examples/mgxs-part-i.ipynb b/docs/source/examples/mgxs-part-i.ipynb new file mode 120000 index 0000000000..a04b1da895 --- /dev/null +++ b/docs/source/examples/mgxs-part-i.ipynb @@ -0,0 +1 @@ +../../../examples/jupyter/mgxs-part-i.ipynb \ No newline at end of file diff --git a/docs/source/examples/mgxs-part-i.rst b/docs/source/examples/mgxs-part-i.rst deleted file mode 100644 index d956e72616..0000000000 --- a/docs/source/examples/mgxs-part-i.rst +++ /dev/null @@ -1,13 +0,0 @@ -.. _notebook_mgxs_part_i: - -========================= -MGXS Part I: Introduction -========================= - -.. only:: html - - .. notebook:: ../../../examples/jupyter/mgxs-part-i.ipynb - -.. only:: latex - - IPython notebooks must be viewed in the online HTML documentation. diff --git a/docs/source/examples/mgxs-part-ii.ipynb b/docs/source/examples/mgxs-part-ii.ipynb new file mode 120000 index 0000000000..dd8af3c438 --- /dev/null +++ b/docs/source/examples/mgxs-part-ii.ipynb @@ -0,0 +1 @@ +../../../examples/jupyter/mgxs-part-ii.ipynb \ No newline at end of file diff --git a/docs/source/examples/mgxs-part-ii.rst b/docs/source/examples/mgxs-part-ii.rst deleted file mode 100644 index 64efc57525..0000000000 --- a/docs/source/examples/mgxs-part-ii.rst +++ /dev/null @@ -1,13 +0,0 @@ -.. _notebook_mgxs_part_ii: - -=============================== -MGXS Part II: Advanced Features -=============================== - -.. only:: html - - .. notebook:: ../../../examples/jupyter/mgxs-part-ii.ipynb - -.. only:: latex - - IPython notebooks must be viewed in the online HTML documentation. diff --git a/docs/source/examples/mgxs-part-iii.ipynb b/docs/source/examples/mgxs-part-iii.ipynb new file mode 120000 index 0000000000..d6acc76baf --- /dev/null +++ b/docs/source/examples/mgxs-part-iii.ipynb @@ -0,0 +1 @@ +../../../examples/jupyter/mgxs-part-iii.ipynb \ No newline at end of file diff --git a/docs/source/examples/mgxs-part-iii.rst b/docs/source/examples/mgxs-part-iii.rst deleted file mode 100644 index 12f3265291..0000000000 --- a/docs/source/examples/mgxs-part-iii.rst +++ /dev/null @@ -1,13 +0,0 @@ -.. _notebook_mgxs_part_iii: - -======================== -MGXS Part III: Libraries -======================== - -.. only:: html - - .. notebook:: ../../../examples/jupyter/mgxs-part-iii.ipynb - -.. only:: latex - - IPython notebooks must be viewed in the online HTML documentation. diff --git a/docs/source/examples/nuclear-data-resonance-covariance.ipynb b/docs/source/examples/nuclear-data-resonance-covariance.ipynb new file mode 120000 index 0000000000..0ab0dd62b5 --- /dev/null +++ b/docs/source/examples/nuclear-data-resonance-covariance.ipynb @@ -0,0 +1 @@ +../../../examples/jupyter/nuclear-data-resonance-covariance.ipynb \ No newline at end of file diff --git a/docs/source/examples/nuclear-data-resonance-covariance.rst b/docs/source/examples/nuclear-data-resonance-covariance.rst deleted file mode 100644 index 4b505c9a58..0000000000 --- a/docs/source/examples/nuclear-data-resonance-covariance.rst +++ /dev/null @@ -1,13 +0,0 @@ -.. _notebook_nuclear_data_resonance_covariance: - -================================== -Nuclear Data: Resonance Covariance -================================== - -.. only:: html - - .. notebook:: ../../../examples/jupyter/nuclear-data-resonance-covariance.ipynb - -.. only:: latex - - IPython notebooks must be viewed in the online HTML documentation. diff --git a/docs/source/examples/nuclear-data.ipynb b/docs/source/examples/nuclear-data.ipynb new file mode 120000 index 0000000000..59721abdc9 --- /dev/null +++ b/docs/source/examples/nuclear-data.ipynb @@ -0,0 +1 @@ +../../../examples/jupyter/nuclear-data.ipynb \ No newline at end of file diff --git a/docs/source/examples/nuclear-data.rst b/docs/source/examples/nuclear-data.rst deleted file mode 100644 index 15dfbde180..0000000000 --- a/docs/source/examples/nuclear-data.rst +++ /dev/null @@ -1,13 +0,0 @@ -.. _notebook_nuclear_data: - -============ -Nuclear Data -============ - -.. only:: html - - .. notebook:: ../../../examples/jupyter/nuclear-data.ipynb - -.. only:: latex - - IPython notebooks must be viewed in the online HTML documentation. diff --git a/docs/source/examples/pandas-dataframes.ipynb b/docs/source/examples/pandas-dataframes.ipynb new file mode 120000 index 0000000000..f41f570beb --- /dev/null +++ b/docs/source/examples/pandas-dataframes.ipynb @@ -0,0 +1 @@ +../../../examples/jupyter/pandas-dataframes.ipynb \ No newline at end of file diff --git a/docs/source/examples/pandas-dataframes.rst b/docs/source/examples/pandas-dataframes.rst deleted file mode 100644 index 701f1630c1..0000000000 --- a/docs/source/examples/pandas-dataframes.rst +++ /dev/null @@ -1,13 +0,0 @@ -.. _examples_pandas: - -================= -Pandas Dataframes -================= - -.. only:: html - - .. notebook:: ../../../examples/jupyter/pandas-dataframes.ipynb - -.. only:: latex - - IPython notebooks must be viewed in the online HTML documentation. diff --git a/docs/source/examples/pincell-depletion.rst b/docs/source/examples/pincell-depletion.rst deleted file mode 100644 index 348f3c6b95..0000000000 --- a/docs/source/examples/pincell-depletion.rst +++ /dev/null @@ -1,14 +0,0 @@ -.. _notebook_depletion: - -================= -Pincell Depletion -================= - - -.. only:: html - - .. notebook:: ../../../examples/jupyter/pincell_depletion.ipynb - -.. only:: latex - - IPython notebooks must be viewed in the online HTML documentation. diff --git a/docs/source/examples/pincell.ipynb b/docs/source/examples/pincell.ipynb new file mode 120000 index 0000000000..edbbb8de24 --- /dev/null +++ b/docs/source/examples/pincell.ipynb @@ -0,0 +1 @@ +../../../examples/jupyter/pincell.ipynb \ No newline at end of file diff --git a/docs/source/examples/pincell.rst b/docs/source/examples/pincell.rst deleted file mode 100644 index 0f149107c1..0000000000 --- a/docs/source/examples/pincell.rst +++ /dev/null @@ -1,13 +0,0 @@ -.. _notebook_pincell: - -=================== -Modeling a Pin-Cell -=================== - -.. only:: html - - .. notebook:: ../../../examples/jupyter/pincell.ipynb - -.. only:: latex - - IPython notebooks must be viewed in the online HTML documentation. diff --git a/docs/source/examples/pincell_depletion.ipynb b/docs/source/examples/pincell_depletion.ipynb new file mode 120000 index 0000000000..1f25930fcb --- /dev/null +++ b/docs/source/examples/pincell_depletion.ipynb @@ -0,0 +1 @@ +../../../examples/jupyter/pincell_depletion.ipynb \ No newline at end of file diff --git a/docs/source/examples/post-processing.ipynb b/docs/source/examples/post-processing.ipynb new file mode 120000 index 0000000000..1f3f4cd713 --- /dev/null +++ b/docs/source/examples/post-processing.ipynb @@ -0,0 +1 @@ +../../../examples/jupyter/post-processing.ipynb \ No newline at end of file diff --git a/docs/source/examples/post-processing.rst b/docs/source/examples/post-processing.rst deleted file mode 100644 index 09c4454e77..0000000000 --- a/docs/source/examples/post-processing.rst +++ /dev/null @@ -1,13 +0,0 @@ -.. _notebook_post_processing: - -=============== -Post Processing -=============== - -.. only:: html - - .. notebook:: ../../../examples/jupyter/post-processing.ipynb - -.. only:: latex - - IPython notebooks must be viewed in the online HTML documentation. diff --git a/docs/source/examples/search.ipynb b/docs/source/examples/search.ipynb new file mode 120000 index 0000000000..fbfb67bc60 --- /dev/null +++ b/docs/source/examples/search.ipynb @@ -0,0 +1 @@ +../../../examples/jupyter/search.ipynb \ No newline at end of file diff --git a/docs/source/examples/search.rst b/docs/source/examples/search.rst deleted file mode 100644 index 1d56ff53ae..0000000000 --- a/docs/source/examples/search.rst +++ /dev/null @@ -1,13 +0,0 @@ -.. _notebook_search: - -================== -Criticality Search -================== - -.. only:: html - - .. notebook:: ../../../examples/jupyter/search.ipynb - -.. only:: latex - - IPython notebooks must be viewed in the online HTML documentation. diff --git a/docs/source/examples/tally-arithmetic.ipynb b/docs/source/examples/tally-arithmetic.ipynb new file mode 120000 index 0000000000..7ffe194626 --- /dev/null +++ b/docs/source/examples/tally-arithmetic.ipynb @@ -0,0 +1 @@ +../../../examples/jupyter/tally-arithmetic.ipynb \ No newline at end of file diff --git a/docs/source/examples/tally-arithmetic.rst b/docs/source/examples/tally-arithmetic.rst deleted file mode 100644 index 7e653e8ff8..0000000000 --- a/docs/source/examples/tally-arithmetic.rst +++ /dev/null @@ -1,11 +0,0 @@ -================ -Tally Arithmetic -================ - -.. only:: html - - .. notebook:: ../../../examples/jupyter/tally-arithmetic.ipynb - -.. only:: latex - - IPython notebooks must be viewed in the online HTML documentation. diff --git a/docs/source/examples/triso.ipynb b/docs/source/examples/triso.ipynb new file mode 120000 index 0000000000..0e51d8add9 --- /dev/null +++ b/docs/source/examples/triso.ipynb @@ -0,0 +1 @@ +../../../examples/jupyter/triso.ipynb \ No newline at end of file diff --git a/docs/source/examples/triso.rst b/docs/source/examples/triso.rst deleted file mode 100644 index 98f2f16439..0000000000 --- a/docs/source/examples/triso.rst +++ /dev/null @@ -1,13 +0,0 @@ -.. _notebook_triso: - -======================== -Modeling TRISO Particles -======================== - -.. only:: html - - .. notebook:: ../../../examples/jupyter/triso.ipynb - -.. only:: latex - - IPython notebooks must be viewed in the online HTML documentation. diff --git a/docs/source/examples/unstructured-mesh-part-i.ipynb b/docs/source/examples/unstructured-mesh-part-i.ipynb new file mode 120000 index 0000000000..b1358788ba --- /dev/null +++ b/docs/source/examples/unstructured-mesh-part-i.ipynb @@ -0,0 +1 @@ +../../../examples/jupyter/unstructured-mesh-part-i.ipynb \ No newline at end of file diff --git a/docs/source/examples/unstructured-mesh-part-i.rst b/docs/source/examples/unstructured-mesh-part-i.rst deleted file mode 100644 index ed2c9c2fd3..0000000000 --- a/docs/source/examples/unstructured-mesh-part-i.rst +++ /dev/null @@ -1,13 +0,0 @@ -.. _notebook_unstructured_mesh_part_i: - -=============================== -Unstructured Mesh: Introduction -=============================== - -.. only:: html - - .. notebook:: ../../../examples/jupyter/unstructured-mesh-part-i.ipynb - -.. only:: latex - - IPython notebooks must be viewed in the online HTML documentation. diff --git a/docs/source/examples/unstructured-mesh-part-ii.ipynb b/docs/source/examples/unstructured-mesh-part-ii.ipynb new file mode 120000 index 0000000000..9074811b70 --- /dev/null +++ b/docs/source/examples/unstructured-mesh-part-ii.ipynb @@ -0,0 +1 @@ +../../../examples/jupyter/unstructured-mesh-part-ii.ipynb \ No newline at end of file diff --git a/docs/source/examples/unstructured-mesh-part-ii.rst b/docs/source/examples/unstructured-mesh-part-ii.rst deleted file mode 100644 index c30be88590..0000000000 --- a/docs/source/examples/unstructured-mesh-part-ii.rst +++ /dev/null @@ -1,13 +0,0 @@ -.. _notebook_unstructured_mesh_part_ii: - -=================================================================================== -Unstructured Mesh: Unstructured Mesh Tallies with CAD and Point Cloud Visualization -=================================================================================== - -.. only:: html - - .. notebook:: ../../../examples/jupyter/unstructured-mesh-part-ii.ipynb - -.. only:: latex - - IPython notebooks must be viewed in the online HTML documentation. diff --git a/docs/source/io_formats/settings.rst b/docs/source/io_formats/settings.rst index 09d7db1236..588b58b478 100644 --- a/docs/source/io_formats/settings.rst +++ b/docs/source/io_formats/settings.rst @@ -465,7 +465,7 @@ attributes/sub-elements: as complex as is required to define the source for your problem. The library has a few basic requirements: - * It must contain a class that inherits from ``openmc::CustomSource``; + * It must contain a class that inherits from ``openmc::Source``; * The class must implement a function called ``sample()``; * There must be an ``openmc_create_source()`` function that creates the source as a unique pointer. This function can be used to pass parameters through to diff --git a/docs/source/io_formats/source.rst b/docs/source/io_formats/source.rst index 6058241e1f..4cd023e12e 100644 --- a/docs/source/io_formats/source.rst +++ b/docs/source/io_formats/source.rst @@ -15,7 +15,7 @@ is that documented here. :Datasets: - **source_bank** (Compound type) -- Source bank information for each - particle. The compound type has fields ``wgt``, ``xyz``, ``uvw``, - ``E``, ``delayed_group``, and ``particle``, which represent the - weight, position, direction, energy, energy group, delayed group, - and type of the source particle, respectively. + particle. The compound type has fields ``r``, ``u``, ``E``, + ``wgt``, ``delayed_group``, and ``particle``, which represent the + position, direction, energy, weight, delayed group, and particle + type (0=neutron, 1=photon, 2=electron, 3=positron), respectively. diff --git a/docs/source/io_formats/statepoint.rst b/docs/source/io_formats/statepoint.rst index f90d5b3af5..3a2ad1600e 100644 --- a/docs/source/io_formats/statepoint.rst +++ b/docs/source/io_formats/statepoint.rst @@ -51,11 +51,11 @@ The current version of the statepoint file format is 17.0. - **global_tallies** (*double[][2]*) -- Accumulated sum and sum-of-squares for each global tally. - **source_bank** (Compound type) -- Source bank information for each - particle. The compound type has fields ``wgt``, ``xyz``, ``uvw``, - ``E``, ``g``, and ``delayed_group``, which represent the weight, - position, direction, energy, energy group, and delayed_group of the - source particle, respectively. Only present when `run_mode` is - 'eigenvalue'. + particle. The compound type has fields ``r``, ``u``, ``E``, + ``wgt``, ``delayed_group``, and ``particle``, which represent the + position, direction, energy, weight, delayed group, and particle + type (0=neutron, 1=photon, 2=electron, 3=positron), respectively. + Only present when `run_mode` is 'eigenvalue'. **/tallies/** diff --git a/docs/source/pythonapi/base.rst b/docs/source/pythonapi/base.rst index d621637bb1..544e7009cb 100644 --- a/docs/source/pythonapi/base.rst +++ b/docs/source/pythonapi/base.rst @@ -22,9 +22,19 @@ Simulation Settings :template: myclass.rst openmc.Source + openmc.SourceParticle openmc.VolumeCalculation openmc.Settings +The following function can be used for generating a source file: + +.. autosummary:: + :toctree: generated + :nosignatures: + :template: myfunction.rst + + openmc.write_source_file + Material Specification ---------------------- diff --git a/docs/source/pythonapi/mgxs.rst b/docs/source/pythonapi/mgxs.rst index a25a89c09c..bf5a845992 100644 --- a/docs/source/pythonapi/mgxs.rst +++ b/docs/source/pythonapi/mgxs.rst @@ -30,6 +30,7 @@ Multi-group Cross Sections :template: myclassinherit.rst openmc.mgxs.MGXS + openmc.mgxs.MatrixMGXS openmc.mgxs.AbsorptionXS openmc.mgxs.CaptureXS openmc.mgxs.Chi @@ -45,6 +46,9 @@ Multi-group Cross Sections openmc.mgxs.ScatterProbabilityMatrix openmc.mgxs.TotalXS openmc.mgxs.TransportXS + openmc.mgxs.ArbitraryXS + openmc.mgxs.ArbitraryMatrixXS + openmc.mgxs.MeshSurfaceMGXS Multi-delayed-group Cross Sections ---------------------------------- @@ -55,6 +59,7 @@ Multi-delayed-group Cross Sections :template: myclassinherit.rst openmc.mgxs.MDGXS + openmc.mgxs.MatrixMDGXS openmc.mgxs.ChiDelayed openmc.mgxs.DelayedNuFissionXS openmc.mgxs.DelayedNuFissionMatrixXS diff --git a/docs/source/usersguide/settings.rst b/docs/source/usersguide/settings.rst index 340d4af00c..df22328e3a 100644 --- a/docs/source/usersguide/settings.rst +++ b/docs/source/usersguide/settings.rst @@ -194,9 +194,9 @@ below. #include "openmc/source.h" #include "openmc/particle.h" - class Source : public openmc::CustomSource + class CustomSource : public openmc::Source { - openmc::Particle::Bank sample(uint64_t* seed) + openmc::Particle::Bank sample(uint64_t* seed) const { openmc::Particle::Bank particle; // weight @@ -216,16 +216,16 @@ below. } }; - extern "C" std::unique_ptr openmc_create_source(std::string parameters) + extern "C" std::unique_ptr openmc_create_source(std::string parameters) { - return std::make_unique(); + return std::make_unique(); } The above source creates monodirectional 14.08 MeV neutrons that are distributed in a ring with a 3 cm radius. This routine is not particularly complex, but should serve as an example upon which to build more complicated sources. - .. note:: The source class must inherit from ``openmc::CustomSource`` and + .. note:: The source class must inherit from ``openmc::Source`` and implement a ``sample()`` function. .. note:: The ``openmc_create_source()`` function signature must be declared @@ -266,12 +266,12 @@ the source class when it is created: #include "openmc/source.h" #include "openmc/particle.h" - class Source : public openmc::CustomSource { + class CustomSource : public openmc::Source { public: - Source(double energy) : energy_{energy} { } + CustomSource(double energy) : energy_{energy} { } // Samples from an instance of this class. - openmc::Particle::Bank sample(uint64_t* seed) + openmc::Particle::Bank sample(uint64_t* seed) const { openmc::Particle::Bank particle; // weight @@ -293,9 +293,9 @@ the source class when it is created: double energy_; }; - extern "C" std::unique_ptr openmc_create_source(std::string parameter) { + extern "C" std::unique_ptr openmc_create_source(std::string parameter) { double energy = std::stod(parameter); - return std::make_unique(energy); + return std::make_unique(energy); } As with the basic custom source functionality, the custom source library diff --git a/docs/sphinxext/LICENSE b/docs/sphinxext/LICENSE deleted file mode 100644 index 2d508d2be9..0000000000 --- a/docs/sphinxext/LICENSE +++ /dev/null @@ -1,68 +0,0 @@ -The file notebook_sphinxext.py was derived from code in PyNE and yt. - -PyNE has the following license: - -------------------------------------------------------------------------------- -Copyright 2011-2015, the PyNE Development Team. All rights reserved. - -Redistribution and use in source and binary forms, with or without modification, are -permitted provided that the following conditions are met: - - 1. Redistributions of source code must retain the above copyright notice, this list of - conditions and the following disclaimer. - - 2. Redistributions in binary form must reproduce the above copyright notice, this list - of conditions and the following disclaimer in the documentation and/or other materials - provided with the distribution. - -THIS SOFTWARE IS PROVIDED BY THE PYNE DEVELOPMENT TEAM ``AS IS'' AND ANY EXPRESS OR IMPLIED -WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND -FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL OR -CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF -ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -The views and conclusions contained in the software and documentation are those of the -authors and should not be interpreted as representing official policies, either expressed -or implied, of the stakeholders of the PyNE project or the employers of PyNE developers. -------------------------------------------------------------------------------- - -yt has the following license: - -------------------------------------------------------------------------------- -yt is licensed under the terms of the Modified BSD License (also known as New -or Revised BSD), as follows: - -Copyright (c) 2013-, yt Development Team -Copyright (c) 2006-2013, Matthew Turk - -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - -Redistributions of source code must retain the above copyright notice, this -list of conditions and the following disclaimer. - -Redistributions in binary form must reproduce the above copyright notice, this -list of conditions and the following disclaimer in the documentation and/or -other materials provided with the distribution. - -Neither the name of the yt Development Team nor the names of its -contributors may be used to endorse or promote products derived from this -software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE -FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, -OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -------------------------------------------------------------------------------- diff --git a/docs/sphinxext/notebook_sphinxext.py b/docs/sphinxext/notebook_sphinxext.py deleted file mode 100644 index eab93cc8a5..0000000000 --- a/docs/sphinxext/notebook_sphinxext.py +++ /dev/null @@ -1,117 +0,0 @@ -import sys -import os.path -import re -import time -from docutils import io, nodes, statemachine, utils -try: - from docutils.utils.error_reporting import ErrorString # the new way -except ImportError: - from docutils.error_reporting import ErrorString # the old way -from docutils.parsers.rst import Directive, convert_directive_function -from docutils.parsers.rst import directives, roles, states -from docutils.parsers.rst.roles import set_classes -from docutils.transforms import misc - -from nbconvert import html - - -class Notebook(Directive): - """Use nbconvert to insert a notebook into the environment. - This is based on the Raw directive in docutils - """ - required_arguments = 1 - optional_arguments = 0 - final_argument_whitespace = True - option_spec = {} - has_content = False - - def run(self): - # check if raw html is supported - if not self.state.document.settings.raw_enabled: - raise self.warning('"%s" directive disabled.' % self.name) - - # set up encoding - attributes = {'format': 'html'} - encoding = self.options.get( - 'encoding', self.state.document.settings.input_encoding) - e_handler = self.state.document.settings.input_encoding_error_handler - - # get path to notebook - source_dir = os.path.dirname( - os.path.abspath(self.state.document.current_source)) - nb_path = os.path.normpath(os.path.join(source_dir, - self.arguments[0])) - nb_path = utils.relative_path(None, nb_path) - - # convert notebook to html - exporter = html.HTMLExporter(template_file='full') - output, resources = exporter.from_filename(nb_path) - header = output.split('', 1)[1].split('',1)[0] - body = output.split('', 1)[1].split('',1)[0] - - # add HTML5 scoped attribute to header style tags - header = header.replace(''] - lines.append(header) - lines.append(body) - lines.append('') - text = '\n'.join(lines) - - # add dependency - self.state.document.settings.record_dependencies.add(nb_path) - attributes['source'] = nb_path - - # create notebook node - nb_node = notebook('', text, **attributes) - (nb_node.source, nb_node.line) = \ - self.state_machine.get_source_and_line(self.lineno) - - return [nb_node] - - -class notebook(nodes.raw): - pass - - -def visit_notebook_node(self, node): - self.visit_raw(node) - - -def depart_notebook_node(self, node): - self.depart_raw(node) - - -def setup(app): - app.add_node(notebook, - html=(visit_notebook_node, depart_notebook_node)) - - app.add_directive('notebook', Notebook) diff --git a/examples/custom_source/source_ring.cpp b/examples/custom_source/source_ring.cpp index bc8a8a7f8d..a752216dce 100644 --- a/examples/custom_source/source_ring.cpp +++ b/examples/custom_source/source_ring.cpp @@ -5,9 +5,9 @@ #include "openmc/source.h" #include "openmc/particle.h" -class Source : public openmc::CustomSource +class RingSource : public openmc::Source { - openmc::Particle::Bank sample(uint64_t* seed) + openmc::Particle::Bank sample(uint64_t* seed) const { openmc::Particle::Bank particle; // wgt @@ -30,7 +30,7 @@ class Source : public openmc::CustomSource // A function to create a unique pointer to an instance of this class when generated // via a plugin call using dlopen/dlsym. // You must have external C linkage here otherwise dlopen will not find the file -extern "C" std::unique_ptr openmc_create_source(std::string parameters) +extern "C" std::unique_ptr openmc_create_source(std::string parameters) { - return std::make_unique(); + return std::make_unique(); } diff --git a/examples/jupyter/cad-based-geometry.ipynb b/examples/jupyter/cad-based-geometry.ipynb index b13c010cb1..5f84ae5e5c 100644 --- a/examples/jupyter/cad-based-geometry.ipynb +++ b/examples/jupyter/cad-based-geometry.ipynb @@ -4,6 +4,7 @@ "cell_type": "markdown", "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", "\n" ] @@ -40,13 +41,6 @@ "This notebook is intended to demonstrate how DagMC problems are run in OpenMC. For more information on how DagMC models are created, please refer to the [DagMC User's Guide](https://svalinn.github.io/DAGMC/usersguide/index.html).\n" ] }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# CAD-Based Geometry in OpenMC using [DagMC](https://svalinn.github.io/DAGMC/)" - ] - }, { "cell_type": "code", "execution_count": 2, @@ -756,7 +750,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.6.6" + "version": "3.8.3" } }, "nbformat": 4, diff --git a/examples/jupyter/candu.ipynb b/examples/jupyter/candu.ipynb index b078d8ac62..eaf1e36d21 100644 --- a/examples/jupyter/candu.ipynb +++ b/examples/jupyter/candu.ipynb @@ -4,6 +4,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ + "# Modeling a CANDU Bundle\n", "In this example, we will create a typical CANDU bundle with rings of fuel pins. At present, OpenMC does not have a specialized lattice for this type of fuel arrangement, so we must resort to manual creation of the array of fuel pins." ] }, @@ -1107,7 +1108,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.8.5" + "version": "3.8.3" } }, "nbformat": 4, diff --git a/examples/jupyter/expansion-filters.ipynb b/examples/jupyter/expansion-filters.ipynb index 0975fca1b6..3b0413a058 100644 --- a/examples/jupyter/expansion-filters.ipynb +++ b/examples/jupyter/expansion-filters.ipynb @@ -4,6 +4,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ + "# Functional Expansions\n", "OpenMC's general tally system accommodates a wide range of tally *filters*. While most filters are meant to identify regions of phase space that contribute to a tally, there are a special set of functional expansion filters that will multiply the tally by a set of orthogonal functions, e.g. Legendre polynomials, so that continuous functions of space or angle can be reconstructed from the tallied moments.\n", "\n", "In this example, we will determine the spatial dependence of the flux along the $z$ axis by making a Legendre polynomial expansion. Let us represent the flux along the z axis, $\\phi(z)$, by the function\n", @@ -1539,7 +1540,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.7.4" + "version": "3.8.3" } }, "nbformat": 4, diff --git a/examples/jupyter/hexagonal-lattice.ipynb b/examples/jupyter/hexagonal-lattice.ipynb index f47b3bc603..07c3ab8344 100644 --- a/examples/jupyter/hexagonal-lattice.ipynb +++ b/examples/jupyter/hexagonal-lattice.ipynb @@ -4,6 +4,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ + "# Modeling Hexagonal Lattices\n", "In this example, we will create a hexagonal lattice and show how the orientation can be changed via the cell rotation property. Let's first just set up some materials and universes that we will use to fill the lattice." ] }, @@ -402,7 +403,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.8.5" + "version": "3.8.3" } }, "nbformat": 4, diff --git a/examples/jupyter/mdgxs-part-i.ipynb b/examples/jupyter/mdgxs-part-i.ipynb index 239b0f2df6..cda79d30a3 100644 --- a/examples/jupyter/mdgxs-part-i.ipynb +++ b/examples/jupyter/mdgxs-part-i.ipynb @@ -4,6 +4,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ + "# Multigroup (Delayed) Cross Section Generation Part I: Introduction\n", "This IPython Notebook introduces the use of the `openmc.mgxs` module to calculate multi-energy-group and multi-delayed-group cross sections for an infinite homogeneous medium. In particular, this Notebook introduces the the following features:\n", "\n", "* Creation of multi-delayed-group cross sections for an **infinite homogeneous medium**\n", @@ -1486,7 +1487,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.7.0" + "version": "3.8.3" } }, "nbformat": 4, diff --git a/examples/jupyter/mdgxs-part-ii.ipynb b/examples/jupyter/mdgxs-part-ii.ipynb index 77b5b55253..bb95384566 100644 --- a/examples/jupyter/mdgxs-part-ii.ipynb +++ b/examples/jupyter/mdgxs-part-ii.ipynb @@ -4,6 +4,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ + "# Multigroup (Delayed) Cross Section Generation Part II: Advanced Features\n", "This IPython Notebook illustrates the use of the **`openmc.mgxs.Library`** class. The `Library` class is designed to automate the calculation of multi-group cross sections for use cases with one or more domains, cross section types, and/or nuclides. In particular, this Notebook illustrates the following features:\n", "\n", "* Calculation of multi-energy-group and multi-delayed-group cross sections for a **fuel assembly**\n", @@ -644,7 +645,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "# Using Tally Arithmetic to Compute the Delayed Neutron Precursor Concentrations" + "## Using Tally Arithmetic to Compute the Delayed Neutron Precursor Concentrations" ] }, { @@ -1170,7 +1171,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.7.0" + "version": "3.8.3" } }, "nbformat": 4, diff --git a/examples/jupyter/mg-mode-part-i.ipynb b/examples/jupyter/mg-mode-part-i.ipynb index 23227b1ed3..a4f3822f28 100644 --- a/examples/jupyter/mg-mode-part-i.ipynb +++ b/examples/jupyter/mg-mode-part-i.ipynb @@ -4,6 +4,7 @@ "cell_type": "markdown", "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." ] }, @@ -11,7 +12,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "# Generate MGXS Library" + "## Generate MGXS Library" ] }, { @@ -137,7 +138,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "# Generate 2-D C5G7 Problem Input Files" + "## Generate 2-D C5G7 Problem Input Files" ] }, { @@ -622,7 +623,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "# Results Visualization\n", + "## Results Visualization\n", "\n", "Now that we have run the simulation, let's look at the fission rate and flux tallies that we tallied." ] @@ -693,7 +694,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.6.7" + "version": "3.8.3" } }, "nbformat": 4, diff --git a/examples/jupyter/mg-mode-part-ii.ipynb b/examples/jupyter/mg-mode-part-ii.ipynb index 85a8d73675..ef9e00017b 100644 --- a/examples/jupyter/mg-mode-part-ii.ipynb +++ b/examples/jupyter/mg-mode-part-ii.ipynb @@ -4,6 +4,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ + "# Multigroup Mode Part II: MGXS Library Generation with OpenMC\n", "The previous Notebook in this series used multi-group mode to perform a calculation with previously defined cross sections. However, in many circumstances the multi-group data is not given and one must instead generate the cross sections for the specific application (or at least verify the use of cross sections from another application). \n", "\n", "This Notebook illustrates the use of the openmc.mgxs.Library class specifically for the calculation of MGXS to be used in OpenMC's multi-group mode. This example notebook is therefore very similar to the MGXS Part III notebook, except OpenMC is used as the multi-group solver instead of OpenMOC.\n", @@ -20,7 +21,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "# Generate Input Files" + "## Generate Input Files" ] }, { @@ -361,7 +362,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "# Create an MGXS Library\n", + "## Create an MGXS Library\n", "\n", "Now we are ready to generate multi-group cross sections! First, let's define a 2-group structure using the built-in EnergyGroups class." ] @@ -680,7 +681,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "# Tally Data Processing\n", + "## Tally Data Processing\n", "\n", "Our simulation ran successfully and created statepoint and summary output files. Let's begin by loading the StatePoint file." ] @@ -727,7 +728,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "# Multi-Group OpenMC Calculation" + "## Multi-Group OpenMC Calculation" ] }, { @@ -1005,7 +1006,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "# Results Comparison\n", + "## Results Comparison\n", "Now we can compare the multi-group and continuous-energy results.\n", "\n", "We will begin by loading the multi-group statepoint file we just finished writing and extracting the calculated keff." @@ -1092,7 +1093,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "# Pin Power Visualizations" + "## Pin Power Visualizations" ] }, { @@ -1208,7 +1209,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "# Scattering Anisotropy Treatments\n", + "## Scattering Anisotropy Treatments\n", "\n", "We will next show how we can work with the scattering angular distributions. OpenMC's MG solver has the capability to use group-to-group angular distributions which are represented as any of the following: a truncated Legendre series of up to the 10th order, a histogram distribution, and a tabular distribution. Any combination of these representations can be used by OpenMC during the transport process, so long as all constituents of a given material use the same representation. This means it is possible to have water represented by a tabular distribution and fuel represented by a Legendre if so desired.\n", "\n", @@ -1224,7 +1225,7 @@ "metadata": {}, "source": [ "\n", - "## Global P0 Scattering\n", + "### Global P0 Scattering\n", "First we begin by re-running with P0 scattering (i.e., isotropic) everywhere. If a global maximum order is requested, the most effective way to do this is to use the `max_order` attribute of our `openmc.Settings` object." ] }, @@ -1355,7 +1356,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "## Mixed Scattering Representations\n", + "### Mixed Scattering Representations\n", "OpenMC's Multi-Group mode also includes a feature where not every data in the library is required to have the same scattering treatment. For example, we could represent the water with P3 scattering, and the fuel and cladding with P0 scattering. This series will show how this can be done.\n", "\n", "First we will convert the data to P0 scattering, unless its water, then we will leave that as P3 data." @@ -1531,7 +1532,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.6.7" + "version": "3.8.3" } }, "nbformat": 4, diff --git a/examples/jupyter/mg-mode-part-iii.ipynb b/examples/jupyter/mg-mode-part-iii.ipynb index e953d64d33..ea1e773f8d 100644 --- a/examples/jupyter/mg-mode-part-iii.ipynb +++ b/examples/jupyter/mg-mode-part-iii.ipynb @@ -4,6 +4,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ + "# Multigroup Mode Part III: Advanced Feature Showcase\n", "This Notebook illustrates the use of the the more advanced features of OpenMC's multi-group mode and the openmc.mgxs.Library class. During this process, this notebook will illustrate the following features:\n", "\n", " - Calculation of multi-group cross sections for a simplified BWR 8x8 assembly with isotropic and angle-dependent MGXS.\n", @@ -17,7 +18,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "# Generate Input Files" + "## Generate Input Files" ] }, { @@ -456,7 +457,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "# Create an MGXS Library\n", + "## Create an MGXS Library\n", "\n", "Now we are ready to generate multi-group cross sections! First, let's define a 2-group structure using the built-in EnergyGroups class." ] @@ -817,7 +818,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "# Tally Data Processing\n", + "## Tally Data Processing\n", "\n", "Our simulation ran successfully and created statepoint and summary output files. Let's begin by loading the StatePoint file, but not automatically linking the summary file." ] @@ -878,7 +879,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "# Isotropic Multi-Group OpenMC Calculation" + "## Isotropic Multi-Group OpenMC Calculation" ] }, { @@ -1100,7 +1101,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "# Angle-Dependent Multi-Group OpenMC Calculation\n", + "## Angle-Dependent Multi-Group OpenMC Calculation\n", "\n", "Let's now run the calculation with the angle-dependent multi-group cross sections. This process will be the exact same as above, except this time we will use the angle-dependent Library as our starting point.\n", "\n", @@ -1200,7 +1201,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "# Results Comparison\n", + "## Results Comparison\n", "In this section we will compare the eigenvalues and fission rate distributions of the continuous-energy, isotropic multi-group and angle-dependent multi-group cases.\n", "\n", "We will begin by loading the multi-group statepoint files, first the isotropic, then angle-dependent. The angle-dependent was not renamed, so we can autolink its summary." @@ -1225,7 +1226,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "## Eigenvalue Comparison\n", + "### Eigenvalue Comparison\n", "Next, we can load the eigenvalues for comparison and do that comparison" ] }, @@ -1280,7 +1281,7 @@ "\n", "It is important to note that both eigenvalues can be improved by the application of finer geometric or energetic discretizations, but this shows that the angle discretization may be a factor for consideration.\n", "\n", - "## Fission Rate Distribution Comparison\n", + "### Fission Rate Distribution Comparison\n", "Next we will visualize the mesh tally results obtained from our three cases.\n", "\n", "This will be performed by first obtaining the one-group fission rate tally information from our state point files. After we have this information we will re-shape the data to match the original mesh laydown. We will then normalize, and finally create side-by-side plots of all." @@ -1417,7 +1418,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.7.0" + "version": "3.8.3" } }, "nbformat": 4, diff --git a/examples/jupyter/mgxs-part-i.ipynb b/examples/jupyter/mgxs-part-i.ipynb index 264f8967cd..62a9b70b10 100644 --- a/examples/jupyter/mgxs-part-i.ipynb +++ b/examples/jupyter/mgxs-part-i.ipynb @@ -4,6 +4,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ + "# Multigroup Cross Section Generation Part I: Introduction\n", "This IPython Notebook introduces the use of the `openmc.mgxs` module to calculate multi-group cross sections for an infinite homogeneous medium. In particular, this Notebook introduces the the following features:\n", "\n", "* **General equations** for scalar-flux averaged multi-group cross sections\n", @@ -1130,7 +1131,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.7.0" + "version": "3.8.3" } }, "nbformat": 4, diff --git a/examples/jupyter/mgxs-part-ii.ipynb b/examples/jupyter/mgxs-part-ii.ipynb index 9e5cde42d2..dd5b21a551 100644 --- a/examples/jupyter/mgxs-part-ii.ipynb +++ b/examples/jupyter/mgxs-part-ii.ipynb @@ -4,6 +4,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ + "# Multigroup Cross Section Generation Part II: Advanced Features\n", "This IPython Notebook illustrates the use of the `openmc.mgxs` module to calculate multi-group cross sections for a heterogeneous fuel pin cell geometry. In particular, this Notebook illustrates the following features:\n", "\n", "* Creation of multi-group cross sections on a **heterogeneous geometry**\n", @@ -2736,7 +2737,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.7.0" + "version": "3.8.3" } }, "nbformat": 4, diff --git a/examples/jupyter/mgxs-part-iii.ipynb b/examples/jupyter/mgxs-part-iii.ipynb index a4c440b3a8..b05dbabd5c 100644 --- a/examples/jupyter/mgxs-part-iii.ipynb +++ b/examples/jupyter/mgxs-part-iii.ipynb @@ -4,6 +4,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ + "# Multigroup Cross Section Generation Part III: Libraries\n", "This IPython Notebook illustrates the use of the **`openmc.mgxs.Library`** class. The `Library` class is designed to automate the calculation of multi-group cross sections for use cases with one or more domains, cross section types, and/or nuclides. In particular, this Notebook illustrates the following features:\n", "\n", "* Calculation of multi-group cross sections for a **fuel assembly**\n", @@ -1659,7 +1660,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.7.0" + "version": "3.8.3" } }, "nbformat": 4, diff --git a/examples/jupyter/nuclear-data-resonance-covariance.ipynb b/examples/jupyter/nuclear-data-resonance-covariance.ipynb index d8bca235dc..8fe85161d2 100644 --- a/examples/jupyter/nuclear-data-resonance-covariance.ipynb +++ b/examples/jupyter/nuclear-data-resonance-covariance.ipynb @@ -4,6 +4,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ + "# Nuclear Data: Resonance Covariance\n", "In this notebook we will explore features of the Python API that allow us to import and manipulate resonance covariance data. A full description of the ENDF-VI and ENDF-VII formats can be found in the [ENDF102 manual](https://www.oecd-nea.org/dbdata/data/manual-endf/endf102.pdf)." ] }, @@ -954,7 +955,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.7.0" + "version": "3.8.3" } }, "nbformat": 4, diff --git a/examples/jupyter/nuclear-data.ipynb b/examples/jupyter/nuclear-data.ipynb index e13b143e4d..c63c24a17f 100644 --- a/examples/jupyter/nuclear-data.ipynb +++ b/examples/jupyter/nuclear-data.ipynb @@ -4,6 +4,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ + "# Nuclear Data\n", "In this notebook, we will go through the salient features of the `openmc.data` package in the Python API. This package enables inspection, analysis, and conversion of nuclear data from ACE files. Most importantly, the package provides a mean to generate HDF5 nuclear data libraries that are used by the transport solver." ] }, @@ -1495,7 +1496,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.7.0" + "version": "3.8.3" } }, "nbformat": 4, diff --git a/examples/jupyter/pandas-dataframes.ipynb b/examples/jupyter/pandas-dataframes.ipynb index ddc8ee429b..f5e5142b51 100644 --- a/examples/jupyter/pandas-dataframes.ipynb +++ b/examples/jupyter/pandas-dataframes.ipynb @@ -4,6 +4,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ + "# Pandas Dataframes\n", "This notebook demonstrates how systematic analysis of tally scores is possible using Pandas dataframes. A dataframe can be automatically generated using the `Tally.get_pandas_dataframe(...)` method. Furthermore, by linking the tally data in a statepoint file with geometry and material information from a summary file, the dataframe can be shown with user-supplied labels." ] }, @@ -2687,7 +2688,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.8.5" + "version": "3.8.3" } }, "nbformat": 4, diff --git a/examples/jupyter/pincell.ipynb b/examples/jupyter/pincell.ipynb index 0f11ca6559..dd0cf13136 100644 --- a/examples/jupyter/pincell.ipynb +++ b/examples/jupyter/pincell.ipynb @@ -4,6 +4,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ + "# Modeling a Pin-Cell\n", "This notebook is intended to demonstrate the basic features of the Python API for constructing input files and running OpenMC. In it, we will show how to create a basic reflective pin-cell model that is equivalent to modeling an infinite array of fuel pins. If you have never used OpenMC, this can serve as a good starting point to learn the Python API. We highly recommend having a copy of the [Python API reference documentation](https://docs.openmc.org/en/stable/pythonapi/index.html) open in another browser tab that you can refer to." ] }, @@ -1574,7 +1575,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.8.5" + "version": "3.8.3" } }, "nbformat": 4, diff --git a/examples/jupyter/pincell_depletion.ipynb b/examples/jupyter/pincell_depletion.ipynb index 94ec479f62..3fa46c00bd 100644 --- a/examples/jupyter/pincell_depletion.ipynb +++ b/examples/jupyter/pincell_depletion.ipynb @@ -4,6 +4,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ + "# Pincell Depletion\n", "This notebook is intended to introduce the reader to the depletion interface contained in OpenMC. It is recommended that you are moderately familiar with building models using the OpenMC Python API. The earlier examples are excellent starting points, as this notebook will not focus heavily on model building.\n", "\n", "If you have a real power reactor, the fuel composition is constantly changing as fission events produce energy, remove some fissile isotopes, and produce fission products. Other reactions, like $(n, \\alpha)$ and $(n, \\gamma)$ will alter the composition as well. Furthermore, some nuclides undergo spontaneous decay with widely ranging frequencies. Depletion is the process of modeling this behavior.\n", @@ -26,7 +27,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "# Build the Geometry\n", + "## Build the Geometry\n", "\n", "Much of this section is borrowed from the \"Modeling a Pin-Cell\" example. If you find yourself not understanding some aspects of this section, feel free to refer to that example, as some details may be glossed over for brevity.\n", "\n", @@ -309,7 +310,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "# Setting up for depletion\n", + "## Setting up for depletion\n", "\n", "The OpenMC depletion interface can be accessed from the `openmc.deplete` module, and has a variety of classes that will help us." ] @@ -475,7 +476,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "# Processing the outputs\n", + "## Processing the outputs\n", "\n", "The depletion simulation produces a few output files. First, the statepoint files from each individual transport simulation are written to `openmc_simulation_n.h5`, where `` indicates the current depletion step. Any tallies that we defined in `tallies.xml` will be included in these files across our simulations. We have 7 such files, one for each our of 6 depletion steps and the initial state." ] @@ -708,7 +709,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "# Helpful tips\n", + "## Helpful tips\n", "\n", "Depletion is a tricky task to get correct. Use too short of time steps and you may never get your results due to running many transport simulations. Use long of time steps and you may get incorrect answers. Consider the xenon plot from above. Xenon-135 is a fission product with a thermal absorption cross section on the order of millions of barns, but has a half life of ~9 hours. Taking smaller time steps at the beginning of your simulation to build up some equilibrium in your fission products is highly recommended.\n", "\n", @@ -770,7 +771,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "# Register depletion chain\n", + "## Register depletion chain\n", "\n", "The depletion chain we created can be registered into the OpenMC `cross_sections.xml` file, so we don't have to always pass the `chain_file` argument to the `Operator`. To do this, we create a `DataLibrary` using `openmc.data`. Without any arguments, the `from_xml` method will look for the file located at `OPENMC_CROSS_SECTIONS`. For this example, we will just create a bare library." ] @@ -911,7 +912,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "# Choice of depletion step size\n", + "## Choice of depletion step size\n", "\n", "A general rule of thumb is to use depletion step sizes around 2 MWd/kgHM, where kgHM is really the initial heavy metal mass in kg. If your problem includes integral burnable absorbers, these typically require shorter time steps at or below 1 MWd/kgHM. These are typically valid for the predictor scheme, as the point of recent schemes is to extend this step size. A good convergence study, where the step size is decreased until some convergence metric is satisfied, is a beneficial exercise.\n", "\n", @@ -988,7 +989,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.7.4" + "version": "3.8.3" } }, "nbformat": 4, diff --git a/examples/jupyter/post-processing.ipynb b/examples/jupyter/post-processing.ipynb index 44a2c2d4e8..d31af5831e 100644 --- a/examples/jupyter/post-processing.ipynb +++ b/examples/jupyter/post-processing.ipynb @@ -4,6 +4,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ + "# Post Processing\n", "This notebook demonstrates some basic post-processing tasks that can be performed with the Python API, such as plotting a 2D mesh tally and plotting neutron source sites from an eigenvalue calculation. The problem we will use is a simple reflected pin-cell." ] }, @@ -971,7 +972,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.8.5" + "version": "3.8.3" } }, "nbformat": 4, diff --git a/examples/jupyter/search.ipynb b/examples/jupyter/search.ipynb index 6c3e2169e3..a712726410 100644 --- a/examples/jupyter/search.ipynb +++ b/examples/jupyter/search.ipynb @@ -4,7 +4,8 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "This Notebook illustrates the usage of the OpenMC Python API's generic eigenvalue search capability. In this Notebook, we will do a critical boron concentration search of a typical PWR pin cell.\n", + "# Criticality Search\n", + "This notebook illustrates the usage of the OpenMC Python API's generic eigenvalue search capability. In this Notebook, we will do a critical boron concentration search of a typical PWR pin cell.\n", "\n", "To use the search functionality, we must create a function which creates our model according to the input parameter we wish to search for (in this case, the boron concentration). \n", "\n", @@ -31,7 +32,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "# Create Parametrized Model\n", + "## Create Parametrized Model\n", "\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", @@ -127,7 +128,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "# Search for the Critical Boron Concentration\n", + "## Search for the Critical Boron Concentration\n", "\n", "To perform the search we imply call the `openmc.search_for_keff` function and pass in the relvant arguments. For our purposes we will be passing in the model building function (`build_model` defined above), a bracketed range for the expected critical Boron concentration (1,000 to 2,500 ppm), the tolerance, and the method we wish to use. \n", "\n", @@ -225,7 +226,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.8.5" + "version": "3.8.3" } }, "nbformat": 4, diff --git a/examples/jupyter/tally-arithmetic.ipynb b/examples/jupyter/tally-arithmetic.ipynb index 40eb2b05ff..0e8b53ac71 100644 --- a/examples/jupyter/tally-arithmetic.ipynb +++ b/examples/jupyter/tally-arithmetic.ipynb @@ -4,6 +4,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ + "# Tally Arithmetic\n", "This notebook shows the how tallies can be combined (added, subtracted, multiplied, etc.) using the Python API in order to create derived tallies. Since no covariance information is obtained, it is assumed that tallies are completely independent of one another when propagating uncertainties. The target problem is a simple pin cell." ] }, @@ -1745,7 +1746,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.7.0" + "version": "3.8.3" } }, "nbformat": 4, diff --git a/examples/jupyter/triso.ipynb b/examples/jupyter/triso.ipynb index 882463efc9..ae17ee3441 100644 --- a/examples/jupyter/triso.ipynb +++ b/examples/jupyter/triso.ipynb @@ -4,6 +4,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ + "# Modeling TRISO Particles\n", "OpenMC includes a few convenience functions for generationing TRISO particle locations and placing them in a lattice. To be clear, this capability is not a stochastic geometry capability like that included in MCNP. It's also important to note that OpenMC does not use delta tracking, which would normally speed up calculations in geometries with tons of surfaces and cells. However, the computational burden can be eased by placing TRISO particles in a lattice." ] }, @@ -357,7 +358,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.8.5" + "version": "3.8.3" } }, "nbformat": 4, diff --git a/examples/jupyter/unstructured-mesh-part-i.ipynb b/examples/jupyter/unstructured-mesh-part-i.ipynb index 4e6d873cc8..f307469de2 100644 --- a/examples/jupyter/unstructured-mesh-part-i.ipynb +++ b/examples/jupyter/unstructured-mesh-part-i.ipynb @@ -4,7 +4,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "# Unstructured Mesh Tallies in OpenMC\n", + "# Unstructured Mesh: Introduction\n", "\n", "In this example we'll look at how to setup and use unstructured mesh tallies in OpenMC. Unstructured meshes are able to provide results over spatial regions of a problem while conforming to a specific geometric features -- something that is often difficult to do using the regular and rectilinear meshes in OpenMC.\n", "\n", @@ -696,7 +696,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.7.3" + "version": "3.8.3" } }, "nbformat": 4, diff --git a/examples/jupyter/unstructured-mesh-part-ii.ipynb b/examples/jupyter/unstructured-mesh-part-ii.ipynb index 8c04ace568..92089cabc1 100644 --- a/examples/jupyter/unstructured-mesh-part-ii.ipynb +++ b/examples/jupyter/unstructured-mesh-part-ii.ipynb @@ -4,7 +4,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "# Unstructured Mesh Tallies with CAD Geometry in OpenMC\n", + "# Unstructured Mesh: Tallies with CAD and Point Cloud Visualization\n", "\n", "In the first notebook on this topic, we looked at how to set up a tally using an unstructured mesh in OpenMC.\n", "In this notebook, we will explore using unstructured mesh in conjunction with CAD-based geometry to perform detailed geometry analysis on complex geomerty.\n", @@ -647,7 +647,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.7.3" + "version": "3.8.3" } }, "nbformat": 4, diff --git a/examples/parameterized_custom_source/parameterized_source_ring.cpp b/examples/parameterized_custom_source/parameterized_source_ring.cpp index c88333e15b..9f913dfee3 100644 --- a/examples/parameterized_custom_source/parameterized_source_ring.cpp +++ b/examples/parameterized_custom_source/parameterized_source_ring.cpp @@ -6,14 +6,13 @@ #include "openmc/source.h" #include "openmc/particle.h" -class Source : public openmc::CustomSource -{ +class RingSource : public openmc::Source { public: - Source(double radius, double energy) : radius_(radius), energy_(energy) { } + RingSource(double radius, double energy) : radius_(radius), energy_(energy) { } // Defines a function that can create a unique pointer to a new instance of this class // by extracting the parameters from the provided string. - static std::unique_ptr from_string(std::string parameters) + static std::unique_ptr from_string(std::string parameters) { std::unordered_map parameter_mapping; @@ -28,11 +27,11 @@ class Source : public openmc::CustomSource double radius = std::stod(parameter_mapping["radius"]); double energy = std::stod(parameter_mapping["energy"]); - return std::make_unique(radius, energy); + return std::make_unique(radius, energy); } // Samples from an instance of this class. - openmc::Particle::Bank sample(uint64_t* seed) + openmc::Particle::Bank sample(uint64_t* seed) const { openmc::Particle::Bank particle; // wgt @@ -60,7 +59,7 @@ class Source : public openmc::CustomSource // A function to create a unique pointer to an instance of this class when generated // via a plugin call using dlopen/dlsym. // You must have external C linkage here otherwise dlopen will not find the file -extern "C" std::unique_ptr openmc_create_source(std::string parameters) +extern "C" std::unique_ptr openmc_create_source(std::string parameters) { - return Source::from_string(parameters); + return RingSource::from_string(parameters); } diff --git a/include/openmc/capi.h b/include/openmc/capi.h index 6d82929d17..8094a2e2f8 100644 --- a/include/openmc/capi.h +++ b/include/openmc/capi.h @@ -131,27 +131,38 @@ extern "C" { int openmc_zernike_filter_set_params(int32_t index, const double* x, const double* y, const double* r); + //! Sets the mesh and energy grid for CMFD reweight + //! \param[in] meshtyally_id id of CMFD Mesh Tally + //! \param[in] cmfd_indices indices storing spatial and energy dimensions of CMFD problem + //! \param[in] norm CMFD normalization factor + extern "C" void openmc_initialize_mesh_egrid(const int meshtally_id, const int* cmfd_indices, + const double norm); + + //! Sets the mesh and energy grid for CMFD reweight + //! \param[in] feedback whether or not to run CMFD feedback + //! \param[in] cmfd_src computed CMFD source + extern "C" void openmc_cmfd_reweight(const bool feedback, const double* cmfd_src); + //! Sets the fixed variables that are used for CMFD linear solver - //! \param[in] CSR format index pointer array of loss matrix - //! \param[in] length of indptr - //! \param[in] CSR format index array of loss matrix - //! \param[in] number of non-zero elements in CMFD loss matrix - //! \param[in] dimension n of nxn CMFD loss matrix - //! \param[in] spectral radius of CMFD matrices and tolerances - //! \param[in] indices storing spatial and energy dimensions of CMFD problem - //! \param[in] coremap for problem, storing accelerated regions + //! \param[in] indptr CSR format index pointer array of loss matrix + //! \param[in] len_indptr length of indptr + //! \param[in] indices CSR format index array of loss matrix + //! \param[in] n_elements number of non-zero elements in CMFD loss matrix + //! \param[in] dim dimension n of nxn CMFD loss matrix + //! \param[in] spectral spectral radius of CMFD matrices and tolerances + //! \param[in] map coremap for problem, storing accelerated regions + //! \param[in] use_all_threads whether to use all threads when running CMFD solver extern "C" void openmc_initialize_linsolver(const int* indptr, int len_indptr, const int* indices, int n_elements, int dim, double spectral, - const int* cmfd_indices, const int* map, bool use_all_threads); //! Runs a Gauss Seidel linear solver to solve CMFD matrix equations //! linear solver - //! \param[in] CSR format data array of coefficient matrix - //! \param[in] right hand side vector - //! \param[out] unknown vector - //! \param[in] tolerance on final error + //! \param[in] A_data CSR format data array of coefficient matrix + //! \param[in] b right hand side vector + //! \param[out] x unknown vector + //! \param[in] tol tolerance on final error //! \return number of inner iterations required to reach convergence extern "C" int openmc_run_linsolver(const double* A_data, const double* b, double* x, double tol); diff --git a/include/openmc/constants.h b/include/openmc/constants.h index 13b62ee87d..24d60b92c4 100644 --- a/include/openmc/constants.h +++ b/include/openmc/constants.h @@ -199,7 +199,7 @@ enum ReactionType { N_3N3HE = 177, N_4N3HE = 178, N_3N2P = 179, - N_3N3A = 180, + N_3N2A = 180, N_3NPA = 181, N_DT = 182, N_NPD = 183, @@ -289,9 +289,9 @@ enum class MgxsType { ABSORPTION, INVERSE_VELOCITY, DECAY_RATE, + NU_SCATTER, SCATTER, - SCATTER_MULT, - SCATTER_FMU_MULT, + NU_SCATTER_FMU, SCATTER_FMU, FISSION, KAPPA_FISSION, diff --git a/include/openmc/mesh.h b/include/openmc/mesh.h index b7dcb017b4..5a8367b8bb 100644 --- a/include/openmc/mesh.h +++ b/include/openmc/mesh.h @@ -105,24 +105,59 @@ public: StructuredMesh(pugi::xml_node node) : Mesh {node} {}; virtual ~StructuredMesh() = default; + int get_bin(Position r) const override; + + int n_bins() const override; + + int n_surface_bins() const override; + + void bins_crossed(const Particle& p, std::vector& bins, + std::vector& lengths) const override; + //! Get bin given mesh indices // //! \param[in] Array of mesh indices //! \return Mesh bin - virtual int get_bin_from_indices(const int* ijk) const = 0; + virtual int get_bin_from_indices(const int* ijk) const; //! Get mesh indices given a position // //! \param[in] r Position to get indices for //! \param[out] ijk Array of mesh indices //! \param[out] in_mesh Whether position is in mesh - virtual void get_indices(Position r, int* ijk, bool* in_mesh) const = 0; + virtual void get_indices(Position r, int* ijk, bool* in_mesh) const; //! Get mesh indices corresponding to a mesh bin // //! \param[in] bin Mesh bin //! \param[out] ijk Mesh indices - virtual void get_indices_from_bin(int bin, int* ijk) const = 0; + virtual void get_indices_from_bin(int bin, int* ijk) const; + + //! Get mesh index in a particular direction + //! + //! \param[in] r Coordinate to get index for + //! \param[in] i Direction index + virtual int get_index_in_direction(double r, int i) const = 0; + + //! Check where a line segment intersects the mesh and if it intersects at all + // + //! \param[in,out] r0 In: starting position, out: intersection point + //! \param[in] r1 Ending position + //! \param[out] ijk Indices of the mesh bin containing the intersection point + //! \return Whether the line segment connecting r0 and r1 intersects mesh + virtual bool intersects(Position& r0, Position r1, int* ijk) const; + + //! Get the coordinate for the mesh grid boundary in the positive direction + //! + //! \param[in] ijk Array of mesh indices + //! \param[in] i Direction index + virtual double positive_grid_boundary(int* ijk, int i) const = 0; + + //! Get the coordinate for the mesh grid boundary in the negative direction + //! + //! \param[in] ijk Array of mesh indices + //! \param[in] i Direction index + virtual double negative_grid_boundary(int* ijk, int i) const = 0; //! Get a label for the mesh bin std::string bin_label(int bin) const override; @@ -130,6 +165,12 @@ public: // Data members xt::xtensor lower_left_; //!< Lower-left coordinates of mesh xt::xtensor upper_right_; //!< Upper-right coordinates of mesh + xt::xtensor shape_; //!< Number of mesh elements in each dimension + +protected: + virtual bool intersects_1d(Position& r0, Position r1, int* ijk) const; + virtual bool intersects_2d(Position& r0, Position r1, int* ijk) const; + virtual bool intersects_3d(Position& r0, Position r1, int* ijk) const; }; //============================================================================== @@ -145,23 +186,14 @@ public: // Overriden methods - void bins_crossed(const Particle& p, std::vector& bins, - std::vector& lengths) const override; - void surface_bins_crossed(const Particle& p, std::vector& bins) const override; - int get_bin(Position r) const override; + int get_index_in_direction(double r, int i) const override; - int get_bin_from_indices(const int* ijk) const override; + double positive_grid_boundary(int* ijk, int i) const override; - void get_indices(Position r, int* ijk, bool* in_mesh) const override; - - void get_indices_from_bin(int bin, int* ijk) const override; - - int n_bins() const override; - - int n_surface_bins() const override; + double negative_grid_boundary(int* ijk, int i) const override; std::pair, std::vector> plot(Position plot_ll, Position plot_ur) const override; @@ -170,14 +202,6 @@ public: // New methods - //! Check where a line segment intersects the mesh and if it intersects at all - // - //! \param[in,out] r0 In: starting position, out: intersection point - //! \param[in] r1 Ending position - //! \param[out] ijk Indices of the mesh bin containing the intersection point - //! \return Whether the line segment connecting r0 and r1 intersects mesh - bool intersects(Position& r0, Position r1, int* ijk) const; - //! Count number of bank sites in each mesh bin / energy bin // //! \param[in] bank Array of bank sites @@ -189,13 +213,7 @@ public: // Data members double volume_frac_; //!< Volume fraction of each mesh element - xt::xtensor shape_; //!< Number of mesh elements in each dimension xt::xtensor width_; //!< Width of each mesh element - -private: - bool intersects_1d(Position& r0, Position r1, int* ijk) const; - bool intersects_2d(Position& r0, Position r1, int* ijk) const; - bool intersects_3d(Position& r0, Position r1, int* ijk) const; }; @@ -207,42 +225,20 @@ public: // Overriden methods - void bins_crossed(const Particle& p, std::vector& bins, - std::vector& lengths) const override; - void surface_bins_crossed(const Particle& p, std::vector& bins) const override; - int get_bin(Position r) const override; + int get_index_in_direction(double r, int i) const override; - int get_bin_from_indices(const int* ijk) const override; + double positive_grid_boundary(int* ijk, int i) const override; - void get_indices(Position r, int* ijk, bool* in_mesh) const override; - - void get_indices_from_bin(int bin, int* ijk) const override; - - int n_bins() const override; - - int n_surface_bins() const override; + double negative_grid_boundary(int* ijk, int i) const override; std::pair, std::vector> plot(Position plot_ll, Position plot_ur) const override; void to_hdf5(hid_t group) const override; - // New methods - - //! Check where a line segment intersects the mesh and if it intersects at all - // - //! \param[in,out] r0 In: starting position, out: intersection point - //! \param[in] r1 Ending position - //! \param[out] ijk Indices of the mesh bin containing the intersection point - //! \return Whether the line segment connecting r0 and r1 intersects mesh - bool intersects(Position& r0, Position r1, int* ijk) const; - - // Data members - xt::xtensor shape_; //!< Number of mesh elements in each dimension - private: std::vector> grid_; }; diff --git a/include/openmc/mgxs.h b/include/openmc/mgxs.h index f9c4722e94..ae7a54ad3e 100644 --- a/include/openmc/mgxs.h +++ b/include/openmc/mgxs.h @@ -117,7 +117,7 @@ class Mgxs { int num_group, int num_delay); //! \brief Constructor that initializes and populates all data to build a - //! macroscopic cross section from microscopic cross section. + //! macroscopic cross section from microscopic cross sections. //! //! @param in_name Name of the object. //! @param mat_kTs temperatures (in units of eV) that data is needed. diff --git a/include/openmc/scattdata.h b/include/openmc/scattdata.h index 75fd7a2fdb..aa91d56885 100644 --- a/include/openmc/scattdata.h +++ b/include/openmc/scattdata.h @@ -33,7 +33,8 @@ class ScattData { //! \brief Combines microscopic ScattDatas into a macroscopic one. void - base_combine(size_t max_order, const std::vector& those_scatts, + base_combine(size_t max_order, size_t order_dim, + const std::vector& those_scatts, const std::vector& scalars, xt::xtensor& in_gmin, xt::xtensor& in_gmax, double_2dvec& sparse_mult, double_3dvec& sparse_scatter); diff --git a/include/openmc/settings.h b/include/openmc/settings.h index 85ef1c71ea..74cbbc1328 100644 --- a/include/openmc/settings.h +++ b/include/openmc/settings.h @@ -59,8 +59,6 @@ extern std::string path_cross_sections; //!< path to cross_sections.xml extern std::string path_input; //!< directory where main .xml files resides extern std::string path_output; //!< directory where output files are written extern std::string path_particle_restart; //!< path to a particle restart file -extern std::string path_source; -extern std::string path_source_library; //!< path to the source shared object extern std::string path_sourcepoint; //!< path to a source file extern "C" std::string path_statepoint; //!< path to a statepoint file diff --git a/include/openmc/source.h b/include/openmc/source.h index 529cb1836e..12e8156992 100644 --- a/include/openmc/source.h +++ b/include/openmc/source.h @@ -19,32 +19,47 @@ namespace openmc { // Global variables //============================================================================== -class SourceDistribution; +class Source; namespace model { -extern std::vector external_sources; +extern std::vector> external_sources; } // namespace model //============================================================================== -//! External source distribution +//! Abstract source interface //============================================================================== -class SourceDistribution { +class Source { +public: + virtual ~Source() = default; + + // Methods that must be implemented + virtual Particle::Bank sample(uint64_t* seed) const = 0; + + // Methods that can be overridden + virtual double strength() const { return 1.0; } +}; + +//============================================================================== +//! Source composed of independent spatial, angle, and energy distributions +//============================================================================== + +class IndependentSource : public Source { public: // Constructors - SourceDistribution(UPtrSpace space, UPtrAngle angle, UPtrDist energy); - explicit SourceDistribution(pugi::xml_node node); + IndependentSource(UPtrSpace space, UPtrAngle angle, UPtrDist energy); + explicit IndependentSource(pugi::xml_node node); //! Sample from the external source distribution //! \param[inout] seed Pseudorandom seed pointer //! \return Sampled site - Particle::Bank sample(uint64_t* seed) const; + Particle::Bank sample(uint64_t* seed) const override; // Properties Particle::Type particle_type() const { return particle_; } - double strength() const { return strength_; } + double strength() const override { return strength_; } // Make observing pointers available SpatialDistribution* space() const { return space_.get(); } @@ -59,14 +74,45 @@ private: UPtrDist energy_; //!< Energy distribution }; -class CustomSource { - public: - virtual ~CustomSource() {} +//============================================================================== +//! Source composed of particles read from a file +//============================================================================== - virtual Particle::Bank sample(uint64_t* seed) = 0; +class FileSource : public Source { +public: + // Constructors + explicit FileSource(std::string path); + + // Methods + Particle::Bank sample(uint64_t* seed) const override; + +private: + std::vector sites_; //!< Source sites from a file }; -typedef std::unique_ptr create_custom_source_t(std::string parameters); +//============================================================================== +//! Wrapper for custom sources that manages opening/closing shared library +//============================================================================== + +class CustomSourceWrapper : public Source { +public: + // Constructors, destructors + CustomSourceWrapper(std::string path, std::string parameters); + ~CustomSourceWrapper(); + + // Defer implementation to custom source library + Particle::Bank sample(uint64_t* seed) const override + { + return custom_source_->sample(seed); + } + + double strength() const override { return custom_source_->strength(); } +private: + void* shared_library_; //!< library from dlopen + std::unique_ptr custom_source_; +}; + +typedef std::unique_ptr create_custom_source_t(std::string parameters); //============================================================================== // Functions @@ -81,18 +127,6 @@ extern "C" void initialize_source(); //! \return Sampled source site Particle::Bank sample_external_source(uint64_t* seed); -//! Sample a site from custom source library -Particle::Bank sample_custom_source_library(uint64_t* seed); - -//! Load custom source library -void load_custom_source_library(); - -//! Release custom source library -void close_custom_source_library(); - -//! Fill source bank at the end of a generation for dlopen based source simulation -void fill_source_bank_custom_source(); - void free_memory_source(); } // namespace openmc diff --git a/include/openmc/state_point.h b/include/openmc/state_point.h index 4a901ac2a2..c50ca355b8 100644 --- a/include/openmc/state_point.h +++ b/include/openmc/state_point.h @@ -2,17 +2,19 @@ #define OPENMC_STATE_POINT_H #include +#include #include "hdf5.h" #include "openmc/capi.h" +#include "openmc/particle.h" namespace openmc { void load_state_point(); void write_source_point(const char* filename); void write_source_bank(hid_t group_id); -void read_source_bank(hid_t group_id); +void read_source_bank(hid_t group_id, std::vector& sites, bool distribute); void write_tally_results_nr(hid_t file_id); void restart_set_keff(); diff --git a/include/openmc/timer.h b/include/openmc/timer.h index a43a66bd42..3acf483d6b 100644 --- a/include/openmc/timer.h +++ b/include/openmc/timer.h @@ -21,7 +21,6 @@ extern Timer time_finalize; extern Timer time_inactive; extern Timer time_initialize; extern Timer time_read_xs; -extern Timer time_sample_source; extern Timer time_statepoint; extern Timer time_tallies; extern Timer time_total; diff --git a/openmc/cmfd.py b/openmc/cmfd.py index 78901b03b9..a99b606193 100644 --- a/openmc/cmfd.py +++ b/openmc/cmfd.py @@ -366,8 +366,6 @@ class CMFDRun: self._current = None self._cmfd_src = None self._openmc_src = None - self._sourcecounts = None - self._weightfactors = None self._entropy = [] self._balance = [] self._src_cmp = [] @@ -914,7 +912,7 @@ class CMFDRun: args = temp_loss.indptr, len(temp_loss.indptr), \ temp_loss.indices, len(temp_loss.indices), n, \ - self._spectral, self._indices, coremap, self._use_all_threads + self._spectral, coremap, self._use_all_threads return openmc.lib._dll.openmc_initialize_linsolver(*args) def _write_cmfd_output(self): @@ -1171,8 +1169,12 @@ class CMFDRun: # Calculate fission source self._calc_fission_source() - # Calculate weight factors - self._cmfd_reweight() + # Calculate weight factors through C++ and manipulate CMFD + # source into a 1-D vector that matches C++ array ordering + src_flipped = np.flip(self._cmfd_src, axis=3) + src_swapped = np.swapaxes(src_flipped, 0, 2) + args = self._feedback, src_swapped.flatten() + openmc.lib._dll.openmc_cmfd_reweight(*args) # Stop CMFD timer if openmc.lib.master(): @@ -1390,151 +1392,6 @@ class CMFDRun: self._src_cmp.append(np.sqrt(1.0 / self._norm * np.sum((self._cmfd_src - self._openmc_src)**2))) - def _cmfd_reweight(self): - """Performs weighting of particles in source bank""" - # Get spatial dimensions and energy groups - nx, ny, nz, ng = self._indices - - # Count bank site in mesh and reverse due to egrid structured - outside = self._count_bank_sites() - - # Check and raise error if source sites exist outside of CMFD mesh - if openmc.lib.master() and outside: - raise OpenMCError('Source sites outside of the CMFD mesh') - - # Have master compute weight factors, ignore any zeros in - # sourcecounts or cmfd_src - if openmc.lib.master(): - # Compute normalization factor - norm = np.sum(self._sourcecounts) / np.sum(self._cmfd_src) - - # Define target reshape dimensions for sourcecounts. This - # defines how self._sourcecounts is ordered by dimension - target_shape = [nz, ny, nx, ng] - - # Reshape sourcecounts to target shape. Swap x and z axes so - # that the shape is now [nx, ny, nz, ng] - sourcecounts = np.swapaxes( - self._sourcecounts.reshape(target_shape), 0, 2) - - # Flip index of energy dimension - sourcecounts = np.flip(sourcecounts, axis=3) - - # Compute weight factors - div_condition = np.logical_and(sourcecounts > 0, - self._cmfd_src > 0) - self._weightfactors = (np.divide(self._cmfd_src * norm, - sourcecounts, where=div_condition, - out=np.ones_like(self._cmfd_src), - dtype=np.float32)) - - if not self._feedback: - return - - # Broadcast weight factors to all procs - if have_mpi: - self._weightfactors = self._intracomm.bcast( - self._weightfactors) - - m = openmc.lib.meshes[self._mesh_id] - energy = self._egrid - ng = self._indices[3] - - # Get locations and energies of all particles in source bank - source_xyz = openmc.lib.source_bank()['r'] - source_energies = openmc.lib.source_bank()['E'] - - # Convert xyz location to the CMFD mesh index - mesh_ijk = np.floor((source_xyz - m.lower_left)/m.width).astype(int) - - # Determine which energy bin each particle's energy belongs to - # Separate into cases bases on where source energies lies on egrid - energy_bins = np.zeros(len(source_energies), dtype=int) - idx = np.where(source_energies < energy[0]) - energy_bins[idx] = ng - 1 - idx = np.where(source_energies > energy[-1]) - energy_bins[idx] = 0 - idx = np.where((source_energies >= energy[0]) & - (source_energies <= energy[-1])) - energy_bins[idx] = ng - np.digitize(source_energies[idx], energy) - - # Determine weight factor of each particle based on its mesh index - # and energy bin and updates its weight - openmc.lib.source_bank()['wgt'] *= self._weightfactors[ - mesh_ijk[:,0], mesh_ijk[:,1], mesh_ijk[:,2], energy_bins] - - if openmc.lib.master() and np.any(source_energies < energy[0]): - print(' WARNING: Source point below energy grid') - sys.stdout.flush() - if openmc.lib.master() and np.any(source_energies > energy[-1]): - print(' WARNING: Source point above energy grid') - sys.stdout.flush() - - def _count_bank_sites(self): - """Determines the number of fission bank sites in each cell of a given - mesh and energy group structure. - Returns - ------- - bool - Wheter any source sites outside of CMFD mesh were found - - """ - # Initialize variables - m = openmc.lib.meshes[self._mesh_id] - bank = openmc.lib.source_bank() - energy = self._egrid - sites_outside = np.zeros(1, dtype=bool) - nxnynz = np.prod(self._indices[0:3]) - ng = self._indices[3] - - outside = np.zeros(1, dtype=bool) - self._sourcecounts = np.zeros((nxnynz, ng)) - count = np.zeros(self._sourcecounts.shape) - - # Get location and energy of each particle in source bank - source_xyz = openmc.lib.source_bank()['r'] - source_energies = openmc.lib.source_bank()['E'] - - # Convert xyz location to mesh index and ravel index to scalar - mesh_locations = np.floor((source_xyz - m.lower_left) / m.width) - mesh_bins = mesh_locations[:,2] * m.dimension[1] * m.dimension[0] + \ - mesh_locations[:,1] * m.dimension[0] + mesh_locations[:,0] - - # Check if any source locations lie outside of defined CMFD mesh - if np.any(mesh_bins < 0) or np.any(mesh_bins >= np.prod(m.dimension)): - outside[0] = True - - # Determine which energy bin each particle's energy belongs to - # Separate into cases bases on where source energies lies on egrid - energy_bins = np.zeros(len(source_energies), dtype=int) - idx = np.where(source_energies < energy[0]) - energy_bins[idx] = 0 - idx = np.where(source_energies > energy[-1]) - energy_bins[idx] = ng - 1 - idx = np.where((source_energies >= energy[0]) & - (source_energies <= energy[-1])) - energy_bins[idx] = np.digitize(source_energies[idx], energy) - 1 - - # Determine all unique combinations of mesh bin and energy bin, and - # count number of particles that belong to these combinations - idx, counts = np.unique(np.array([mesh_bins, energy_bins]), axis=1, - return_counts=True) - - # Store counts to appropriate mesh-energy combination - count[idx[0].astype(int), idx[1].astype(int)] = counts - - if have_mpi: - # Collect values of count from all processors - self._intracomm.Reduce(count, self._sourcecounts, MPI.SUM) - # Check if there were sites outside the mesh for any processor - self._intracomm.Reduce(outside, sites_outside, MPI.LOR) - # Deal with case if MPI not defined (only one proc) - else: - sites_outside = outside - self._sourcecounts = count - - return sites_outside[0] - def _build_loss_matrix(self, adjoint): # Extract spatial and energy indices and define matrix dimension ng = self._indices[3] @@ -3045,3 +2902,7 @@ class CMFDRun: # Set all tallies to be active from beginning cmfd_tally.active = True + + # Initialize CMFD mesh and energy grid in C++ for CMFD reweight + args = self._tally_ids[0], self._indices, self._norm + openmc.lib._dll.openmc_initialize_mesh_egrid(*args) diff --git a/openmc/data/reaction.py b/openmc/data/reaction.py index 9360d05289..474967167e 100644 --- a/openmc/data/reaction.py +++ b/openmc/data/reaction.py @@ -56,7 +56,7 @@ REACTION_NAME = {1: '(n,total)', 2: '(n,elastic)', 4: '(n,level)', 301: 'heating', 444: 'damage-energy', 649: '(n,pc)', 699: '(n,dc)', 749: '(n,tc)', 799: '(n,3Hec)', 849: '(n,ac)', 891: '(n,2nc)', 901: 'heating-local'} -REACTION_NAME.update({i: '(n,n{})'.format(i - 50) for i in range(50, 91)}) +REACTION_NAME.update({i: '(n,n{})'.format(i - 50) for i in range(51, 91)}) REACTION_NAME.update({i: '(n,p{})'.format(i - 600) for i in range(600, 649)}) REACTION_NAME.update({i: '(n,d{})'.format(i - 650) for i in range(650, 699)}) REACTION_NAME.update({i: '(n,t{})'.format(i - 700) for i in range(700, 749)}) @@ -64,6 +64,9 @@ REACTION_NAME.update({i: '(n,3He{})'.format(i - 750) for i in range(750, 799)}) REACTION_NAME.update({i: '(n,a{})'.format(i - 800) for i in range(800, 849)}) REACTION_NAME.update({i: '(n,2n{})'.format(i - 875) for i in range(875, 891)}) +REACTION_MT = {name: mt for mt, name in REACTION_NAME.items()} +REACTION_MT['fission'] = 18 + FISSION_MTS = (18, 19, 20, 21, 38) diff --git a/openmc/deplete/helpers.py b/openmc/deplete/helpers.py index b275dc0a58..6c3badc090 100644 --- a/openmc/deplete/helpers.py +++ b/openmc/deplete/helpers.py @@ -1,17 +1,18 @@ """ Class for normalizing fission energy deposition """ +import bisect +from collections import defaultdict from copy import deepcopy from itertools import product from numbers import Real -import bisect -from collections import defaultdict +import sys from numpy import dot, zeros, newaxis, asarray from . import comm from openmc.checkvalue import check_type, check_greater_than -from openmc.data import JOULE_PER_EV, REACTION_NAME +from openmc.data import JOULE_PER_EV, REACTION_MT from openmc.lib import ( Tally, MaterialFilter, EnergyFilter, EnergyFunctionFilter) import openmc.lib @@ -168,10 +169,8 @@ class FluxCollapseHelper(ReactionRateHelper): """ self._materials = materials - # Convert reactions to MT values (needed when collapsing) - mt_values = {v: k for k, v in REACTION_NAME.items()} - mt_values['fission'] = 18 - self._mts = [mt_values[x] for x in scores] + # adds an entry for fisson to the dictionary of reactions + self._mts = [REACTION_MT[x] for x in scores] self._scores = scores # Create flux tally with material and energy filters diff --git a/openmc/deplete/operator.py b/openmc/deplete/operator.py index 1f99abe955..0e28b7ed33 100644 --- a/openmc/deplete/operator.py +++ b/openmc/deplete/operator.py @@ -371,15 +371,17 @@ class Operator(TransportOperator): [mat for mat in self.geometry.get_all_materials().values() if mat.depletable and mat.num_instances > 1]) + for mat in distribmats: + if mat.volume is None: + raise RuntimeError("Volume not specified for depletable " + "material with ID={}.".format(mat.id)) + mat.volume /= mat.num_instances + if distribmats: # Assign distribmats to cells for cell in self.geometry.get_all_material_cells().values(): - if cell.fill in distribmats and cell.num_instances > 1: + if cell.fill in distribmats: mat = cell.fill - if mat.volume is None: - raise RuntimeError("Volume not specified for depletable " - "material with ID={}.".format(mat.id)) - mat.volume /= mat.num_instances cell.fill = [mat.clone() for i in range(cell.num_instances)] diff --git a/openmc/element.py b/openmc/element.py index 6a808df621..2eacaf867d 100644 --- a/openmc/element.py +++ b/openmc/element.py @@ -149,30 +149,28 @@ class Element(str): mutual_nuclides = sorted(list(mutual_nuclides)) absent_nuclides = sorted(list(absent_nuclides)) - # If all natural nuclides are present in the library, - # expand element using all natural nuclides + # If all naturally ocurring isotopes are present in the library, + # add them based on their abundance if len(absent_nuclides) == 0: for nuclide in mutual_nuclides: abundances[nuclide] = NATURAL_ABUNDANCE[nuclide] - # If no natural elements are present in the library, check if the - # 0 nuclide is present. If so, set the abundance to 1 for this - # nuclide. Else, raise an error. - elif len(mutual_nuclides) == 0: - nuclide_0 = self + '0' - if nuclide_0 in library_nuclides: - abundances[nuclide_0] = 1.0 - else: - msg = 'Unable to expand element {0} because the cross '\ - 'section library provided does not contain any of '\ - 'the natural isotopes for that element.'\ - .format(self) - raise ValueError(msg) + # If some naturally occurring isotopes are not present in the + # library, check if the "natural" nuclide (e.g., C0) is present. If + # so, set the abundance to 1 for this nuclide. + elif (self + '0') in library_nuclides: + abundances[self + '0'] = 1.0 - # If some, but not all, natural nuclides are in the library, add - # the mutual nuclides. For the absent nuclides, add them based on - # our knowledge of the common cross section libraries - # (ENDF, JEFF, and JENDL) + elif len(mutual_nuclides) == 0: + msg = ('Unable to expand element {} because the cross ' + 'section library provided does not contain any of ' + 'the natural isotopes for that element.' + .format(self)) + raise ValueError(msg) + + # If some naturally occurring isotopes are in the library, add them. + # For the absent nuclides, add them based on our knowledge of the + # common cross section libraries (ENDF, JEFF, and JENDL) else: # Add the mutual isotopes for nuclide in mutual_nuclides: diff --git a/openmc/lib/core.py b/openmc/lib/core.py index 3fe75dccf6..7be94e03d3 100644 --- a/openmc/lib/core.py +++ b/openmc/lib/core.py @@ -31,6 +31,8 @@ _array_1d_dble = np.ctypeslib.ndpointer(dtype=np.double, ndim=1, _dll.openmc_calculate_volumes.restype = c_int _dll.openmc_calculate_volumes.errcheck = _error_handler +_dll.openmc_cmfd_reweight.argtypes = c_bool, _array_1d_dble +_dll.openmc_cmfd_reweight.restype = None _dll.openmc_finalize.restype = c_int _dll.openmc_finalize.errcheck = _error_handler _dll.openmc_find_cell.argtypes = [POINTER(c_double*3), POINTER(c_int32), @@ -45,8 +47,12 @@ _dll.openmc_init.errcheck = _error_handler _dll.openmc_get_keff.argtypes = [POINTER(c_double*2)] _dll.openmc_get_keff.restype = c_int _dll.openmc_get_keff.errcheck = _error_handler +_dll.openmc_initialize_mesh_egrid.argtypes = [ + c_int, _array_1d_int, c_double +] +_dll.openmc_initialize_mesh_egrid.restype = None _init_linsolver_argtypes = [_array_1d_int, c_int, _array_1d_int, c_int, c_int, - c_double, _array_1d_int, _array_1d_int, c_bool] + c_double, _array_1d_int, c_bool] _dll.openmc_initialize_linsolver.argtypes = _init_linsolver_argtypes _dll.openmc_initialize_linsolver.restype = None _dll.openmc_is_statepoint_batch.restype = c_bool diff --git a/openmc/mgxs/library.py b/openmc/mgxs/library.py index e2ba0bc6a1..5c70720334 100644 --- a/openmc/mgxs/library.py +++ b/openmc/mgxs/library.py @@ -277,7 +277,9 @@ class Library: @mgxs_types.setter def mgxs_types(self, mgxs_types): - all_mgxs_types = openmc.mgxs.MGXS_TYPES + openmc.mgxs.MDGXS_TYPES + all_mgxs_types = openmc.mgxs.MGXS_TYPES + openmc.mgxs.MDGXS_TYPES + \ + openmc.mgxs.ARBITRARY_VECTOR_TYPES + \ + openmc.mgxs.ARBITRARY_MATRIX_TYPES if mgxs_types == 'all': self._mgxs_types = all_mgxs_types else: @@ -612,8 +614,10 @@ class Library: ---------- domain : openmc.Material or openmc.Cell or openmc.Universe or openmc.RegularMesh or Integral The material, cell, or universe object of interest (or its ID) - mgxs_type : {'total', 'transport', 'nu-transport', 'absorption', 'capture', 'fission', 'nu-fission', 'kappa-fission', 'scatter', 'nu-scatter', 'scatter matrix', 'nu-scatter matrix', 'multiplicity matrix', 'nu-fission matrix', chi', 'chi-prompt', 'inverse-velocity', 'prompt-nu-fission', 'prompt-nu-fission matrix', 'delayed-nu-fission', 'delayed-nu-fission matrix', 'chi-delayed', 'beta'} - The type of multi-group cross section object to return + mgxs_type : str + The type of multi-group cross section object to return; allowable + values are those MGXS to the Library and present in the + mgxs_types attribute. Returns ------- @@ -912,7 +916,7 @@ class Library: return pickle.load(f) def get_xsdata(self, domain, xsdata_name, nuclide='total', xs_type='macro', - subdomain=None): + subdomain=None, apply_domain_chi=False): """Generates an openmc.XSdata object describing a multi-group cross section dataset for writing to an openmc.MGXSLibrary object. @@ -939,6 +943,15 @@ class Library: mesh cell of interest in the openmc.RegularMesh object. Note: this parameter currently only supports subdomains within a mesh, and not the subdomains of a distribcell. + apply_domain_chi : bool + This parameter sets whether (True) or not (False) the + domain-averaged values of chi, chi-prompt, and chi-delayed are to + be applied to each of the nuclide-dependent fission energy spectra + of a domain. In effect, if this is True, then every nuclide in the + domain receives the same flux-weighted Chi. This is useful for + downstream multigroup solvers that precompute a material-specific + chi before the transport solve provides group-wise fluxes. Defaults + to False. Returns ------- @@ -1046,18 +1059,30 @@ class Library: if 'chi' in self.mgxs_types: mymgxs = self.get_mgxs(domain, 'chi') - xsdata.set_chi_mgxs(mymgxs, xs_type=xs_type, nuclide=[nuclide], + if apply_domain_chi and nuclide != "total": + nuc = "sum" + else: + nuc = nuclide + xsdata.set_chi_mgxs(mymgxs, xs_type=xs_type, nuclide=[nuc], subdomain=subdomain) if 'chi-prompt' in self.mgxs_types: mymgxs = self.get_mgxs(domain, 'chi-prompt') + if apply_domain_chi and nuclide != "total": + nuc = "sum" + else: + nuc = nuclide xsdata.set_chi_prompt_mgxs(mymgxs, xs_type=xs_type, - nuclide=[nuclide], subdomain=subdomain) + nuclide=[nuc], subdomain=subdomain) if 'chi-delayed' in self.mgxs_types: mymgxs = self.get_mgxs(domain, 'chi-delayed') + if apply_domain_chi and nuclide != "total": + nuc = "sum" + else: + nuc = nuclide xsdata.set_chi_delayed_mgxs(mymgxs, xs_type=xs_type, - nuclide=[nuclide], subdomain=subdomain) + nuclide=[nuc], subdomain=subdomain) if 'nu-fission' in self.mgxs_types: mymgxs = self.get_mgxs(domain, 'nu-fission') @@ -1196,7 +1221,8 @@ class Library: return xsdata - def create_mg_library(self, xs_type='macro', xsdata_names=None): + def create_mg_library(self, xs_type='macro', xsdata_names=None, + apply_domain_chi=False): """Creates an openmc.MGXSLibrary object to contain the MGXS data for the Multi-Group mode of OpenMC. @@ -1213,6 +1239,15 @@ class Library: xsdata_names : Iterable of str List of names to apply to the "xsdata" entries in the resultant mgxs data file. Defaults to 'set1', 'set2', ... + apply_domain_chi : bool + This parameter sets whether (True) or not (False) the + domain-averaged values of chi, chi-prompt, and chi-delayed are to + be applied to each of the nuclide-dependent fission energy spectra + of a domain. In effect, if this is True, then every nuclide in the + domain receives the same flux-weighted Chi. This is useful for + downstream multigroup solvers that precompute a material-specific + chi before the transport solve provides group-wise fluxes. Defaults + to False. Returns ------- @@ -1284,13 +1319,15 @@ class Library: xsdata_name = xsdata_names[i] xsdata = self.get_xsdata(domain, xsdata_name, - nuclide=nuclide, xs_type=xs_type) + nuclide=nuclide, xs_type=xs_type, + apply_domain_chi=apply_domain_chi) mgxs_file.add_xsdata(xsdata) return mgxs_file - def create_mg_mode(self, xsdata_names=None, bc=['reflective'] * 6): + def create_mg_mode(self, xsdata_names=None, bc=['reflective'] * 6, + apply_domain_chi=False): """Creates an openmc.MGXSLibrary object to contain the MGXS data for the Multi-Group mode of OpenMC as well as the associated openmc.Materials and openmc.Geometry objects. @@ -1314,6 +1351,15 @@ class Library: (if applying to a 3D mesh) provided in the following order: [x min, x max, y min, y max, z min, z max]. 2-D cells do not contain the z min and z max entries. + apply_domain_chi : bool + This parameter sets whether (True) or not (False) the + domain-averaged values of chi, chi-prompt, and chi-delayed are to + be applied to each of the nuclide-dependent fission energy spectra + of a domain. In effect, if this is True, then every nuclide in the + domain receives the same flux-weighted Chi. This is useful for + downstream multigroup solvers that precompute a material-specific + chi before the transport solve provides group-wise fluxes. Defaults + to False. Returns ------- @@ -1354,7 +1400,8 @@ class Library: cv.check_length("domains", self.domains, 1, 1) # Get the MGXS File Data - mgxs_file = self.create_mg_library('macro', xsdata_names) + mgxs_file = self.create_mg_library('macro', xsdata_names, + apply_domain_chi=apply_domain_chi) # Now move on the creating the geometry and assigning materials if self.domain_type == 'mesh': @@ -1415,7 +1462,7 @@ class Library: if not isinstance(cell.fill, openmc.Material): warn('If the library domain includes a lattice or universe cell ' 'in conjunction with a consituent cell of that lattice/universe, ' - 'the multi-group simulation will fail') + 'the multi-group simulation will fail') if cell.id == domain.id: cell.fill = material diff --git a/openmc/mgxs/mdgxs.py b/openmc/mgxs/mdgxs.py index 8f35d58799..f511579528 100644 --- a/openmc/mgxs/mdgxs.py +++ b/openmc/mgxs/mdgxs.py @@ -2044,13 +2044,9 @@ class DecayRate(MDGXS): num_delayed_groups) else: new_shape = (num_subdomains, num_delayed_groups) + new_shape += xs.shape[1:] xs = np.reshape(xs, new_shape) - # Reverse data if user requested increasing energy groups since - # tally data is stored in order of increasing energies - if order_groups == 'increasing': - xs = xs[..., ::-1, :] - if squeeze: # We want to squeeze out everything but the polar, azimuthal, # delayed group, and energy group data. diff --git a/openmc/mgxs/mgxs.py b/openmc/mgxs/mgxs.py index 175742b970..0f1bf56a12 100644 --- a/openmc/mgxs/mgxs.py +++ b/openmc/mgxs/mgxs.py @@ -8,6 +8,7 @@ import h5py import numpy as np import openmc +from openmc.data import REACTION_MT, REACTION_NAME, FISSION_MTS import openmc.checkvalue as cv from ..tallies import ESTIMATOR_TYPES from . import EnergyGroups @@ -42,6 +43,22 @@ MGXS_TYPES = ( 'nu-diffusion-coefficient' ) +# Some scores from REACTION_MT are not supported, or are simply overkill to +# support and test (like inelastic levels), remoev those from consideration +_BAD_SCORES = ["(n,misc)", "(n,absorption)", "(n,total)", "fission"] +_BAD_SCORES += [REACTION_NAME[mt] for mt in FISSION_MTS] +ARBITRARY_VECTOR_TYPES = tuple(k for k in REACTION_MT.keys() + if k not in _BAD_SCORES) +ARBITRARY_MATRIX_TYPES = [] +for rxn in ARBITRARY_VECTOR_TYPES: + # Preclude the fission channels from being treated as a matrix + if rxn not in [REACTION_NAME[mt] for mt in FISSION_MTS]: + split_rxn = rxn.strip("()").split(",") + if len(split_rxn) > 1 and "n" in split_rxn[1]: + # Then there is a neutron product, so it can also be a matrix + ARBITRARY_MATRIX_TYPES.append(rxn + " matrix") +ARBITRARY_MATRIX_TYPES = tuple(ARBITRARY_MATRIX_TYPES) + # Supported domain types DOMAIN_TYPES = ( 'cell', @@ -698,8 +715,13 @@ class MGXS: Parameters ---------- - mgxs_type : {'total', 'transport', 'nu-transport', 'absorption', 'capture', 'fission', 'nu-fission', 'kappa-fission', 'scatter', 'nu-scatter', 'scatter matrix', 'nu-scatter matrix', 'multiplicity matrix', 'nu-fission matrix', 'chi', 'chi-prompt', 'inverse-velocity', 'prompt-nu-fission', 'prompt-nu-fission matrix', 'current', 'diffusion-coefficient', 'nu-diffusion-coefficient'} - The type of multi-group cross section object to return + mgxs_type : str or Integral + The type of multi-group cross section object to return; valid + values are members of MGXS_TYPES, or the reaction types that are + the keys of REACTION_MT. Note that if a reaction type from + REACTION_MT is used, it can be appended with ' matrix' to obtain + a multigroup matrix (from incoming to outgoing energy groups) for + reactions with a neutron in an outgoing channel. domain : openmc.Material or openmc.Cell or openmc.Universe or openmc.RegularMesh The domain for spatial homogenization domain_type : {'material', 'cell', 'distribcell', 'universe', 'mesh'} @@ -727,7 +749,9 @@ class MGXS: """ - cv.check_value('mgxs_type', mgxs_type, MGXS_TYPES) + cv.check_value( + "mgxs_type", mgxs_type, + MGXS_TYPES + ARBITRARY_VECTOR_TYPES + ARBITRARY_MATRIX_TYPES) if mgxs_type == 'total': mgxs = TotalXS(domain, domain_type, energy_groups) @@ -782,6 +806,13 @@ class MGXS: mgxs = DiffusionCoefficient(domain, domain_type, energy_groups) elif mgxs_type == 'nu-diffusion-coefficient': mgxs = DiffusionCoefficient(domain, domain_type, energy_groups, nu=True) + elif mgxs_type in ARBITRARY_VECTOR_TYPES: + # Then it is a reaction not covered by the above that is + # supported by the ArbitraryXS Class + mgxs = ArbitraryXS(mgxs_type, domain, domain_type, energy_groups) + elif mgxs_type in ARBITRARY_MATRIX_TYPES: + mgxs = ArbitraryMatrixXS(mgxs_type, domain, domain_type, + energy_groups) mgxs.by_nuclide = by_nuclide mgxs.name = name @@ -1139,6 +1170,119 @@ class MGXS: return xs + def get_flux(self, groups='all', subdomains='all', + order_groups='increasing', value='mean', + squeeze=True, **kwargs): + r"""Returns an array of the fluxes used to weight the MGXS. + + This method constructs a 2D NumPy array for the requested + weighting flux for one or more subdomains (1st dimension), and + energy groups (2nd dimension). + + Parameters + ---------- + groups : Iterable of Integral or 'all' + Energy groups of interest. Defaults to 'all'. + subdomains : Iterable of Integral or 'all' + Subdomain IDs of interest. Defaults to 'all'. + order_groups: {'increasing', 'decreasing'} + Return the cross section indexed according to increasing or + decreasing energy groups (decreasing or increasing energies). + Defaults to 'increasing'. + value : {'mean', 'std_dev', 'rel_err'} + A string for the type of value to return. Defaults to 'mean'. + squeeze : bool + A boolean representing whether to eliminate the extra dimensions + of the multi-dimensional array to be returned. Defaults to True. + + Returns + ------- + numpy.ndarray + A NumPy array of the flux indexed in the order + each group and subdomain is listed in the parameters. + + Raises + ------ + ValueError + When this method is called before the data is available from tally + data, or, when this is used on an MGXS type without a flux score. + + """ + + cv.check_value('value', value, ['mean', 'std_dev', 'rel_err']) + + filters = [] + filter_bins = [] + + # Construct a collection of the domain filter bins + if not isinstance(subdomains, str): + cv.check_iterable_type('subdomains', subdomains, Integral, + max_depth=3) + + filters.append(_DOMAIN_TO_FILTER[self.domain_type]) + subdomain_bins = [] + for subdomain in subdomains: + subdomain_bins.append(subdomain) + filter_bins.append(tuple(subdomain_bins)) + + # Construct list of energy group bounds tuples for all requested groups + if not isinstance(groups, str): + cv.check_iterable_type('groups', groups, Integral) + filters.append(openmc.EnergyFilter) + energy_bins = [] + for group in groups: + energy_bins.append( + (self.energy_groups.get_group_bounds(group),)) + filter_bins.append(tuple(energy_bins)) + + # Determine which flux to obtain + # Step through in order of usefulness + for key in ['flux', 'flux (tracklength)', 'flux (analog)']: + if key in self.tally_keys: + tally = self.tallies[key] + break + else: + msg = "MGXS of Type {} do not have an explicit weighting flux!" + raise ValueError(msg.format(self.__name__)) + + flux = tally.get_values(filters=filters, filter_bins=filter_bins, + nuclides=['total'], value=value) + + # Eliminate the trivial score dimension + flux = np.squeeze(flux, axis=len(flux.shape) - 1) + # Eliminate the trivial nuclide dimension + flux = np.squeeze(flux, axis=len(flux.shape) - 1) + flux = np.nan_to_num(flux) + + if groups == 'all': + num_groups = self.num_groups + else: + num_groups = len(groups) + + # Reshape tally data array with separate axes for domain and energy + # Accomodate the polar and azimuthal bins if needed + num_subdomains = int(flux.shape[0] / (num_groups * self.num_polar * + self.num_azimuthal)) + if self.num_polar > 1 or self.num_azimuthal > 1: + new_shape = (self.num_polar, self.num_azimuthal, num_subdomains, + num_groups) + else: + new_shape = (num_subdomains, num_groups) + new_shape += flux.shape[1:] + flux = np.reshape(flux, new_shape) + + # Reverse data if user requested increasing energy groups since + # tally data is stored in order of increasing energies + if order_groups == 'increasing': + flux = flux[..., ::-1] + + if squeeze: + # We want to squeeze out everything but the polar, azimuthal, + # and energy group data. + flux = self._squeeze_xs(flux) + + return flux + def get_condensed_xs(self, coarse_groups): """Construct an energy-condensed version of this cross section. @@ -2872,7 +3016,7 @@ class DiffusionCoefficient(TransportXS): \phi \rangle}{\langle \phi \rangle} \\ D = \frac{1}{3 \sigma_{tr}} \end{aligned} - + To incorporate the effect of scattering multiplication in the above relation, the `nu` parameter can be set to `True`. @@ -3057,7 +3201,7 @@ class DiffusionCoefficient(TransportXS): filter_bins=[('P1',)], squeeze=True) p1_tally._scores = ['scatter-1'] - + total = self.tallies['total'] / self.tallies['flux (tracklength)'] trans_corr = p1_tally / self.tallies['flux (analog)'] transport = (total - trans_corr) @@ -3066,7 +3210,7 @@ class DiffusionCoefficient(TransportXS): else: dif_coef = self.rxn_rate_tally - + flux_tally = condensed_xs.tallies['flux (tracklength)'] condensed_xs._tallies = OrderedDict() condensed_xs._tallies[self._rxn_type] = dif_coef @@ -3850,6 +3994,265 @@ class ScatterXS(MGXS): self._valid_estimators = ['analog'] +class ArbitraryXS(MGXS): + r"""A multi-group cross section for an arbitrary reaction type. + + This class can be used for both OpenMC input generation and tally data + post-processing to compute spatially-homogenized and energy-integrated + multi-group total cross sections for multi-group neutronics calculations. + At a minimum, one needs to set the :attr:`ArbitraryXS.energy_groups` and + :attr:`ArbitraryXS.domain` properties. Tallies for the flux and appropriate + reaction rates over the specified domain are generated automatically via the + :attr:`ArbitraryXS.tallies` property, which can then be appended to a + :class:`openmc.Tallies` instance. + + For post-processing, the :meth:`MGXS.load_from_statepoint` will pull in the + necessary data to compute multi-group cross sections from a + :class:`openmc.StatePoint` instance. The derived multi-group cross section + can then be obtained from the :attr:`ArbitraryXS.xs_tally` property. + + For a spatial domain :math:`V` and energy group :math:`[E_g,E_{g-1}]`, the + requested cross section is calculated as: + + .. math:: + + \frac{\int_{r \in V} dr \int_{4\pi} d\Omega \int_{E_g}^{E_{g-1}} dE \; + \sigma_X (r, E) \psi (r, E, \Omega)}{\int_{r \in V} dr \int_{4\pi} + d\Omega \int_{E_g}^{E_{g-1}} dE \; \psi (r, E, \Omega)} + + where :math:`\sigma_X` is the requested reaction type of interest. + + Parameters + ---------- + rxn_type : str + Reaction type (e.g., '(n,2n)', '(n,Xt)', etc.) + domain : openmc.Material or openmc.Cell or openmc.Universe or openmc.RegularMesh + The domain for spatial homogenization + domain_type : {'material', 'cell', 'distribcell', 'universe', 'mesh'} + The domain type for spatial homogenization + groups : openmc.mgxs.EnergyGroups + The energy group structure for energy condensation + by_nuclide : bool + If true, computes cross sections for each nuclide in domain + name : str, optional + Name of the multi-group cross section. Used as a label to identify + tallies in OpenMC 'tallies.xml' file. + num_polar : Integral, optional + Number of equi-width polar angle bins for angle discretization; + defaults to one bin + num_azimuthal : Integral, optional + Number of equi-width azimuthal angle bins for angle discretization; + defaults to one bin + + Attributes + ---------- + name : str, optional + Name of the multi-group cross section + rxn_type : str + Reaction type (e.g., '(n,2n)', '(n,Xt)', etc.) + by_nuclide : bool + If true, computes cross sections for each nuclide in domain + domain : openmc.Material or openmc.Cell or openmc.Universe or openmc.RegularMesh + Domain for spatial homogenization + domain_type : {'material', 'cell', 'distribcell', 'universe', 'mesh'} + Domain type for spatial homogenization + energy_groups : openmc.mgxs.EnergyGroups + Energy group structure for energy condensation + num_polar : Integral + Number of equi-width polar angle bins for angle discretization + num_azimuthal : Integral + Number of equi-width azimuthal angle bins for angle discretization + tally_trigger : openmc.Trigger + An (optional) tally precision trigger given to each tally used to + compute the cross section + scores : list of str + The scores in each tally used to compute the multi-group cross section + filters : list of openmc.Filter + The filters in each tally used to compute the multi-group cross section + tally_keys : list of str + The keys into the tallies dictionary for each tally used to compute + the multi-group cross section + estimator : {'tracklength', 'collision', 'analog'} + The tally estimator used to compute the multi-group cross section + tallies : collections.OrderedDict + OpenMC tallies needed to compute the multi-group cross section. The keys + are strings listed in the :attr:`TotalXS.tally_keys` property and values + are instances of :class:`openmc.Tally`. + rxn_rate_tally : openmc.Tally + Derived tally for the reaction rate tally used in the numerator to + compute the multi-group cross section. This attribute is None + unless the multi-group cross section has been computed. + xs_tally : openmc.Tally + Derived tally for the multi-group cross section. This attribute + is None unless the multi-group cross section has been computed. + num_subdomains : int + The number of subdomains is unity for 'material', 'cell' and 'universe' + domain types. This is equal to the number of cell instances + for 'distribcell' domain types (it is equal to unity prior to loading + tally data from a statepoint file). + num_nuclides : int + The number of nuclides for which the multi-group cross section is + being tracked. This is unity if the by_nuclide attribute is False. + nuclides : Iterable of str or 'sum' + The optional user-specified nuclides for which to compute cross + sections (e.g., 'U238', 'O16'). If by_nuclide is True but nuclides + are not specified by the user, all nuclides in the spatial domain + are included. This attribute is 'sum' if by_nuclide is false. + sparse : bool + Whether or not the MGXS' tallies use SciPy's LIL sparse matrix format + for compressed data storage + loaded_sp : bool + Whether or not a statepoint file has been loaded with tally data + derived : bool + Whether or not the MGXS is merged from one or more other MGXS + hdf5_key : str + The key used to index multi-group cross sections in an HDF5 data store + + """ + + def __init__(self, rxn_type, domain=None, domain_type=None, groups=None, + by_nuclide=False, name='', num_polar=1, num_azimuthal=1): + cv.check_value("rxn_type", rxn_type, ARBITRARY_VECTOR_TYPES) + super().__init__(domain, domain_type, groups, by_nuclide, name, + num_polar, num_azimuthal) + self._rxn_type = rxn_type + + +class ArbitraryMatrixXS(MatrixMGXS): + r"""A multi-group matrix cross section for an arbitrary reaction type. + + This class can be used for both OpenMC input generation and tally data + post-processing to compute spatially-homogenized and energy-integrated + multi-group cross sections for multi-group neutronics calculations. At a + minimum, one needs to set the :attr:`ArbitraryMatrixXS.energy_groups` and + :attr:`ArbitraryMatrixXS.domain` properties. Tallies for the flux and + appropriate reaction rates over the specified domain are generated + automatically via the :attr:`ArbitraryMatrixXS.tallies` property, which can + then be appended to a :class:`openmc.Tallies` instance. + + For post-processing, the :meth:`MGXS.load_from_statepoint` will pull in the + necessary data to compute multi-group cross sections from a + :class:`openmc.StatePoint` instance. The derived multi-group cross section + can then be obtained from the :attr:`ArbitraryMatrixXS.xs_tally` property. + + For a spatial domain :math:`V`, incoming energy group + :math:`[E_{g'},E_{g'-1}]`, and outgoing energy group :math:`[E_g,E_{g-1}]`, + the fission production is calculated as: + + .. math:: + + \begin{aligned} + \langle \sigma_{X,g'\rightarrow g} \phi \rangle &= \int_{r \in V} dr + \int_{4\pi} d\Omega' \int_{E_{g'}}^{E_{g'-1}} dE' \int_{E_g}^{E_{g-1}} dE + \; \chi(E) \sigma_X (r, E') \psi(r, E', \Omega')\\ + \langle \phi \rangle &= \int_{r \in V} dr \int_{4\pi} d\Omega + \int_{E_g}^{E_{g-1}} dE \; \psi (r, E, \Omega) \\ + \sigma_{X,g'\rightarrow g} &= \frac{\langle \sigma_{X,g'\rightarrow + g} \phi \rangle}{\langle \phi \rangle} + \end{aligned} + + where :math:`\sigma_X` is the requested reaction type of interest. + + Parameters + ---------- + rxn_type : str + Reaction type (e.g., '(n,2n)', '(n,nta)', etc.). Valid names have + neutrons as a product. + domain : openmc.Material or openmc.Cell or openmc.Universe or openmc.RegularMesh + The domain for spatial homogenization + domain_type : {'material', 'cell', 'distribcell', 'universe', 'mesh'} + The domain type for spatial homogenization + groups : openmc.mgxs.EnergyGroups + The energy group structure for energy condensation + by_nuclide : bool + If true, computes cross sections for each nuclide in domain + name : str, optional + Name of the multi-group cross section. Used as a label to identify + tallies in OpenMC 'tallies.xml' file. + num_polar : Integral, optional + Number of equi-width polar angle bins for angle discretization; + defaults to one bin + num_azimuthal : Integral, optional + Number of equi-width azimuthal angle bins for angle discretization; + defaults to one bin + + Attributes + ---------- + name : str, optional + Name of the multi-group cross section + rxn_type : str + Reaction type (e.g., 'total', 'nu-fission', etc.) + by_nuclide : bool + If true, computes cross sections for each nuclide in domain + domain : openmc.Material or openmc.Cell or openmc.Universe or openmc.RegularMesh + Domain for spatial homogenization + domain_type : {'material', 'cell', 'distribcell', 'universe', 'mesh'} + Domain type for spatial homogenization + energy_groups : openmc.mgxs.EnergyGroups + Energy group structure for energy condensation + num_polar : Integral + Number of equi-width polar angle bins for angle discretization + num_azimuthal : Integral + Number of equi-width azimuthal angle bins for angle discretization + tally_trigger : openmc.Trigger + An (optional) tally precision trigger given to each tally used to + compute the cross section + scores : list of str + The scores in each tally used to compute the multi-group cross section + filters : list of openmc.Filter + The filters in each tally used to compute the multi-group cross section + tally_keys : list of str + The keys into the tallies dictionary for each tally used to compute + the multi-group cross section + estimator : 'analog' + The tally estimator used to compute the multi-group cross section + tallies : collections.OrderedDict + OpenMC tallies needed to compute the multi-group cross section. The keys + are strings listed in the :attr:`NuFissionMatrixXS.tally_keys` + property and values are instances of :class:`openmc.Tally`. + rxn_rate_tally : openmc.Tally + Derived tally for the reaction rate tally used in the numerator to + compute the multi-group cross section. This attribute is None + unless the multi-group cross section has been computed. + xs_tally : openmc.Tally + Derived tally for the multi-group cross section. This attribute + is None unless the multi-group cross section has been computed. + num_subdomains : int + The number of subdomains is unity for 'material', 'cell' and 'universe' + domain types. This is equal to the number of cell instances + for 'distribcell' domain types (it is equal to unity prior to loading + tally data from a statepoint file). + num_nuclides : int + The number of nuclides for which the multi-group cross section is + being tracked. This is unity if the by_nuclide attribute is False. + nuclides : Iterable of str or 'sum' + The optional user-specified nuclides for which to compute cross + sections (e.g., 'U238', 'O16'). If by_nuclide is True but nuclides + are not specified by the user, all nuclides in the spatial domain + are included. This attribute is 'sum' if by_nuclide is false. + sparse : bool + Whether or not the MGXS' tallies use SciPy's LIL sparse matrix format + for compressed data storage + loaded_sp : bool + Whether or not a statepoint file has been loaded with tally data + derived : bool + Whether or not the MGXS is merged from one or more other MGXS + hdf5_key : str + The key used to index multi-group cross sections in an HDF5 data store + + """ + + def __init__(self, rxn_type, domain=None, domain_type=None, groups=None, + by_nuclide=False, name='', num_polar=1, + num_azimuthal=1): + cv.check_value("rxn_type", rxn_type, ARBITRARY_MATRIX_TYPES) + super().__init__(domain, domain_type, groups, by_nuclide, name, + num_polar, num_azimuthal) + self._rxn_type = rxn_type.split(" ")[0] + self._estimator = 'analog' + self._valid_estimators = ['analog'] + + class ScatterMatrixXS(MatrixMGXS): r"""A scattering matrix multi-group cross section with the cosine of the change-in-angle represented as one or more Legendre moments or a histogram. @@ -5633,8 +6036,8 @@ class Chi(MGXS): """ # Store whether or not the number density should be removed for microscopic - # values of this data; since this chi data is normalized to 1.0, the - # data should not be divided by the number density + # values of this data; since this chi data is normalized to 1.0, the + # data should not be divided by the number density _divide_by_density = False def __init__(self, domain=None, domain_type=None, groups=None, @@ -6554,7 +6957,7 @@ class MeshSurfaceMGXS(MGXS): surfaces = df.pop(col_key) df.insert(len(self.domain.dimension), col_key, surfaces) if len(self.domain.dimension) == 1: - df.sort_values(by=[(mesh_str, 'x'), (mesh_str, 'surf')] + df.sort_values(by=[(mesh_str, 'x'), (mesh_str, 'surf')] + columns, inplace=True) elif len(self.domain.dimension) == 2: df.sort_values(by=[(mesh_str, 'x'), (mesh_str, 'y'), @@ -6642,7 +7045,7 @@ class Current(MeshSurfaceMGXS): is None unless the multi-group cross section has been computed. num_subdomains : int The number of subdomains is equal to the number of mesh surfaces times - two to account for both the incoming and outgoing current from the + two to account for both the incoming and outgoing current from the mesh cell surfaces. num_nuclides : int Unused in MeshSurfaceMGXS diff --git a/openmc/model/surface_composite.py b/openmc/model/surface_composite.py index 9f9cd39c60..09a3c0170f 100644 --- a/openmc/model/surface_composite.py +++ b/openmc/model/surface_composite.py @@ -163,7 +163,7 @@ class RectangularParallelepiped(CompositeSurface): return +self.xmin & -self.xmax & +self.ymin & -self.ymax & +self.zmin & -self.zmax def __pos__(self): - return -self.xmin | +self.ymax | -self.ymin | +self.ymax | -self.zmin | +self.zmax + return -self.xmin | +self.xmax | -self.ymin | +self.ymax | -self.zmin | +self.zmax class XConeOneSided(CompositeSurface): diff --git a/openmc/plotter.py b/openmc/plotter.py index dfa6a13ba1..c6f069aa62 100644 --- a/openmc/plotter.py +++ b/openmc/plotter.py @@ -309,8 +309,9 @@ def _calculate_cexs_nuclide(this, types, temperature=294., sab_name=None, Nuclide object to source data from types : Iterable of str or Integral The type of cross sections to calculate; values can either be those - in openmc.PLOT_TYPES or integers which correspond to reaction - channel (MT) numbers. + in openmc.PLOT_TYPES or keys from openmc.data.REACTION_MT which + correspond to a reaction description e.g '(n,2n)' or integers which + correspond to reaction channel (MT) numbers. temperature : float, optional Temperature in Kelvin to plot. If not specified, a default temperature of 294K will be plotted. Note that the nearest @@ -404,7 +405,15 @@ def _calculate_cexs_nuclide(this, types, temperature=294., sab_name=None, ops.append((np.add,) * (len(tmp_mts) - 2) + (np.multiply,)) else: ops.append((np.add,) * (len(tmp_mts) - 1)) - else: + elif line in openmc.data.REACTION_MT: + mt_number = openmc.data.REACTION_MT[line] + cv.check_type('MT in types', mt_number, Integral) + cv.check_greater_than('MT in types', mt_number, 0) + tmp_mts = nuc.get_reaction_components(mt_number) + mts.append(tmp_mts) + ops.append((np.add,) * (len(tmp_mts) - 1)) + yields.append(False) + elif isinstance(line, int): # Not a built-in type, we have to parse it ourselves cv.check_type('MT in types', line, Integral) cv.check_greater_than('MT in types', line, 0) @@ -412,6 +421,8 @@ def _calculate_cexs_nuclide(this, types, temperature=294., sab_name=None, mts.append(tmp_mts) ops.append((np.add,) * (len(tmp_mts) - 1)) yields.append(False) + else: + raise TypeError("Invalid type", line) for i, mt_set in enumerate(mts): # Get the reaction xs data from the nuclide diff --git a/openmc/settings.py b/openmc/settings.py index 16d4e9578d..4825432a8e 100644 --- a/openmc/settings.py +++ b/openmc/settings.py @@ -3,6 +3,7 @@ from enum import Enum from pathlib import Path from numbers import Real, Integral from xml.etree import ElementTree as ET +from math import ceil import openmc.checkvalue as cv from . import VolumeCalculation, Source, RegularMesh @@ -58,7 +59,7 @@ class Settings: Set whether the calculation should be continuous-energy or multi-group. entropy_mesh : openmc.RegularMesh Mesh to be used to calculate Shannon entropy. If the mesh dimensions are - not specified. OpenMC assigns a mesh such that 20 source sites per mesh + not specified, OpenMC assigns a mesh such that 20 source sites per mesh cell are to be expected on average. event_based : bool Indicate whether to use event-based parallelism instead of the default @@ -927,6 +928,16 @@ class Settings: def _create_entropy_mesh_subelement(self, root): if self.entropy_mesh is not None: + # use default heuristic for entropy mesh if not set by user + if self.entropy_mesh.dimension is None: + if self.particles is None: + raise RuntimeError("Number of particles must be set in order to " \ + "use entropy mesh dimension heuristic") + else: + n = ceil((self.particles / 20.0)**(1.0 / 3.0)) + d = len(self.entropy_mesh.lower_left) + self.entropy_mesh.dimension = (n,)*d + # See if a element already exists -- if not, add it path = "./mesh[@id='{}']".format(self.entropy_mesh.id) if root.find(path) is None: diff --git a/openmc/source.py b/openmc/source.py index 22952b4a59..b5b53167c5 100644 --- a/openmc/source.py +++ b/openmc/source.py @@ -1,6 +1,10 @@ +from enum import Enum from numbers import Real from xml.etree import ElementTree as ET +import numpy as np +import h5py + import openmc.checkvalue as cv from openmc.stats.multivariate import UnitSphere, Spatial from openmc.stats.univariate import Univariate @@ -226,3 +230,89 @@ class Source: source.energy = Univariate.from_xml_element(energy) return source + + +class ParticleType(Enum): + NEUTRON = 0 + PHOTON = 1 + ELECTRON = 2 + POSITRON = 3 + + +class SourceParticle: + """Source particle + + This class can be used to create source particles that can be written to a + file and used by OpenMC + + Parameters + ---------- + r : iterable of float + Position of particle in Cartesian coordinates + u : iterable of float + Directional cosines + E : float + Energy of particle in [eV] + wgt : float + Weight of the particle + delayed_group : int + Delayed group particle was created in (neutrons only) + particle : ParticleType + Type of the particle + + """ + def __init__(self, r=(0., 0., 0.), u=(0., 0., 1.), E=1.0e6, wgt=1.0, + delayed_group=0, particle=ParticleType.NEUTRON): + self.r = tuple(r) + self.u = tuple(u) + self.E = float(E) + self.wgt = float(wgt) + self.delayed_group = delayed_group + self.particle = particle + + def to_tuple(self): + """Return source particle attributes as a tuple + + Returns + ------- + tuple + Source particle attributes + + """ + return (self.r, self.u, self.E, self.wgt, + self.delayed_group, self.particle.value) + + +def write_source_file(source_particles, filename, **kwargs): + """Write a source file using a collection of source particles + + Parameters + ---------- + source_particles : iterable of SourceParticle + Source particles to write to file + filename : str or path-like + Path to source file to write + **kwargs + Keyword arguments to pass to :class:`h5py.File` + + """ + # Create compound datatype for source particles + pos_dtype = np.dtype([('x', ' indexmap; int use_all_threads; +RegularMesh* mesh; + +std::vector egrid; + +double norm; + } // namespace cmfd +//============================================================================== +// GET_CMFD_ENERGY_BIN returns the energy bin for a source site energy +//============================================================================== + +int get_cmfd_energy_bin(const double E) +{ + // Check if energy is out of grid bounds + if (E < cmfd::egrid[0]) { + // throw warning message + warning("Detected source point below energy grid"); + return 0; + } else if (E >= cmfd::egrid[cmfd::ng]) { + // throw warning message + warning("Detected source point above energy grid"); + return cmfd::ng - 1; + } else { + // Iterate through energy grid to find matching bin + for (int g = 0; g < cmfd::ng; g++) { + if (E >= cmfd::egrid[g] && E < cmfd::egrid[g+1]) { + return g; + } + } + } + // Return -1 by default + return -1; +} + +//============================================================================== +// COUNT_BANK_SITES bins fission sites according to CMFD mesh and energy +//============================================================================== + +xt::xtensor count_bank_sites(xt::xtensor& bins, bool* outside) +{ + // Determine shape of array for counts + std::size_t cnt_size = cmfd::nx * cmfd::ny * cmfd::nz * cmfd::ng; + std::vector cnt_shape = {cnt_size}; + + // Create array of zeros + xt::xarray cnt {cnt_shape, 0.0}; + bool outside_ = false; + + auto bank_size = simulation::source_bank.size(); + for (int i = 0; i < bank_size; i++) { + const auto& site = simulation::source_bank[i]; + + // determine scoring bin for CMFD mesh + int mesh_bin = cmfd::mesh->get_bin(site.r); + + // if outside mesh, skip particle + if (mesh_bin < 0) { + outside_ = true; + continue; + } + + // determine scoring bin for CMFD energy + int energy_bin = get_cmfd_energy_bin(site.E); + + // add to appropriate bin + cnt(mesh_bin*cmfd::ng+energy_bin) += site.wgt; + + // store bin index which is used again when updating weights + bins[i] = mesh_bin*cmfd::ng+energy_bin; + } + + // 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{}.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 + MPI_Reduce(&outside_, outside, 1, MPI_C_BOOL, MPI_LOR, 0, mpi::intracomm); + +#else + std::copy(cnt.data(), cnt.data() + total, cnt_reduced); + *outside = outside_; +#endif + + // Adapt reduced values in array back into an xarray + auto arr = xt::adapt(cnt_reduced, total, xt::acquire_ownership(), cnt_shape); + xt::xarray counts = arr; + + return counts; +} + +//============================================================================== +// OPENMC_CMFD_REWEIGHT performs reweighting of particles in source bank +//============================================================================== + +extern "C" +void openmc_cmfd_reweight(const bool feedback, const double* cmfd_src) +{ + // Get size of source bank and cmfd_src + auto bank_size = simulation::source_bank.size(); + std::size_t src_size = cmfd::nx * cmfd::ny * cmfd::nz * cmfd::ng; + + // count bank sites for CMFD mesh, store bins in bank_bins for reweighting + xt::xtensor bank_bins({bank_size}, 0); + bool sites_outside; + xt::xtensor sourcecounts = count_bank_sites(bank_bins, + &sites_outside); + + // Compute CMFD weightfactors + xt::xtensor weightfactors = xt::xtensor({src_size}, 1.); + if (mpi::master) { + if (sites_outside) { + fatal_error("Source sites outside of the CMFD mesh"); + } + + double norm = xt::sum(sourcecounts)()/cmfd::norm; + for (int i = 0; i < src_size; i++) { + if (sourcecounts[i] > 0 && cmfd_src[i] > 0) { + weightfactors[i] = cmfd_src[i] * norm / sourcecounts[i]; + } + } + } + + if (!feedback) return; + +#ifdef OPENMC_MPI + // Send weightfactors to all processors + MPI_Bcast(weightfactors.data(), src_size, MPI_DOUBLE, 0, mpi::intracomm); +#endif + + // Iterate through fission bank and update particle weights + for (int64_t i = 0; i < bank_size; i++) { + auto& site = simulation::source_bank[i]; + site.wgt *= weightfactors(bank_bins(i)); + } +} + +//============================================================================== +// OPENMC_INITIALIZE_MESH_EGRID sets the mesh and energy grid for CMFD reweight +//============================================================================== + +extern "C" +void openmc_initialize_mesh_egrid(const int meshtally_id, const int* cmfd_indices, + const double norm) +{ + // Make sure all CMFD memory is freed + free_memory_cmfd(); + + // Set CMFD indices + cmfd::nx = cmfd_indices[0]; + cmfd::ny = cmfd_indices[1]; + cmfd::nz = cmfd_indices[2]; + cmfd::ng = cmfd_indices[3]; + + // Set CMFD reweight properties + cmfd::norm = norm; + + // Find index corresponding to tally id + int32_t tally_index; + openmc_get_tally_index(meshtally_id, &tally_index); + + // Get filters assocaited with tally + const auto& tally_filters = model::tallies[tally_index]->filters(); + + // Get mesh filter index + auto meshfilter_index = tally_filters[0]; + + // Store energy filter index if defined, otherwise set to -1 + auto energy_index = (tally_filters.size() == 2) ? tally_filters[1] : -1; + + // Get mesh index from mesh filter index + int32_t mesh_index; + openmc_mesh_filter_get_mesh(meshfilter_index, &mesh_index); + + // Get mesh from mesh index + cmfd::mesh = get_regular_mesh(mesh_index); + + // Get energy bins from energy index, otherwise use default + if (energy_index != -1) { + auto efilt_base = model::tally_filters[energy_index].get(); + auto* efilt = dynamic_cast(efilt_base); + cmfd::egrid = efilt->bins(); + } else { + cmfd::egrid = {0.0, INFTY}; + } +} + //============================================================================== // MATRIX_TO_INDICES converts a matrix index to spatial and group // indices @@ -309,12 +507,9 @@ int cmfd_linsolver_ng(const double* A_data, const double* b, double* x, extern "C" void openmc_initialize_linsolver(const int* indptr, int len_indptr, const int* indices, int n_elements, int dim, - double spectral, const int* cmfd_indices, - const int* map, bool use_all_threads) + double spectral, const int* map, + bool use_all_threads) { - // Make sure vectors are empty - free_memory_cmfd(); - // Store elements of indptr for (int i = 0; i < len_indptr; i++) cmfd::indptr.push_back(indptr[i]); @@ -327,15 +522,8 @@ void openmc_initialize_linsolver(const int* indptr, int len_indptr, cmfd::dim = dim; cmfd::spectral = spectral; - // Set number of groups - cmfd::ng = cmfd_indices[3]; - - // Set problem dimensions and indexmap if 1 or 2 group problem + // Set indexmap if 1 or 2 group problem if (cmfd::ng == 1 || cmfd::ng == 2) { - cmfd::nx = cmfd_indices[0]; - cmfd::ny = cmfd_indices[1]; - cmfd::nz = cmfd_indices[2]; - // Resize indexmap and set its elements cmfd::indexmap.resize({static_cast(dim), 3}); set_indexmap(map); @@ -366,10 +554,16 @@ int openmc_run_linsolver(const double* A_data, const double* b, double* x, void free_memory_cmfd() { + // Clear std::vectors cmfd::indptr.clear(); cmfd::indices.clear(); - // Resize indexmap to be an empty array + cmfd::egrid.clear(); + + // Resize xtensors to be empty cmfd::indexmap.resize({0}); + + // Set pointers to null + cmfd::mesh = nullptr; } } // namespace openmc diff --git a/src/material.cpp b/src/material.cpp index 1d4e18108e..89d5d5add2 100644 --- a/src/material.cpp +++ b/src/material.cpp @@ -149,7 +149,7 @@ Material::Material(pugi::xml_node node) // Set density for macroscopic data if (units == "macro") { - densities.push_back(1.0); + densities.push_back(density_); } else { fatal_error("Units can only be macro for macroscopic data " + name); } @@ -169,7 +169,7 @@ Material::Material(pugi::xml_node node) // Check if no atom/weight percents were specified or if both atom and // weight percents were specified if (units == "macro") { - densities.push_back(1.0); + densities.push_back(density_); } else { bool has_ao = check_for_node(node_nuc, "ao"); bool has_wo = check_for_node(node_nuc, "wo"); @@ -211,10 +211,12 @@ Material::Material(pugi::xml_node node) for (int i = 0; i < n; ++i) { const auto& name {names[i]}; - // Check that this nuclide is listed in the cross_sections.xml file + // Check that this nuclide is listed in the nuclear data library + // (cross_sections.xml for CE and the MGXS HDF5 for MG) LibraryKey key {Library::Type::neutron, name}; if (data::library_map.find(key) == data::library_map.end()) { - fatal_error("Could not find nuclide " + name + " in cross_sections.xml."); + fatal_error("Could not find nuclide " + name + " in the " + "nuclear data library."); } // If this nuclide hasn't been encountered yet, we need to add its name diff --git a/src/mesh.cpp b/src/mesh.cpp index 54d99250c8..a5409f05a0 100644 --- a/src/mesh.cpp +++ b/src/mesh.cpp @@ -102,6 +102,421 @@ StructuredMesh::bin_label(int bin) const { } } +void StructuredMesh::get_indices(Position r, int* ijk, bool* in_mesh) const +{ + *in_mesh = true; + for (int i = 0; i < n_dimension_; ++i) { + ijk[i] = get_index_in_direction(r[i], i); + + if (ijk[i] < 1 || ijk[i] > shape_[i]) *in_mesh = false; + } +} + +int StructuredMesh::get_bin_from_indices(const int* ijk) const +{ + switch (n_dimension_) { + case 1: + return ijk[0] - 1; + case 2: + return (ijk[1] - 1)*shape_[0] + ijk[0] - 1; + case 3: + return ((ijk[2] - 1)*shape_[1] + (ijk[1] - 1))*shape_[0] + ijk[0] - 1; + default: + throw std::runtime_error{"Invalid number of mesh dimensions"}; + } +} + +void StructuredMesh::get_indices_from_bin(int bin, int* ijk) const +{ + if (n_dimension_ == 1) { + ijk[0] = bin + 1; + } else if (n_dimension_ == 2) { + ijk[0] = bin % shape_[0] + 1; + ijk[1] = bin / shape_[0] + 1; + } else if (n_dimension_ == 3) { + ijk[0] = bin % shape_[0] + 1; + ijk[1] = (bin % (shape_[0] * shape_[1])) / shape_[0] + 1; + ijk[2] = bin / (shape_[0] * shape_[1]) + 1; + } +} + +int StructuredMesh::get_bin(Position r) const +{ + // Determine indices + std::vector ijk(n_dimension_); + bool in_mesh; + get_indices(r, ijk.data(), &in_mesh); + if (!in_mesh) return -1; + + // Convert indices to bin + return get_bin_from_indices(ijk.data()); +} + +int StructuredMesh::n_bins() const +{ + return xt::prod(shape_)(); +} + +int StructuredMesh::n_surface_bins() const +{ + return 4 * n_dimension_ * n_bins(); +} + +bool StructuredMesh::intersects(Position& r0, Position r1, int* ijk) const +{ + switch(n_dimension_) { + case 1: + return intersects_1d(r0, r1, ijk); + case 2: + return intersects_2d(r0, r1, ijk); + case 3: + return intersects_3d(r0, r1, ijk); + default: + throw std::runtime_error{"Invalid number of mesh dimensions."}; + } +} + +bool StructuredMesh::intersects_1d(Position& r0, Position r1, int* ijk) const +{ + // Copy coordinates of starting point + double x0 = r0.x; + double y0 = r0.y; + double z0 = r0.z; + + // Copy coordinates of ending point + double x1 = r1.x; + double y1 = r1.y; + double z1 = r1.z; + + // Copy coordinates of mesh lower_left and upper_right + double xm0 = lower_left_[0]; + double xm1 = upper_right_[0]; + + double min_dist = INFTY; + + // Check if line intersects left surface -- calculate the intersection point + // (y,z) + if ((x0 < xm0 && x1 > xm0) || (x0 > xm0 && x1 < xm0)) { + double yi = y0 + (xm0 - x0) * (y1 - y0) / (x1 - x0); + double zi = z0 + (xm0 - x0) * (z1 - z0) / (x1 - x0); + if (check_intersection_point(xm0, x0, yi, yi, zi, zi, r0, min_dist)) { + ijk[0] = 1; + } + } + + // Check if line intersects right surface -- calculate the intersection point + // (y,z) + if ((x0 < xm1 && x1 > xm1) || (x0 > xm1 && x1 < xm1)) { + double yi = y0 + (xm1 - x0) * (y1 - y0) / (x1 - x0); + double zi = z0 + (xm1 - x0) * (z1 - z0) / (x1 - x0); + if (check_intersection_point(xm1, x0, yi, yi, zi, zi, r0, min_dist)) { + ijk[0] = shape_[0]; + } + } + + return min_dist < INFTY; +} + +bool StructuredMesh::intersects_2d(Position& r0, Position r1, int* ijk) const +{ + // Copy coordinates of starting point + double x0 = r0.x; + double y0 = r0.y; + double z0 = r0.z; + + // Copy coordinates of ending point + double x1 = r1.x; + double y1 = r1.y; + double z1 = r1.z; + + // Copy coordinates of mesh lower_left + double xm0 = lower_left_[0]; + double ym0 = lower_left_[1]; + + // Copy coordinates of mesh upper_right + double xm1 = upper_right_[0]; + double ym1 = upper_right_[1]; + + double min_dist = INFTY; + + // Check if line intersects left surface -- calculate the intersection point + // (y,z) + if ((x0 < xm0 && x1 > xm0) || (x0 > xm0 && x1 < xm0)) { + double yi = y0 + (xm0 - x0) * (y1 - y0) / (x1 - x0); + double zi = z0 + (xm0 - x0) * (z1 - z0) / (x1 - x0); + if (yi >= ym0 && yi < ym1) { + if (check_intersection_point(xm0, x0, yi, y0, zi, zi, r0, min_dist)) { + ijk[0] = 1; + ijk[1] = get_index_in_direction(yi, 1); + } + } + } + + // Check if line intersects back surface -- calculate the intersection point + // (x,z) + if ((y0 < ym0 && y1 > ym0) || (y0 > ym0 && y1 < ym0)) { + double xi = x0 + (ym0 - y0) * (x1 - x0) / (y1 - y0); + double zi = z0 + (ym0 - y0) * (z1 - z0) / (y1 - y0); + if (xi >= xm0 && xi < xm1) { + if (check_intersection_point(xi, x0, ym0, y0, zi, zi, r0, min_dist)) { + ijk[0] = get_index_in_direction(xi, 0); + ijk[1] = 1; + } + } + } + + // Check if line intersects right surface -- calculate the intersection point + // (y,z) + if ((x0 < xm1 && x1 > xm1) || (x0 > xm1 && x1 < xm1)) { + double yi = y0 + (xm1 - x0) * (y1 - y0) / (x1 - x0); + double zi = z0 + (xm1 - x0) * (z1 - z0) / (x1 - x0); + if (yi >= ym0 && yi < ym1) { + if (check_intersection_point(xm1, x0, yi, y0, zi, zi, r0, min_dist)) { + ijk[0] = shape_[0]; + ijk[1] = get_index_in_direction(yi, 1); + } + } + } + + // Check if line intersects front surface -- calculate the intersection point + // (x,z) + if ((y0 < ym1 && y1 > ym1) || (y0 > ym1 && y1 < ym1)) { + double xi = x0 + (ym1 - y0) * (x1 - x0) / (y1 - y0); + double zi = z0 + (ym1 - y0) * (z1 - z0) / (y1 - y0); + if (xi >= xm0 && xi < xm1) { + if (check_intersection_point(xi, x0, ym1, y0, zi, zi, r0, min_dist)) { + ijk[0] = get_index_in_direction(xi, 0); + ijk[1] = shape_[1]; + } + } + } + + return min_dist < INFTY; +} + +bool StructuredMesh::intersects_3d(Position& r0, Position r1, int* ijk) const +{ + // Copy coordinates of starting point + double x0 = r0.x; + double y0 = r0.y; + double z0 = r0.z; + + // Copy coordinates of ending point + double x1 = r1.x; + double y1 = r1.y; + double z1 = r1.z; + + // Copy coordinates of mesh lower_left + double xm0 = lower_left_[0]; + double ym0 = lower_left_[1]; + double zm0 = lower_left_[2]; + + // Copy coordinates of mesh upper_right + double xm1 = upper_right_[0]; + double ym1 = upper_right_[1]; + double zm1 = upper_right_[2]; + + double min_dist = INFTY; + + // Check if line intersects left surface -- calculate the intersection point + // (y,z) + if ((x0 < xm0 && x1 > xm0) || (x0 > xm0 && x1 < xm0)) { + double yi = y0 + (xm0 - x0) * (y1 - y0) / (x1 - x0); + double zi = z0 + (xm0 - x0) * (z1 - z0) / (x1 - x0); + if (yi >= ym0 && yi < ym1 && zi >= zm0 && zi < zm1) { + if (check_intersection_point(xm0, x0, yi, y0, zi, z0, r0, min_dist)) { + ijk[0] = 1; + ijk[1] = get_index_in_direction(yi, 1); + ijk[2] = get_index_in_direction(zi, 2); + } + } + } + + // Check if line intersects back surface -- calculate the intersection point + // (x,z) + if ((y0 < ym0 && y1 > ym0) || (y0 > ym0 && y1 < ym0)) { + double xi = x0 + (ym0 - y0) * (x1 - x0) / (y1 - y0); + double zi = z0 + (ym0 - y0) * (z1 - z0) / (y1 - y0); + if (xi >= xm0 && xi < xm1 && zi >= zm0 && zi < zm1) { + if (check_intersection_point(xi, x0, ym0, y0, zi, z0, r0, min_dist)) { + ijk[0] = get_index_in_direction(xi, 0); + ijk[1] = 1; + ijk[2] = get_index_in_direction(zi, 2); + } + } + } + + // Check if line intersects bottom surface -- calculate the intersection + // point (x,y) + if ((z0 < zm0 && z1 > zm0) || (z0 > zm0 && z1 < zm0)) { + double xi = x0 + (zm0 - z0) * (x1 - x0) / (z1 - z0); + double yi = y0 + (zm0 - z0) * (y1 - y0) / (z1 - z0); + if (xi >= xm0 && xi < xm1 && yi >= ym0 && yi < ym1) { + if (check_intersection_point(xi, x0, yi, y0, zm0, z0, r0, min_dist)) { + ijk[0] = get_index_in_direction(xi, 0); + ijk[1] = get_index_in_direction(yi, 1); + ijk[2] = 1; + } + } + } + + // Check if line intersects right surface -- calculate the intersection point + // (y,z) + if ((x0 < xm1 && x1 > xm1) || (x0 > xm1 && x1 < xm1)) { + double yi = y0 + (xm1 - x0) * (y1 - y0) / (x1 - x0); + double zi = z0 + (xm1 - x0) * (z1 - z0) / (x1 - x0); + if (yi >= ym0 && yi < ym1 && zi >= zm0 && zi < zm1) { + if (check_intersection_point(xm1, x0, yi, y0, zi, z0, r0, min_dist)) { + ijk[0] = shape_[0]; + ijk[1] = get_index_in_direction(yi, 1); + ijk[2] = get_index_in_direction(zi, 2); + } + } + } + + // Check if line intersects front surface -- calculate the intersection point + // (x,z) + if ((y0 < ym1 && y1 > ym1) || (y0 > ym1 && y1 < ym1)) { + double xi = x0 + (ym1 - y0) * (x1 - x0) / (y1 - y0); + double zi = z0 + (ym1 - y0) * (z1 - z0) / (y1 - y0); + if (xi >= xm0 && xi < xm1 && zi >= zm0 && zi < zm1) { + if (check_intersection_point(xi, x0, ym1, y0, zi, z0, r0, min_dist)) { + ijk[0] = get_index_in_direction(xi, 0); + ijk[1] = shape_[1]; + ijk[2] = get_index_in_direction(zi, 2); + } + } + } + + // Check if line intersects top surface -- calculate the intersection point + // (x,y) + if ((z0 < zm1 && z1 > zm1) || (z0 > zm1 && z1 < zm1)) { + double xi = x0 + (zm1 - z0) * (x1 - x0) / (z1 - z0); + double yi = y0 + (zm1 - z0) * (y1 - y0) / (z1 - z0); + if (xi >= xm0 && xi < xm1 && yi >= ym0 && yi < ym1) { + if (check_intersection_point(xi, x0, yi, y0, zm1, z0, r0, min_dist)) { + ijk[0] = get_index_in_direction(xi, 0); + ijk[1] = get_index_in_direction(yi, 1); + ijk[2] = shape_[2]; + } + } + } + + return min_dist < INFTY; +} + +void StructuredMesh::bins_crossed(const Particle& p, std::vector& bins, + std::vector& lengths) const +{ + // ======================================================================== + // Determine where the track intersects the mesh and if it intersects at all. + + // Copy the starting and ending coordinates of the particle. + Position last_r {p.r_last_}; + Position r {p.r()}; + Direction u {p.u()}; + + // Compute the length of the entire track. + double total_distance = (r - last_r).norm(); + + // While determining if this track intersects the mesh, offset the starting + // and ending coords by a bit. This avoid finite-precision errors that can + // occur when the mesh surfaces coincide with lattice or geometric surfaces. + Position r0 = last_r + TINY_BIT*u; + Position r1 = r - TINY_BIT*u; + + // Determine the mesh indices for the starting and ending coords. Here, we + // use arrays for ijk0 and ijk1 instead of std::vector because we obtain a + // small performance improvement by forcing this data to live on the stack, + // rather than on the heap. We know the maximum length is 3, and by + // ensuring that all loops are only indexed up to n_dimension, we will not + // access any non-initialized values. The same concept is used throughout. + int n = n_dimension_; + int ijk0[3], ijk1[3]; + bool start_in_mesh; + get_indices(r0, ijk0, &start_in_mesh); + bool end_in_mesh; + get_indices(r1, ijk1, &end_in_mesh); + + // Reset coordinates and check for a mesh intersection if necessary. + if (start_in_mesh) { + // The initial coords lie in the mesh, use those coords for tallying. + r0 = last_r; + } else { + // The initial coords do not lie in the mesh. Check to see if the particle + // eventually intersects the mesh and compute the relevant coords and + // indices. + if (!intersects(r0, r1, ijk0)) return; + } + r1 = r; + + // The TINY_BIT offsets above mean that the preceding logic cannot always find + // the correct ijk0 and ijk1 indices. For tracks shorter than 2*TINY_BIT, just + // assume the track lies in only one mesh bin. These tracks are very short so + // any error caused by this assumption will be small. It is important that + // ijk0 values are used rather than ijk1 because the previous logic guarantees + // ijk0 is a valid mesh bin. + if (total_distance < 2*TINY_BIT) { + for (int i = 0; i < n; ++i) ijk1[i] = ijk0[i]; + } + + // ======================================================================== + // Find which mesh cells are traversed and the length of each traversal. + + while (true) { + if (std::equal(ijk0, ijk0 + n, ijk1)) { + // The track ends in this cell. Use the particle end location rather + // than the mesh surface and stop iterating. + double distance = (r1 - r0).norm(); + bins.push_back(get_bin_from_indices(ijk0)); + lengths.push_back(distance / total_distance); + break; + } + + // The track exits this cell. Determine the distance to each mesh surface. + double d[3]; + for (int k = 0; k < n; ++k) { + if (std::fabs(u[k]) < FP_PRECISION) { + d[k] = INFTY; + } else if (u[k] > 0) { + double xyz_cross = positive_grid_boundary(ijk0, k); + d[k] = (xyz_cross - r0[k]) / u[k]; + } else { + double xyz_cross = negative_grid_boundary(ijk0, k); + d[k] = (xyz_cross - r0[k]) / u[k]; + } + } + + // Pick the closest mesh surface and append this traversal to the output. + auto j = std::min_element(d, d + n) - d; + double distance = d[j]; + bins.push_back(get_bin_from_indices(ijk0)); + lengths.push_back(distance / total_distance); + + // Translate to the oncoming mesh surface. + r0 += distance * u; + + // Increment the indices into the next mesh cell. + if (u[j] > 0.0) { + ++ijk0[j]; + } else { + --ijk0[j]; + } + + // If the next indices are invalid, then the track has left the mesh and + // we are done. + bool in_mesh = true; + for (int i = 0; i < n; ++i) { + if (ijk0[i] < 1 || ijk0[i] > shape_[i]) { + in_mesh = false; + break; + } + } + if (!in_mesh) break; + } +} + + //============================================================================== // RegularMesh implementation //============================================================================== @@ -110,18 +525,21 @@ RegularMesh::RegularMesh(pugi::xml_node node) : StructuredMesh {node} { // Determine number of dimensions for mesh - if (check_for_node(node, "dimension")) { - shape_ = get_node_xarray(node, "dimension"); - int n = n_dimension_ = shape_.size(); - if (n != 1 && n != 2 && n != 3) { - fatal_error("Mesh must be one, two, or three dimensions."); - } + if (!check_for_node(node, "dimension")) { + fatal_error("Must specify on a regular mesh."); + } - // Check that dimensions are all greater than zero - if (xt::any(shape_ <= 0)) { - fatal_error("All entries on the element for a tally " - "mesh must be positive."); - } + + shape_ = get_node_xarray(node, "dimension"); + int n = n_dimension_ = shape_.size(); + if (n != 1 && n != 2 && n != 3) { + fatal_error("Mesh must be one, two, or three dimensions."); + } + + // Check that dimensions are all greater than zero + if (xt::any(shape_ <= 0)) { + fatal_error("All entries on the element for a tally " + "mesh must be positive."); } // Check for lower-left coordinates @@ -132,6 +550,12 @@ RegularMesh::RegularMesh(pugi::xml_node node) fatal_error("Must specify on a mesh."); } + // Make sure lower_left and dimension match + if (shape_.size() != lower_left_.size()) { + fatal_error("Number of entries on must be the same " + "as the number of entries on ."); + } + if (check_for_node(node, "width")) { // Make sure both upper-right or width were specified if (check_for_node(node, "upper_right")) { @@ -172,436 +596,28 @@ RegularMesh::RegularMesh(pugi::xml_node node) } // Set width - if (shape_.size() > 0) { - width_ = xt::eval((upper_right_ - lower_left_) / shape_); - } + width_ = xt::eval((upper_right_ - lower_left_) / shape_); } else { fatal_error("Must specify either and on a mesh."); } - // Make sure lower_left and dimension match - if (shape_.size() > 0) { - if (shape_.size() != lower_left_.size()) { - fatal_error("Number of entries on must be the same " - "as the number of entries on ."); - } - - // Set volume fraction - volume_frac_ = 1.0/xt::prod(shape_)(); - } + // Set volume fraction + volume_frac_ = 1.0/xt::prod(shape_)(); } -int RegularMesh::get_bin(Position r) const +int RegularMesh::get_index_in_direction(double r, int i) const { - // Determine indices - std::vector ijk(n_dimension_); - bool in_mesh; - get_indices(r, ijk.data(), &in_mesh); - if (!in_mesh) return -1; - - // Convert indices to bin - return get_bin_from_indices(ijk.data()); + return std::ceil((r - lower_left_[i]) / width_[i]); } -int RegularMesh::get_bin_from_indices(const int* ijk) const +double RegularMesh::positive_grid_boundary(int* ijk, int i) const { - switch (n_dimension_) { - case 1: - return ijk[0] - 1; - case 2: - return (ijk[1] - 1)*shape_[0] + ijk[0] - 1; - case 3: - return ((ijk[2] - 1)*shape_[1] + (ijk[1] - 1))*shape_[0] + ijk[0] - 1; - default: - throw std::runtime_error{"Invalid number of mesh dimensions"}; - } + return lower_left_[i] + ijk[i] * width_[i]; } -void RegularMesh::get_indices(Position r, int* ijk, bool* in_mesh) const +double RegularMesh::negative_grid_boundary(int* ijk, int i) const { - // Find particle in mesh - *in_mesh = true; - for (int i = 0; i < n_dimension_; ++i) { - ijk[i] = std::ceil((r[i] - lower_left_[i]) / width_[i]); - - // Check if indices are within bounds - if (ijk[i] < 1 || ijk[i] > shape_[i]) *in_mesh = false; - } -} - -void RegularMesh::get_indices_from_bin(int bin, int* ijk) const -{ - if (n_dimension_ == 1) { - ijk[0] = bin + 1; - } else if (n_dimension_ == 2) { - ijk[0] = bin % shape_[0] + 1; - ijk[1] = bin / shape_[0] + 1; - } else if (n_dimension_ == 3) { - ijk[0] = bin % shape_[0] + 1; - ijk[1] = (bin % (shape_[0] * shape_[1])) / shape_[0] + 1; - ijk[2] = bin / (shape_[0] * shape_[1]) + 1; - } -} - -int RegularMesh::n_bins() const -{ - int n_bins = 1; - for (auto dim : shape_) n_bins *= dim; - return n_bins; -} - -int RegularMesh::n_surface_bins() const -{ - return 4 * n_dimension_ * n_bins(); -} - -bool RegularMesh::intersects(Position& r0, Position r1, int* ijk) const -{ - switch(n_dimension_) { - case 1: - return intersects_1d(r0, r1, ijk); - case 2: - return intersects_2d(r0, r1, ijk); - case 3: - return intersects_3d(r0, r1, ijk); - default: - throw std::runtime_error{"Invalid number of mesh dimensions."}; - } -} - -bool RegularMesh::intersects_1d(Position& r0, Position r1, int* ijk) const -{ - // Copy coordinates of starting point - double x0 = r0.x; - double y0 = r0.y; - double z0 = r0.z; - - // Copy coordinates of ending point - double x1 = r1.x; - double y1 = r1.y; - double z1 = r1.z; - - // Copy coordinates of mesh lower_left and upper_right - double xm0 = lower_left_[0]; - double xm1 = upper_right_[0]; - - double min_dist = INFTY; - - // Check if line intersects left surface -- calculate the intersection point - // (y,z) - if ((x0 < xm0 && x1 > xm0) || (x0 > xm0 && x1 < xm0)) { - double yi = y0 + (xm0 - x0) * (y1 - y0) / (x1 - x0); - double zi = z0 + (xm0 - x0) * (z1 - z0) / (x1 - x0); - if (check_intersection_point(xm0, x0, yi, yi, zi, zi, r0, min_dist)) { - ijk[0] = 1; - } - } - - // Check if line intersects right surface -- calculate the intersection point - // (y,z) - if ((x0 < xm1 && x1 > xm1) || (x0 > xm1 && x1 < xm1)) { - double yi = y0 + (xm1 - x0) * (y1 - y0) / (x1 - x0); - double zi = z0 + (xm1 - x0) * (z1 - z0) / (x1 - x0); - if (check_intersection_point(xm1, x0, yi, yi, zi, zi, r0, min_dist)) { - ijk[0] = shape_[0]; - } - } - - return min_dist < INFTY; -} - -bool RegularMesh::intersects_2d(Position& r0, Position r1, int* ijk) const -{ - // Copy coordinates of starting point - double x0 = r0.x; - double y0 = r0.y; - double z0 = r0.z; - - // Copy coordinates of ending point - double x1 = r1.x; - double y1 = r1.y; - double z1 = r1.z; - - // Copy coordinates of mesh lower_left - double xm0 = lower_left_[0]; - double ym0 = lower_left_[1]; - - // Copy coordinates of mesh upper_right - double xm1 = upper_right_[0]; - double ym1 = upper_right_[1]; - - double min_dist = INFTY; - - // Check if line intersects left surface -- calculate the intersection point - // (y,z) - if ((x0 < xm0 && x1 > xm0) || (x0 > xm0 && x1 < xm0)) { - double yi = y0 + (xm0 - x0) * (y1 - y0) / (x1 - x0); - double zi = z0 + (xm0 - x0) * (z1 - z0) / (x1 - x0); - if (yi >= ym0 && yi < ym1) { - if (check_intersection_point(xm0, x0, yi, y0, zi, zi, r0, min_dist)) { - ijk[0] = 1; - ijk[1] = std::ceil((yi - lower_left_[1]) / width_[1]); - } - } - } - - // Check if line intersects back surface -- calculate the intersection point - // (x,z) - if ((y0 < ym0 && y1 > ym0) || (y0 > ym0 && y1 < ym0)) { - double xi = x0 + (ym0 - y0) * (x1 - x0) / (y1 - y0); - double zi = z0 + (ym0 - y0) * (z1 - z0) / (y1 - y0); - if (xi >= xm0 && xi < xm1) { - if (check_intersection_point(xi, x0, ym0, y0, zi, zi, r0, min_dist)) { - ijk[0] = std::ceil((xi - lower_left_[0]) / width_[0]); - ijk[1] = 1; - } - } - } - - // Check if line intersects right surface -- calculate the intersection point - // (y,z) - if ((x0 < xm1 && x1 > xm1) || (x0 > xm1 && x1 < xm1)) { - double yi = y0 + (xm1 - x0) * (y1 - y0) / (x1 - x0); - double zi = z0 + (xm1 - x0) * (z1 - z0) / (x1 - x0); - if (yi >= ym0 && yi < ym1) { - if (check_intersection_point(xm1, x0, yi, y0, zi, zi, r0, min_dist)) { - ijk[0] = shape_[0]; - ijk[1] = std::ceil((yi - lower_left_[1]) / width_[1]); - } - } - } - - // Check if line intersects front surface -- calculate the intersection point - // (x,z) - if ((y0 < ym1 && y1 > ym1) || (y0 > ym1 && y1 < ym1)) { - double xi = x0 + (ym1 - y0) * (x1 - x0) / (y1 - y0); - double zi = z0 + (ym1 - y0) * (z1 - z0) / (y1 - y0); - if (xi >= xm0 && xi < xm1) { - if (check_intersection_point(xi, x0, ym1, y0, zi, zi, r0, min_dist)) { - ijk[0] = std::ceil((xi - lower_left_[0]) / width_[0]); - ijk[1] = shape_[1]; - } - } - } - - return min_dist < INFTY; -} - -bool RegularMesh::intersects_3d(Position& r0, Position r1, int* ijk) const -{ - // Copy coordinates of starting point - double x0 = r0.x; - double y0 = r0.y; - double z0 = r0.z; - - // Copy coordinates of ending point - double x1 = r1.x; - double y1 = r1.y; - double z1 = r1.z; - - // Copy coordinates of mesh lower_left - double xm0 = lower_left_[0]; - double ym0 = lower_left_[1]; - double zm0 = lower_left_[2]; - - // Copy coordinates of mesh upper_right - double xm1 = upper_right_[0]; - double ym1 = upper_right_[1]; - double zm1 = upper_right_[2]; - - double min_dist = INFTY; - - // Check if line intersects left surface -- calculate the intersection point - // (y,z) - if ((x0 < xm0 && x1 > xm0) || (x0 > xm0 && x1 < xm0)) { - double yi = y0 + (xm0 - x0) * (y1 - y0) / (x1 - x0); - double zi = z0 + (xm0 - x0) * (z1 - z0) / (x1 - x0); - if (yi >= ym0 && yi < ym1 && zi >= zm0 && zi < zm1) { - if (check_intersection_point(xm0, x0, yi, y0, zi, z0, r0, min_dist)) { - ijk[0] = 1; - ijk[1] = std::ceil((yi - lower_left_[1]) / width_[1]); - ijk[2] = std::ceil((zi - lower_left_[2]) / width_[2]); - } - } - } - - // Check if line intersects back surface -- calculate the intersection point - // (x,z) - if ((y0 < ym0 && y1 > ym0) || (y0 > ym0 && y1 < ym0)) { - double xi = x0 + (ym0 - y0) * (x1 - x0) / (y1 - y0); - double zi = z0 + (ym0 - y0) * (z1 - z0) / (y1 - y0); - if (xi >= xm0 && xi < xm1 && zi >= zm0 && zi < zm1) { - if (check_intersection_point(xi, x0, ym0, y0, zi, z0, r0, min_dist)) { - ijk[0] = std::ceil((xi - lower_left_[0]) / width_[0]); - ijk[1] = 1; - ijk[2] = std::ceil((zi - lower_left_[2]) / width_[2]); - } - } - } - - // Check if line intersects bottom surface -- calculate the intersection - // point (x,y) - if ((z0 < zm0 && z1 > zm0) || (z0 > zm0 && z1 < zm0)) { - double xi = x0 + (zm0 - z0) * (x1 - x0) / (z1 - z0); - double yi = y0 + (zm0 - z0) * (y1 - y0) / (z1 - z0); - if (xi >= xm0 && xi < xm1 && yi >= ym0 && yi < ym1) { - if (check_intersection_point(xi, x0, yi, y0, zm0, z0, r0, min_dist)) { - ijk[0] = std::ceil((xi - lower_left_[0]) / width_[0]); - ijk[1] = std::ceil((yi - lower_left_[1]) / width_[1]); - ijk[2] = 1; - } - } - } - - // Check if line intersects right surface -- calculate the intersection point - // (y,z) - if ((x0 < xm1 && x1 > xm1) || (x0 > xm1 && x1 < xm1)) { - double yi = y0 + (xm1 - x0) * (y1 - y0) / (x1 - x0); - double zi = z0 + (xm1 - x0) * (z1 - z0) / (x1 - x0); - if (yi >= ym0 && yi < ym1 && zi >= zm0 && zi < zm1) { - if (check_intersection_point(xm1, x0, yi, y0, zi, z0, r0, min_dist)) { - ijk[0] = shape_[0]; - ijk[1] = std::ceil((yi - lower_left_[1]) / width_[1]); - ijk[2] = std::ceil((zi - lower_left_[2]) / width_[2]); - } - } - } - - // Check if line intersects front surface -- calculate the intersection point - // (x,z) - if ((y0 < ym1 && y1 > ym1) || (y0 > ym1 && y1 < ym1)) { - double xi = x0 + (ym1 - y0) * (x1 - x0) / (y1 - y0); - double zi = z0 + (ym1 - y0) * (z1 - z0) / (y1 - y0); - if (xi >= xm0 && xi < xm1 && zi >= zm0 && zi < zm1) { - if (check_intersection_point(xi, x0, ym1, y0, zi, z0, r0, min_dist)) { - ijk[0] = std::ceil((xi - lower_left_[0]) / width_[0]); - ijk[1] = shape_[1]; - ijk[2] = std::ceil((zi - lower_left_[2]) / width_[2]); - } - } - } - - // Check if line intersects top surface -- calculate the intersection point - // (x,y) - if ((z0 < zm1 && z1 > zm1) || (z0 > zm1 && z1 < zm1)) { - double xi = x0 + (zm1 - z0) * (x1 - x0) / (z1 - z0); - double yi = y0 + (zm1 - z0) * (y1 - y0) / (z1 - z0); - if (xi >= xm0 && xi < xm1 && yi >= ym0 && yi < ym1) { - if (check_intersection_point(xi, x0, yi, y0, zm1, z0, r0, min_dist)) { - ijk[0] = std::ceil((xi - lower_left_[0]) / width_[0]); - ijk[1] = std::ceil((yi - lower_left_[1]) / width_[1]); - ijk[2] = shape_[2]; - } - } - } - - return min_dist < INFTY; -} - -void RegularMesh::bins_crossed(const Particle& p, std::vector& bins, - std::vector& lengths) const -{ - // ======================================================================== - // Determine where the track intersects the mesh and if it intersects at all. - - // Copy the starting and ending coordinates of the particle. - Position last_r {p.r_last_}; - Position r {p.r()}; - Direction u {p.u()}; - - // Compute the length of the entire track. - double total_distance = (r - last_r).norm(); - - // While determining if this track intersects the mesh, offset the starting - // and ending coords by a bit. This avoid finite-precision errors that can - // occur when the mesh surfaces coincide with lattice or geometric surfaces. - Position r0 = last_r + TINY_BIT*u; - Position r1 = r - TINY_BIT*u; - - // Determine the mesh indices for the starting and ending coords. - int n = n_dimension_; - std::vector ijk0(n), ijk1(n); - bool start_in_mesh; - get_indices(r0, ijk0.data(), &start_in_mesh); - bool end_in_mesh; - get_indices(r1, ijk1.data(), &end_in_mesh); - - // Reset coordinates and check for a mesh intersection if necessary. - if (start_in_mesh) { - // The initial coords lie in the mesh, use those coords for tallying. - r0 = last_r; - } else { - // The initial coords do not lie in the mesh. Check to see if the particle - // eventually intersects the mesh and compute the relevant coords and - // indices. - if (!intersects(r0, r1, ijk0.data())) return; - } - r1 = r; - - // The TINY_BIT offsets above mean that the preceding logic cannot always find - // the correct ijk0 and ijk1 indices. For tracks shorter than 2*TINY_BIT, just - // assume the track lies in only one mesh bin. These tracks are very short so - // any error caused by this assumption will be small. It is important that - // ijk0 values are used rather than ijk1 because the previous logic guarantees - // ijk0 is a valid mesh bin. - if (total_distance < 2*TINY_BIT) { - for (int i = 0; i < n; ++i) ijk1[i] = ijk0[i]; - } - - // ======================================================================== - // Find which mesh cells are traversed and the length of each traversal. - - while (true) { - if (ijk0 == ijk1) { - // The track ends in this cell. Use the particle end location rather - // than the mesh surface and stop iterating. - double distance = (r1 - r0).norm(); - bins.push_back(get_bin_from_indices(ijk0.data())); - lengths.push_back(distance / total_distance); - break; - } - - // The track exits this cell. Determine the distance to each mesh surface. - std::vector d(n); - for (int k = 0; k < n; ++k) { - if (std::fabs(u[k]) < FP_PRECISION) { - d[k] = INFTY; - } else if (u[k] > 0) { - double xyz_cross = lower_left_[k] + ijk0[k] * width_[k]; - d[k] = (xyz_cross - r0[k]) / u[k]; - } else { - double xyz_cross = lower_left_[k] + (ijk0[k] - 1) * width_[k]; - d[k] = (xyz_cross - r0[k]) / u[k]; - } - } - - // Pick the closest mesh surface and append this traversal to the output. - auto j = std::min_element(d.begin(), d.end()) - d.begin(); - double distance = d[j]; - bins.push_back(get_bin_from_indices(ijk0.data())); - lengths.push_back(distance / total_distance); - - // Translate to the oncoming mesh surface. - r0 += distance * u; - - // Increment the indices into the next mesh cell. - if (u[j] > 0.0) { - ++ijk0[j]; - } else { - --ijk0[j]; - } - - // If the next indices are invalid, then the track has left the mesh and - // we are done. - bool in_mesh = true; - for (int i = 0; i < n; ++i) { - if (ijk0[i] < 1 || ijk0[i] > shape_[i]) { - in_mesh = false; - break; - } - } - if (!in_mesh) break; - } + return lower_left_[i] + (ijk[i] - 1) * width_[i]; } void RegularMesh::surface_bins_crossed(const Particle& p, @@ -642,9 +658,9 @@ void RegularMesh::surface_bins_crossed(const Particle& p, Position xyz_cross; for (int i = 0; i < n; ++i) { if (u[i] > 0.0) { - xyz_cross[i] = lower_left_[i] + ijk0[i] * width_[i]; + xyz_cross[i] = positive_grid_boundary(ijk0.data(), i); } else { - xyz_cross[i] = lower_left_[i] + (ijk0[i] - 1) * width_[i]; + xyz_cross[i] = negative_grid_boundary(ijk0.data(), i); } } @@ -889,109 +905,14 @@ RectilinearMesh::RectilinearMesh(pugi::xml_node node) upper_right_ = {grid_[0].back(), grid_[1].back(), grid_[2].back()}; } -void RectilinearMesh::bins_crossed(const Particle& p, std::vector& bins, - std::vector& lengths) const +double RectilinearMesh::positive_grid_boundary(int* ijk, int i) const { - // ======================================================================== - // Determine where the track intersects the mesh and if it intersects at all. + return grid_[i][ijk[i]]; +} - // Copy the starting and ending coordinates of the particle. - Position last_r {p.r_last_}; - Position r {p.r()}; - Direction u {p.u()}; - - // Compute the length of the entire track. - double total_distance = (r - last_r).norm(); - - // While determining if this track intersects the mesh, offset the starting - // and ending coords by a bit. This avoid finite-precision errors that can - // occur when the mesh surfaces coincide with lattice or geometric surfaces. - Position r0 = last_r + TINY_BIT*u; - Position r1 = r - TINY_BIT*u; - - // Determine the mesh indices for the starting and ending coords. - int ijk0[3], ijk1[3]; - bool start_in_mesh; - get_indices(r0, ijk0, &start_in_mesh); - bool end_in_mesh; - get_indices(r1, ijk1, &end_in_mesh); - - // Reset coordinates and check for a mesh intersection if necessary. - if (start_in_mesh) { - // The initial coords lie in the mesh, use those coords for tallying. - r0 = last_r; - } else { - // The initial coords do not lie in the mesh. Check to see if the particle - // eventually intersects the mesh and compute the relevant coords and - // indices. - if (!intersects(r0, r1, ijk0)) return; - } - r1 = r; - - // The TINY_BIT offsets above mean that the preceding logic cannot always find - // the correct ijk0 and ijk1 indices. For tracks shorter than 2*TINY_BIT, just - // assume the track lies in only one mesh bin. These tracks are very short so - // any error caused by this assumption will be small. It is important that - // ijk0 values are used rather than ijk1 because the previous logic guarantees - // ijk0 is a valid mesh bin. - if (total_distance < 2*TINY_BIT) { - for (int i = 0; i < 3; ++i) ijk1[i] = ijk0[i]; - } - - // ======================================================================== - // Find which mesh cells are traversed and the length of each traversal. - - while (true) { - if (std::equal(ijk0, ijk0+3, ijk1)) { - // The track ends in this cell. Use the particle end location rather - // than the mesh surface and stop iterating. - double distance = (r1 - r0).norm(); - bins.push_back(get_bin_from_indices(ijk0)); - lengths.push_back(distance / total_distance); - break; - } - - // The track exits this cell. Determine the distance to each mesh surface. - double d[3]; - for (int k = 0; k < 3; ++k) { - if (std::fabs(u[k]) < FP_PRECISION) { - d[k] = INFTY; - } else if (u[k] > 0) { - double xyz_cross = grid_[k][ijk0[k]]; - d[k] = (xyz_cross - r0[k]) / u[k]; - } else { - double xyz_cross = grid_[k][ijk0[k] - 1]; - d[k] = (xyz_cross - r0[k]) / u[k]; - } - } - - // Pick the closest mesh surface and append this traversal to the output. - auto j = std::min_element(d, d+3) - d; - double distance = d[j]; - bins.push_back(get_bin_from_indices(ijk0)); - lengths.push_back(distance / total_distance); - - // Translate to the oncoming mesh surface. - r0 += distance * u; - - // Increment the indices into the next mesh cell. - if (u[j] > 0.0) { - ++ijk0[j]; - } else { - --ijk0[j]; - } - - // If the next indices are invalid, then the track has left the mesh and - // we are done. - bool in_mesh = true; - for (int i = 0; i < 3; ++i) { - if (ijk0[i] < 1 || ijk0[i] > shape_[i]) { - in_mesh = false; - break; - } - } - if (!in_mesh) break; - } +double RectilinearMesh::negative_grid_boundary(int* ijk, int i) const +{ + return grid_[i][ijk[i] - 1]; } void RectilinearMesh::surface_bins_crossed(const Particle& p, @@ -1088,9 +1009,9 @@ void RectilinearMesh::surface_bins_crossed(const Particle& p, Position xyz_cross; for (int i = 0; i < 3; ++i) { if (u[i] > 0.0) { - xyz_cross[i] = grid_[i][ijk0[i]]; + xyz_cross[i] = positive_grid_boundary(ijk0, i); } else { - xyz_cross[i] = grid_[i][ijk0[i] - 1]; + xyz_cross[i] = negative_grid_boundary(ijk0, i); } } @@ -1162,52 +1083,9 @@ void RectilinearMesh::surface_bins_crossed(const Particle& p, } } -int RectilinearMesh::get_bin(Position r) const +int RectilinearMesh::get_index_in_direction(double r, int i) const { - // Determine indices - int ijk[3]; - bool in_mesh; - get_indices(r, ijk, &in_mesh); - if (!in_mesh) return -1; - - // Convert indices to bin - return get_bin_from_indices(ijk); -} - -int RectilinearMesh::get_bin_from_indices(const int* ijk) const -{ - return ((ijk[2] - 1)*shape_[1] + (ijk[1] - 1))*shape_[0] + ijk[0] - 1; -} - -void RectilinearMesh::get_indices(Position r, int* ijk, bool* in_mesh) const -{ - *in_mesh = true; - - for (int i = 0; i < 3; ++i) { - if (r[i] < grid_[i].front() || r[i] > grid_[i].back()) { - ijk[i] = -1; - *in_mesh = false; - } else { - ijk[i] = lower_bound_index(grid_[i].begin(), grid_[i].end(), r[i]) + 1; - } - } -} - -void RectilinearMesh::get_indices_from_bin(int bin, int* ijk) const -{ - ijk[0] = bin % shape_[0] + 1; - ijk[1] = (bin % (shape_[0] * shape_[1])) / shape_[0] + 1; - ijk[2] = bin / (shape_[0] * shape_[1]) + 1; -} - -int RectilinearMesh::n_bins() const -{ - return xt::prod(shape_)(); -} - -int RectilinearMesh::n_surface_bins() const -{ - return 4 * n_dimension_ * n_bins(); + return lower_bound_index(grid_[i].begin(), grid_[i].end(), r) + 1; } std::pair, std::vector> @@ -1252,117 +1130,6 @@ void RectilinearMesh::to_hdf5(hid_t group) const close_group(mesh_group); } -bool RectilinearMesh::intersects(Position& r0, Position r1, int* ijk) const -{ - // Copy coordinates of starting point - double x0 = r0.x; - double y0 = r0.y; - double z0 = r0.z; - - // Copy coordinates of ending point - double x1 = r1.x; - double y1 = r1.y; - double z1 = r1.z; - - // Copy coordinates of mesh lower_left - double xm0 = grid_[0].front(); - double ym0 = grid_[1].front(); - double zm0 = grid_[2].front(); - - // Copy coordinates of mesh upper_right - double xm1 = grid_[0].back(); - double ym1 = grid_[1].back(); - double zm1 = grid_[2].back(); - - double min_dist = INFTY; - - // Check if line intersects left surface -- calculate the intersection point - // (y,z) - if ((x0 < xm0 && x1 > xm0) || (x0 > xm0 && x1 < xm0)) { - double yi = y0 + (xm0 - x0) * (y1 - y0) / (x1 - x0); - double zi = z0 + (xm0 - x0) * (z1 - z0) / (x1 - x0); - if (yi >= ym0 && yi < ym1 && zi >= zm0 && zi < zm1) { - if (check_intersection_point(xm0, x0, yi, y0, zi, z0, r0, min_dist)) { - ijk[0] = 1; - ijk[1] = lower_bound_index(grid_[1].begin(), grid_[1].end(), yi) + 1; - ijk[2] = lower_bound_index(grid_[2].begin(), grid_[2].end(), zi) + 1; - } - } - } - - // Check if line intersects back surface -- calculate the intersection point - // (x,z) - if ((y0 < ym0 && y1 > ym0) || (y0 > ym0 && y1 < ym0)) { - double xi = x0 + (ym0 - y0) * (x1 - x0) / (y1 - y0); - double zi = z0 + (ym0 - y0) * (z1 - z0) / (y1 - y0); - if (xi >= xm0 && xi < xm1 && zi >= zm0 && zi < zm1) { - if (check_intersection_point(xi, x0, ym0, y0, zi, z0, r0, min_dist)) { - ijk[0] = lower_bound_index(grid_[0].begin(), grid_[0].end(), xi) + 1; - ijk[1] = 1; - ijk[2] = lower_bound_index(grid_[2].begin(), grid_[2].end(), zi) + 1; - } - } - } - - // Check if line intersects bottom surface -- calculate the intersection - // point (x,y) - if ((z0 < zm0 && z1 > zm0) || (z0 > zm0 && z1 < zm0)) { - double xi = x0 + (zm0 - z0) * (x1 - x0) / (z1 - z0); - double yi = y0 + (zm0 - z0) * (y1 - y0) / (z1 - z0); - if (xi >= xm0 && xi < xm1 && yi >= ym0 && yi < ym1) { - if (check_intersection_point(xi, x0, yi, y0, zm0, z0, r0, min_dist)) { - ijk[0] = lower_bound_index(grid_[0].begin(), grid_[0].end(), xi) + 1; - ijk[1] = lower_bound_index(grid_[1].begin(), grid_[1].end(), yi) + 1; - ijk[2] = 1; - } - } - } - - // Check if line intersects right surface -- calculate the intersection point - // (y,z) - if ((x0 < xm1 && x1 > xm1) || (x0 > xm1 && x1 < xm1)) { - double yi = y0 + (xm1 - x0) * (y1 - y0) / (x1 - x0); - double zi = z0 + (xm1 - x0) * (z1 - z0) / (x1 - x0); - if (yi >= ym0 && yi < ym1 && zi >= zm0 && zi < zm1) { - if (check_intersection_point(xm1, x0, yi, y0, zi, z0, r0, min_dist)) { - ijk[0] = shape_[0]; - ijk[1] = lower_bound_index(grid_[1].begin(), grid_[1].end(), yi) + 1; - ijk[2] = lower_bound_index(grid_[2].begin(), grid_[2].end(), zi) + 1; - } - } - } - - // Check if line intersects front surface -- calculate the intersection point - // (x,z) - if ((y0 < ym1 && y1 > ym1) || (y0 > ym1 && y1 < ym1)) { - double xi = x0 + (ym1 - y0) * (x1 - x0) / (y1 - y0); - double zi = z0 + (ym1 - y0) * (z1 - z0) / (y1 - y0); - if (xi >= xm0 && xi < xm1 && zi >= zm0 && zi < zm1) { - if (check_intersection_point(xi, x0, ym1, y0, zi, z0, r0, min_dist)) { - ijk[0] = lower_bound_index(grid_[0].begin(), grid_[0].end(), xi) + 1; - ijk[1] = shape_[1]; - ijk[2] = lower_bound_index(grid_[2].begin(), grid_[2].end(), zi) + 1; - } - } - } - - // Check if line intersects top surface -- calculate the intersection point - // (x,y) - if ((z0 < zm1 && z1 > zm1) || (z0 > zm1 && z1 < zm1)) { - double xi = x0 + (zm1 - z0) * (x1 - x0) / (z1 - z0); - double yi = y0 + (zm1 - z0) * (y1 - y0) / (z1 - z0); - if (xi >= xm0 && xi < xm1 && yi >= ym0 && yi < ym1) { - if (check_intersection_point(xi, x0, yi, y0, zm1, z0, r0, min_dist)) { - ijk[0] = lower_bound_index(grid_[0].begin(), grid_[0].end(), xi) + 1; - ijk[1] = lower_bound_index(grid_[1].begin(), grid_[1].end(), yi) + 1; - ijk[2] = shape_[2]; - } - } - } - - return min_dist < INFTY; -} - //============================================================================== // Helper functions for the C API //============================================================================== diff --git a/src/mgxs.cpp b/src/mgxs.cpp index d5c144658d..dec505f3cc 100644 --- a/src/mgxs.cpp +++ b/src/mgxs.cpp @@ -318,7 +318,8 @@ Mgxs::Mgxs(const std::string& in_name, const std::vector& mat_kTs, // Get the minimum data needed to initialize: // Dont need awr, but lets just initialize it anyways double in_awr = -1.; - // start with the assumption it is not fissionable + // start with the assumption it is not fissionable and set + // the fissionable status if we learn differently bool in_fissionable = false; for (int m = 0; m < micros.size(); m++) { if (micros[m]->fissionable) in_fissionable = true; @@ -377,25 +378,43 @@ Mgxs::Mgxs(const std::string& in_name, const std::vector& mat_kTs, } // end switch } // end microscopic temperature loop - // We are about to loop through each of the microscopic objects - // and incorporate the contribution of each microscopic data at - // one of the two temperature interpolants to this macroscopic quantity. - // If we are doing nearest temperature interpolation, then we don't need - // to do the 2nd temperature - int num_interp_points = 2; - if (settings::temperature_method == TemperatureMethod::NEAREST) num_interp_points = 1; - std::vector interp(micros.size()); - std::vector temp_indices(micros.size()); - for (int interp_point = 0; interp_point < num_interp_points; interp_point++) { - for (int m = 0; m < micros.size(); m++) { - interp[m] = (1. - micro_t_interp[m]) * atom_densities[m]; - temp_indices[m] = micro_t[m] + interp_point; - micro_t_interp[m] = 1. - micro_t_interp[m]; + // Now combine the microscopic data at each relevant temperature + // We will do this by treating the multiple temperatures of a nuclide as + // a different nuclide. Mathematically this just means the temperature + // interpolant is included in the number density. + // These interpolants are contained within interpolant. + std::vector interpolant; // the interpolant for the Mgxs + std::vector temp_indices; // the temperature index for each Mgxs + std::vector mgxs_to_combine; // The Mgxs to combine + // Now go through and build the above vectors so that we can use them to + // combine the data. We will step through each microscopic data and + // add in its lower and upper temperature points + for (int m = 0; m < micros.size(); m++) { + if (settings::temperature_method == TemperatureMethod::NEAREST) { + // Nearest interpolation only has one temperature point per isotope + // and so we dont need to include a temperature interpolant in + // the interpolant vector + interpolant.push_back(atom_densities[m]); + temp_indices.push_back(micro_t[m]); + mgxs_to_combine.push_back(micros[m]); + } else { + // This will be an interpolation between two points so get both these + // points + // Start with the low point + interpolant.push_back((1. - micro_t_interp[m]) * atom_densities[m]); + temp_indices.push_back(micro_t[m]); + mgxs_to_combine.push_back(micros[m]); + // The higher point + interpolant.push_back((micro_t_interp[m]) * atom_densities[m]); + temp_indices.push_back(micro_t[m] + 1); + mgxs_to_combine.push_back(micros[m]); } + } - combine(micros, interp, temp_indices, t); - } // end loop to sum all micros across the temperatures + // And finally, combine the data + combine(mgxs_to_combine, interpolant, temp_indices, t); } // end temperature (t) loop + } //============================================================================== @@ -407,9 +426,6 @@ Mgxs::combine(const std::vector& micros, const std::vector& scala // Build the vector of pointers to the xs objects within micros std::vector those_xs(micros.size()); for (int i = 0; i < micros.size(); i++) { - if (!xs[this_t].equiv(micros[i]->xs[micro_ts[i]])) { - fatal_error("Cannot combine the Mgxs objects!"); - } those_xs[i] = &(micros[i]->xs[micro_ts[i]]); } @@ -448,9 +464,9 @@ Mgxs::get_xs(MgxsType xstype, int gin, const int* gout, const double* mu, case MgxsType::KAPPA_FISSION: val = fissionable ? xs_t->kappa_fission(a, gin) : 0.; break; + case MgxsType::NU_SCATTER: case MgxsType::SCATTER: - case MgxsType::SCATTER_MULT: - case MgxsType::SCATTER_FMU_MULT: + case MgxsType::NU_SCATTER_FMU: case MgxsType::SCATTER_FMU: val = xs_t->scatter[a]->get_xs(xstype, gin, gout, mu); break; diff --git a/src/reaction.cpp b/src/reaction.cpp index a5406fdb4a..3e4d3b9818 100644 --- a/src/reaction.cpp +++ b/src/reaction.cpp @@ -243,7 +243,7 @@ std::unordered_map REACTION_NAME_MAP { {N_3N3HE, "(n,3n3He)"}, {N_4N3HE, "(n,4n3He)"}, {N_3N2P, "(n,3n2p)"}, - {N_3N3A, "(n,3n3a)"}, + {N_3N2A, "(n,3n2a)"}, {N_3NPA, "(n,3npa)"}, {N_DT, "(n,dt)"}, {N_NPD, "(n,npd)"}, diff --git a/src/scattdata.cpp b/src/scattdata.cpp index e3c97512c3..6c20b8e37d 100644 --- a/src/scattdata.cpp +++ b/src/scattdata.cpp @@ -5,6 +5,7 @@ #include #include "xtensor/xbuilder.hpp" +#include "xtensor/xview.hpp" #include "openmc/constants.h" #include "openmc/error.h" @@ -36,6 +37,22 @@ ScattData::base_init(int order, const xt::xtensor& in_gmin, energy[gin] = in_energy[gin]; mult[gin] = in_mult[gin]; + // Make sure the multiplicity does not have 0s + unsigned long int num_converted = 0; + for (int go = 0; go < mult[gin].size(); go++) { + if (mult[gin][go] == 0.) { + num_converted += 1; + mult[gin][go] = 1.; + } + } + + if (num_converted > 0) { + // Raise a warning to the user if we did have to do the conversion + std::string msg = std::to_string(num_converted) + + "entries in the Multiplicity Matrix were changed from 0 to 1"; + warning(msg); + } + // Make sure the energy is normalized double norm = std::accumulate(energy[gin].begin(), energy[gin].end(), 0.); @@ -54,77 +71,45 @@ ScattData::base_init(int order, const xt::xtensor& in_gmin, //============================================================================== void -ScattData::base_combine(size_t max_order, - const std::vector& those_scatts, const std::vector& scalars, - xt::xtensor& in_gmin, xt::xtensor& in_gmax, double_2dvec& sparse_mult, +ScattData::base_combine(size_t max_order, size_t order_dim, + const std::vector& those_scatts, + const std::vector& scalars, xt::xtensor& in_gmin, + xt::xtensor& in_gmax, double_2dvec& sparse_mult, double_3dvec& sparse_scatter) { size_t groups = those_scatts[0] -> energy.size(); // Now allocate and zero our storage spaces - xt::xtensor this_matrix({groups, groups, max_order}, 0.); - xt::xtensor mult_numer({groups, groups}, 0.); - xt::xtensor mult_denom({groups, groups}, 0.); - // TODO: Need to review this: - if (this->scattxs.size() > 0) { - this_matrix = this->get_matrix(max_order); - } + xt::xtensor this_nuscatt_matrix({groups, groups, order_dim}, 0.); + xt::xtensor this_nuscatt_P0({groups, groups}, 0.); + xt::xtensor this_scatt_P0({groups, groups}, 0.); + xt::xtensor this_mult({groups, groups}, 1.); + // Build the dense scattering and multiplicity matrices - // Get the multiplicity_matrix - // To combine from nuclidic data we need to use the final relationship - // mult_{gg'} = sum_i(N_i*nuscatt_{i,g,g'}) / - // sum_i(N_i*(nuscatt_{i,g,g'} / mult_{i,g,g'})) - // Developed as follows: - // mult_{gg'} = nuScatt{g,g'} / Scatt{g,g'} - // mult_{gg'} = sum_i(N_i*nuscatt_{i,g,g'}) / sum(N_i*scatt_{i,g,g'}) - // mult_{gg'} = sum_i(N_i*nuscatt_{i,g,g'}) / - // sum_i(N_i*(nuscatt_{i,g,g'} / mult_{i,g,g'})) - // nuscatt_{i,g,g'} can be reconstructed from the energy and scattxs member - // variables for (int i = 0; i < those_scatts.size(); i++) { ScattData* that = those_scatts[i]; // Build the dense matrix for that object xt::xtensor that_matrix = that->get_matrix(max_order); - // Now add that to this for the scattering and multiplicity + // Now add that to this for the nu-scatter matrix + this_nuscatt_matrix += scalars[i] * that_matrix; + + // Do the same with the P0 matrices for (int gin = 0; gin < groups; gin++) { - // Only spend time adding that's gmin to gmax data since the rest will - // be zeros - int i_gout = 0; - for (int gout = that->gmin(gin); gout <= that->gmax(gin); gout++) { - // Do the scattering matrix - for (int l = 0; l < max_order; l++) { - this_matrix(gin, gout, l) += scalars[i] * that_matrix(gin, gout, l); - } - - // Incorporate that's contribution to the multiplicity matrix data - double nuscatt = that->scattxs(gin) * that->energy[gin][i_gout]; - mult_numer(gin, gout) += scalars[i] * nuscatt; - if (that->mult[gin][i_gout] > 0.) { - mult_denom(gin, gout) += scalars[i] * nuscatt / that->mult[gin][i_gout]; - } else { - mult_denom(gin, gout) += scalars[i]; - } - i_gout++; + for (int go = 0; go < groups; go++) { + this_nuscatt_P0(gin, go) += + scalars[i] * that->get_xs(MgxsType::NU_SCATTER, gin, &go, nullptr); + this_scatt_P0(gin, go) += + scalars[i] * + that->get_xs(MgxsType::SCATTER, gin, &go, nullptr); } } } - // Combine mult_numer and mult_denom into the combined multiplicity matrix - xt::xtensor this_mult({groups, groups}, 1.); - // TODO: Need to check this too - for (int gin = 0; gin < groups; gin++) { - for (int gout = 0; gout < groups; gout++) { - if (std::abs(mult_denom(gin, gout)) > 0.0) { - this_mult(gin, gout) = mult_numer(gin, gout) / mult_denom(gin, gout); - } else { - if (mult_numer(gin, gout) == 0.0) { - this_mult(gin, gout) = 1.0; - } - } - } - } + // Now we have the dense nuscatt and scatt, we can easily compute the + // multiplicity matrix by dividing the two and fixing any nans + this_mult = xt::nan_to_num(this_nuscatt_P0 / this_scatt_P0); // We have the data, now we need to convert to a jagged array and then use // the initialize function to store it on the object. @@ -133,8 +118,8 @@ ScattData::base_combine(size_t max_order, int gmin_; for (gmin_ = 0; gmin_ < groups; gmin_++) { bool non_zero = false; - for (int l = 0; l < this_matrix.shape()[2]; l++) { - if (this_matrix(gin, gmin_, l) != 0.) { + for (int l = 0; l < this_nuscatt_matrix.shape()[2]; l++) { + if (this_nuscatt_matrix(gin, gmin_, l) != 0.) { non_zero = true; break; } @@ -144,8 +129,8 @@ ScattData::base_combine(size_t max_order, int gmax_; for (gmax_ = groups - 1; gmax_ >= 0; gmax_--) { bool non_zero = false; - for (int l = 0; l < this_matrix.shape()[2]; l++) { - if (this_matrix(gin, gmax_, l) != 0.) { + for (int l = 0; l < this_nuscatt_matrix.shape()[2]; l++) { + if (this_nuscatt_matrix(gin, gmax_, l) != 0.) { non_zero = true; break; } @@ -168,9 +153,9 @@ ScattData::base_combine(size_t max_order, sparse_mult[gin].resize(gmax_ - gmin_ + 1); int i_gout = 0; for (int gout = gmin_; gout <= gmax_; gout++) { - sparse_scatter[gin][i_gout].resize(this_matrix.shape()[2]); - for (int l = 0; l < this_matrix.shape()[2]; l++) { - sparse_scatter[gin][i_gout][l] = this_matrix(gin, gout, l); + sparse_scatter[gin][i_gout].resize(this_nuscatt_matrix.shape()[2]); + for (int l = 0; l < this_nuscatt_matrix.shape()[2]; l++) { + sparse_scatter[gin][i_gout][l] = this_nuscatt_matrix(gin, gout, l); } sparse_mult[gin][i_gout] = this_mult(gin, gout); i_gout++; @@ -178,6 +163,7 @@ ScattData::base_combine(size_t max_order, } } + //============================================================================== void @@ -212,10 +198,10 @@ ScattData::get_xs(MgxsType xstype, int gin, const int* gout, const double* mu) double val = scattxs[gin]; switch(xstype) { - case MgxsType::SCATTER: + case MgxsType::NU_SCATTER: if (gout != nullptr) val *= energy[gin][i_gout]; break; - case MgxsType::SCATTER_MULT: + case MgxsType::SCATTER: if (gout != nullptr) { val *= energy[gin][i_gout] / mult[gin][i_gout]; } else { @@ -223,7 +209,7 @@ ScattData::get_xs(MgxsType xstype, int gin, const int* gout, const double* mu) energy[gin].begin(), 0.0); } break; - case MgxsType::SCATTER_FMU_MULT: + case MgxsType::NU_SCATTER_FMU: if ((gout != nullptr) && (mu != nullptr)) { val *= energy[gin][i_gout] * calc_f(gin, *gout, *mu); } else { @@ -407,7 +393,6 @@ ScattDataLegendre::combine(const std::vector& those_scatts, size_t that_order = that->get_order(); if (that_order > max_order) max_order = that_order; } - max_order++; // Add one since this is a Legendre size_t groups = those_scatts[0] -> energy.size(); @@ -419,8 +404,9 @@ ScattDataLegendre::combine(const std::vector& those_scatts, // The rest of the steps do not depend on the type of angular representation // so we use a base class method to sum up xs and create new energy and mult // matrices - ScattData::base_combine(max_order, those_scatts, scalars, in_gmin, in_gmax, - sparse_mult, sparse_scatter); + size_t order_dim = max_order + 1; + ScattData::base_combine(max_order, order_dim, those_scatts, scalars, in_gmin, + in_gmax, sparse_mult, sparse_scatter); // Got everything we need, store it. init(in_gmin, in_gmax, sparse_mult, sparse_scatter); @@ -636,8 +622,9 @@ ScattDataHistogram::combine(const std::vector& those_scatts, // The rest of the steps do not depend on the type of angular representation // so we use a base class method to sum up xs and create new energy and mult // matrices - ScattData::base_combine(max_order, those_scatts, scalars, in_gmin, in_gmax, - sparse_mult, sparse_scatter); + size_t order_dim = max_order; + ScattData::base_combine(max_order, order_dim, those_scatts, scalars, in_gmin, + in_gmax, sparse_mult, sparse_scatter); // Got everything we need, store it. init(in_gmin, in_gmax, sparse_mult, sparse_scatter); @@ -854,8 +841,9 @@ ScattDataTabular::combine(const std::vector& those_scatts, // The rest of the steps do not depend on the type of angular representation // so we use a base class method to sum up xs and create new energy and mult // matrices - ScattData::base_combine(max_order, those_scatts, scalars, in_gmin, in_gmax, - sparse_mult, sparse_scatter); + size_t order_dim = max_order; + ScattData::base_combine(max_order, order_dim, those_scatts, scalars, in_gmin, + in_gmax, sparse_mult, sparse_scatter); // Got everything we need, store it. init(in_gmin, in_gmax, sparse_mult, sparse_scatter); diff --git a/src/settings.cpp b/src/settings.cpp index d2980701c7..5a868d445b 100644 --- a/src/settings.cpp +++ b/src/settings.cpp @@ -73,8 +73,6 @@ std::string path_cross_sections; std::string path_input; std::string path_output; std::string path_particle_restart; -std::string path_source; -std::string path_source_library; std::string path_sourcepoint; std::string path_statepoint; @@ -421,17 +419,31 @@ void read_settings_xml() // Get point to list of elements and make sure there is at least one for (pugi::xml_node node : root.children("source")) { - model::external_sources.emplace_back(node); + if (check_for_node(node, "file")) { + auto path = get_node_value(node, "file", false, true); + model::external_sources.push_back(std::make_unique(path)); + } else if (check_for_node(node, "library")) { + // Get shared library path and parameters + auto path = get_node_value(node, "library", false, true); + std::string parameters; + if (check_for_node(node, "parameters")) { + parameters = get_node_value(node, "parameters", false, true); + } + + // Create custom source + model::external_sources.push_back(std::make_unique(path, parameters)); + } else { + model::external_sources.push_back(std::make_unique(node)); + } } // If no source specified, default to isotropic point source at origin with Watt spectrum if (model::external_sources.empty()) { - SourceDistribution source { + model::external_sources.push_back(std::make_unique( UPtrSpace{new SpatialPoint({0.0, 0.0, 0.0})}, UPtrAngle{new Isotropic()}, UPtrDist{new Watt(0.988e6, 2.249e-6)} - }; - model::external_sources.push_back(std::move(source)); + )); } // Check if we want to write out source @@ -510,88 +522,46 @@ void read_settings_xml() read_meshes(root); // Shannon Entropy mesh - int32_t index_entropy_mesh = -1; if (check_for_node(root, "entropy_mesh")) { int temp = std::stoi(get_node_value(root, "entropy_mesh")); if (model::mesh_map.find(temp) == model::mesh_map.end()) { fatal_error(fmt::format( "Mesh {} specified for Shannon entropy does not exist.", temp)); } - index_entropy_mesh = model::mesh_map.at(temp); - } else if (check_for_node(root, "entropy")) { - warning("Specifying a Shannon entropy mesh via the element " - "is deprecated. Please create a mesh using and then reference " - "it by specifying its ID in an element."); - - // Read entropy mesh from - auto node_entropy = root.child("entropy"); - model::meshes.push_back(std::make_unique(node_entropy)); - - // Set entropy mesh index - index_entropy_mesh = model::meshes.size() - 1; - - // Assign ID and set mapping - model::meshes.back()->id_ = 10000; - model::mesh_map[10000] = index_entropy_mesh; - } - - if (index_entropy_mesh >= 0) { auto* m = dynamic_cast( - model::meshes[index_entropy_mesh].get()); + model::meshes[model::mesh_map.at(temp)].get()); if (!m) fatal_error("Only regular meshes can be used as an entropy mesh"); simulation::entropy_mesh = m; - if (m->shape_.size() == 0) { - // If the user did not specify how many mesh cells are to be used in - // each direction, we automatically determine an appropriate number of - // cells - int n = std::ceil(std::pow(n_particles / 20.0, 1.0/3.0)); - m->shape_ = {n, n, n}; - m->n_dimension_ = 3; - - // Calculate width - m->width_ = (m->upper_right_ - m->lower_left_) / m->shape_; - } - // Turn on Shannon entropy calculation entropy_on = true; + + } else if (check_for_node(root, "entropy")) { + fatal_error("Specifying a Shannon entropy mesh via the element " + "is deprecated. Please create a mesh using and then reference " + "it by specifying its ID in an element."); } // Uniform fission source weighting mesh - int32_t i_ufs_mesh = -1; if (check_for_node(root, "ufs_mesh")) { auto temp = std::stoi(get_node_value(root, "ufs_mesh")); if (model::mesh_map.find(temp) == model::mesh_map.end()) { fatal_error(fmt::format("Mesh {} specified for uniform fission site " "method does not exist.", temp)); } - i_ufs_mesh = model::mesh_map.at(temp); - } else if (check_for_node(root, "uniform_fs")) { - warning("Specifying a UFS mesh via the element " - "is deprecated. Please create a mesh using and then reference " - "it by specifying its ID in a element."); - - // Read entropy mesh from - auto node_ufs = root.child("uniform_fs"); - model::meshes.push_back(std::make_unique(node_ufs)); - - // Set entropy mesh index - i_ufs_mesh = model::meshes.size() - 1; - - // Assign ID and set mapping - model::meshes.back()->id_ = 10001; - model::mesh_map[10001] = index_entropy_mesh; - } - - if (i_ufs_mesh >= 0) { - auto* m = dynamic_cast(model::meshes[i_ufs_mesh].get()); + auto* m = dynamic_cast(model::meshes[model::mesh_map.at(temp)].get()); if (!m) fatal_error("Only regular meshes can be used as a UFS mesh"); simulation::ufs_mesh = m; // Turn on uniform fission source weighting ufs_on = true; + + } else if (check_for_node(root, "uniform_fs")) { + fatal_error("Specifying a UFS mesh via the element " + "is deprecated. Please create a mesh using and then reference " + "it by specifying its ID in a element."); } // Check if the user has specified to write state points diff --git a/src/simulation.cpp b/src/simulation.cpp index c95c0386c0..1e35adeeea 100644 --- a/src/simulation.cpp +++ b/src/simulation.cpp @@ -121,12 +121,6 @@ int openmc_simulation_init() } } - // If fixed source and using custom source library then need to load - if (settings::run_mode == RunMode::FIXED_SOURCE && - !settings::path_source_library.empty()) { - load_custom_source_library(); - } - // Display header if (mpi::master) { if (settings::run_mode == RunMode::FIXED_SOURCE) { @@ -173,12 +167,6 @@ int openmc_simulation_finalize() t->active_ = false; } - // If fixed source and using custom source library then need to close - if (settings::run_mode == RunMode::FIXED_SOURCE && - !settings::path_source_library.empty()) { - close_custom_source_library(); - } - // Stop timers and show timing statistics simulation::time_finalize.stop(); simulation::time_total.stop(); diff --git a/src/source.cpp b/src/source.cpp index 4f4ad117bb..87644f054d 100644 --- a/src/source.cpp +++ b/src/source.cpp @@ -39,27 +39,18 @@ namespace openmc { namespace model { -std::vector external_sources; +std::vector> external_sources; } -namespace { - -void* custom_source_library; -std::string custom_source_parameters; -std::unique_ptr custom_source; - -} - - //============================================================================== -// SourceDistribution implementation +// IndependentSource implementation //============================================================================== -SourceDistribution::SourceDistribution(UPtrSpace space, UPtrAngle angle, UPtrDist energy) +IndependentSource::IndependentSource(UPtrSpace space, UPtrAngle angle, UPtrDist energy) : space_{std::move(space)}, angle_{std::move(angle)}, energy_{std::move(energy)} { } -SourceDistribution::SourceDistribution(pugi::xml_node node) +IndependentSource::IndependentSource(pugi::xml_node node) { // Check for particle type if (check_for_node(node, "particle")) { @@ -81,24 +72,7 @@ SourceDistribution::SourceDistribution(pugi::xml_node node) // Check for external source file if (check_for_node(node, "file")) { - // Copy path of source file - settings::path_source = get_node_value(node, "file", false, true); - // Check if source file exists - if (!file_exists(settings::path_source)) { - fatal_error(fmt::format("Source file '{}' does not exist.", - settings::path_source)); - } - } else if (check_for_node(node, "library")) { - settings::path_source_library = get_node_value(node, "library", false, true); - if (!file_exists(settings::path_source_library)) { - fatal_error(fmt::format("Source library '{}' does not exist.", - settings::path_source_library)); - } - - if (check_for_node(node, "parameters")) { - custom_source_parameters = get_node_value(node, "parameters", false, true); - } } else { // Spatial distribution for external source @@ -167,8 +141,7 @@ SourceDistribution::SourceDistribution(pugi::xml_node node) } } - -Particle::Bank SourceDistribution::sample(uint64_t* seed) const +Particle::Bank IndependentSource::sample(uint64_t* seed) const { Particle::Bank site; @@ -185,10 +158,10 @@ Particle::Bank SourceDistribution::sample(uint64_t* seed) const // Sample spatial distribution site.r = space_->sample(seed); - double xyz[] {site.r.x, site.r.y, site.r.z}; // Now search to see if location exists in geometry int32_t cell_index, instance; + double xyz[] {site.r.x, site.r.y, site.r.z}; int err = openmc_find_cell(xyz, &cell_index, &instance); found = (err != OPENMC_E_GEOMETRY); @@ -256,6 +229,94 @@ Particle::Bank SourceDistribution::sample(uint64_t* seed) const return site; } +//============================================================================== +// FileSource implementation +//============================================================================== + +FileSource::FileSource(std::string path) +{ + // Check if source file exists + if (!file_exists(path)) { + fatal_error(fmt::format("Source file '{}' does not exist.", path)); + } + + // Read the source from a binary file instead of sampling from some + // assumed source distribution + write_message(6, "Reading source file from {}...", path); + + // Open the binary file + hid_t file_id = file_open(path, 'r', true); + + // Check to make sure this is a source file + std::string filetype; + read_attribute(file_id, "filetype", filetype); + if (filetype != "source" && filetype != "statepoint") { + fatal_error("Specified starting source file not a source file type."); + } + + // Read in the source particles + read_source_bank(file_id, sites_, false); + + // Close file + file_close(file_id); +} + +Particle::Bank FileSource::sample(uint64_t* seed) const +{ + size_t i_site = sites_.size()*prn(seed); + return sites_[i_site]; +} + +//============================================================================== +// CustomSourceWrapper implementation +//============================================================================== + +CustomSourceWrapper::CustomSourceWrapper(std::string path, std::string parameters) +{ +#ifdef HAS_DYNAMIC_LINKING + // Open the library + shared_library_ = dlopen(path.c_str(), RTLD_LAZY); + if (!shared_library_) { + fatal_error("Couldn't open source library " + path); + } + + // reset errors + dlerror(); + + // get the function to create the custom source from the library + auto create_custom_source = reinterpret_cast( + dlsym(shared_library_, "openmc_create_source")); + + // check for any dlsym errors + auto dlsym_error = dlerror(); + if (dlsym_error) { + std::string error_msg = fmt::format("Couldn't open the openmc_create_source symbol: {}", dlsym_error); + dlclose(shared_library_); + fatal_error(error_msg); + } + + // create a pointer to an instance of the custom source + custom_source_ = create_custom_source(parameters); + +#else + fatal_error("Custom source libraries have not yet been implemented for " + "non-POSIX systems"); +#endif +} + +CustomSourceWrapper::~CustomSourceWrapper() +{ + // Make sure custom source is cleared before closing shared library + if (custom_source_.get()) custom_source_.reset(); + +#ifdef HAS_DYNAMIC_LINKING + dlclose(shared_library_); +#else + fatal_error("Custom source libraries have not yet been implemented for " + "non-POSIX systems"); +#endif +} + //============================================================================== // Non-member functions //============================================================================== @@ -264,47 +325,16 @@ void initialize_source() { write_message("Initializing source particles...", 5); - if (!settings::path_source.empty()) { - // Read the source from a binary file instead of sampling from some - // assumed source distribution + // Generation source sites from specified distribution in user input + #pragma omp parallel for + for (int64_t i = 0; i < simulation::work_per_rank; ++i) { + // initialize random number seed + int64_t id = simulation::total_gen*settings::n_particles + + simulation::work_index[mpi::rank] + i + 1; + uint64_t seed = init_seed(id, STREAM_SOURCE); - write_message(6, "Reading source file from {}...", settings::path_source); - - // Open the binary file - hid_t file_id = file_open(settings::path_source, 'r', true); - - // Read the file type - std::string filetype; - read_attribute(file_id, "filetype", filetype); - - // Check to make sure this is a source file - if (filetype != "source" && filetype != "statepoint") { - fatal_error("Specified starting source file not a source file type."); - } - - // Read in the source bank - read_source_bank(file_id); - - // Close file - file_close(file_id); - } else if (!settings::path_source_library.empty()) { - - write_message(6, "Sampling library source {}...", settings::path_source); - - fill_source_bank_custom_source(); - - } else { - // Generation source sites from specified distribution in user input - #pragma omp parallel for - for (int64_t i = 0; i < simulation::work_per_rank; ++i) { - // initialize random number seed - int64_t id = simulation::total_gen*settings::n_particles + - simulation::work_index[mpi::rank] + i + 1; - uint64_t seed = init_seed(id, STREAM_SOURCE); - - // sample external source distribution - simulation::source_bank[i] = sample_external_source(&seed); - } + // sample external source distribution + simulation::source_bank[i] = sample_external_source(&seed); } // Write out initial source @@ -319,15 +349,10 @@ void initialize_source() Particle::Bank sample_external_source(uint64_t* seed) { - // return values from custom source if using - if (!settings::path_source_library.empty()) { - return sample_custom_source_library(seed); - } - // Determine total source strength double total_strength = 0.0; for (auto& s : model::external_sources) - total_strength += s.strength(); + total_strength += s->strength(); // Sample from among multiple source distributions int i = 0; @@ -335,13 +360,13 @@ Particle::Bank sample_external_source(uint64_t* seed) double xi = prn(seed)*total_strength; double c = 0.0; for (; i < model::external_sources.size(); ++i) { - c += model::external_sources[i].strength(); + c += model::external_sources[i]->strength(); if (xi < c) break; } } // Sample source site from i-th source distribution - Particle::Bank site {model::external_sources[i].sample(seed)}; + Particle::Bank site {model::external_sources[i]->sample(seed)}; // If running in MG, convert site.E to group if (!settings::run_CE) { @@ -358,80 +383,4 @@ void free_memory_source() model::external_sources.clear(); } -void load_custom_source_library() -{ -#ifdef HAS_DYNAMIC_LINKING - - // Open the library - custom_source_library = dlopen(settings::path_source_library.c_str(), RTLD_LAZY); - if (!custom_source_library) { - fatal_error("Couldn't open source library " + settings::path_source_library); - } - - // reset errors - dlerror(); - - // get the function to create the CustomSource from the library - auto create_custom_source = reinterpret_cast( - dlsym(custom_source_library, "openmc_create_source")); - - // check for any dlsym errors - auto dlsym_error = dlerror(); - if (dlsym_error) { - std::string error_msg = fmt::format("Couldn't open the openmc_create_source symbol: {}", dlsym_error); - dlclose(custom_source_library); - fatal_error(error_msg); - } - - // create a pointer to an instance of the CustomSource - custom_source = create_custom_source(custom_source_parameters); - -#else - fatal_error("Custom source libraries have not yet been implemented for " - "non-POSIX systems"); -#endif -} - -void close_custom_source_library() -{ - if (custom_source.get()) { - // Make sure the custom source is destroyed before we close it's libary. - custom_source.reset(); - } - -#ifdef HAS_DYNAMIC_LINKING - dlclose(custom_source_library); -#else - fatal_error("Custom source libraries have not yet been implemented for " - "non-POSIX systems"); -#endif -} - -Particle::Bank sample_custom_source_library(uint64_t* seed) -{ - // sample from the instance of the CustomSource - return custom_source->sample(seed); -} - -void fill_source_bank_custom_source() -{ - // Load the custom library - load_custom_source_library(); - - // Generation source sites from specified distribution in the - // library source - for (int64_t i = 0; i < simulation::work_per_rank; ++i) { - // initialize random number seed - int64_t id = (simulation::total_gen + overall_generation()) * - settings::n_particles + simulation::work_index[mpi::rank] + i + 1; - uint64_t seed = init_seed(id, STREAM_SOURCE); - - // sample custom library source - simulation::source_bank[i] = sample_custom_source_library(&seed); - } - - // release the library - close_custom_source_library(); -} - } // namespace openmc diff --git a/src/state_point.cpp b/src/state_point.cpp index 14260051cc..66706a676f 100644 --- a/src/state_point.cpp +++ b/src/state_point.cpp @@ -293,8 +293,6 @@ openmc_statepoint_write(const char* filename, bool* write_source) write_dataset(runtime_group, "synchronizing fission bank", time_bank.elapsed()); write_dataset(runtime_group, "sampling source sites", time_bank_sample.elapsed()); write_dataset(runtime_group, "SEND-RECV source sites", time_bank_sendrecv.elapsed()); - } else { - write_dataset(runtime_group, "sampling source sites", time_sample_source.elapsed()); } write_dataset(runtime_group, "accumulating tallies", time_tallies.elapsed()); write_dataset(runtime_group, "total", time_total.elapsed()); @@ -487,11 +485,11 @@ void load_state_point() + "...", 5); // Open source file - file_id = file_open(settings::path_source.c_str(), 'r', true); + file_id = file_open(settings::path_sourcepoint.c_str(), 'r', true); } // Read source - read_source_bank(file_id); + read_source_bank(file_id, simulation::source_bank, true); } @@ -508,6 +506,12 @@ hid_t h5banktype() { H5Tinsert(postype, "z", HOFFSET(Position, z), H5T_NATIVE_DOUBLE); // Create bank datatype + // + // If you make changes to the compound datatype here, make sure you update: + // - openmc/source.py + // - openmc/statepoint.py + // - docs/source/io_formats/statepoint.rst + // - docs/source/io_formats/source.rst hid_t banktype = H5Tcreate(H5T_COMPOUND, sizeof(struct Particle::Bank)); H5Tinsert(banktype, "r", HOFFSET(Particle::Bank, r), postype); H5Tinsert(banktype, "u", HOFFSET(Particle::Bank, u), postype); @@ -649,43 +653,51 @@ write_source_bank(hid_t group_id) } -void read_source_bank(hid_t group_id) +void read_source_bank(hid_t group_id, std::vector& sites, bool distribute) { hid_t banktype = h5banktype(); // Open the dataset hid_t dset = H5Dopen(group_id, "source_bank", H5P_DEFAULT); - - // Create another data space but for each proc individually - hsize_t dims[] {static_cast(simulation::work_per_rank)}; - hid_t memspace = H5Screate_simple(1, dims, nullptr); - - // Make sure source bank is big enough hid_t dspace = H5Dget_space(dset); - hsize_t dims_all[1]; - H5Sget_simple_extent_dims(dspace, dims_all, nullptr); - if (simulation::work_index[mpi::n_procs] > dims_all[0]) { - fatal_error("Number of source sites in source file is less " - "than number of source particles per generation."); - } + hsize_t n_sites; + H5Sget_simple_extent_dims(dspace, &n_sites, nullptr); - // Select hyperslab for each process - hsize_t start[] {static_cast(simulation::work_index[mpi::rank])}; - H5Sselect_hyperslab(dspace, H5S_SELECT_SET, start, nullptr, dims, nullptr); + // Make sure vector is big enough in case where we're reading entire source on + // each process + if (!distribute) sites.resize(n_sites); + + hid_t memspace; + if (distribute) { + if (simulation::work_index[mpi::n_procs] > n_sites) { + fatal_error("Number of source sites in source file is less " + "than number of source particles per generation."); + } + + // Create another data space but for each proc individually + hsize_t n_sites_local = simulation::work_per_rank; + memspace = H5Screate_simple(1, &n_sites_local, nullptr); + + // Select hyperslab for each process + hsize_t offset = simulation::work_index[mpi::rank]; + H5Sselect_hyperslab(dspace, H5S_SELECT_SET, &offset, nullptr, &n_sites_local, nullptr); + } else { + memspace = H5S_ALL; + } #ifdef PHDF5 // Read data in parallel hid_t plist = H5Pcreate(H5P_DATASET_XFER); H5Pset_dxpl_mpio(plist, H5FD_MPIO_COLLECTIVE); - H5Dread(dset, banktype, memspace, dspace, plist, simulation::source_bank.data()); + H5Dread(dset, banktype, memspace, dspace, plist, sites.data()); H5Pclose(plist); #else - H5Dread(dset, banktype, memspace, dspace, H5P_DEFAULT, simulation::source_bank.data()); + H5Dread(dset, banktype, memspace, dspace, H5P_DEFAULT, sites.data()); #endif // Close all ids H5Sclose(dspace); - H5Sclose(memspace); + if (distribute) H5Sclose(memspace); H5Dclose(dset); H5Tclose(banktype); } diff --git a/src/tallies/tally.cpp b/src/tallies/tally.cpp index d5cc7dfb6f..038bcec649 100644 --- a/src/tallies/tally.cpp +++ b/src/tallies/tally.cpp @@ -632,7 +632,7 @@ void Tally::accumulate() double total_source = 0.0; if (settings::run_mode == RunMode::FIXED_SOURCE) { for (const auto& s : model::external_sources) { - total_source += s.strength(); + total_source += s->strength(); } } else { total_source = 1.0; diff --git a/src/tallies/tally_scoring.cpp b/src/tallies/tally_scoring.cpp index 396ab2f82b..e936c10d90 100644 --- a/src/tallies/tally_scoring.cpp +++ b/src/tallies/tally_scoring.cpp @@ -1566,17 +1566,17 @@ score_general_mg(Particle& p, int i_tally, int start_index, int filter_index, score = p.wgt_last_ * flux; if (i_nuclide >= 0) { score *= atom_density * nuc_xs.get_xs( - MgxsType::SCATTER_FMU_MULT, p.g_last_, &p.g_, &p.mu_, nullptr) + MgxsType::SCATTER_FMU, p.g_last_, &p.g_, &p.mu_, nullptr) / macro_xs.get_xs( - MgxsType::SCATTER_FMU_MULT, p.g_last_, &p.g_, &p.mu_, nullptr); + MgxsType::SCATTER_FMU, p.g_last_, &p.g_, &p.mu_, nullptr); } } else { if (i_nuclide >= 0) { score = atom_density * flux * nuc_xs.get_xs( - MgxsType::SCATTER_MULT, p_g, nullptr, &p.mu_, nullptr); + MgxsType::SCATTER, p_g, nullptr, &p.mu_, nullptr); } else { score = flux * macro_xs.get_xs( - MgxsType::SCATTER_MULT, p_g, nullptr, &p.mu_, nullptr); + MgxsType::SCATTER, p_g, nullptr, &p.mu_, nullptr); } } break; @@ -1595,16 +1595,16 @@ score_general_mg(Particle& p, int i_tally, int start_index, int filter_index, // adjust the score by the actual probability for that nuclide. if (i_nuclide >= 0) { score *= atom_density - * nuc_xs.get_xs(MgxsType::SCATTER_FMU, p.g_last_, &p.g_, + * nuc_xs.get_xs(MgxsType::NU_SCATTER_FMU, p.g_last_, &p.g_, &p.mu_, nullptr) - / macro_xs.get_xs(MgxsType::SCATTER_FMU, p.g_last_, &p.g_, + / macro_xs.get_xs(MgxsType::NU_SCATTER_FMU, p.g_last_, &p.g_, &p.mu_, nullptr); } } else { if (i_nuclide >= 0) { - score = atom_density * flux * nuc_xs.get_xs(MgxsType::SCATTER, p_g); + score = atom_density * flux * nuc_xs.get_xs(MgxsType::NU_SCATTER, p_g); } else { - score = flux * macro_xs.get_xs(MgxsType::SCATTER, p_g); + score = flux * macro_xs.get_xs(MgxsType::NU_SCATTER, p_g); } } break; @@ -1995,13 +1995,13 @@ score_general_mg(Particle& p, int i_tally, int start_index, int filter_index, for (auto d_bin = 0; d_bin < filt.n_bins(); ++d_bin) { auto d = filt.groups()[d_bin] - 1; if (i_nuclide >= 0) { - score += atom_density * flux + score = atom_density * flux * nuc_xs.get_xs(MgxsType::DECAY_RATE, p_g, nullptr, nullptr, &d) * nuc_xs.get_xs(MgxsType::DELAYED_NU_FISSION, p_g, nullptr, nullptr, &d); } else { - score += flux + score = flux * macro_xs.get_xs(MgxsType::DECAY_RATE, p_g, nullptr, nullptr, &d) * macro_xs.get_xs(MgxsType::DELAYED_NU_FISSION, p_g, nullptr, diff --git a/src/timer.cpp b/src/timer.cpp index ff1d91b3a1..395fa0988f 100644 --- a/src/timer.cpp +++ b/src/timer.cpp @@ -16,7 +16,6 @@ Timer time_finalize; Timer time_inactive; Timer time_initialize; Timer time_read_xs; -Timer time_sample_source; Timer time_statepoint; Timer time_tallies; Timer time_total; @@ -76,7 +75,6 @@ void reset_timers() simulation::time_inactive.reset(); simulation::time_initialize.reset(); simulation::time_read_xs.reset(); - simulation::time_sample_source.reset(); simulation::time_statepoint.reset(); simulation::time_tallies.reset(); simulation::time_total.reset(); diff --git a/src/xsdata.cpp b/src/xsdata.cpp index d4698e2a08..ff360c0529 100644 --- a/src/xsdata.cpp +++ b/src/xsdata.cpp @@ -529,12 +529,25 @@ XsData::combine(const std::vector& those_xs, kappa_fission += scalar * that->kappa_fission; fission += scalar * that->fission; delayed_nu_fission += scalar * that->delayed_nu_fission; - chi_prompt += scalar * that->chi_prompt; - chi_delayed += scalar * that->chi_delayed; + chi_prompt += scalar * + xt::view(xt::sum(that->prompt_nu_fission, {1}), + xt::all(), xt::newaxis(), xt::newaxis()) * + that->chi_prompt; + chi_delayed += scalar * + xt::view(xt::sum(that->delayed_nu_fission, {2}), + xt::all(), xt::all(), xt::newaxis(), xt::newaxis()) * + that->chi_delayed; } decay_rate += scalar * that->decay_rate; } + // Ensure the chi_prompt and chi_delayed are normalized to 1 for each + // azimuthal angle and delayed group (for chi_delayed) + chi_prompt /= + xt::view(xt::sum(chi_prompt, {2}), xt::all(), xt::all(), xt::newaxis()); + chi_delayed /= xt::view(xt::sum(chi_delayed, {3}), xt::all(), xt::all(), + xt::all(), xt::newaxis()); + // Allow the ScattData object to combine itself for (size_t a = 0; a < total.shape()[0]; a++) { // Build vector of the scattering objects to incorporate diff --git a/tests/regression_tests/cmfd_feed/results_true.dat b/tests/regression_tests/cmfd_feed/results_true.dat index ea25c88565..85498af19c 100644 --- a/tests/regression_tests/cmfd_feed/results_true.dat +++ b/tests/regression_tests/cmfd_feed/results_true.dat @@ -16,7 +16,7 @@ tally 1: 3.347757E+01 1.124264E+02 2.931336E+01 -8.607238E+01 +8.607239E+01 2.182947E+01 4.789565E+01 1.147668E+01 @@ -378,7 +378,7 @@ tally 5: 5.253064E+00 1.396224E+00 2.996497E+01 -4.508839E+01 +4.508840E+01 3.818076E+00 7.509442E-01 1.574994E+01 @@ -461,17 +461,17 @@ cmfd dominance ratio cmfd openmc source comparison 6.959834E-03 5.655657E-03 -3.886186E-03 +3.886185E-03 4.035116E-03 3.043277E-03 -5.455474E-03 -4.515310E-03 +5.455475E-03 +4.515311E-03 2.439840E-03 2.114032E-03 -2.673131E-03 +2.673132E-03 2.431749E-03 4.330928E-03 -3.404646E-03 +3.404647E-03 3.680298E-03 3.309620E-03 3.705541E-03 diff --git a/tests/regression_tests/cmfd_feed_2g/results_true.dat b/tests/regression_tests/cmfd_feed_2g/results_true.dat index d928b33e8a..4b3dc3c960 100644 --- a/tests/regression_tests/cmfd_feed_2g/results_true.dat +++ b/tests/regression_tests/cmfd_feed_2g/results_true.dat @@ -80,7 +80,7 @@ tally 3: 0.000000E+00 0.000000E+00 1.796382E-02 -3.190855E-05 +3.190854E-05 4.343238E+00 9.514040E-01 3.504683E+00 @@ -90,7 +90,7 @@ tally 3: 9.818871E+01 4.822799E+02 8.401346E-01 -3.664038E-02 +3.664037E-02 6.130607E+01 1.882837E+02 0.000000E+00 @@ -212,7 +212,7 @@ tally 4: 0.000000E+00 0.000000E+00 0.000000E+00 -9.042232E+00 +9.042233E+00 4.097018E+00 3.711597E+01 6.891834E+01 @@ -256,7 +256,7 @@ tally 4: 4.161211E+00 3.715168E+01 6.904544E+01 -9.042232E+00 +9.042233E+00 4.097018E+00 3.711597E+01 6.891834E+01 @@ -314,7 +314,7 @@ tally 5: 1.007512E+02 5.078162E+02 1.403236E+01 -9.884346E+00 +9.884347E+00 4.598486E+01 1.058070E+02 6.194677E+01 @@ -377,13 +377,13 @@ cmfd balance 4.16856E-04 6.38469E-04 3.92822E-04 -3.78984E-04 +3.78983E-04 2.68486E-04 4.84991E-04 1.08402E-03 -1.09177E-03 +1.09178E-03 5.45977E-04 -4.45554E-04 +4.45555E-04 4.01147E-04 3.71025E-04 3.57715E-04 @@ -408,21 +408,21 @@ cmfd dominance ratio 5.996E-03 cmfd openmc source comparison 1.931386E-05 -2.839161E-05 -1.407963E-05 -6.718156E-06 -9.164199E-06 -1.382540E-05 +2.839162E-05 +1.407962E-05 +6.718148E-06 +9.164193E-06 +1.382539E-05 2.871606E-05 4.192300E-05 -5.327515E-05 +5.327516E-05 6.566500E-05 -6.655540E-05 +6.655541E-05 6.034977E-05 6.004677E-05 -5.711622E-05 -6.271263E-05 -6.425362E-05 +5.711623E-05 +6.271264E-05 +6.425363E-05 cmfd source 2.510278E-01 2.480592E-01 diff --git a/tests/regression_tests/cmfd_feed_expanding_window/results_true.dat b/tests/regression_tests/cmfd_feed_expanding_window/results_true.dat index 897f9e9a88..8253d82c33 100644 --- a/tests/regression_tests/cmfd_feed_expanding_window/results_true.dat +++ b/tests/regression_tests/cmfd_feed_expanding_window/results_true.dat @@ -37,7 +37,7 @@ tally 2: 3.708857E+00 1.375562E+01 2.698010E+00 -7.279259E+00 +7.279260E+00 4.233192E+00 1.791991E+01 3.023990E+00 @@ -51,11 +51,11 @@ tally 2: 2.497751E+00 6.238760E+00 2.974675E+00 -8.848691E+00 +8.848690E+00 2.121163E+00 4.499332E+00 2.329248E+00 -5.425398E+00 +5.425397E+00 1.658233E+00 2.749736E+00 1.158552E+00 @@ -109,7 +109,7 @@ tally 4: 0.000000E+00 0.000000E+00 1.420707E-01 -2.018410E-02 +2.018409E-02 2.633150E-01 6.933479E-02 0.000000E+00 @@ -131,7 +131,7 @@ tally 4: 2.633150E-01 6.933479E-02 1.420707E-01 -2.018410E-02 +2.018409E-02 2.628613E-01 6.909608E-02 3.590382E-01 @@ -229,7 +229,7 @@ tally 4: 4.909661E-01 2.410477E-01 5.152690E-01 -2.655022E-01 +2.655021E-01 4.788649E-01 2.293116E-01 0.000000E+00 @@ -251,7 +251,7 @@ tally 4: 4.788649E-01 2.293116E-01 5.152690E-01 -2.655022E-01 +2.655021E-01 4.266876E-01 1.820623E-01 3.401342E-01 @@ -277,7 +277,7 @@ tally 4: 4.266876E-01 1.820623E-01 3.724186E-01 -1.386957E-01 +1.386956E-01 2.560013E-01 6.553669E-02 0.000000E+00 @@ -299,7 +299,7 @@ tally 4: 2.560013E-01 6.553669E-02 3.724186E-01 -1.386957E-01 +1.386956E-01 2.892134E-01 8.364439E-02 1.556176E-01 @@ -441,13 +441,13 @@ cmfd dominance ratio cmfd openmc source comparison 7.459013E-03 5.012869E-03 -1.770224E-03 -5.242540E-03 -3.888027E-03 +1.770225E-03 +5.242539E-03 +3.888028E-03 6.653433E-03 8.839928E-03 -5.456904E-03 -5.668412E-03 +5.456903E-03 +5.668411E-03 4.016377E-03 4.179381E-03 cmfd source diff --git a/tests/regression_tests/cmfd_feed_ng/results_true.dat b/tests/regression_tests/cmfd_feed_ng/results_true.dat index d9660f7bb5..7074114598 100644 --- a/tests/regression_tests/cmfd_feed_ng/results_true.dat +++ b/tests/regression_tests/cmfd_feed_ng/results_true.dat @@ -572,7 +572,7 @@ cmfd entropy 1.999693E+00 cmfd balance 8.98944E-04 -4.45874E-04 +4.45875E-04 2.18562E-04 2.83412E-04 3.60924E-04 @@ -599,13 +599,13 @@ cmfd openmc source comparison 2.585546E-05 2.217204E-05 2.121913E-05 -9.253928E-06 -2.940947E-05 -3.083596E-05 -2.547491E-05 -2.602691E-05 -2.561169E-05 -2.816825E-05 +9.253920E-06 +2.940945E-05 +3.083595E-05 +2.547490E-05 +2.602689E-05 +2.561168E-05 +2.816824E-05 cmfd source 2.417661E-01 2.547768E-01 diff --git a/tests/regression_tests/cmfd_feed_ref_d/results_true.dat b/tests/regression_tests/cmfd_feed_ref_d/results_true.dat index b1f14ac58f..2f0d4713cd 100644 --- a/tests/regression_tests/cmfd_feed_ref_d/results_true.dat +++ b/tests/regression_tests/cmfd_feed_ref_d/results_true.dat @@ -1,7 +1,7 @@ k-combined: 1.165408E+00 1.127320E-02 tally 1: -1.141008E+01 +1.141009E+01 1.305436E+01 2.074878E+01 4.311543E+01 @@ -29,7 +29,7 @@ tally 2: 1.991651E+00 3.966673E+00 1.411802E+00 -1.993185E+00 +1.993186E+00 2.978294E+00 8.870233E+00 2.130084E+00 @@ -63,7 +63,7 @@ tally 2: 8.282626E-01 6.860190E-01 tally 3: -7.459524E-01 +7.459525E-01 5.564451E-01 4.877161E-02 2.378670E-03 @@ -345,10 +345,10 @@ tally 4: 0.000000E+00 0.000000E+00 tally 5: -7.459524E-01 +7.459525E-01 5.564451E-01 1.149859E-01 -1.322176E-02 +1.322177E-02 1.356729E+00 1.840713E+00 1.801152E-01 @@ -362,7 +362,7 @@ tally 5: 3.360312E-01 1.129170E-01 2.909427E+00 -8.464764E+00 +8.464765E+00 4.095398E-01 1.677229E-01 2.805095E+00 @@ -442,13 +442,13 @@ cmfd openmc source comparison 7.433111E-03 5.006211E-03 1.766072E-03 -5.184425E-03 -3.864321E-03 -6.617152E-03 +5.184426E-03 +3.864323E-03 +6.617153E-03 8.841210E-03 -5.454747E-03 -5.652690E-03 -4.006767E-03 +5.454745E-03 +5.652688E-03 +4.006766E-03 4.167617E-03 cmfd source 4.116746E-02 diff --git a/tests/regression_tests/cmfd_feed_rolling_window/results_true.dat b/tests/regression_tests/cmfd_feed_rolling_window/results_true.dat index 0974fcb8be..5d3ea4ec9d 100644 --- a/tests/regression_tests/cmfd_feed_rolling_window/results_true.dat +++ b/tests/regression_tests/cmfd_feed_rolling_window/results_true.dat @@ -31,7 +31,7 @@ tally 2: 1.324803E+00 1.755104E+00 2.585263E+00 -6.683587E+00 +6.683586E+00 1.840969E+00 3.389167E+00 3.737263E+00 @@ -41,7 +41,7 @@ tally 2: 3.989056E+00 1.591257E+01 2.843382E+00 -8.084820E+00 +8.084819E+00 3.951710E+00 1.561601E+01 2.838216E+00 @@ -54,7 +54,7 @@ tally 2: 1.050543E+01 2.315684E+00 5.362392E+00 -2.459493E+00 +2.459494E+00 6.049108E+00 1.734344E+00 3.007949E+00 @@ -72,7 +72,7 @@ tally 3: 7.284456E-02 5.306329E-03 1.779821E+00 -3.167762E+00 +3.167761E+00 1.110012E-01 1.232127E-02 2.586020E+00 @@ -92,7 +92,7 @@ tally 3: 1.503142E-01 2.259435E-02 2.233122E+00 -4.986832E+00 +4.986833E+00 1.456891E-01 2.122532E-02 1.682929E+00 @@ -301,7 +301,7 @@ tally 4: 4.201532E-01 1.765287E-01 2.898817E-01 -8.403142E-02 +8.403143E-02 1.509185E-01 2.277639E-02 0.000000E+00 @@ -323,7 +323,7 @@ tally 4: 1.509185E-01 2.277639E-02 2.898817E-01 -8.403142E-02 +8.403143E-02 1.482175E-01 2.196844E-02 0.000000E+00 @@ -354,7 +354,7 @@ tally 5: 1.458271E-01 2.126554E-02 1.779821E+00 -3.167762E+00 +3.167761E+00 2.705917E-01 7.321987E-02 2.584069E+00 @@ -374,9 +374,9 @@ tally 5: 3.296244E-01 1.086523E-01 2.233122E+00 -4.986832E+00 +4.986833E+00 3.106254E-01 -9.648813E-02 +9.648814E-02 1.682929E+00 2.832250E+00 2.709632E-01 @@ -440,16 +440,16 @@ cmfd dominance ratio 5.321E-01 cmfd openmc source comparison 7.693485E-03 -4.158805E-03 +4.158806E-03 2.962505E-03 -4.415044E-03 -2.304495E-03 -7.921580E-03 -8.609203E-03 -8.945198E-03 -8.054204E-03 +4.415043E-03 +2.304496E-03 +7.921579E-03 +8.609204E-03 +8.945200E-03 +8.054206E-03 1.164189E-02 -5.945645E-03 +5.945644E-03 cmfd source 4.077779E-02 6.659143E-02 diff --git a/tests/regression_tests/cmfd_restart/results_true.dat b/tests/regression_tests/cmfd_restart/results_true.dat index ea25c88565..85498af19c 100644 --- a/tests/regression_tests/cmfd_restart/results_true.dat +++ b/tests/regression_tests/cmfd_restart/results_true.dat @@ -16,7 +16,7 @@ tally 1: 3.347757E+01 1.124264E+02 2.931336E+01 -8.607238E+01 +8.607239E+01 2.182947E+01 4.789565E+01 1.147668E+01 @@ -378,7 +378,7 @@ tally 5: 5.253064E+00 1.396224E+00 2.996497E+01 -4.508839E+01 +4.508840E+01 3.818076E+00 7.509442E-01 1.574994E+01 @@ -461,17 +461,17 @@ cmfd dominance ratio cmfd openmc source comparison 6.959834E-03 5.655657E-03 -3.886186E-03 +3.886185E-03 4.035116E-03 3.043277E-03 -5.455474E-03 -4.515310E-03 +5.455475E-03 +4.515311E-03 2.439840E-03 2.114032E-03 -2.673131E-03 +2.673132E-03 2.431749E-03 4.330928E-03 -3.404646E-03 +3.404647E-03 3.680298E-03 3.309620E-03 3.705541E-03 diff --git a/tests/regression_tests/cpp_driver/driver.cpp b/tests/regression_tests/cpp_driver/driver.cpp index f6fde30fd3..3b4bd1daa2 100644 --- a/tests/regression_tests/cpp_driver/driver.cpp +++ b/tests/regression_tests/cpp_driver/driver.cpp @@ -2,6 +2,7 @@ #include "openmc/capi.h" #include "openmc/cell.h" #include "openmc/geometry.h" +#include "openmc/message_passing.h" #include "openmc/summary.h" #include "openmc/tallies/filter.h" #include "openmc/tallies/filter_cell.h" @@ -48,7 +49,11 @@ int main(int argc, char** argv) { // the summary file will be used to check that // temperatures were set correctly so clear // error output can be provided +#ifdef OPENMC_MPI + if (openmc::mpi::master) openmc::write_summary(); +#else openmc::write_summary(); +#endif openmc_run(); openmc_finalize(); diff --git a/tests/regression_tests/mg_convert/inputs_true.dat b/tests/regression_tests/mg_convert/inputs_true.dat index e2c3a01fa7..9db9b7d7c3 100644 --- a/tests/regression_tests/mg_convert/inputs_true.dat +++ b/tests/regression_tests/mg_convert/inputs_true.dat @@ -10,7 +10,7 @@ ./mgxs.h5 - + diff --git a/tests/regression_tests/mg_convert/results_true.dat b/tests/regression_tests/mg_convert/results_true.dat index a52b929dcf..5a17fe1073 100644 --- a/tests/regression_tests/mg_convert/results_true.dat +++ b/tests/regression_tests/mg_convert/results_true.dat @@ -1,24 +1,24 @@ k-combined: -9.930873E-01 2.221904E-03 +9.834385E-01 7.095193E-03 k-combined: -9.948148E-01 1.216270E-03 +9.936965E-01 4.118371E-03 k-combined: -9.930873E-01 2.221904E-03 +9.834385E-01 7.095193E-03 k-combined: -9.755034E-01 6.178296E-03 +9.977232E-01 1.084193E-02 k-combined: -9.738059E-01 4.529068E-03 +9.945011E-01 5.571771E-03 k-combined: -9.866847E-01 9.485912E-03 +9.982627E-01 2.662444E-03 k-combined: -9.755024E-01 6.179047E-03 +9.977232E-01 1.084193E-02 k-combined: -9.738061E-01 4.529462E-03 +9.945007E-01 5.571589E-03 k-combined: -9.866835E-01 9.485832E-03 +9.982620E-01 2.662746E-03 k-combined: -9.719024E-01 4.213166E-03 +1.000071E+00 3.364791E-03 k-combined: -9.930873E-01 2.221904E-03 +9.834385E-01 7.095193E-03 k-combined: -9.930873E-01 2.221904E-03 +9.834385E-01 7.095193E-03 diff --git a/tests/regression_tests/mg_convert/test.py b/tests/regression_tests/mg_convert/test.py index 4cc6b656a2..f22c15dc07 100755 --- a/tests/regression_tests/mg_convert/test.py +++ b/tests/regression_tests/mg_convert/test.py @@ -67,7 +67,7 @@ class MGXSTestHarness(PyAPITestHarness): # Instantiate some Materials and register the appropriate objects mat = openmc.Material(material_id=1, name='UO2 fuel') - mat.set_density('macro', 1.0) + mat.set_density('macro', 1.1) mat.add_macroscopic(uo2_data) # Instantiate a Materials collection and export to XML diff --git a/tests/regression_tests/mgxs_library_hdf5/results_true.dat b/tests/regression_tests/mgxs_library_hdf5/results_true.dat index 4a796b0a51..4aa243b9e3 100644 --- a/tests/regression_tests/mgxs_library_hdf5/results_true.dat +++ b/tests/regression_tests/mgxs_library_hdf5/results_true.dat @@ -193,10 +193,18 @@ domain=1 type=beta [1.21876271e-04 8.77101834e-05] [4.95946084e-05 3.67414816e-05]] domain=1 type=decay-rate -[1.33568413e-02 3.25887984e-02 1.21105565e-01 3.06139633e-01 - 8.62763808e-01 2.89789222e+00] -[9.57055016e-04 2.28222032e-03 8.35436401e-03 2.06734948e-02 - 5.63019289e-02 1.89486538e-01] +[[1.33568413e-02] + [3.25887984e-02] + [1.21105565e-01] + [3.06139633e-01] + [8.62763808e-01] + [2.89789222e+00]] +[[9.57055016e-04] + [2.28222032e-03] + [8.35436401e-03] + [2.06734948e-02] + [5.63019289e-02] + [1.89486538e-01]] domain=1 type=delayed-nu-fission matrix [[[0.00000000e+00 0.00000000e+00] [0.00000000e+00 0.00000000e+00]] diff --git a/tests/regression_tests/mgxs_library_no_nuclides/inputs_true.dat b/tests/regression_tests/mgxs_library_no_nuclides/inputs_true.dat index e629fa115e..0d9dbf8215 100644 --- a/tests/regression_tests/mgxs_library_no_nuclides/inputs_true.dat +++ b/tests/regression_tests/mgxs_library_no_nuclides/inputs_true.dat @@ -68,13 +68,13 @@ 0.0 20000000.0 - + 1 2 3 4 5 6 - + 2 - + 3 @@ -438,883 +438,1423 @@ tracklength - 1 73 2 + 1 2 total - delayed-nu-fission + (n,elastic) tracklength - 1 73 52 + 1 2 total - delayed-nu-fission - analog + flux + tracklength - 1 73 5 + 1 2 total - delayed-nu-fission - analog + (n,level) + tracklength 1 2 total - nu-fission + flux tracklength - 1 73 2 + 1 2 total - delayed-nu-fission + (n,2n) tracklength - 1 73 + 1 2 total - delayed-nu-fission + flux tracklength - 1 73 + 1 2 total - decay-rate + (n,na) tracklength 1 2 total flux - analog + tracklength - 1 73 2 5 + 1 2 total - delayed-nu-fission - analog + (n,nc) + tracklength - 87 2 + 1 2 total flux tracklength - 87 2 + 1 2 total - total + (n,gamma) tracklength - 87 2 + 1 2 total flux tracklength - 87 2 + 1 2 total - total + (n,a) tracklength - 87 2 + 1 2 total flux - analog + tracklength - 87 5 6 + 1 2 total - scatter - analog + (n,Xa) + tracklength - 87 2 + 1 2 total flux tracklength - 87 2 + 1 2 total - total + heating tracklength - 87 2 + 1 2 total flux - analog + tracklength - 87 5 6 + 1 2 total - nu-scatter - analog + damage-energy + tracklength - 87 2 + 1 2 total flux tracklength - 87 2 + 1 2 total - absorption + (n,n1) tracklength - 87 2 + 1 2 total flux tracklength - 87 2 + 1 2 + total + (n,a0) + tracklength + + + 1 2 + total + flux + analog + + + 1 2 5 + total + (n,nc) + analog + + + 1 2 + total + flux + analog + + + 1 2 5 + total + (n,n1) + analog + + + 1 2 + total + flux + analog + + + 1 2 5 + total + (n,2n) + analog + + + 1 2 + total + flux + tracklength + + + 1 106 2 + total + delayed-nu-fission + tracklength + + + 1 106 52 + total + delayed-nu-fission + analog + + + 1 106 5 + total + delayed-nu-fission + analog + + + 1 2 + total + nu-fission + tracklength + + + 1 106 2 + total + delayed-nu-fission + tracklength + + + 1 106 + total + delayed-nu-fission + tracklength + + + 1 106 + total + decay-rate + tracklength + + + 1 2 + total + flux + analog + + + 1 106 2 5 + total + delayed-nu-fission + analog + + + 120 2 + total + flux + tracklength + + + 120 2 + total + total + tracklength + + + 120 2 + total + flux + tracklength + + + 120 2 + total + total + tracklength + + + 120 2 + total + flux + analog + + + 120 5 6 + total + scatter + analog + + + 120 2 + total + flux + tracklength + + + 120 2 + total + total + tracklength + + + 120 2 + total + flux + analog + + + 120 5 6 + total + nu-scatter + analog + + + 120 2 + total + flux + tracklength + + + 120 2 total absorption tracklength - - 87 2 - total - fission - tracklength - - - 87 2 - total - flux - tracklength - - - 87 2 - total - fission - tracklength - - - 87 2 - total - flux - tracklength - - - 87 2 - total - nu-fission - tracklength - - - 87 2 - total - flux - tracklength - - - 87 2 - total - kappa-fission - tracklength - - - 87 2 - total - flux - tracklength - - - 87 2 - total - scatter - tracklength - - - 87 2 - total - flux - analog - - - 87 2 - total - nu-scatter - analog - - - 87 2 - total - flux - analog - - - 87 2 5 28 - total - scatter - analog - - - 87 2 - total - flux - analog - - - 87 2 5 28 - total - nu-scatter - analog - - - 87 2 5 - total - nu-scatter - analog - - - 87 2 5 - total - scatter - analog - - - 87 2 - total - flux - analog - - - 87 2 5 - total - nu-fission - analog - - - 87 2 5 - total - scatter - analog - - - 87 2 - total - flux - tracklength - - - 87 2 - total - scatter - tracklength - - - 87 2 5 28 - total - scatter - analog - - - 87 2 - total - flux - tracklength - - - 87 2 - total - scatter - tracklength - - - 87 2 5 28 - total - scatter - analog - - - 87 2 5 - total - nu-scatter - analog - - - 87 52 - total - nu-fission - analog - - 87 5 + 120 2 total - nu-fission - analog + flux + tracklength - 87 52 + 120 2 total - prompt-nu-fission - analog + absorption + tracklength - 87 5 + 120 2 total - prompt-nu-fission - analog + fission + tracklength - 87 2 + 120 2 total flux tracklength - 87 2 + 120 2 total - inverse-velocity + fission tracklength - 87 2 + 120 2 total flux tracklength - 87 2 + 120 2 total - prompt-nu-fission + nu-fission tracklength - 87 2 + 120 2 total flux - analog + tracklength - 87 2 5 + 120 2 total - prompt-nu-fission - analog + kappa-fission + tracklength - 87 2 + 120 2 total flux tracklength - 87 2 + 120 2 total - total + scatter tracklength - 87 2 + 120 2 total flux analog - 87 5 6 + 120 2 + total + nu-scatter + analog + + + 120 2 + total + flux + analog + + + 120 2 5 28 total scatter analog - - 87 2 - total - flux - tracklength - - - 87 2 - total - total - tracklength - - 87 2 + 120 2 total flux analog - 87 5 6 + 120 2 5 28 total nu-scatter analog - 87 2 + 120 2 5 total - flux - tracklength + nu-scatter + analog - 87 73 2 - total - delayed-nu-fission - tracklength - - - 87 73 52 - total - delayed-nu-fission - analog - - - 87 73 5 - total - delayed-nu-fission - analog - - - 87 2 - total - nu-fission - tracklength - - - 87 73 2 - total - delayed-nu-fission - tracklength - - - 87 73 - total - delayed-nu-fission - tracklength - - - 87 73 - total - decay-rate - tracklength - - - 87 2 - total - flux - analog - - - 87 73 2 5 - total - delayed-nu-fission - analog - - - 173 2 - total - flux - tracklength - - - 173 2 - total - total - tracklength - - - 173 2 - total - flux - tracklength - - - 173 2 - total - total - tracklength - - - 173 2 - total - flux - analog - - - 173 5 6 + 120 2 5 total scatter analog + + 120 2 + total + flux + analog + + + 120 2 5 + total + nu-fission + analog + + + 120 2 5 + total + scatter + analog + + + 120 2 + total + flux + tracklength + + + 120 2 + total + scatter + tracklength + + + 120 2 5 28 + total + scatter + analog + + + 120 2 + total + flux + tracklength + + + 120 2 + total + scatter + tracklength + + + 120 2 5 28 + total + scatter + analog + + + 120 2 5 + total + nu-scatter + analog + + + 120 52 + total + nu-fission + analog + + + 120 5 + total + nu-fission + analog + + + 120 52 + total + prompt-nu-fission + analog + + + 120 5 + total + prompt-nu-fission + analog + - 173 2 + 120 2 total flux tracklength - 173 2 + 120 2 total - total + inverse-velocity tracklength - 173 2 + 120 2 total flux - analog + tracklength - 173 5 6 + 120 2 total - nu-scatter - analog + prompt-nu-fission + tracklength - 173 2 + 120 2 total flux - tracklength + analog - 173 2 + 120 2 5 total - absorption - tracklength + prompt-nu-fission + analog - 173 2 + 120 2 total flux tracklength - 173 2 + 120 2 total - absorption + total tracklength - 173 2 - total - fission - tracklength - - - 173 2 + 120 2 total flux - tracklength + analog + + + 120 5 6 + total + scatter + analog - 173 2 + 120 2 total - fission + flux tracklength - 173 2 + 120 2 total - flux + total tracklength - 173 2 - total - nu-fission - tracklength - - - 173 2 + 120 2 total flux - tracklength + analog + + + 120 5 6 + total + nu-scatter + analog - 173 2 + 120 2 total - kappa-fission + flux tracklength - 173 2 + 120 2 total - flux + (n,elastic) tracklength - 173 2 + 120 2 total - scatter + flux tracklength - 173 2 + 120 2 total - flux - analog + (n,level) + tracklength - 173 2 + 120 2 total - nu-scatter - analog + flux + tracklength - 173 2 + 120 2 total - flux - analog + (n,2n) + tracklength - 173 2 5 28 + 120 2 total - scatter - analog + flux + tracklength - 173 2 + 120 2 total - flux - analog + (n,na) + tracklength - 173 2 5 28 - total - nu-scatter - analog - - - 173 2 5 - total - nu-scatter - analog - - - 173 2 5 - total - scatter - analog - - - 173 2 + 120 2 total flux - analog + tracklength + + + 120 2 + total + (n,nc) + tracklength + + + 120 2 + total + flux + tracklength + + + 120 2 + total + (n,gamma) + tracklength - 173 2 5 + 120 2 total - nu-fission - analog + flux + tracklength - 173 2 5 + 120 2 total - scatter - analog + (n,a) + tracklength - 173 2 + 120 2 total flux tracklength - 173 2 + 120 2 total - scatter + (n,Xa) tracklength - 173 2 5 28 - total - scatter - analog - - - 173 2 + 120 2 total flux tracklength + + 120 2 + total + heating + tracklength + - 173 2 + 120 2 total - scatter + flux tracklength - 173 2 5 28 + 120 2 total - scatter - analog + damage-energy + tracklength - 173 2 5 + 120 2 total - nu-scatter - analog + flux + tracklength - 173 52 + 120 2 total - nu-fission - analog + (n,n1) + tracklength - 173 5 + 120 2 total - nu-fission - analog + flux + tracklength - 173 52 + 120 2 total - prompt-nu-fission - analog + (n,a0) + tracklength - 173 5 + 120 2 total - prompt-nu-fission + flux analog - 173 2 + 120 2 5 total - flux - tracklength + (n,nc) + analog - 173 2 + 120 2 total - inverse-velocity - tracklength + flux + analog - 173 2 + 120 2 5 total - flux - tracklength + (n,n1) + analog - 173 2 - total - prompt-nu-fission - tracklength - - - 173 2 + 120 2 total flux analog + + 120 2 5 + total + (n,2n) + analog + - 173 2 5 - total - prompt-nu-fission - analog - - - 173 2 + 120 2 total flux tracklength + + 120 106 2 + total + delayed-nu-fission + tracklength + - 173 2 + 120 106 52 total - total - tracklength + delayed-nu-fission + analog - 173 2 + 120 106 5 total - flux + delayed-nu-fission analog - 173 5 6 - total - scatter - analog - - - 173 2 - total - flux - tracklength - - - 173 2 - total - total - tracklength - - - 173 2 - total - flux - analog - - - 173 5 6 - total - nu-scatter - analog - - - 173 2 - total - flux - tracklength - - - 173 73 2 - total - delayed-nu-fission - tracklength - - - 173 73 52 - total - delayed-nu-fission - analog - - - 173 73 5 - total - delayed-nu-fission - analog - - - 173 2 + 120 2 total nu-fission tracklength - - 173 73 2 + + 120 106 2 total delayed-nu-fission tracklength - - 173 73 + + 120 106 total delayed-nu-fission tracklength - - 173 73 + + 120 106 total decay-rate tracklength - - 173 2 + + 120 2 total flux analog + + 120 106 2 5 + total + delayed-nu-fission + analog + + + 239 2 + total + flux + tracklength + + + 239 2 + total + total + tracklength + + + 239 2 + total + flux + tracklength + + + 239 2 + total + total + tracklength + + + 239 2 + total + flux + analog + + + 239 5 6 + total + scatter + analog + + + 239 2 + total + flux + tracklength + + + 239 2 + total + total + tracklength + - 173 73 2 5 + 239 2 + total + flux + analog + + + 239 5 6 + total + nu-scatter + analog + + + 239 2 + total + flux + tracklength + + + 239 2 + total + absorption + tracklength + + + 239 2 + total + flux + tracklength + + + 239 2 + total + absorption + tracklength + + + 239 2 + total + fission + tracklength + + + 239 2 + total + flux + tracklength + + + 239 2 + total + fission + tracklength + + + 239 2 + total + flux + tracklength + + + 239 2 + total + nu-fission + tracklength + + + 239 2 + total + flux + tracklength + + + 239 2 + total + kappa-fission + tracklength + + + 239 2 + total + flux + tracklength + + + 239 2 + total + scatter + tracklength + + + 239 2 + total + flux + analog + + + 239 2 + total + nu-scatter + analog + + + 239 2 + total + flux + analog + + + 239 2 5 28 + total + scatter + analog + + + 239 2 + total + flux + analog + + + 239 2 5 28 + total + nu-scatter + analog + + + 239 2 5 + total + nu-scatter + analog + + + 239 2 5 + total + scatter + analog + + + 239 2 + total + flux + analog + + + 239 2 5 + total + nu-fission + analog + + + 239 2 5 + total + scatter + analog + + + 239 2 + total + flux + tracklength + + + 239 2 + total + scatter + tracklength + + + 239 2 5 28 + total + scatter + analog + + + 239 2 + total + flux + tracklength + + + 239 2 + total + scatter + tracklength + + + 239 2 5 28 + total + scatter + analog + + + 239 2 5 + total + nu-scatter + analog + + + 239 52 + total + nu-fission + analog + + + 239 5 + total + nu-fission + analog + + + 239 52 + total + prompt-nu-fission + analog + + + 239 5 + total + prompt-nu-fission + analog + + + 239 2 + total + flux + tracklength + + + 239 2 + total + inverse-velocity + tracklength + + + 239 2 + total + flux + tracklength + + + 239 2 + total + prompt-nu-fission + tracklength + + + 239 2 + total + flux + analog + + + 239 2 5 + total + prompt-nu-fission + analog + + + 239 2 + total + flux + tracklength + + + 239 2 + total + total + tracklength + + + 239 2 + total + flux + analog + + + 239 5 6 + total + scatter + analog + + + 239 2 + total + flux + tracklength + + + 239 2 + total + total + tracklength + + + 239 2 + total + flux + analog + + + 239 5 6 + total + nu-scatter + analog + + + 239 2 + total + flux + tracklength + + + 239 2 + total + (n,elastic) + tracklength + + + 239 2 + total + flux + tracklength + + + 239 2 + total + (n,level) + tracklength + + + 239 2 + total + flux + tracklength + + + 239 2 + total + (n,2n) + tracklength + + + 239 2 + total + flux + tracklength + + + 239 2 + total + (n,na) + tracklength + + + 239 2 + total + flux + tracklength + + + 239 2 + total + (n,nc) + tracklength + + + 239 2 + total + flux + tracklength + + + 239 2 + total + (n,gamma) + tracklength + + + 239 2 + total + flux + tracklength + + + 239 2 + total + (n,a) + tracklength + + + 239 2 + total + flux + tracklength + + + 239 2 + total + (n,Xa) + tracklength + + + 239 2 + total + flux + tracklength + + + 239 2 + total + heating + tracklength + + + 239 2 + total + flux + tracklength + + + 239 2 + total + damage-energy + tracklength + + + 239 2 + total + flux + tracklength + + + 239 2 + total + (n,n1) + tracklength + + + 239 2 + total + flux + tracklength + + + 239 2 + total + (n,a0) + tracklength + + + 239 2 + total + flux + analog + + + 239 2 5 + total + (n,nc) + analog + + + 239 2 + total + flux + analog + + + 239 2 5 + total + (n,n1) + analog + + + 239 2 + total + flux + analog + + + 239 2 5 + total + (n,2n) + analog + + + 239 2 + total + flux + tracklength + + + 239 106 2 + total + delayed-nu-fission + tracklength + + + 239 106 52 + total + delayed-nu-fission + analog + + + 239 106 5 + total + delayed-nu-fission + analog + + + 239 2 + total + nu-fission + tracklength + + + 239 106 2 + total + delayed-nu-fission + tracklength + + + 239 106 + total + delayed-nu-fission + tracklength + + + 239 106 + total + decay-rate + tracklength + + + 239 2 + total + flux + analog + + + 239 106 2 5 total delayed-nu-fission analog diff --git a/tests/regression_tests/mgxs_library_no_nuclides/results_true.dat b/tests/regression_tests/mgxs_library_no_nuclides/results_true.dat index 4dfb7f68a4..398c3e783d 100644 --- a/tests/regression_tests/mgxs_library_no_nuclides/results_true.dat +++ b/tests/regression_tests/mgxs_library_no_nuclides/results_true.dat @@ -1,33 +1,44 @@ +total material group in nuclide mean std. dev. 1 1 1 total 0.414825 0.022793 0 1 2 total 0.660170 0.047519 +transport material group in nuclide mean std. dev. 1 1 1 total 0.363092 0.023838 0 1 2 total 0.644851 0.047675 +nu-transport material group in nuclide mean std. dev. 1 1 1 total 0.363092 0.023838 0 1 2 total 0.644851 0.047675 +absorption material group in nuclide mean std. dev. 1 1 1 total 0.027408 0.002692 0 1 2 total 0.264511 0.023367 +capture material group in nuclide mean std. dev. 1 1 1 total 0.019845 0.002643 0 1 2 total 0.071719 0.025208 +fission material group in nuclide mean std. dev. 1 1 1 total 0.007563 0.000508 0 1 2 total 0.192791 0.017106 +nu-fission material group in nuclide mean std. dev. 1 1 1 total 0.019432 0.001323 0 1 2 total 0.469775 0.041682 +kappa-fission material group in nuclide mean std. dev. 1 1 1 total 1.474570e+06 9.923536e+04 0 1 2 total 3.728689e+07 3.308375e+06 +scatter material group in nuclide mean std. dev. 1 1 1 total 0.387418 0.020626 0 1 2 total 0.395659 0.025125 +nu-scatter material group in nuclide mean std. dev. 1 1 1 total 0.385188 0.026946 0 1 2 total 0.412389 0.015425 +scatter matrix material group in group out legendre nuclide mean std. dev. 12 1 1 1 P0 total 0.384199 0.027001 13 1 1 1 P1 total 0.051870 0.006983 @@ -45,6 +56,7 @@ 1 1 2 2 P1 total 0.016482 0.004502 2 1 2 2 P2 total 0.006371 0.010551 3 1 2 2 P3 total -0.010499 0.010438 +nu-scatter matrix material group in group out legendre nuclide mean std. dev. 12 1 1 1 P0 total 0.384199 0.027001 13 1 1 1 P1 total 0.051870 0.006983 @@ -62,21 +74,25 @@ 1 1 2 2 P1 total 0.016482 0.004502 2 1 2 2 P2 total 0.006371 0.010551 3 1 2 2 P3 total -0.010499 0.010438 +multiplicity matrix material group in group out nuclide mean std. dev. 3 1 1 1 total 1.0 0.078516 2 1 1 2 total 1.0 0.687184 1 1 2 1 total 1.0 1.414214 0 1 2 2 total 1.0 0.041130 +nu-fission matrix material group in group out nuclide mean std. dev. 3 1 1 1 total 0.020142 0.003149 2 1 1 2 total 0.000000 0.000000 1 1 2 1 total 0.454366 0.027426 0 1 2 2 total 0.000000 0.000000 +scatter probability matrix material group in group out nuclide mean std. dev. 3 1 1 1 total 0.997433 0.078224 2 1 1 2 total 0.002567 0.001256 1 1 2 1 total 0.002242 0.002243 0 1 2 2 total 0.997758 0.041053 +consistent scatter matrix material group in group out legendre nuclide mean std. dev. 12 1 1 1 P0 total 0.386423 0.036629 13 1 1 1 P1 total 0.052170 0.007767 @@ -94,6 +110,7 @@ 1 1 2 2 P1 total 0.015813 0.004443 2 1 2 2 P2 total 0.006113 0.010131 3 1 2 2 P3 total -0.010073 0.010037 +consistent nu-scatter matrix material group in group out legendre nuclide mean std. dev. 12 1 1 1 P0 total 0.386423 0.047563 13 1 1 1 P1 total 0.052170 0.008781 @@ -111,33 +128,107 @@ 1 1 2 2 P1 total 0.015813 0.004491 2 1 2 2 P2 total 0.006113 0.010134 3 1 2 2 P3 total -0.010073 0.010045 +chi material group out nuclide mean std. dev. 1 1 1 total 1.0 0.046071 0 1 2 total 0.0 0.000000 +chi-prompt material group out nuclide mean std. dev. 1 1 1 total 1.0 0.051471 0 1 2 total 0.0 0.000000 +inverse-velocity material group in nuclide mean std. dev. 1 1 1 total 5.709324e-08 4.687938e-09 0 1 2 total 2.855739e-06 2.442164e-07 +prompt-nu-fission material group in nuclide mean std. dev. 1 1 1 total 0.019239 0.001310 0 1 2 total 0.466719 0.041411 +prompt-nu-fission matrix material group in group out nuclide mean std. dev. 3 1 1 1 total 0.020142 0.003149 2 1 1 2 total 0.000000 0.000000 1 1 2 1 total 0.445819 0.028675 0 1 2 2 total 0.000000 0.000000 +diffusion-coefficient material group in legendre nuclide mean std. dev. 2 1 1 P0 total 10.942878 12.704137 3 1 1 P1 total 0.918041 0.075837 0 1 2 P0 total 1.370855 0.292448 1 1 2 P1 total 0.516916 0.050251 +nu-diffusion-coefficient material group in legendre nuclide mean std. dev. 2 1 1 P0 total 10.942878 12.704137 3 1 1 P1 total 0.918041 0.075837 0 1 2 P0 total 1.370855 0.292448 1 1 2 P1 total 0.516916 0.050251 +(n,elastic) + material group in nuclide mean std. dev. +1 1 1 total 0.358207 0.019662 +0 1 2 total 0.395659 0.025125 +(n,level) + material group in nuclide mean std. dev. +1 1 1 total 0.000619 0.000049 +0 1 2 total 0.000000 0.000000 +(n,2n) + material group in nuclide mean std. dev. +1 1 1 total 0.000121 0.000054 +0 1 2 total 0.000000 0.000000 +(n,na) + material group in nuclide mean std. dev. +1 1 1 total 9.209364e-11 9.154237e-11 +0 1 2 total 0.000000e+00 0.000000e+00 +(n,nc) + material group in nuclide mean std. dev. +1 1 1 total 0.009458 0.000768 +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 +0 1 2 total 0.071719 0.006262 +(n,a) + material group in nuclide mean std. dev. +1 1 1 total 0.000124 0.000023 +0 1 2 total 0.000000 0.000000 +(n,Xa) + material group in nuclide mean std. dev. +1 1 1 total 0.000124 0.000023 +0 1 2 total 0.000000 0.000000 +heating + material group in nuclide mean std. dev. +1 1 1 total 1.287977e+06 8.806399e+04 +0 1 2 total 3.222710e+07 2.903396e+06 +damage-energy + material group in nuclide mean std. dev. +1 1 1 total 2471.829371 114.012620 +0 1 2 total 1357.269536 120.427363 +(n,n1) + material group in nuclide mean std. dev. +1 1 1 total 0.011877 0.000507 +0 1 2 total 0.000000 0.000000 +(n,a0) + material group in nuclide mean std. dev. +1 1 1 total 0.000115 0.000024 +0 1 2 total 0.000000 0.000000 +(n,nc) matrix + material group in group out nuclide mean std. dev. +3 1 1 1 total 0.010878 0.001184 +2 1 1 2 total 0.000000 0.000000 +1 1 2 1 total 0.000000 0.000000 +0 1 2 2 total 0.000000 0.000000 +(n,n1) matrix + material group in group out nuclide mean std. dev. +3 1 1 1 total 0.011043 0.000937 +2 1 1 2 total 0.000000 0.000000 +1 1 2 1 total 0.000000 0.000000 +0 1 2 2 total 0.000000 0.000000 +(n,2n) matrix + material group in group out nuclide mean std. dev. +3 1 1 1 total 0.0 0.0 +2 1 1 2 total 0.0 0.0 +1 1 2 1 total 0.0 0.0 +0 1 2 2 total 0.0 0.0 +delayed-nu-fission material delayedgroup group in nuclide mean std. dev. 1 1 1 1 total 0.000004 2.897486e-07 3 1 2 1 total 0.000027 1.850037e-06 @@ -151,6 +242,7 @@ 6 1 4 2 total 0.001182 1.048679e-04 8 1 5 2 total 0.000485 4.299445e-05 10 1 6 2 total 0.000203 1.801022e-05 +chi-delayed material delayedgroup group out nuclide mean std. dev. 1 1 1 1 total 0.0 0.000000 3 1 2 1 total 1.0 0.869128 @@ -164,6 +256,7 @@ 6 1 4 2 total 0.0 0.000000 8 1 5 2 total 0.0 0.000000 10 1 6 2 total 0.0 0.000000 +beta material delayedgroup group in nuclide mean std. dev. 1 1 1 1 total 0.000222 0.000018 3 1 2 1 total 0.001388 0.000115 @@ -177,6 +270,7 @@ 6 1 4 2 total 0.002516 0.000273 8 1 5 2 total 0.001031 0.000112 10 1 6 2 total 0.000432 0.000047 +decay-rate material delayedgroup nuclide mean std. dev. 0 1 1 total 0.013355 0.001272 1 1 2 total 0.032600 0.003048 @@ -184,6 +278,7 @@ 3 1 4 total 0.305910 0.027728 4 1 5 total 0.861934 0.075425 5 1 6 total 2.895065 0.253942 +delayed-nu-fission matrix material delayedgroup group in group out nuclide mean std. dev. 3 1 1 1 1 total 0.000000 0.000000 7 1 2 1 1 total 0.000000 0.000000 @@ -209,36 +304,47 @@ 12 1 4 2 2 total 0.000000 0.000000 16 1 5 2 2 total 0.000000 0.000000 20 1 6 2 2 total 0.000000 0.000000 +total material group in nuclide mean std. dev. 1 2 1 total 0.313738 0.015582 0 2 2 total 0.300821 0.028052 +transport material group in nuclide mean std. dev. 1 2 1 total 0.275508 0.017742 0 2 2 total 0.312035 0.032384 +nu-transport material group in nuclide mean std. dev. 1 2 1 total 0.275508 0.017742 0 2 2 total 0.312035 0.032384 +absorption material group in nuclide mean std. dev. 1 2 1 total 0.001575 0.000323 0 2 2 total 0.005400 0.000618 +capture material group in nuclide mean std. dev. 1 2 1 total 0.001575 0.000323 0 2 2 total 0.005400 0.000618 +fission material group in nuclide mean std. dev. 1 2 1 total 0.0 0.0 0 2 2 total 0.0 0.0 +nu-fission material group in nuclide mean std. dev. 1 2 1 total 0.0 0.0 0 2 2 total 0.0 0.0 +kappa-fission material group in nuclide mean std. dev. 1 2 1 total 0.0 0.0 0 2 2 total 0.0 0.0 +scatter material group in nuclide mean std. dev. 1 2 1 total 0.312163 0.015322 0 2 2 total 0.295421 0.027446 +nu-scatter material group in nuclide mean std. dev. 1 2 1 total 0.310121 0.033788 0 2 2 total 0.296264 0.043792 +scatter matrix material group in group out legendre nuclide mean std. dev. 12 2 1 1 P0 total 0.310121 0.033788 13 2 1 1 P1 total 0.038230 0.008484 @@ -256,6 +362,7 @@ 1 2 2 2 P1 total -0.011214 0.016180 2 2 2 2 P2 total 0.008837 0.011504 3 2 2 2 P3 total -0.003270 0.007329 +nu-scatter matrix material group in group out legendre nuclide mean std. dev. 12 2 1 1 P0 total 0.310121 0.033788 13 2 1 1 P1 total 0.038230 0.008484 @@ -273,21 +380,25 @@ 1 2 2 2 P1 total -0.011214 0.016180 2 2 2 2 P2 total 0.008837 0.011504 3 2 2 2 P3 total -0.003270 0.007329 +multiplicity matrix material group in group out nuclide mean std. dev. 3 2 1 1 total 1.0 0.108779 2 2 1 2 total 0.0 0.000000 1 2 2 1 total 0.0 0.000000 0 2 2 2 total 1.0 0.142427 +nu-fission matrix material group in group out nuclide mean std. dev. 3 2 1 1 total 0.0 0.0 2 2 1 2 total 0.0 0.0 1 2 2 1 total 0.0 0.0 0 2 2 2 total 0.0 0.0 +scatter probability matrix material group in group out nuclide mean std. dev. 3 2 1 1 total 1.0 0.108779 2 2 1 2 total 0.0 0.000000 1 2 2 1 total 0.0 0.000000 0 2 2 2 total 1.0 0.142427 +consistent scatter matrix material group in group out legendre nuclide mean std. dev. 12 2 1 1 P0 total 0.312163 0.037253 13 2 1 1 P1 total 0.038481 0.008743 @@ -305,6 +416,7 @@ 1 2 2 2 P1 total -0.011182 0.016162 2 2 2 2 P2 total 0.008811 0.011495 3 2 2 2 P3 total -0.003261 0.007313 +consistent nu-scatter matrix material group in group out legendre nuclide mean std. dev. 12 2 1 1 P0 total 0.312163 0.050407 13 2 1 1 P1 total 0.038481 0.009693 @@ -322,33 +434,107 @@ 1 2 2 2 P1 total -0.011182 0.016240 2 2 2 2 P2 total 0.008811 0.011563 3 2 2 2 P3 total -0.003261 0.007328 +chi material group out nuclide mean std. dev. 1 2 1 total 0.0 0.0 0 2 2 total 0.0 0.0 +chi-prompt material group out nuclide mean std. dev. 1 2 1 total 0.0 0.0 0 2 2 total 0.0 0.0 +inverse-velocity material group in nuclide mean std. dev. 1 2 1 total 5.995979e-08 4.553085e-09 0 2 2 total 2.985490e-06 3.417020e-07 +prompt-nu-fission material group in nuclide mean std. dev. 1 2 1 total 0.0 0.0 0 2 2 total 0.0 0.0 +prompt-nu-fission matrix material group in group out nuclide mean std. dev. 3 2 1 1 total 0.0 0.0 2 2 1 2 total 0.0 0.0 1 2 2 1 total 0.0 0.0 0 2 2 2 total 0.0 0.0 +diffusion-coefficient material group in legendre nuclide mean std. dev. 2 2 1 P0 total 92.158584 948.055013 3 2 1 P1 total 1.209886 0.097583 0 2 2 P0 total 73.145434 834.775399 1 2 2 P1 total 1.068256 0.148711 +nu-diffusion-coefficient material group in legendre nuclide mean std. dev. 2 2 1 P0 total 92.158584 948.055013 3 2 1 P1 total 1.209886 0.097583 0 2 2 P0 total 73.145434 834.775399 1 2 2 P1 total 1.068256 0.148711 +(n,elastic) + material group in nuclide mean std. dev. +1 2 1 total 0.301031 0.014977 +0 2 2 total 0.295421 0.027446 +(n,level) + material group in nuclide mean std. dev. +1 2 1 total 0.0 0.0 +0 2 2 total 0.0 0.0 +(n,2n) + material group in nuclide mean std. dev. +1 2 1 total 0.000005 0.000005 +0 2 2 total 0.000000 0.000000 +(n,na) + material group in nuclide mean std. dev. +1 2 1 total 1.259778e-09 1.152715e-09 +0 2 2 total 0.000000e+00 0.000000e+00 +(n,nc) + material group in nuclide mean std. dev. +1 2 1 total 0.002607 0.000356 +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 +0 2 2 total 0.005400 0.000618 +(n,a) + material group in nuclide mean std. dev. +1 2 1 total 1.032353e-06 1.308817e-07 +0 2 2 total 2.735898e-07 2.541726e-08 +(n,Xa) + material group in nuclide mean std. dev. +1 2 1 total 1.033613e-06 1.318182e-07 +0 2 2 total 2.735898e-07 2.541726e-08 +heating + material group in nuclide mean std. dev. +1 2 1 total 2819.023866 149.123603 +0 2 2 total 2.414215 0.196172 +damage-energy + material group in nuclide mean std. dev. +1 2 1 total 1712.186983 87.224250 +0 2 2 total 0.294202 0.032716 +(n,n1) + material group in nuclide mean std. dev. +1 2 1 total 0.003108 0.000252 +0 2 2 total 0.000000 0.000000 +(n,a0) + material group in nuclide mean std. dev. +1 2 1 total 8.426133e-07 7.088213e-08 +0 2 2 total 2.733143e-07 2.539166e-08 +(n,nc) matrix + material group in group out nuclide mean std. dev. +3 2 1 1 total 0.001782 0.000845 +2 2 1 2 total 0.000000 0.000000 +1 2 2 1 total 0.000000 0.000000 +0 2 2 2 total 0.000000 0.000000 +(n,n1) matrix + material group in group out nuclide mean std. dev. +3 2 1 1 total 0.002228 0.000725 +2 2 1 2 total 0.000000 0.000000 +1 2 2 1 total 0.000000 0.000000 +0 2 2 2 total 0.000000 0.000000 +(n,2n) matrix + material group in group out nuclide mean std. dev. +3 2 1 1 total 0.0 0.0 +2 2 1 2 total 0.0 0.0 +1 2 2 1 total 0.0 0.0 +0 2 2 2 total 0.0 0.0 +delayed-nu-fission material delayedgroup group in nuclide mean std. dev. 1 2 1 1 total 0.0 0.0 3 2 2 1 total 0.0 0.0 @@ -362,6 +548,7 @@ 6 2 4 2 total 0.0 0.0 8 2 5 2 total 0.0 0.0 10 2 6 2 total 0.0 0.0 +chi-delayed material delayedgroup group out nuclide mean std. dev. 1 2 1 1 total 0.0 0.0 3 2 2 1 total 0.0 0.0 @@ -375,6 +562,7 @@ 6 2 4 2 total 0.0 0.0 8 2 5 2 total 0.0 0.0 10 2 6 2 total 0.0 0.0 +beta material delayedgroup group in nuclide mean std. dev. 1 2 1 1 total 0.0 0.0 3 2 2 1 total 0.0 0.0 @@ -388,6 +576,7 @@ 6 2 4 2 total 0.0 0.0 8 2 5 2 total 0.0 0.0 10 2 6 2 total 0.0 0.0 +decay-rate material delayedgroup nuclide mean std. dev. 0 2 1 total 0.0 0.0 1 2 2 total 0.0 0.0 @@ -395,6 +584,7 @@ 3 2 4 total 0.0 0.0 4 2 5 total 0.0 0.0 5 2 6 total 0.0 0.0 +delayed-nu-fission matrix material delayedgroup group in group out nuclide mean std. dev. 3 2 1 1 1 total 0.0 0.0 7 2 2 1 1 total 0.0 0.0 @@ -420,36 +610,47 @@ 12 2 4 2 2 total 0.0 0.0 16 2 5 2 2 total 0.0 0.0 20 2 6 2 2 total 0.0 0.0 +total material group in nuclide mean std. dev. 1 3 1 total 0.664572 0.031215 0 3 2 total 2.052384 0.224343 +transport material group in nuclide mean std. dev. 1 3 1 total 0.283323 0.035206 0 3 2 total 1.499740 0.230902 +nu-transport material group in nuclide mean std. dev. 1 3 1 total 0.283323 0.035206 0 3 2 total 1.499740 0.230902 +absorption material group in nuclide mean std. dev. 1 3 1 total 0.000690 0.000044 0 3 2 total 0.031687 0.003747 +capture material group in nuclide mean std. dev. 1 3 1 total 0.000690 0.000044 0 3 2 total 0.031687 0.003747 +fission material group in nuclide mean std. dev. 1 3 1 total 0.0 0.0 0 3 2 total 0.0 0.0 +nu-fission material group in nuclide mean std. dev. 1 3 1 total 0.0 0.0 0 3 2 total 0.0 0.0 +kappa-fission material group in nuclide mean std. dev. 1 3 1 total 0.0 0.0 0 3 2 total 0.0 0.0 +scatter material group in nuclide mean std. dev. 1 3 1 total 0.663882 0.031173 0 3 2 total 2.020697 0.220604 +nu-scatter material group in nuclide mean std. dev. 1 3 1 total 0.671269 0.026186 0 3 2 total 2.035388 0.258060 +scatter matrix material group in group out legendre nuclide mean std. dev. 12 3 1 1 P0 total 0.639901 0.024709 13 3 1 1 P1 total 0.381167 0.016243 @@ -467,6 +668,7 @@ 1 3 2 2 P1 total 0.509940 0.051236 2 3 2 2 P2 total 0.111175 0.013020 3 3 2 2 P3 total 0.024988 0.008312 +nu-scatter matrix material group in group out legendre nuclide mean std. dev. 12 3 1 1 P0 total 0.639901 0.024709 13 3 1 1 P1 total 0.381167 0.016243 @@ -484,21 +686,25 @@ 1 3 2 2 P1 total 0.509940 0.051236 2 3 2 2 P2 total 0.111175 0.013020 3 3 2 2 P3 total 0.024988 0.008312 +multiplicity matrix material group in group out nuclide mean std. dev. 3 3 1 1 total 1.0 0.038609 2 3 1 2 total 1.0 0.067667 1 3 2 1 total 1.0 1.414214 0 3 2 2 total 1.0 0.135929 +nu-fission matrix material group in group out nuclide mean std. dev. 3 3 1 1 total 0.0 0.0 2 3 1 2 total 0.0 0.0 1 3 2 1 total 0.0 0.0 0 3 2 2 total 0.0 0.0 +scatter probability matrix material group in group out nuclide mean std. dev. 3 3 1 1 total 0.953271 0.036018 2 3 1 2 total 0.046729 0.002547 1 3 2 1 total 0.000218 0.000219 0 3 2 2 total 0.999782 0.135885 +consistent scatter matrix material group in group out legendre nuclide mean std. dev. 12 3 1 1 P0 total 0.632859 0.038142 13 3 1 1 P1 total 0.376973 0.023715 @@ -516,6 +722,7 @@ 1 3 2 2 P1 total 0.506260 0.079140 2 3 2 2 P2 total 0.110372 0.018488 3 3 2 2 P3 total 0.024808 0.008771 +consistent nu-scatter matrix material group in group out legendre nuclide mean std. dev. 12 3 1 1 P0 total 0.632859 0.045297 13 3 1 1 P1 total 0.376973 0.027825 @@ -533,33 +740,107 @@ 1 3 2 2 P1 total 0.506260 0.104875 2 3 2 2 P2 total 0.110372 0.023809 3 3 2 2 P3 total 0.024808 0.009397 +chi material group out nuclide mean std. dev. 1 3 1 total 0.0 0.0 0 3 2 total 0.0 0.0 +chi-prompt material group out nuclide mean std. dev. 1 3 1 total 0.0 0.0 0 3 2 total 0.0 0.0 +inverse-velocity material group in nuclide mean std. dev. 1 3 1 total 6.022078e-08 3.780437e-09 0 3 2 total 3.044955e-06 3.600077e-07 +prompt-nu-fission material group in nuclide mean std. dev. 1 3 1 total 0.0 0.0 0 3 2 total 0.0 0.0 +prompt-nu-fission matrix material group in group out nuclide mean std. dev. 3 3 1 1 total 0.0 0.0 2 3 1 2 total 0.0 0.0 1 3 2 1 total 0.0 0.0 0 3 2 2 total 0.0 0.0 +diffusion-coefficient material group in legendre nuclide mean std. dev. 2 3 1 P0 total 13.561252 21.988396 3 3 1 P1 total 1.176515 0.154807 0 3 2 P0 total -2.459765 6.393743 1 3 2 P1 total 0.222261 0.040518 +nu-diffusion-coefficient material group in legendre nuclide mean std. dev. 2 3 1 P0 total 13.561252 21.988396 3 3 1 P1 total 1.176515 0.154807 0 3 2 P0 total -2.459765 6.393743 1 3 2 P1 total 0.222261 0.040518 +(n,elastic) + material group in nuclide mean std. dev. +1 3 1 total 0.663837 0.031175 +0 3 2 total 2.020697 0.220604 +(n,level) + material group in nuclide mean std. dev. +1 3 1 total 0.000045 0.000027 +0 3 2 total 0.000000 0.000000 +(n,2n) + material group in nuclide mean std. dev. +1 3 1 total 0.0 0.0 +0 3 2 total 0.0 0.0 +(n,na) + material group in nuclide mean std. dev. +1 3 1 total 6.743945e-11 6.604830e-11 +0 3 2 total 0.000000e+00 0.000000e+00 +(n,nc) + material group in nuclide mean std. dev. +1 3 1 total 0.0 0.0 +0 3 2 total 0.0 0.0 +(n,gamma) + material group in nuclide mean std. dev. +1 3 1 total 0.000219 0.000014 +0 3 2 total 0.011034 0.001305 +(n,a) + material group in nuclide mean std. dev. +1 3 1 total 0.000471 0.000031 +0 3 2 total 0.020653 0.002442 +(n,Xa) + material group in nuclide mean std. dev. +1 3 1 total 0.000472 0.000031 +0 3 2 total 0.020653 0.002442 +heating + material group in nuclide mean std. dev. +1 3 1 total 86854.045343 3785.266424 +0 3 2 total 61907.411870 6000.898789 +damage-energy + material group in nuclide mean std. dev. +1 3 1 total 1186.090822 44.862980 +0 3 2 total 337.187426 39.868517 +(n,n1) + material group in nuclide mean std. dev. +1 3 1 total 0.000001 6.118682e-07 +0 3 2 total 0.000000 0.000000e+00 +(n,a0) + material group in nuclide mean std. dev. +1 3 1 total 0.000084 0.000012 +0 3 2 total 0.001299 0.000154 +(n,nc) matrix + material group in group out nuclide mean std. dev. +3 3 1 1 total 0.0 0.0 +2 3 1 2 total 0.0 0.0 +1 3 2 1 total 0.0 0.0 +0 3 2 2 total 0.0 0.0 +(n,n1) matrix + material group in group out nuclide mean std. dev. +3 3 1 1 total 0.0 0.0 +2 3 1 2 total 0.0 0.0 +1 3 2 1 total 0.0 0.0 +0 3 2 2 total 0.0 0.0 +(n,2n) matrix + material group in group out nuclide mean std. dev. +3 3 1 1 total 0.0 0.0 +2 3 1 2 total 0.0 0.0 +1 3 2 1 total 0.0 0.0 +0 3 2 2 total 0.0 0.0 +delayed-nu-fission material delayedgroup group in nuclide mean std. dev. 1 3 1 1 total 0.0 0.0 3 3 2 1 total 0.0 0.0 @@ -573,6 +854,7 @@ 6 3 4 2 total 0.0 0.0 8 3 5 2 total 0.0 0.0 10 3 6 2 total 0.0 0.0 +chi-delayed material delayedgroup group out nuclide mean std. dev. 1 3 1 1 total 0.0 0.0 3 3 2 1 total 0.0 0.0 @@ -586,6 +868,7 @@ 6 3 4 2 total 0.0 0.0 8 3 5 2 total 0.0 0.0 10 3 6 2 total 0.0 0.0 +beta material delayedgroup group in nuclide mean std. dev. 1 3 1 1 total 0.0 0.0 3 3 2 1 total 0.0 0.0 @@ -599,6 +882,7 @@ 6 3 4 2 total 0.0 0.0 8 3 5 2 total 0.0 0.0 10 3 6 2 total 0.0 0.0 +decay-rate material delayedgroup nuclide mean std. dev. 0 3 1 total 0.0 0.0 1 3 2 total 0.0 0.0 @@ -606,6 +890,7 @@ 3 3 4 total 0.0 0.0 4 3 5 total 0.0 0.0 5 3 6 total 0.0 0.0 +delayed-nu-fission matrix material delayedgroup group in group out nuclide mean std. dev. 3 3 1 1 1 total 0.0 0.0 7 3 2 1 1 total 0.0 0.0 diff --git a/tests/regression_tests/mgxs_library_no_nuclides/test.py b/tests/regression_tests/mgxs_library_no_nuclides/test.py index f005c095ec..af14a5dc8f 100644 --- a/tests/regression_tests/mgxs_library_no_nuclides/test.py +++ b/tests/regression_tests/mgxs_library_no_nuclides/test.py @@ -19,9 +19,17 @@ class MGXSTestHarness(PyAPITestHarness): self.mgxs_lib = openmc.mgxs.Library(self._model.geometry) self.mgxs_lib.by_nuclide = False - # Test all relevant MGXS types + # Test relevant MGXS types relevant_MGXS_TYPES = [item for item in openmc.mgxs.MGXS_TYPES if item != 'current'] + # Add in a subset of openmc.mgxs.ARBITRARY_VECTOR_TYPES and + # openmc.mgxs.ARBITRARY_MATRIX_TYPES so we can see the code works, + # but not use too much resources + relevant_MGXS_TYPES += [ + "(n,elastic)", "(n,level)", "(n,2n)", "(n,na)", "(n,nc)", + "(n,gamma)", "(n,a)", "(n,Xa)", "heating", "damage-energy", + "(n,n1)", "(n,a0)", "(n,nc) matrix", "(n,n1) matrix", + "(n,2n) matrix"] self.mgxs_lib.mgxs_types = tuple(relevant_MGXS_TYPES) + \ openmc.mgxs.MDGXS_TYPES self.mgxs_lib.energy_groups = energy_groups @@ -48,7 +56,7 @@ class MGXSTestHarness(PyAPITestHarness): for mgxs_type in self.mgxs_lib.mgxs_types: mgxs = self.mgxs_lib.get_mgxs(domain, mgxs_type) df = mgxs.get_pandas_dataframe() - outstr += df.to_string() + '\n' + outstr += mgxs_type + '\n' + df.to_string() + '\n' # Hash the results if necessary if hash_output: diff --git a/tests/regression_tests/mgxs_library_nuclides/inputs_true.dat b/tests/regression_tests/mgxs_library_nuclides/inputs_true.dat index dc63ef0cbf..f29a41f3d7 100644 --- a/tests/regression_tests/mgxs_library_nuclides/inputs_true.dat +++ b/tests/regression_tests/mgxs_library_nuclides/inputs_true.dat @@ -68,10 +68,10 @@ 0.0 20000000.0 - + 2 - + 3 @@ -429,711 +429,1251 @@ analog - 71 2 + 1 2 total flux tracklength - 71 2 - Zr90 Zr91 Zr92 Zr94 Zr96 - total + 1 2 + U234 U235 U238 O16 + (n,elastic) tracklength - 71 2 + 1 2 total flux tracklength - 71 2 - Zr90 Zr91 Zr92 Zr94 Zr96 - total + 1 2 + U234 U235 U238 O16 + (n,level) tracklength - 71 2 + 1 2 total flux - analog + tracklength - 71 5 6 - Zr90 Zr91 Zr92 Zr94 Zr96 - scatter - analog + 1 2 + U234 U235 U238 O16 + (n,2n) + tracklength - 71 2 + 1 2 total flux tracklength - 71 2 - Zr90 Zr91 Zr92 Zr94 Zr96 - total + 1 2 + U234 U235 U238 O16 + (n,na) tracklength - 71 2 + 1 2 total flux - analog + tracklength - 71 5 6 - Zr90 Zr91 Zr92 Zr94 Zr96 - nu-scatter - analog + 1 2 + U234 U235 U238 O16 + (n,nc) + tracklength - 71 2 + 1 2 total flux tracklength - 71 2 - Zr90 Zr91 Zr92 Zr94 Zr96 - absorption + 1 2 + U234 U235 U238 O16 + (n,gamma) tracklength - 71 2 + 1 2 total flux tracklength - 71 2 + 1 2 + U234 U235 U238 O16 + (n,a) + tracklength + + + 1 2 + total + flux + tracklength + + + 1 2 + U234 U235 U238 O16 + (n,Xa) + tracklength + + + 1 2 + total + flux + tracklength + + + 1 2 + U234 U235 U238 O16 + heating + tracklength + + + 1 2 + total + flux + tracklength + + + 1 2 + U234 U235 U238 O16 + damage-energy + tracklength + + + 1 2 + total + flux + tracklength + + + 1 2 + U234 U235 U238 O16 + (n,n1) + tracklength + + + 1 2 + total + flux + tracklength + + + 1 2 + U234 U235 U238 O16 + (n,a0) + tracklength + + + 1 2 + total + flux + analog + + + 1 2 5 + U234 U235 U238 O16 + (n,nc) + analog + + + 1 2 + total + flux + analog + + + 1 2 5 + U234 U235 U238 O16 + (n,n1) + analog + + + 1 2 + total + flux + analog + + + 1 2 5 + U234 U235 U238 O16 + (n,2n) + analog + + + 104 2 + total + flux + tracklength + + + 104 2 + Zr90 Zr91 Zr92 Zr94 Zr96 + total + tracklength + + + 104 2 + total + flux + tracklength + + + 104 2 + Zr90 Zr91 Zr92 Zr94 Zr96 + total + tracklength + + + 104 2 + total + flux + analog + + + 104 5 6 + Zr90 Zr91 Zr92 Zr94 Zr96 + scatter + analog + + + 104 2 + total + flux + tracklength + + + 104 2 + Zr90 Zr91 Zr92 Zr94 Zr96 + total + tracklength + + + 104 2 + total + flux + analog + + + 104 5 6 + Zr90 Zr91 Zr92 Zr94 Zr96 + nu-scatter + analog + + + 104 2 + total + flux + tracklength + + + 104 2 Zr90 Zr91 Zr92 Zr94 Zr96 absorption tracklength - - 71 2 - Zr90 Zr91 Zr92 Zr94 Zr96 - fission - tracklength - - - 71 2 - total - flux - tracklength - - - 71 2 - Zr90 Zr91 Zr92 Zr94 Zr96 - fission - tracklength - - - 71 2 - total - flux - tracklength - - - 71 2 - Zr90 Zr91 Zr92 Zr94 Zr96 - nu-fission - tracklength - - - 71 2 - total - flux - tracklength - - - 71 2 - Zr90 Zr91 Zr92 Zr94 Zr96 - kappa-fission - tracklength - - - 71 2 - total - flux - tracklength - - - 71 2 - Zr90 Zr91 Zr92 Zr94 Zr96 - scatter - tracklength - - - 71 2 - total - flux - analog - - - 71 2 - Zr90 Zr91 Zr92 Zr94 Zr96 - nu-scatter - analog - - - 71 2 - total - flux - analog - - - 71 2 5 28 - Zr90 Zr91 Zr92 Zr94 Zr96 - scatter - analog - - - 71 2 - total - flux - analog - - - 71 2 5 28 - Zr90 Zr91 Zr92 Zr94 Zr96 - nu-scatter - analog - - - 71 2 5 - Zr90 Zr91 Zr92 Zr94 Zr96 - nu-scatter - analog - - - 71 2 5 - Zr90 Zr91 Zr92 Zr94 Zr96 - scatter - analog - - - 71 2 - total - flux - analog - - - 71 2 5 - Zr90 Zr91 Zr92 Zr94 Zr96 - nu-fission - analog - - - 71 2 5 - Zr90 Zr91 Zr92 Zr94 Zr96 - scatter - analog - - - 71 2 - total - flux - tracklength - - - 71 2 - Zr90 Zr91 Zr92 Zr94 Zr96 - scatter - tracklength - - - 71 2 5 28 - Zr90 Zr91 Zr92 Zr94 Zr96 - scatter - analog - - - 71 2 - total - flux - tracklength - - - 71 2 - Zr90 Zr91 Zr92 Zr94 Zr96 - scatter - tracklength - - - 71 2 5 28 - Zr90 Zr91 Zr92 Zr94 Zr96 - scatter - analog - - - 71 2 5 - Zr90 Zr91 Zr92 Zr94 Zr96 - nu-scatter - analog - - - 71 52 - Zr90 Zr91 Zr92 Zr94 Zr96 - nu-fission - analog - - 71 5 - Zr90 Zr91 Zr92 Zr94 Zr96 - nu-fission - analog + 104 2 + total + flux + tracklength - 71 52 + 104 2 Zr90 Zr91 Zr92 Zr94 Zr96 - prompt-nu-fission - analog + absorption + tracklength - 71 5 + 104 2 Zr90 Zr91 Zr92 Zr94 Zr96 - prompt-nu-fission - analog + fission + tracklength - 71 2 + 104 2 total flux tracklength - 71 2 + 104 2 Zr90 Zr91 Zr92 Zr94 Zr96 - inverse-velocity + fission tracklength - 71 2 + 104 2 total flux tracklength - 71 2 + 104 2 Zr90 Zr91 Zr92 Zr94 Zr96 - prompt-nu-fission + nu-fission tracklength - 71 2 + 104 2 total flux - analog + tracklength - 71 2 5 + 104 2 Zr90 Zr91 Zr92 Zr94 Zr96 - prompt-nu-fission - analog + kappa-fission + tracklength - 71 2 + 104 2 total flux tracklength - 71 2 + 104 2 Zr90 Zr91 Zr92 Zr94 Zr96 - total + scatter tracklength - 71 2 + 104 2 total flux analog - 71 5 6 + 104 2 + Zr90 Zr91 Zr92 Zr94 Zr96 + nu-scatter + analog + + + 104 2 + total + flux + analog + + + 104 2 5 28 Zr90 Zr91 Zr92 Zr94 Zr96 scatter analog - - 71 2 - total - flux - tracklength - - - 71 2 - Zr90 Zr91 Zr92 Zr94 Zr96 - total - tracklength - - 71 2 + 104 2 total flux analog - 71 5 6 + 104 2 5 28 Zr90 Zr91 Zr92 Zr94 Zr96 nu-scatter analog - 141 2 - total - flux - tracklength + 104 2 5 + Zr90 Zr91 Zr92 Zr94 Zr96 + nu-scatter + analog - 141 2 - H1 O16 B10 B11 - total - tracklength + 104 2 5 + Zr90 Zr91 Zr92 Zr94 Zr96 + scatter + analog - 141 2 + 104 2 total flux - tracklength + analog - 141 2 - H1 O16 B10 B11 - total - tracklength + 104 2 5 + Zr90 Zr91 Zr92 Zr94 Zr96 + nu-fission + analog - 141 2 - total - flux + 104 2 5 + Zr90 Zr91 Zr92 Zr94 Zr96 + scatter analog - 141 5 6 - H1 O16 B10 B11 - scatter - analog - - - 141 2 + 104 2 total flux tracklength + + 104 2 + Zr90 Zr91 Zr92 Zr94 Zr96 + scatter + tracklength + - 141 2 - H1 O16 B10 B11 - total - tracklength - - - 141 2 - total - flux + 104 2 5 28 + Zr90 Zr91 Zr92 Zr94 Zr96 + scatter analog + + 104 2 + total + flux + tracklength + - 141 5 6 - H1 O16 B10 B11 + 104 2 + Zr90 Zr91 Zr92 Zr94 Zr96 + scatter + tracklength + + + 104 2 5 28 + Zr90 Zr91 Zr92 Zr94 Zr96 + scatter + analog + + + 104 2 5 + Zr90 Zr91 Zr92 Zr94 Zr96 nu-scatter analog - - 141 2 - total - flux - tracklength - - - 141 2 - H1 O16 B10 B11 - absorption - tracklength - - 141 2 - total - flux - tracklength + 104 52 + Zr90 Zr91 Zr92 Zr94 Zr96 + nu-fission + analog - 141 2 - H1 O16 B10 B11 - absorption - tracklength + 104 5 + Zr90 Zr91 Zr92 Zr94 Zr96 + nu-fission + analog - 141 2 - H1 O16 B10 B11 - fission - tracklength + 104 52 + Zr90 Zr91 Zr92 Zr94 Zr96 + prompt-nu-fission + analog - 141 2 - total - flux - tracklength + 104 5 + Zr90 Zr91 Zr92 Zr94 Zr96 + prompt-nu-fission + analog - 141 2 - H1 O16 B10 B11 - fission + 104 2 + total + flux tracklength - 141 2 - total - flux + 104 2 + Zr90 Zr91 Zr92 Zr94 Zr96 + inverse-velocity tracklength - 141 2 - H1 O16 B10 B11 - nu-fission + 104 2 + total + flux tracklength - 141 2 - total - flux + 104 2 + Zr90 Zr91 Zr92 Zr94 Zr96 + prompt-nu-fission tracklength - 141 2 - H1 O16 B10 B11 - kappa-fission - tracklength - - - 141 2 + 104 2 total flux - tracklength + analog + + + 104 2 5 + Zr90 Zr91 Zr92 Zr94 Zr96 + prompt-nu-fission + analog - 141 2 - H1 O16 B10 B11 - scatter + 104 2 + total + flux tracklength - 141 2 - total - flux - analog + 104 2 + Zr90 Zr91 Zr92 Zr94 Zr96 + total + tracklength - 141 2 - H1 O16 B10 B11 - nu-scatter + 104 2 + total + flux analog - 141 2 - total - flux - analog - - - 141 2 5 28 - H1 O16 B10 B11 + 104 5 6 + Zr90 Zr91 Zr92 Zr94 Zr96 scatter analog + + 104 2 + total + flux + tracklength + - 141 2 + 104 2 + Zr90 Zr91 Zr92 Zr94 Zr96 + total + tracklength + + + 104 2 total flux analog - - 141 2 5 28 - H1 O16 B10 B11 - nu-scatter - analog - - 141 2 5 - H1 O16 B10 B11 + 104 5 6 + Zr90 Zr91 Zr92 Zr94 Zr96 nu-scatter analog - 141 2 5 - H1 O16 B10 B11 - scatter - analog - - - 141 2 + 104 2 total flux - analog + tracklength + + + 104 2 + Zr90 Zr91 Zr92 Zr94 Zr96 + (n,elastic) + tracklength - 141 2 5 - H1 O16 B10 B11 - nu-fission - analog + 104 2 + total + flux + tracklength - 141 2 5 - H1 O16 B10 B11 - scatter - analog + 104 2 + Zr90 Zr91 Zr92 Zr94 Zr96 + (n,level) + tracklength - 141 2 + 104 2 total flux tracklength - 141 2 - H1 O16 B10 B11 - scatter + 104 2 + Zr90 Zr91 Zr92 Zr94 Zr96 + (n,2n) tracklength - 141 2 5 28 - H1 O16 B10 B11 - scatter - analog - - - 141 2 + 104 2 total flux tracklength + + 104 2 + Zr90 Zr91 Zr92 Zr94 Zr96 + (n,na) + tracklength + - 141 2 - H1 O16 B10 B11 - scatter + 104 2 + total + flux tracklength - 141 2 5 28 + 104 2 + Zr90 Zr91 Zr92 Zr94 Zr96 + (n,nc) + tracklength + + + 104 2 + total + flux + tracklength + + + 104 2 + Zr90 Zr91 Zr92 Zr94 Zr96 + (n,gamma) + tracklength + + + 104 2 + total + flux + tracklength + + + 104 2 + Zr90 Zr91 Zr92 Zr94 Zr96 + (n,a) + tracklength + + + 104 2 + total + flux + tracklength + + + 104 2 + Zr90 Zr91 Zr92 Zr94 Zr96 + (n,Xa) + tracklength + + + 104 2 + total + flux + tracklength + + + 104 2 + Zr90 Zr91 Zr92 Zr94 Zr96 + heating + tracklength + + + 104 2 + total + flux + tracklength + + + 104 2 + Zr90 Zr91 Zr92 Zr94 Zr96 + damage-energy + tracklength + + + 104 2 + total + flux + tracklength + + + 104 2 + Zr90 Zr91 Zr92 Zr94 Zr96 + (n,n1) + tracklength + + + 104 2 + total + flux + tracklength + + + 104 2 + Zr90 Zr91 Zr92 Zr94 Zr96 + (n,a0) + tracklength + + + 104 2 + total + flux + analog + + + 104 2 5 + Zr90 Zr91 Zr92 Zr94 Zr96 + (n,nc) + analog + + + 104 2 + total + flux + analog + + + 104 2 5 + Zr90 Zr91 Zr92 Zr94 Zr96 + (n,n1) + analog + + + 104 2 + total + flux + analog + + + 104 2 5 + Zr90 Zr91 Zr92 Zr94 Zr96 + (n,2n) + analog + + + 207 2 + total + flux + tracklength + + + 207 2 + H1 O16 B10 B11 + total + tracklength + + + 207 2 + total + flux + tracklength + + + 207 2 + H1 O16 B10 B11 + total + tracklength + + + 207 2 + total + flux + analog + + + 207 5 6 H1 O16 B10 B11 scatter analog - - 141 2 5 + + 207 2 + total + flux + tracklength + + + 207 2 + H1 O16 B10 B11 + total + tracklength + + + 207 2 + total + flux + analog + + + 207 5 6 H1 O16 B10 B11 nu-scatter analog - - 141 52 - H1 O16 B10 B11 - nu-fission - analog - - - 141 5 - H1 O16 B10 B11 - nu-fission - analog - - - 141 52 - H1 O16 B10 B11 - prompt-nu-fission - analog - - - 141 5 - H1 O16 B10 B11 - prompt-nu-fission - analog - - - 141 2 + + 207 2 total flux tracklength - - 141 2 + + 207 2 + H1 O16 B10 B11 + absorption + tracklength + + + 207 2 + total + flux + tracklength + + + 207 2 + H1 O16 B10 B11 + absorption + tracklength + + + 207 2 + H1 O16 B10 B11 + fission + tracklength + + + 207 2 + total + flux + tracklength + + + 207 2 + H1 O16 B10 B11 + fission + tracklength + + + 207 2 + total + flux + tracklength + + + 207 2 + H1 O16 B10 B11 + nu-fission + tracklength + + + 207 2 + total + flux + tracklength + + + 207 2 + H1 O16 B10 B11 + kappa-fission + tracklength + + + 207 2 + total + flux + tracklength + + + 207 2 + H1 O16 B10 B11 + scatter + tracklength + + + 207 2 + total + flux + analog + + + 207 2 + H1 O16 B10 B11 + nu-scatter + analog + + + 207 2 + total + flux + analog + + + 207 2 5 28 + H1 O16 B10 B11 + scatter + analog + + + 207 2 + total + flux + analog + + + 207 2 5 28 + H1 O16 B10 B11 + nu-scatter + analog + + + 207 2 5 + H1 O16 B10 B11 + nu-scatter + analog + + + 207 2 5 + H1 O16 B10 B11 + scatter + analog + + + 207 2 + total + flux + analog + + + 207 2 5 + H1 O16 B10 B11 + nu-fission + analog + + + 207 2 5 + H1 O16 B10 B11 + scatter + analog + + + 207 2 + total + flux + tracklength + + + 207 2 + H1 O16 B10 B11 + scatter + tracklength + + + 207 2 5 28 + H1 O16 B10 B11 + scatter + analog + + + 207 2 + total + flux + tracklength + + + 207 2 + H1 O16 B10 B11 + scatter + tracklength + + + 207 2 5 28 + H1 O16 B10 B11 + scatter + analog + + + 207 2 5 + H1 O16 B10 B11 + nu-scatter + analog + + + 207 52 + H1 O16 B10 B11 + nu-fission + analog + + + 207 5 + H1 O16 B10 B11 + nu-fission + analog + + + 207 52 + H1 O16 B10 B11 + prompt-nu-fission + analog + + + 207 5 + H1 O16 B10 B11 + prompt-nu-fission + analog + + + 207 2 + total + flux + tracklength + + + 207 2 H1 O16 B10 B11 inverse-velocity tracklength - - 141 2 + + 207 2 total flux tracklength - - 141 2 + + 207 2 H1 O16 B10 B11 prompt-nu-fission tracklength - - 141 2 + + 207 2 total flux analog - - 141 2 5 + + 207 2 5 H1 O16 B10 B11 prompt-nu-fission analog - - 141 2 + + 207 2 total flux tracklength - - 141 2 + + 207 2 H1 O16 B10 B11 total tracklength - - 141 2 + + 207 2 total flux analog - - 141 5 6 + + 207 5 6 H1 O16 B10 B11 scatter analog - - 141 2 + + 207 2 total flux tracklength - - 141 2 + + 207 2 H1 O16 B10 B11 total tracklength - - 141 2 + + 207 2 total flux analog - - 141 5 6 + + 207 5 6 H1 O16 B10 B11 nu-scatter analog + + 207 2 + total + flux + tracklength + + + 207 2 + H1 O16 B10 B11 + (n,elastic) + tracklength + + + 207 2 + total + flux + tracklength + + + 207 2 + H1 O16 B10 B11 + (n,level) + tracklength + + + 207 2 + total + flux + tracklength + + + 207 2 + H1 O16 B10 B11 + (n,2n) + tracklength + + + 207 2 + total + flux + tracklength + + + 207 2 + H1 O16 B10 B11 + (n,na) + tracklength + + + 207 2 + total + flux + tracklength + + + 207 2 + H1 O16 B10 B11 + (n,nc) + tracklength + + + 207 2 + total + flux + tracklength + + + 207 2 + H1 O16 B10 B11 + (n,gamma) + tracklength + + + 207 2 + total + flux + tracklength + + + 207 2 + H1 O16 B10 B11 + (n,a) + tracklength + + + 207 2 + total + flux + tracklength + + + 207 2 + H1 O16 B10 B11 + (n,Xa) + tracklength + + + 207 2 + total + flux + tracklength + + + 207 2 + H1 O16 B10 B11 + heating + tracklength + + + 207 2 + total + flux + tracklength + + + 207 2 + H1 O16 B10 B11 + damage-energy + tracklength + + + 207 2 + total + flux + tracklength + + + 207 2 + H1 O16 B10 B11 + (n,n1) + tracklength + + + 207 2 + total + flux + tracklength + + + 207 2 + H1 O16 B10 B11 + (n,a0) + tracklength + + + 207 2 + total + flux + analog + + + 207 2 5 + H1 O16 B10 B11 + (n,nc) + analog + + + 207 2 + total + flux + analog + + + 207 2 5 + H1 O16 B10 B11 + (n,n1) + analog + + + 207 2 + total + flux + analog + + + 207 2 5 + H1 O16 B10 B11 + (n,2n) + analog + diff --git a/tests/regression_tests/mgxs_library_nuclides/results_true.dat b/tests/regression_tests/mgxs_library_nuclides/results_true.dat index 1a93a03188..a2be43e800 100644 --- a/tests/regression_tests/mgxs_library_nuclides/results_true.dat +++ b/tests/regression_tests/mgxs_library_nuclides/results_true.dat @@ -1 +1 @@ -14f7fb2e399a4ad124b25b88dda5104d43cca9192aa1c17261da40bcc0e4394e56781f42f79c90107d0ff6b3e901f034bed09b037670e60b9ac4009b3805e17d \ No newline at end of file +a9999488e2aa2ad0f1d694afedb71fbb56f1d0c8e8abdb6616698505a9d85302bf90586866fdb58eac96f76712a2dfbc884cc03087df7b5d148fb29d14dd2bbb \ No newline at end of file diff --git a/tests/regression_tests/mgxs_library_nuclides/test.py b/tests/regression_tests/mgxs_library_nuclides/test.py index 87a65723c5..8a7673565e 100644 --- a/tests/regression_tests/mgxs_library_nuclides/test.py +++ b/tests/regression_tests/mgxs_library_nuclides/test.py @@ -18,9 +18,17 @@ class MGXSTestHarness(PyAPITestHarness): self.mgxs_lib = openmc.mgxs.Library(self._model.geometry) self.mgxs_lib.by_nuclide = True - # Test relevant all MGXS types + # Test relevant MGXS types relevant_MGXS_TYPES = [item for item in openmc.mgxs.MGXS_TYPES if item != 'current'] + # Add in a subset of openmc.mgxs.ARBITRARY_VECTOR_TYPES and + # openmc.mgxs.ARBITRARY_MATRIX_TYPES so we can see the code works, + # but not use too much resources + relevant_MGXS_TYPES += [ + "(n,elastic)", "(n,level)", "(n,2n)", "(n,na)", "(n,nc)", + "(n,gamma)", "(n,a)", "(n,Xa)", "heating", "damage-energy", + "(n,n1)", "(n,a0)", "(n,nc) matrix", "(n,n1) matrix", + "(n,2n) matrix"] self.mgxs_lib.mgxs_types = tuple(relevant_MGXS_TYPES) self.mgxs_lib.energy_groups = energy_groups self.mgxs_lib.legendre_order = 3 diff --git a/tests/regression_tests/plot/test.py b/tests/regression_tests/plot/test.py index bfaef019c1..a6f7306a0e 100644 --- a/tests/regression_tests/plot/test.py +++ b/tests/regression_tests/plot/test.py @@ -42,10 +42,10 @@ class PlotTestHarness(TestHarness): # Add voxel data to results with h5py.File(fname, 'r') as fh: outstr += fh.attrs['filetype'] - outstr += fh.attrs['num_voxels'].tostring() - outstr += fh.attrs['lower_left'].tostring() - outstr += fh.attrs['voxel_width'].tostring() - outstr += fh['data'].value.tostring() + outstr += fh.attrs['num_voxels'].tobytes() + outstr += fh.attrs['lower_left'].tobytes() + outstr += fh.attrs['voxel_width'].tobytes() + outstr += fh['data'][()].tobytes() # Hash the information and return. sha512 = hashlib.sha512() diff --git a/tests/regression_tests/plot_overlaps/test.py b/tests/regression_tests/plot_overlaps/test.py index d8c0943cf5..62236081b3 100644 --- a/tests/regression_tests/plot_overlaps/test.py +++ b/tests/regression_tests/plot_overlaps/test.py @@ -42,10 +42,10 @@ class PlotTestHarness(TestHarness): # Add voxel data to results with h5py.File(fname, 'r') as fh: outstr += fh.attrs['filetype'] - outstr += fh.attrs['num_voxels'].tostring() - outstr += fh.attrs['lower_left'].tostring() - outstr += fh.attrs['voxel_width'].tostring() - outstr += fh['data'].value.tostring() + outstr += fh.attrs['num_voxels'].tobytes() + outstr += fh.attrs['lower_left'].tobytes() + outstr += fh.attrs['voxel_width'].tobytes() + outstr += fh['data'][()].tobytes() # Hash the information and return. sha512 = hashlib.sha512() diff --git a/tests/regression_tests/plot_voxel/test.py b/tests/regression_tests/plot_voxel/test.py index d2767e2f18..3b7a6bef28 100644 --- a/tests/regression_tests/plot_voxel/test.py +++ b/tests/regression_tests/plot_voxel/test.py @@ -23,7 +23,7 @@ class PlotVoxelTestHarness(TestHarness): check_call(['../../../scripts/openmc-voxel-to-vtk'] + glob.glob('plot_4.h5')) - + def _test_output_created(self): """Make sure *.ppm has been created.""" for fname in self._plot_names: @@ -44,10 +44,10 @@ class PlotVoxelTestHarness(TestHarness): # Add voxel data to results with h5py.File(fname, 'r') as fh: outstr += fh.attrs['filetype'] - outstr += fh.attrs['num_voxels'].tostring() - outstr += fh.attrs['lower_left'].tostring() - outstr += fh.attrs['voxel_width'].tostring() - outstr += fh['data'].value.tostring() + outstr += fh.attrs['num_voxels'].tobytes() + outstr += fh.attrs['lower_left'].tobytes() + outstr += fh.attrs['voxel_width'].tobytes() + outstr += fh['data'][()].tobytes() # Hash the information and return. sha512 = hashlib.sha512() diff --git a/tests/regression_tests/source_dlopen/source_sampling.cpp b/tests/regression_tests/source_dlopen/source_sampling.cpp index ea74afdd97..8eaf6265cc 100644 --- a/tests/regression_tests/source_dlopen/source_sampling.cpp +++ b/tests/regression_tests/source_dlopen/source_sampling.cpp @@ -5,16 +5,16 @@ #include "openmc/source.h" #include "openmc/particle.h" -class Source : openmc::CustomSource +class CustomSource : public openmc::Source { - openmc::Particle::Bank sample(uint64_t *seed) + openmc::Particle::Bank sample(uint64_t *seed) const { openmc::Particle::Bank particle; // wgt particle.particle = openmc::Particle::Type::neutron; particle.wgt = 1.0; // position - + particle.r.x = 0.; particle.r.y = 0.; particle.r.z = 0.; @@ -22,14 +22,14 @@ class Source : openmc::CustomSource particle.u = {1.0, 0.0, 0.0}; particle.E = 14.08e6; particle.delayed_group = 0; - return particle; + return particle; } }; // A function to create a unique pointer to an instance of this class when generated // via a plugin call using dlopen/dlsym. // You must have external C linkage here otherwise dlopen will not find the file -extern "C" std::unique_ptr openmc_create_source(std::string parameters) +extern "C" std::unique_ptr openmc_create_source(std::string parameters) { - return std::make_unique(); + return std::make_unique(); } diff --git a/tests/regression_tests/source_file/results_true.dat b/tests/regression_tests/source_file/results_true.dat index 4ab7993d88..44c422eeff 100644 --- a/tests/regression_tests/source_file/results_true.dat +++ b/tests/regression_tests/source_file/results_true.dat @@ -1,2 +1,2 @@ k-combined: -2.939525E-01 6.311780E-03 +3.080726E-01 9.554124E-03 diff --git a/tests/regression_tests/source_parameterized_dlopen/parameterized_source_sampling.cpp b/tests/regression_tests/source_parameterized_dlopen/parameterized_source_sampling.cpp index 3b0875bb03..da7d70e378 100644 --- a/tests/regression_tests/source_parameterized_dlopen/parameterized_source_sampling.cpp +++ b/tests/regression_tests/source_parameterized_dlopen/parameterized_source_sampling.cpp @@ -1,12 +1,12 @@ #include "openmc/source.h" #include "openmc/particle.h" -class Source : public openmc::CustomSource { +class CustomSource : public openmc::Source { public: - Source(double energy) : energy_(energy) { } + CustomSource(double energy) : energy_(energy) { } // Samples from an instance of this class. - openmc::Particle::Bank sample(uint64_t* seed) + openmc::Particle::Bank sample(uint64_t* seed) const { openmc::Particle::Bank particle; // wgt @@ -31,8 +31,8 @@ class Source : public openmc::CustomSource { // A function to create a unique pointer to an instance of this class when generated // via a plugin call using dlopen/dlsym. // You must have external C linkage here otherwise dlopen will not find the file -extern "C" std::unique_ptr openmc_create_source(std::string parameter) +extern "C" std::unique_ptr openmc_create_source(std::string parameter) { double energy = std::stod(parameter); - return std::make_unique(energy); + return std::make_unique(energy); } diff --git a/tests/regression_tests/uniform_fs/settings.xml b/tests/regression_tests/uniform_fs/settings.xml index 3e6ef672fd..e2c9c095eb 100644 --- a/tests/regression_tests/uniform_fs/settings.xml +++ b/tests/regression_tests/uniform_fs/settings.xml @@ -10,10 +10,12 @@ - + 10 10 10 -10. -10. -10. 10. 10. 10. - + + + 1 diff --git a/tests/unit_tests/test_source_file.py b/tests/unit_tests/test_source_file.py new file mode 100644 index 0000000000..ae6eff97f7 --- /dev/null +++ b/tests/unit_tests/test_source_file.py @@ -0,0 +1,45 @@ +from random import random + +import h5py +import numpy as np +import openmc +import pytest + + +def test_source_file(run_in_tmpdir): + # write_source_file shouldn't accept non-SourceParticle items + with pytest.raises(TypeError): + openmc.write_source_file([1, 2, 3], 'test_source.h5') + + # Create source particles + source = [] + n = 1000 + for i in range(n): + source.append(openmc.SourceParticle( + r=(random(), i, 0), + u=(0., 0., 1.), + E=float(n - i), + )) + + # Create source file + openmc.write_source_file(source, 'test_source.h5') + + # Get array of source particles from file + with h5py.File('test_source.h5', 'r') as fh: + filetype = fh.attrs['filetype'] + arr = fh['source_bank'][...] + + # Ensure data is consistent + assert filetype == b'source' + r = arr['r'] + assert np.all((r['x'] > 0.0) & (r['x'] < 1.0)) + assert np.all(r['y'] == np.arange(1000)) + assert np.all(r['z'] == 0.0) + u = arr['u'] + assert np.all(u['x'] == 0.0) + assert np.all(u['y'] == 0.0) + assert np.all(u['z'] == 1.0) + assert np.all(arr['E'] == n - np.arange(n)) + assert np.all(arr['wgt'] == 1.0) + assert np.all(arr['delayed_group'] == 0) + assert np.all(arr['particle'] == 0) diff --git a/tools/ci/travis-before-script.sh b/tools/ci/gha-before-script.sh similarity index 100% rename from tools/ci/travis-before-script.sh rename to tools/ci/gha-before-script.sh diff --git a/tools/ci/travis-install-dagmc.sh b/tools/ci/gha-install-dagmc.sh similarity index 89% rename from tools/ci/travis-install-dagmc.sh rename to tools/ci/gha-install-dagmc.sh index 8c9cc61a46..eabb9d3821 100755 --- a/tools/ci/travis-install-dagmc.sh +++ b/tools/ci/gha-install-dagmc.sh @@ -21,8 +21,6 @@ git clone -b $MOAB_BRANCH $MOAB_REPO mkdir build && cd build cmake ../moab -DENABLE_HDF5=ON -DBUILD_SHARED_LIBS=ON -DCMAKE_INSTALL_PREFIX=$MOAB_INSTALL_DIR -DENABLE_BLASLAPACK=OFF make -j && make -j install -cmake ../moab -DBUILD_SHARED_LIBS=OFF -make -j install rm -rf $HOME/MOAB/moab $HOME/MOAB/build # DAGMC Install @@ -30,7 +28,7 @@ cd $HOME mkdir DAGMC && cd DAGMC git clone -b $DAGMC_BRANCH $DAGMC_REPO mkdir build && cd build -cmake ../dagmc -DBUILD_TALLY=ON -DCMAKE_INSTALL_PREFIX=$DAGMC_INSTALL_DIR -DMOAB_DIR=$MOAB_INSTALL_DIR +cmake ../dagmc -DBUILD_TALLY=ON -DCMAKE_INSTALL_PREFIX=$DAGMC_INSTALL_DIR -DBUILD_STATIC_LIBS=OFF -DMOAB_DIR=$MOAB_INSTALL_DIR make -j install rm -rf $HOME/DAGMC/dagmc $HOME/DAGMC/build diff --git a/tools/ci/travis-install-njoy.sh b/tools/ci/gha-install-njoy.sh similarity index 100% rename from tools/ci/travis-install-njoy.sh rename to tools/ci/gha-install-njoy.sh diff --git a/tools/ci/travis-install-vectfit.sh b/tools/ci/gha-install-vectfit.sh similarity index 100% rename from tools/ci/travis-install-vectfit.sh rename to tools/ci/gha-install-vectfit.sh diff --git a/tools/ci/travis-install.py b/tools/ci/gha-install.py similarity index 97% rename from tools/ci/travis-install.py rename to tools/ci/gha-install.py index a2b1b61753..2f573b1a97 100644 --- a/tools/ci/travis-install.py +++ b/tools/ci/gha-install.py @@ -47,6 +47,7 @@ def install(omp=False, mpi=False, phdf5=False, dagmc=False): if dagmc: cmake_cmd.append('-Ddagmc=ON') + cmake_cmd.append('-DCMAKE_PREFIX_PATH=~/DAGMC') # Build in coverage mode for coverage testing cmake_cmd.append('-Dcoverage=on') diff --git a/tools/ci/travis-install.sh b/tools/ci/gha-install.sh similarity index 82% rename from tools/ci/travis-install.sh rename to tools/ci/gha-install.sh index 7bbe160aa5..debf833145 100755 --- a/tools/ci/travis-install.sh +++ b/tools/ci/gha-install.sh @@ -1,31 +1,31 @@ #!/bin/bash set -ex -# Install NJOY 2016 -./tools/ci/travis-install-njoy.sh - -# Install DAGMC if needed -if [[ $DAGMC = 'y' ]]; then - ./tools/ci/travis-install-dagmc.sh -fi - -# Install vectfit for WMP generation if needed -if [[ $VECTFIT = 'y' ]]; then - ./tools/ci/travis-install-vectfit.sh -fi - # Upgrade pip, pytest, numpy before doing anything else pip install --upgrade pip pip install --upgrade pytest pip install --upgrade numpy +# Install NJOY 2016 +./tools/ci/gha-install-njoy.sh + +# Install DAGMC if needed +if [[ $DAGMC = 'y' ]]; then + ./tools/ci/gha-install-dagmc.sh +fi + +# Install vectfit for WMP generation if needed +if [[ $VECTFIT = 'y' ]]; then + ./tools/ci/gha-install-vectfit.sh +fi + # Install mpi4py for MPI configurations if [[ $MPI == 'y' ]]; then pip install --no-binary=mpi4py mpi4py fi # Build and install OpenMC executable -python tools/ci/travis-install.py +python tools/ci/gha-install.py # Install Python API in editable mode pip install -e .[test,vtk] diff --git a/tools/ci/travis-script.sh b/tools/ci/gha-script.sh similarity index 100% rename from tools/ci/travis-script.sh rename to tools/ci/gha-script.sh