mirror of
https://github.com/openmc-dev/openmc.git
synced 2026-07-25 20:45:35 -04:00
Merge branch 'develop' into mg_docs
This commit is contained in:
commit
9924248d25
254 changed files with 25829 additions and 20840 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
|
@ -26,6 +26,7 @@ examples/python/**/*.xml
|
|||
docs/build
|
||||
docs/source/_images/*.pdf
|
||||
docs/source/_images/*.aux
|
||||
docs/source/pythonapi/generated/
|
||||
|
||||
# Source build
|
||||
build
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@ before_install:
|
|||
- conda config --set always_yes yes --set changeps1 no
|
||||
- conda update -q conda
|
||||
- conda info -a
|
||||
- conda create -q -n test-environment python=$TRAVIS_PYTHON_VERSION numpy scipy h5py pandas
|
||||
- conda create -q -n test-environment python=$TRAVIS_PYTHON_VERSION numpy scipy h5py=2.5 pandas
|
||||
- source activate test-environment
|
||||
|
||||
# Install GCC, MPICH, HDF5, PHDF5
|
||||
|
|
|
|||
7
docs/source/_templates/myclass.rst
Normal file
7
docs/source/_templates/myclass.rst
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
{{ fullname }}
|
||||
{{ underline }}
|
||||
|
||||
.. currentmodule:: {{ module }}
|
||||
|
||||
.. autoclass:: {{ objname }}
|
||||
:members:
|
||||
8
docs/source/_templates/myclassinherit.rst
Normal file
8
docs/source/_templates/myclassinherit.rst
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
{{ fullname }}
|
||||
{{ underline }}
|
||||
|
||||
.. currentmodule:: {{ module }}
|
||||
|
||||
.. autoclass:: {{ objname }}
|
||||
:members:
|
||||
:inherited-members:
|
||||
6
docs/source/_templates/myfunction.rst
Normal file
6
docs/source/_templates/myfunction.rst
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
{{ fullname }}
|
||||
{{ underline }}
|
||||
|
||||
.. currentmodule:: {{ module }}
|
||||
|
||||
.. autofunction:: {{ objname }}
|
||||
|
|
@ -24,13 +24,8 @@ except ImportError:
|
|||
from mock import Mock as MagicMock
|
||||
|
||||
|
||||
class Mock(MagicMock):
|
||||
@classmethod
|
||||
def __getattr__(cls, name):
|
||||
return Mock()
|
||||
|
||||
MOCK_MODULES = ['numpy', 'h5py', 'pandas', 'opencg']
|
||||
sys.modules.update((mod_name, Mock()) for mod_name in MOCK_MODULES)
|
||||
sys.modules.update((mod_name, MagicMock()) for mod_name in MOCK_MODULES)
|
||||
|
||||
|
||||
# If extensions (or modules to document with autodoc) are in another directory,
|
||||
|
|
@ -48,6 +43,8 @@ extensions = ['sphinx.ext.autodoc',
|
|||
'sphinx.ext.napoleon',
|
||||
'sphinx.ext.mathjax',
|
||||
'sphinx.ext.autosummary',
|
||||
'sphinx.ext.intersphinx',
|
||||
'sphinx.ext.viewcode',
|
||||
'sphinx_numfig',
|
||||
'notebook_sphinxext']
|
||||
|
||||
|
|
@ -65,7 +62,7 @@ master_doc = 'index'
|
|||
|
||||
# General information about the project.
|
||||
project = u'OpenMC'
|
||||
copyright = u'2011-2015, Massachusetts Institute of Technology'
|
||||
copyright = u'2011-2016, Massachusetts Institute of Technology'
|
||||
|
||||
# The version info for the project you're documenting, acts as replacement for
|
||||
# |version| and |release|, also used in various other places throughout the
|
||||
|
|
@ -122,20 +119,13 @@ pygments_style = 'tango'
|
|||
|
||||
# -- Options for HTML output ---------------------------------------------------
|
||||
|
||||
# The theme to use for HTML and HTML Help pages. Major themes that come with
|
||||
# Sphinx are currently 'default' and 'sphinxdoc'.
|
||||
if on_rtd:
|
||||
html_theme = 'default'
|
||||
html_logo = '_images/openmc200px.png'
|
||||
else:
|
||||
html_theme = 'haiku'
|
||||
html_theme_options = {'full_logo': True,
|
||||
'linkcolor': '#0c3762',
|
||||
'visitedlinkcolor': '#0c3762'}
|
||||
html_logo = '_images/openmc.png'
|
||||
# The theme to use for HTML and HTML Help pages
|
||||
if not on_rtd:
|
||||
import sphinx_rtd_theme
|
||||
html_theme = 'sphinx_rtd_theme'
|
||||
html_theme_path = [sphinx_rtd_theme.get_html_theme_path()]
|
||||
|
||||
# Add any paths that contain custom themes here, relative to this directory.
|
||||
#html_theme_path = ["_theme"]
|
||||
html_logo = '_images/openmc200px.png'
|
||||
|
||||
# The name for this set of Sphinx documents. If None, it defaults to
|
||||
# "<project> v<release> documentation".
|
||||
|
|
@ -248,4 +238,12 @@ latex_elements = {
|
|||
#Autodocumentation Flags
|
||||
#autodoc_member_order = "groupwise"
|
||||
#autoclass_content = "both"
|
||||
#autosummary_generate = []
|
||||
autosummary_generate = True
|
||||
|
||||
napoleon_use_ivar = True
|
||||
|
||||
intersphinx_mapping = {
|
||||
'python': ('https://docs.python.org/3', None),
|
||||
'numpy': ('http://docs.scipy.org/doc/numpy/', None),
|
||||
'pandas': ('http://pandas.pydata.org/pandas-docs/stable/', None)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,11 +13,14 @@ OpenMC was originally developed by members of the `Computational Reactor Physics
|
|||
Group`_ at the `Massachusetts Institute of Technology`_ starting
|
||||
in 2011. Various universities, laboratories, and other organizations now
|
||||
contribute to the development of OpenMC. For more information on OpenMC, feel
|
||||
free to send a message to the User's Group `mailing list`_.
|
||||
free to send a message to the User's Group `mailing list`_. Documentation for
|
||||
the latest developmental version of the develop branch can be found on
|
||||
`Read the Docs`_.
|
||||
|
||||
.. _Computational Reactor Physics Group: http://crpg.mit.edu
|
||||
.. _Massachusetts Institute of Technology: http://web.mit.edu
|
||||
.. _mailing list: https://groups.google.com/forum/?fromgroups=#!forum/openmc-users
|
||||
.. _Read the Docs: http://openmc.readthedocs.io/en/latest/
|
||||
|
||||
.. only:: html
|
||||
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
License Agreement
|
||||
=================
|
||||
|
||||
Copyright © 2011-2015 Massachusetts Institute of Technology
|
||||
Copyright © 2011-2016 Massachusetts Institute of Technology
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
this software and associated documentation files (the "Software"), to deal in
|
||||
|
|
|
|||
|
|
@ -437,6 +437,8 @@ where :math:`(x_0, y_0, z_0)` are the coordinates to the lower-left-bottom
|
|||
corner of the lattice, and :math:`p_0, p_1, p_2` are the pitches along the
|
||||
:math:`x`, :math:`y`, and :math:`z` axes, respectively.
|
||||
|
||||
.. _hexagonal_indexing:
|
||||
|
||||
Hexagonal Lattice Indexing
|
||||
--------------------------
|
||||
|
||||
|
|
|
|||
|
|
@ -1,8 +0,0 @@
|
|||
.. _pythonapi_ace:
|
||||
|
||||
==========
|
||||
ACE Format
|
||||
==========
|
||||
|
||||
.. automodule:: openmc.ace
|
||||
:members:
|
||||
|
|
@ -1,8 +0,0 @@
|
|||
.. _pythonapi_cmfd:
|
||||
|
||||
====
|
||||
CMFD
|
||||
====
|
||||
|
||||
.. automodule:: openmc.cmfd
|
||||
:members:
|
||||
|
|
@ -1,8 +0,0 @@
|
|||
.. _pythonapi_element:
|
||||
|
||||
=======
|
||||
Element
|
||||
=======
|
||||
|
||||
.. automodule:: openmc.element
|
||||
:members:
|
||||
|
|
@ -1,8 +0,0 @@
|
|||
.. _pythonapi_energy_groups:
|
||||
|
||||
=============
|
||||
Energy Groups
|
||||
=============
|
||||
|
||||
.. automodule:: openmc.mgxs.groups
|
||||
:members:
|
||||
|
|
@ -141,15 +141,12 @@
|
|||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"%matplotlib inline\n",
|
||||
"import numpy as np\n",
|
||||
"import matplotlib.pyplot as plt\n",
|
||||
"\n",
|
||||
"import openmc\n",
|
||||
"import openmc.mgxs as mgxs\n",
|
||||
"from openmc.source import Source\n",
|
||||
"from openmc.stats import Box\n",
|
||||
"\n",
|
||||
"%matplotlib inline"
|
||||
"import openmc.mgxs as mgxs"
|
||||
]
|
||||
},
|
||||
{
|
||||
|
|
@ -204,7 +201,7 @@
|
|||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"With our material, we can now create a `MaterialsFile` object that can be exported to an actual XML file."
|
||||
"With our material, we can now create a `Materials` object that can be exported to an actual XML file."
|
||||
]
|
||||
},
|
||||
{
|
||||
|
|
@ -215,10 +212,9 @@
|
|||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# Instantiate a MaterialsFile, register all Materials, and export to XML\n",
|
||||
"materials_file = openmc.MaterialsFile()\n",
|
||||
"# Instantiate a Materials collection and export to XML\n",
|
||||
"materials_file = openmc.Materials([inf_medium])\n",
|
||||
"materials_file.default_xs = '71c'\n",
|
||||
"materials_file.add_material(inf_medium)\n",
|
||||
"materials_file.export_to_xml()"
|
||||
]
|
||||
},
|
||||
|
|
@ -293,7 +289,7 @@
|
|||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"We now must create a geometry that is assigned a root universe, put the geometry into a `GeometryFile` object, and export it to XML."
|
||||
"We now must create a geometry that is assigned a root universe and export it to XML."
|
||||
]
|
||||
},
|
||||
{
|
||||
|
|
@ -308,12 +304,8 @@
|
|||
"openmc_geometry = openmc.Geometry()\n",
|
||||
"openmc_geometry.root_universe = root_universe\n",
|
||||
"\n",
|
||||
"# Instantiate a GeometryFile\n",
|
||||
"geometry_file = openmc.GeometryFile()\n",
|
||||
"geometry_file.geometry = openmc_geometry\n",
|
||||
"\n",
|
||||
"# Export to \"geometry.xml\"\n",
|
||||
"geometry_file.export_to_xml()"
|
||||
"openmc_geometry.export_to_xml()"
|
||||
]
|
||||
},
|
||||
{
|
||||
|
|
@ -336,15 +328,17 @@
|
|||
"inactive = 10\n",
|
||||
"particles = 2500\n",
|
||||
"\n",
|
||||
"# Instantiate a SettingsFile\n",
|
||||
"settings_file = openmc.SettingsFile()\n",
|
||||
"# Instantiate a Settings object\n",
|
||||
"settings_file = openmc.Settings()\n",
|
||||
"settings_file.batches = batches\n",
|
||||
"settings_file.inactive = inactive\n",
|
||||
"settings_file.particles = particles\n",
|
||||
"settings_file.output = {'tallies': True}\n",
|
||||
"\n",
|
||||
"# Create an initial uniform spatial source distribution over fissionable zones\n",
|
||||
"bounds = [-0.63, -0.63, -0.63, 0.63, 0.63, 0.63]\n",
|
||||
"settings_file.source = Source(space=Box(\n",
|
||||
" bounds[:3], bounds[3:], only_fissionable=True))\n",
|
||||
"uniform_dist = openmc.stats.Box(bounds[:3], bounds[3:], only_fissionable=True)\n",
|
||||
"settings_file.source = openmc.source.Source(space=uniform_dist)\n",
|
||||
"\n",
|
||||
"# Export to \"settings.xml\"\n",
|
||||
"settings_file.export_to_xml()"
|
||||
|
|
@ -378,10 +372,12 @@
|
|||
"\n",
|
||||
"* `TotalXS`\n",
|
||||
"* `TransportXS`\n",
|
||||
"* `NuTransportXS`\n",
|
||||
"* `AbsorptionXS`\n",
|
||||
"* `CaptureXS`\n",
|
||||
"* `FissionXS`\n",
|
||||
"* `NuFissionXS`\n",
|
||||
"* `KappaFissionXS`\n",
|
||||
"* `ScatterXS`\n",
|
||||
"* `NuScatterXS`\n",
|
||||
"* `ScatterMatrixXS`\n",
|
||||
|
|
@ -400,9 +396,9 @@
|
|||
"outputs": [],
|
||||
"source": [
|
||||
"# Instantiate a few different sections\n",
|
||||
"total = mgxs.TotalXS(domain=cell, domain_type='cell', groups=groups)\n",
|
||||
"absorption = mgxs.AbsorptionXS(domain=cell, domain_type='cell', groups=groups)\n",
|
||||
"scattering = mgxs.ScatterXS(domain=cell, domain_type='cell', groups=groups)"
|
||||
"total = mgxs.TotalXS(domain=cell, groups=groups)\n",
|
||||
"absorption = mgxs.AbsorptionXS(domain=cell, groups=groups)\n",
|
||||
"scattering = mgxs.ScatterXS(domain=cell, groups=groups)"
|
||||
]
|
||||
},
|
||||
{
|
||||
|
|
@ -423,22 +419,24 @@
|
|||
"data": {
|
||||
"text/plain": [
|
||||
"OrderedDict([('flux', Tally\n",
|
||||
" \tID =\t10000\n",
|
||||
" \tName =\t\n",
|
||||
" \tFilters =\t\n",
|
||||
" \t\tcell\t[1]\n",
|
||||
" \t\tenergy\t[ 0.00000000e+00 6.25000000e-07 2.00000000e+01]\n",
|
||||
" \tNuclides =\ttotal \n",
|
||||
" \tScores =\t['flux']\n",
|
||||
" \tEstimator =\ttracklength), ('absorption', Tally\n",
|
||||
" \tID =\t10001\n",
|
||||
" \tName =\t\n",
|
||||
" \tFilters =\t\n",
|
||||
" \t\tcell\t[1]\n",
|
||||
" \t\tenergy\t[ 0.00000000e+00 6.25000000e-07 2.00000000e+01]\n",
|
||||
" \tNuclides =\ttotal \n",
|
||||
" \tScores =\t['absorption']\n",
|
||||
" \tEstimator =\ttracklength)])"
|
||||
"\tID =\t10000\n",
|
||||
"\tName =\t\n",
|
||||
"\tFilters =\t\n",
|
||||
" \t\tcell\t[1]\n",
|
||||
" \t\tenergy\t[ 0.00000000e+00 6.25000000e-07 2.00000000e+01]\n",
|
||||
"\tNuclides =\ttotal \n",
|
||||
"\tScores =\t['flux']\n",
|
||||
"\tEstimator =\ttracklength\n",
|
||||
"), ('absorption', Tally\n",
|
||||
"\tID =\t10001\n",
|
||||
"\tName =\t\n",
|
||||
"\tFilters =\t\n",
|
||||
" \t\tcell\t[1]\n",
|
||||
" \t\tenergy\t[ 0.00000000e+00 6.25000000e-07 2.00000000e+01]\n",
|
||||
"\tNuclides =\ttotal \n",
|
||||
"\tScores =\t['absorption']\n",
|
||||
"\tEstimator =\ttracklength\n",
|
||||
")])"
|
||||
]
|
||||
},
|
||||
"execution_count": 13,
|
||||
|
|
@ -454,7 +452,7 @@
|
|||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"The `Absorption` object includes tracklength tallies for the 'absorption' and 'flux' scores in the 2-group structure in cell 1. Now that each `MGXS` object contains the tallies that it needs, we must add these tallies to a `TalliesFile` object to generate the \"tallies.xml\" input file for OpenMC."
|
||||
"The `Absorption` object includes tracklength tallies for the 'absorption' and 'flux' scores in the 2-group structure in cell 1. Now that each `MGXS` object contains the tallies that it needs, we must add these tallies to a `Tallies` object to generate the \"tallies.xml\" input file for OpenMC."
|
||||
]
|
||||
},
|
||||
{
|
||||
|
|
@ -465,21 +463,18 @@
|
|||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# Instantiate an empty TalliesFile\n",
|
||||
"tallies_file = openmc.TalliesFile()\n",
|
||||
"# Instantiate an empty Tallies object\n",
|
||||
"tallies_file = openmc.Tallies()\n",
|
||||
"\n",
|
||||
"# Add total tallies to the tallies file\n",
|
||||
"for tally in total.tallies.values():\n",
|
||||
" tallies_file.add_tally(tally)\n",
|
||||
"tallies_file += total.tallies.values()\n",
|
||||
"\n",
|
||||
"# Add absorption tallies to the tallies file\n",
|
||||
"for tally in absorption.tallies.values():\n",
|
||||
" tallies_file.add_tally(tally)\n",
|
||||
"tallies_file += absorption.tallies.values()\n",
|
||||
"\n",
|
||||
"# Add scattering tallies to the tallies file\n",
|
||||
"for tally in scattering.tallies.values():\n",
|
||||
" tallies_file.add_tally(tally)\n",
|
||||
" \n",
|
||||
"tallies_file += scattering.tallies.values()\n",
|
||||
"\n",
|
||||
"# Export to \"tallies.xml\"\n",
|
||||
"tallies_file.export_to_xml()"
|
||||
]
|
||||
|
|
@ -515,11 +510,11 @@
|
|||
" 888\n",
|
||||
" 888\n",
|
||||
"\n",
|
||||
" Copyright: 2011-2015 Massachusetts Institute of Technology\n",
|
||||
" License: http://mit-crpg.github.io/openmc/license.html\n",
|
||||
" Copyright: 2011-2016 Massachusetts Institute of Technology\n",
|
||||
" License: http://openmc.readthedocs.io/en/latest/license.html\n",
|
||||
" Version: 0.7.1\n",
|
||||
" Git SHA1: 34381b40a9445a727e360873aaa6ef892af1cb6a\n",
|
||||
" Date/Time: 2016-02-07 15:58:16\n",
|
||||
" Git SHA1: 19feb55e6d5e8350398627f39fb55ee8e2e63011\n",
|
||||
" Date/Time: 2016-05-13 10:19:16\n",
|
||||
" MPI Processes: 1\n",
|
||||
"\n",
|
||||
" ===========================================================================\n",
|
||||
|
|
@ -546,56 +541,56 @@
|
|||
"\n",
|
||||
" Bat./Gen. k Average k \n",
|
||||
" ========= ======== ==================== \n",
|
||||
" 1/1 1.19804 \n",
|
||||
" 2/1 1.12945 \n",
|
||||
" 3/1 1.15573 \n",
|
||||
" 4/1 1.13929 \n",
|
||||
" 5/1 1.16300 \n",
|
||||
" 6/1 1.22117 \n",
|
||||
" 7/1 1.19012 \n",
|
||||
" 8/1 1.11299 \n",
|
||||
" 9/1 1.16066 \n",
|
||||
" 10/1 1.12566 \n",
|
||||
" 11/1 1.20854 \n",
|
||||
" 12/1 1.14691 1.17773 +/- 0.03082\n",
|
||||
" 13/1 1.17204 1.17583 +/- 0.01789\n",
|
||||
" 14/1 1.14148 1.16724 +/- 0.01529\n",
|
||||
" 15/1 1.17272 1.16834 +/- 0.01189\n",
|
||||
" 16/1 1.18575 1.17124 +/- 0.01014\n",
|
||||
" 17/1 1.20498 1.17606 +/- 0.00983\n",
|
||||
" 18/1 1.14754 1.17249 +/- 0.00923\n",
|
||||
" 19/1 1.18141 1.17348 +/- 0.00820\n",
|
||||
" 20/1 1.15074 1.17121 +/- 0.00768\n",
|
||||
" 21/1 1.15914 1.17011 +/- 0.00703\n",
|
||||
" 22/1 1.14586 1.16809 +/- 0.00673\n",
|
||||
" 23/1 1.18999 1.16978 +/- 0.00642\n",
|
||||
" 24/1 1.15101 1.16844 +/- 0.00609\n",
|
||||
" 25/1 1.13791 1.16640 +/- 0.00602\n",
|
||||
" 26/1 1.19791 1.16837 +/- 0.00597\n",
|
||||
" 27/1 1.19818 1.17012 +/- 0.00587\n",
|
||||
" 28/1 1.14160 1.16854 +/- 0.00576\n",
|
||||
" 29/1 1.11487 1.16571 +/- 0.00614\n",
|
||||
" 30/1 1.17538 1.16620 +/- 0.00584\n",
|
||||
" 31/1 1.20210 1.16791 +/- 0.00581\n",
|
||||
" 32/1 1.20078 1.16940 +/- 0.00574\n",
|
||||
" 33/1 1.14624 1.16839 +/- 0.00558\n",
|
||||
" 34/1 1.14618 1.16747 +/- 0.00542\n",
|
||||
" 35/1 1.16866 1.16752 +/- 0.00520\n",
|
||||
" 36/1 1.18565 1.16821 +/- 0.00504\n",
|
||||
" 37/1 1.16824 1.16821 +/- 0.00485\n",
|
||||
" 38/1 1.18299 1.16874 +/- 0.00471\n",
|
||||
" 39/1 1.21418 1.17031 +/- 0.00480\n",
|
||||
" 40/1 1.11167 1.16835 +/- 0.00504\n",
|
||||
" 41/1 1.11545 1.16665 +/- 0.00516\n",
|
||||
" 42/1 1.11114 1.16491 +/- 0.00529\n",
|
||||
" 43/1 1.14227 1.16423 +/- 0.00517\n",
|
||||
" 44/1 1.14104 1.16355 +/- 0.00506\n",
|
||||
" 45/1 1.16756 1.16366 +/- 0.00492\n",
|
||||
" 46/1 1.13065 1.16274 +/- 0.00487\n",
|
||||
" 47/1 1.11251 1.16139 +/- 0.00492\n",
|
||||
" 48/1 1.14731 1.16101 +/- 0.00481\n",
|
||||
" 49/1 1.16691 1.16117 +/- 0.00469\n",
|
||||
" 50/1 1.19679 1.16206 +/- 0.00465\n",
|
||||
" 1/1 1.11184 \n",
|
||||
" 2/1 1.15820 \n",
|
||||
" 3/1 1.18468 \n",
|
||||
" 4/1 1.17492 \n",
|
||||
" 5/1 1.19645 \n",
|
||||
" 6/1 1.18436 \n",
|
||||
" 7/1 1.14070 \n",
|
||||
" 8/1 1.15150 \n",
|
||||
" 9/1 1.19202 \n",
|
||||
" 10/1 1.17677 \n",
|
||||
" 11/1 1.20272 \n",
|
||||
" 12/1 1.21366 1.20819 +/- 0.00547\n",
|
||||
" 13/1 1.15906 1.19181 +/- 0.01668\n",
|
||||
" 14/1 1.14687 1.18058 +/- 0.01629\n",
|
||||
" 15/1 1.14570 1.17360 +/- 0.01442\n",
|
||||
" 16/1 1.13480 1.16713 +/- 0.01343\n",
|
||||
" 17/1 1.17680 1.16852 +/- 0.01144\n",
|
||||
" 18/1 1.16866 1.16853 +/- 0.00990\n",
|
||||
" 19/1 1.19253 1.17120 +/- 0.00913\n",
|
||||
" 20/1 1.18124 1.17220 +/- 0.00823\n",
|
||||
" 21/1 1.19206 1.17401 +/- 0.00766\n",
|
||||
" 22/1 1.17681 1.17424 +/- 0.00700\n",
|
||||
" 23/1 1.17634 1.17440 +/- 0.00644\n",
|
||||
" 24/1 1.13659 1.17170 +/- 0.00654\n",
|
||||
" 25/1 1.17144 1.17169 +/- 0.00609\n",
|
||||
" 26/1 1.20649 1.17386 +/- 0.00610\n",
|
||||
" 27/1 1.11238 1.17024 +/- 0.00678\n",
|
||||
" 28/1 1.18911 1.17129 +/- 0.00647\n",
|
||||
" 29/1 1.14681 1.17000 +/- 0.00626\n",
|
||||
" 30/1 1.12152 1.16758 +/- 0.00641\n",
|
||||
" 31/1 1.12729 1.16566 +/- 0.00639\n",
|
||||
" 32/1 1.15399 1.16513 +/- 0.00612\n",
|
||||
" 33/1 1.13547 1.16384 +/- 0.00599\n",
|
||||
" 34/1 1.17723 1.16440 +/- 0.00576\n",
|
||||
" 35/1 1.09296 1.16154 +/- 0.00622\n",
|
||||
" 36/1 1.19621 1.16287 +/- 0.00612\n",
|
||||
" 37/1 1.12560 1.16149 +/- 0.00605\n",
|
||||
" 38/1 1.17872 1.16211 +/- 0.00586\n",
|
||||
" 39/1 1.17721 1.16263 +/- 0.00568\n",
|
||||
" 40/1 1.13724 1.16178 +/- 0.00555\n",
|
||||
" 41/1 1.18526 1.16254 +/- 0.00542\n",
|
||||
" 42/1 1.13779 1.16177 +/- 0.00531\n",
|
||||
" 43/1 1.15066 1.16143 +/- 0.00516\n",
|
||||
" 44/1 1.12174 1.16026 +/- 0.00514\n",
|
||||
" 45/1 1.17479 1.16068 +/- 0.00501\n",
|
||||
" 46/1 1.14146 1.16014 +/- 0.00489\n",
|
||||
" 47/1 1.20464 1.16135 +/- 0.00491\n",
|
||||
" 48/1 1.15119 1.16108 +/- 0.00479\n",
|
||||
" 49/1 1.17938 1.16155 +/- 0.00468\n",
|
||||
" 50/1 1.15798 1.16146 +/- 0.00457\n",
|
||||
" Creating state point statepoint.50.h5...\n",
|
||||
"\n",
|
||||
" ===========================================================================\n",
|
||||
|
|
@ -605,27 +600,27 @@
|
|||
"\n",
|
||||
" =======================> TIMING STATISTICS <=======================\n",
|
||||
"\n",
|
||||
" Total time for initialization = 3.2100E-01 seconds\n",
|
||||
" Reading cross sections = 7.4000E-02 seconds\n",
|
||||
" Total time in simulation = 8.3830E+00 seconds\n",
|
||||
" Time in transport only = 8.3670E+00 seconds\n",
|
||||
" Time in inactive batches = 1.0330E+00 seconds\n",
|
||||
" Time in active batches = 7.3500E+00 seconds\n",
|
||||
" Time synchronizing fission bank = 4.0000E-03 seconds\n",
|
||||
" Sampling source sites = 1.0000E-03 seconds\n",
|
||||
" SEND/RECV source sites = 3.0000E-03 seconds\n",
|
||||
" Total time for initialization = 4.2300E-01 seconds\n",
|
||||
" Reading cross sections = 9.3000E-02 seconds\n",
|
||||
" Total time in simulation = 1.6549E+01 seconds\n",
|
||||
" Time in transport only = 1.6535E+01 seconds\n",
|
||||
" Time in inactive batches = 2.3650E+00 seconds\n",
|
||||
" Time in active batches = 1.4184E+01 seconds\n",
|
||||
" Time synchronizing fission bank = 5.0000E-03 seconds\n",
|
||||
" Sampling source sites = 3.0000E-03 seconds\n",
|
||||
" SEND/RECV source sites = 0.0000E+00 seconds\n",
|
||||
" Time accumulating tallies = 0.0000E+00 seconds\n",
|
||||
" Total time for finalization = 1.0000E-03 seconds\n",
|
||||
" Total time elapsed = 8.7140E+00 seconds\n",
|
||||
" Calculation Rate (inactive) = 24201.4 neutrons/second\n",
|
||||
" Calculation Rate (active) = 13605.4 neutrons/second\n",
|
||||
" Total time for finalization = 0.0000E+00 seconds\n",
|
||||
" Total time elapsed = 1.6981E+01 seconds\n",
|
||||
" Calculation Rate (inactive) = 10570.8 neutrons/second\n",
|
||||
" Calculation Rate (active) = 7050.20 neutrons/second\n",
|
||||
"\n",
|
||||
" ============================> RESULTS <============================\n",
|
||||
"\n",
|
||||
" k-effective (Collision) = 1.16131 +/- 0.00453\n",
|
||||
" k-effective (Track-length) = 1.16206 +/- 0.00465\n",
|
||||
" k-effective (Absorption) = 1.16096 +/- 0.00364\n",
|
||||
" Combined k-effective = 1.16120 +/- 0.00325\n",
|
||||
" k-effective (Collision) = 1.15984 +/- 0.00411\n",
|
||||
" k-effective (Track-length) = 1.16146 +/- 0.00457\n",
|
||||
" k-effective (Absorption) = 1.16177 +/- 0.00380\n",
|
||||
" Combined k-effective = 1.16105 +/- 0.00364\n",
|
||||
" Leakage Fraction = 0.00000 +/- 0.00000\n",
|
||||
"\n"
|
||||
]
|
||||
|
|
@ -643,8 +638,7 @@
|
|||
],
|
||||
"source": [
|
||||
"# Run OpenMC\n",
|
||||
"executor = openmc.Executor()\n",
|
||||
"executor.run_simulation()"
|
||||
"openmc.run()"
|
||||
]
|
||||
},
|
||||
{
|
||||
|
|
@ -677,20 +671,7 @@
|
|||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"In addition to the statepoint file, our simulation also created a summary file which encapsulates information about the materials and geometry. This is necessary for the `openmc.mgxs` module to properly process the tally data. We first create a `Summary` object and link it with the statepoint."
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 17,
|
||||
"metadata": {
|
||||
"collapsed": false
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# Load the summary file and link it with the statepoint\n",
|
||||
"su = openmc.Summary('summary.h5')\n",
|
||||
"sp.link_with_summary(su)"
|
||||
"In addition to the statepoint file, our simulation also created a summary file which encapsulates information about the materials and geometry. By default, a `Summary` object is automatically linked when a `StatePoint` is loaded. This is necessary for the `openmc.mgxs` module to properly process the tally data."
|
||||
]
|
||||
},
|
||||
{
|
||||
|
|
@ -702,7 +683,7 @@
|
|||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 18,
|
||||
"execution_count": 17,
|
||||
"metadata": {
|
||||
"collapsed": false
|
||||
},
|
||||
|
|
@ -737,7 +718,7 @@
|
|||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 19,
|
||||
"execution_count": 18,
|
||||
"metadata": {
|
||||
"collapsed": false
|
||||
},
|
||||
|
|
@ -751,8 +732,8 @@
|
|||
"\tDomain Type =\tcell\n",
|
||||
"\tDomain ID =\t1\n",
|
||||
"\tCross Sections [cm^-1]:\n",
|
||||
" Group 1 [6.25e-07 - 20.0 MeV]:\t6.81e-01 +/- 1.88e-01%\n",
|
||||
" Group 2 [0.0 - 6.25e-07 MeV]:\t1.40e+00 +/- 5.91e-01%\n",
|
||||
" Group 1 [6.25e-07 - 20.0 MeV]:\t6.81e-01 +/- 2.69e-01%\n",
|
||||
" Group 2 [0.0 - 6.25e-07 MeV]:\t1.40e+00 +/- 5.93e-01%\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"\n"
|
||||
|
|
@ -772,7 +753,7 @@
|
|||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 20,
|
||||
"execution_count": 19,
|
||||
"metadata": {
|
||||
"collapsed": false
|
||||
},
|
||||
|
|
@ -780,7 +761,7 @@
|
|||
{
|
||||
"data": {
|
||||
"text/html": [
|
||||
"<div style=\"max-height:1000px;max-width:1500px;overflow:auto;\">\n",
|
||||
"<div>\n",
|
||||
"<table border=\"1\" class=\"dataframe\">\n",
|
||||
" <thead>\n",
|
||||
" <tr style=\"text-align: right;\">\n",
|
||||
|
|
@ -795,19 +776,19 @@
|
|||
" <tbody>\n",
|
||||
" <tr>\n",
|
||||
" <th>1</th>\n",
|
||||
" <td> 1</td>\n",
|
||||
" <td> 1</td>\n",
|
||||
" <td> total</td>\n",
|
||||
" <td> 0.668323</td>\n",
|
||||
" <td> 0.001264</td>\n",
|
||||
" <td>1</td>\n",
|
||||
" <td>1</td>\n",
|
||||
" <td>total</td>\n",
|
||||
" <td>0.667787</td>\n",
|
||||
" <td>0.001802</td>\n",
|
||||
" </tr>\n",
|
||||
" <tr>\n",
|
||||
" <th>0</th>\n",
|
||||
" <td> 1</td>\n",
|
||||
" <td> 2</td>\n",
|
||||
" <td> total</td>\n",
|
||||
" <td> 1.293258</td>\n",
|
||||
" <td> 0.007624</td>\n",
|
||||
" <td>1</td>\n",
|
||||
" <td>2</td>\n",
|
||||
" <td>total</td>\n",
|
||||
" <td>1.292013</td>\n",
|
||||
" <td>0.007642</td>\n",
|
||||
" </tr>\n",
|
||||
" </tbody>\n",
|
||||
"</table>\n",
|
||||
|
|
@ -815,11 +796,11 @@
|
|||
],
|
||||
"text/plain": [
|
||||
" cell group in nuclide mean std. dev.\n",
|
||||
"1 1 1 total 0.668323 0.001264\n",
|
||||
"0 1 2 total 1.293258 0.007624"
|
||||
"1 1 1 total 0.667787 0.001802\n",
|
||||
"0 1 2 total 1.292013 0.007642"
|
||||
]
|
||||
},
|
||||
"execution_count": 20,
|
||||
"execution_count": 19,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
|
|
@ -838,7 +819,7 @@
|
|||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 21,
|
||||
"execution_count": 20,
|
||||
"metadata": {
|
||||
"collapsed": true
|
||||
},
|
||||
|
|
@ -856,7 +837,7 @@
|
|||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 22,
|
||||
"execution_count": 21,
|
||||
"metadata": {
|
||||
"collapsed": false
|
||||
},
|
||||
|
|
@ -883,7 +864,7 @@
|
|||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 23,
|
||||
"execution_count": 22,
|
||||
"metadata": {
|
||||
"collapsed": false
|
||||
},
|
||||
|
|
@ -891,7 +872,7 @@
|
|||
{
|
||||
"data": {
|
||||
"text/html": [
|
||||
"<div style=\"max-height:1000px;max-width:1500px;overflow:auto;\">\n",
|
||||
"<div>\n",
|
||||
"<table border=\"1\" class=\"dataframe\">\n",
|
||||
" <thead>\n",
|
||||
" <tr style=\"text-align: right;\">\n",
|
||||
|
|
@ -908,23 +889,23 @@
|
|||
" <tbody>\n",
|
||||
" <tr>\n",
|
||||
" <th>0</th>\n",
|
||||
" <td> 1</td>\n",
|
||||
" <td> 0.000000</td>\n",
|
||||
" <td> 0.000001</td>\n",
|
||||
" <td> total</td>\n",
|
||||
" <td> (((total / flux) - (absorption / flux)) - (sca...</td>\n",
|
||||
" <td> 4.884981e-15</td>\n",
|
||||
" <td> 0.011274</td>\n",
|
||||
" <td>1</td>\n",
|
||||
" <td>0.000000e+00</td>\n",
|
||||
" <td>6.250000e-07</td>\n",
|
||||
" <td>total</td>\n",
|
||||
" <td>(((total / flux) - (absorption / flux)) - (sca...</td>\n",
|
||||
" <td>-3.774758e-15</td>\n",
|
||||
" <td>0.011292</td>\n",
|
||||
" </tr>\n",
|
||||
" <tr>\n",
|
||||
" <th>1</th>\n",
|
||||
" <td> 1</td>\n",
|
||||
" <td> 0.000001</td>\n",
|
||||
" <td> 20.000000</td>\n",
|
||||
" <td> total</td>\n",
|
||||
" <td> (((total / flux) - (absorption / flux)) - (sca...</td>\n",
|
||||
" <td> 1.221245e-15</td>\n",
|
||||
" <td> 0.001802</td>\n",
|
||||
" <td>1</td>\n",
|
||||
" <td>6.250000e-07</td>\n",
|
||||
" <td>2.000000e+01</td>\n",
|
||||
" <td>total</td>\n",
|
||||
" <td>(((total / flux) - (absorption / flux)) - (sca...</td>\n",
|
||||
" <td>1.443290e-15</td>\n",
|
||||
" <td>0.002570</td>\n",
|
||||
" </tr>\n",
|
||||
" </tbody>\n",
|
||||
"</table>\n",
|
||||
|
|
@ -935,12 +916,12 @@
|
|||
"0 1 0.00e+00 6.25e-07 total \n",
|
||||
"1 1 6.25e-07 2.00e+01 total \n",
|
||||
"\n",
|
||||
" score mean std. dev. \n",
|
||||
"0 (((total / flux) - (absorption / flux)) - (sca... 4.88e-15 1.13e-02 \n",
|
||||
"1 (((total / flux) - (absorption / flux)) - (sca... 1.22e-15 1.80e-03 "
|
||||
" score mean std. dev. \n",
|
||||
"0 (((total / flux) - (absorption / flux)) - (sca... -3.77e-15 1.13e-02 \n",
|
||||
"1 (((total / flux) - (absorption / flux)) - (sca... 1.44e-15 2.57e-03 "
|
||||
]
|
||||
},
|
||||
"execution_count": 23,
|
||||
"execution_count": 22,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
|
|
@ -962,7 +943,7 @@
|
|||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 24,
|
||||
"execution_count": 23,
|
||||
"metadata": {
|
||||
"collapsed": false
|
||||
},
|
||||
|
|
@ -970,7 +951,7 @@
|
|||
{
|
||||
"data": {
|
||||
"text/html": [
|
||||
"<div style=\"max-height:1000px;max-width:1500px;overflow:auto;\">\n",
|
||||
"<div>\n",
|
||||
"<table border=\"1\" class=\"dataframe\">\n",
|
||||
" <thead>\n",
|
||||
" <tr style=\"text-align: right;\">\n",
|
||||
|
|
@ -987,23 +968,23 @@
|
|||
" <tbody>\n",
|
||||
" <tr>\n",
|
||||
" <th>0</th>\n",
|
||||
" <td> 1</td>\n",
|
||||
" <td> 0.000000</td>\n",
|
||||
" <td> 0.000001</td>\n",
|
||||
" <td> total</td>\n",
|
||||
" <td> ((absorption / flux) / (total / flux))</td>\n",
|
||||
" <td> 0.076219</td>\n",
|
||||
" <td> 0.000651</td>\n",
|
||||
" <td>1</td>\n",
|
||||
" <td>0.000000e+00</td>\n",
|
||||
" <td>6.250000e-07</td>\n",
|
||||
" <td>total</td>\n",
|
||||
" <td>((absorption / flux) / (total / flux))</td>\n",
|
||||
" <td>0.076115</td>\n",
|
||||
" <td>0.000649</td>\n",
|
||||
" </tr>\n",
|
||||
" <tr>\n",
|
||||
" <th>1</th>\n",
|
||||
" <td> 1</td>\n",
|
||||
" <td> 0.000001</td>\n",
|
||||
" <td> 20.000000</td>\n",
|
||||
" <td> total</td>\n",
|
||||
" <td> ((absorption / flux) / (total / flux))</td>\n",
|
||||
" <td> 0.019319</td>\n",
|
||||
" <td> 0.000086</td>\n",
|
||||
" <td>1</td>\n",
|
||||
" <td>6.250000e-07</td>\n",
|
||||
" <td>2.000000e+01</td>\n",
|
||||
" <td>total</td>\n",
|
||||
" <td>((absorption / flux) / (total / flux))</td>\n",
|
||||
" <td>0.019263</td>\n",
|
||||
" <td>0.000095</td>\n",
|
||||
" </tr>\n",
|
||||
" </tbody>\n",
|
||||
"</table>\n",
|
||||
|
|
@ -1015,11 +996,11 @@
|
|||
"1 1 6.25e-07 2.00e+01 total \n",
|
||||
"\n",
|
||||
" score mean std. dev. \n",
|
||||
"0 ((absorption / flux) / (total / flux)) 7.62e-02 6.51e-04 \n",
|
||||
"1 ((absorption / flux) / (total / flux)) 1.93e-02 8.65e-05 "
|
||||
"0 ((absorption / flux) / (total / flux)) 7.61e-02 6.49e-04 \n",
|
||||
"1 ((absorption / flux) / (total / flux)) 1.93e-02 9.46e-05 "
|
||||
]
|
||||
},
|
||||
"execution_count": 24,
|
||||
"execution_count": 23,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
|
|
@ -1034,7 +1015,7 @@
|
|||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 25,
|
||||
"execution_count": 24,
|
||||
"metadata": {
|
||||
"collapsed": false
|
||||
},
|
||||
|
|
@ -1042,7 +1023,7 @@
|
|||
{
|
||||
"data": {
|
||||
"text/html": [
|
||||
"<div style=\"max-height:1000px;max-width:1500px;overflow:auto;\">\n",
|
||||
"<div>\n",
|
||||
"<table border=\"1\" class=\"dataframe\">\n",
|
||||
" <thead>\n",
|
||||
" <tr style=\"text-align: right;\">\n",
|
||||
|
|
@ -1059,23 +1040,23 @@
|
|||
" <tbody>\n",
|
||||
" <tr>\n",
|
||||
" <th>0</th>\n",
|
||||
" <td> 1</td>\n",
|
||||
" <td> 0.000000</td>\n",
|
||||
" <td> 0.000001</td>\n",
|
||||
" <td> total</td>\n",
|
||||
" <td> ((scatter / flux) / (total / flux))</td>\n",
|
||||
" <td> 0.923781</td>\n",
|
||||
" <td> 0.007714</td>\n",
|
||||
" <td>1</td>\n",
|
||||
" <td>0.000000e+00</td>\n",
|
||||
" <td>6.250000e-07</td>\n",
|
||||
" <td>total</td>\n",
|
||||
" <td>((scatter / flux) / (total / flux))</td>\n",
|
||||
" <td>0.923885</td>\n",
|
||||
" <td>0.007736</td>\n",
|
||||
" </tr>\n",
|
||||
" <tr>\n",
|
||||
" <th>1</th>\n",
|
||||
" <td> 1</td>\n",
|
||||
" <td> 0.000001</td>\n",
|
||||
" <td> 20.000000</td>\n",
|
||||
" <td> total</td>\n",
|
||||
" <td> ((scatter / flux) / (total / flux))</td>\n",
|
||||
" <td> 0.980681</td>\n",
|
||||
" <td> 0.002617</td>\n",
|
||||
" <td>1</td>\n",
|
||||
" <td>6.250000e-07</td>\n",
|
||||
" <td>2.000000e+01</td>\n",
|
||||
" <td>total</td>\n",
|
||||
" <td>((scatter / flux) / (total / flux))</td>\n",
|
||||
" <td>0.980737</td>\n",
|
||||
" <td>0.003737</td>\n",
|
||||
" </tr>\n",
|
||||
" </tbody>\n",
|
||||
"</table>\n",
|
||||
|
|
@ -1087,11 +1068,11 @@
|
|||
"1 1 6.25e-07 2.00e+01 total \n",
|
||||
"\n",
|
||||
" score mean std. dev. \n",
|
||||
"0 ((scatter / flux) / (total / flux)) 9.24e-01 7.71e-03 \n",
|
||||
"1 ((scatter / flux) / (total / flux)) 9.81e-01 2.62e-03 "
|
||||
"0 ((scatter / flux) / (total / flux)) 9.24e-01 7.74e-03 \n",
|
||||
"1 ((scatter / flux) / (total / flux)) 9.81e-01 3.74e-03 "
|
||||
]
|
||||
},
|
||||
"execution_count": 25,
|
||||
"execution_count": 24,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
|
|
@ -1113,7 +1094,7 @@
|
|||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 26,
|
||||
"execution_count": 25,
|
||||
"metadata": {
|
||||
"collapsed": false
|
||||
},
|
||||
|
|
@ -1121,7 +1102,7 @@
|
|||
{
|
||||
"data": {
|
||||
"text/html": [
|
||||
"<div style=\"max-height:1000px;max-width:1500px;overflow:auto;\">\n",
|
||||
"<div>\n",
|
||||
"<table border=\"1\" class=\"dataframe\">\n",
|
||||
" <thead>\n",
|
||||
" <tr style=\"text-align: right;\">\n",
|
||||
|
|
@ -1138,23 +1119,23 @@
|
|||
" <tbody>\n",
|
||||
" <tr>\n",
|
||||
" <th>0</th>\n",
|
||||
" <td> 1</td>\n",
|
||||
" <td> 0.000000</td>\n",
|
||||
" <td> 0.000001</td>\n",
|
||||
" <td> total</td>\n",
|
||||
" <td> (((absorption / flux) / (total / flux)) + ((sc...</td>\n",
|
||||
" <td> 1</td>\n",
|
||||
" <td> 0.007741</td>\n",
|
||||
" <td>1</td>\n",
|
||||
" <td>0.000000e+00</td>\n",
|
||||
" <td>6.250000e-07</td>\n",
|
||||
" <td>total</td>\n",
|
||||
" <td>(((absorption / flux) / (total / flux)) + ((sc...</td>\n",
|
||||
" <td>1.0</td>\n",
|
||||
" <td>0.007763</td>\n",
|
||||
" </tr>\n",
|
||||
" <tr>\n",
|
||||
" <th>1</th>\n",
|
||||
" <td> 1</td>\n",
|
||||
" <td> 0.000001</td>\n",
|
||||
" <td> 20.000000</td>\n",
|
||||
" <td> total</td>\n",
|
||||
" <td> (((absorption / flux) / (total / flux)) + ((sc...</td>\n",
|
||||
" <td> 1</td>\n",
|
||||
" <td> 0.002619</td>\n",
|
||||
" <td>1</td>\n",
|
||||
" <td>6.250000e-07</td>\n",
|
||||
" <td>2.000000e+01</td>\n",
|
||||
" <td>total</td>\n",
|
||||
" <td>(((absorption / flux) / (total / flux)) + ((sc...</td>\n",
|
||||
" <td>1.0</td>\n",
|
||||
" <td>0.003739</td>\n",
|
||||
" </tr>\n",
|
||||
" </tbody>\n",
|
||||
"</table>\n",
|
||||
|
|
@ -1166,11 +1147,11 @@
|
|||
"1 1 6.25e-07 2.00e+01 total \n",
|
||||
"\n",
|
||||
" score mean std. dev. \n",
|
||||
"0 (((absorption / flux) / (total / flux)) + ((sc... 1.00e+00 7.74e-03 \n",
|
||||
"1 (((absorption / flux) / (total / flux)) + ((sc... 1.00e+00 2.62e-03 "
|
||||
"0 (((absorption / flux) / (total / flux)) + ((sc... 1.00e+00 7.76e-03 \n",
|
||||
"1 (((absorption / flux) / (total / flux)) + ((sc... 1.00e+00 3.74e-03 "
|
||||
]
|
||||
},
|
||||
"execution_count": 26,
|
||||
"execution_count": 25,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
|
|
@ -1200,7 +1181,7 @@
|
|||
"name": "python",
|
||||
"nbconvert_exporter": "python",
|
||||
"pygments_lexer": "ipython2",
|
||||
"version": "2.7.10"
|
||||
"version": "2.7.6"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
|
|
|
|||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
1461
docs/source/pythonapi/examples/mgxs-part-iv.ipynb
Normal file
1461
docs/source/pythonapi/examples/mgxs-part-iv.ipynb
Normal file
File diff suppressed because one or more lines are too long
13
docs/source/pythonapi/examples/mgxs-part-iv.rst
Normal file
13
docs/source/pythonapi/examples/mgxs-part-iv.rst
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
.. _notebook_mgxs_part_iv:
|
||||
|
||||
====================================================
|
||||
MGXS Part IV: Multi-Group Mode Cross-Section Library
|
||||
====================================================
|
||||
|
||||
.. only:: html
|
||||
|
||||
.. notebook:: mgxs-part-iv.ipynb
|
||||
|
||||
.. only:: latex
|
||||
|
||||
IPython notebooks must be viewed in the online HTML documentation.
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large
Load diff
|
|
@ -1,8 +0,0 @@
|
|||
.. _pythonapi_executor:
|
||||
|
||||
========
|
||||
Executor
|
||||
========
|
||||
|
||||
.. automodule:: openmc.executor
|
||||
:members:
|
||||
|
|
@ -1,8 +0,0 @@
|
|||
.. _pythonapi_filter:
|
||||
|
||||
======
|
||||
Filter
|
||||
======
|
||||
|
||||
.. automodule:: openmc.filter
|
||||
:members:
|
||||
|
|
@ -1,8 +0,0 @@
|
|||
.. _pythonapi_geometry:
|
||||
|
||||
========
|
||||
Geometry
|
||||
========
|
||||
|
||||
.. automodule:: openmc.geometry
|
||||
:members:
|
||||
|
|
@ -13,62 +13,9 @@ online. We recommend going through the modules from Codecademy_ and/or the
|
|||
`Scipy lectures`_. The full API documentation serves to provide more information
|
||||
on a given module or class.
|
||||
|
||||
**Handling nuclear data:**
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 1
|
||||
|
||||
ace
|
||||
|
||||
**Creating input files:**
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 1
|
||||
|
||||
cmfd
|
||||
element
|
||||
filter
|
||||
geometry
|
||||
material
|
||||
mesh
|
||||
nuclide
|
||||
opencg_compatible
|
||||
plots
|
||||
settings
|
||||
source
|
||||
stats
|
||||
surface
|
||||
tallies
|
||||
trigger
|
||||
universe
|
||||
|
||||
**Running OpenMC:**
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 1
|
||||
|
||||
executor
|
||||
|
||||
**Post-processing:**
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 1
|
||||
|
||||
particle_restart
|
||||
statepoint
|
||||
summary
|
||||
tallies
|
||||
|
||||
**Multi-Group Cross Section Generation**
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 1
|
||||
|
||||
mgxs
|
||||
energy_groups
|
||||
mgxs_library
|
||||
|
||||
**Example Jupyter Notebooks:**
|
||||
-------------------------
|
||||
Example Jupyter Notebooks
|
||||
-------------------------
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 1
|
||||
|
|
@ -79,6 +26,278 @@ on a given module or class.
|
|||
examples/mgxs-part-i
|
||||
examples/mgxs-part-ii
|
||||
examples/mgxs-part-iii
|
||||
examples/mgxs-part-iv
|
||||
|
||||
------------------------------------
|
||||
:mod:`openmc` -- Basic Functionality
|
||||
------------------------------------
|
||||
|
||||
Handling nuclear data
|
||||
---------------------
|
||||
|
||||
Classes
|
||||
+++++++
|
||||
|
||||
.. autosummary::
|
||||
:toctree: generated
|
||||
:nosignatures:
|
||||
:template: myclass.rst
|
||||
|
||||
openmc.XSdata
|
||||
openmc.MGXSLibrary
|
||||
|
||||
Functions
|
||||
+++++++++
|
||||
|
||||
.. autosummary::
|
||||
:toctree: generated
|
||||
:nosignatures:
|
||||
|
||||
openmc.ace.ascii_to_binary
|
||||
|
||||
Simulation Settings
|
||||
-------------------
|
||||
|
||||
.. autosummary::
|
||||
:toctree: generated
|
||||
:nosignatures:
|
||||
:template: myclass.rst
|
||||
|
||||
openmc.Source
|
||||
openmc.ResonanceScattering
|
||||
openmc.Settings
|
||||
|
||||
Material Specification
|
||||
----------------------
|
||||
|
||||
.. autosummary::
|
||||
:toctree: generated
|
||||
:nosignatures:
|
||||
:template: myclass.rst
|
||||
|
||||
openmc.Nuclide
|
||||
openmc.Element
|
||||
openmc.Macroscopic
|
||||
openmc.Material
|
||||
openmc.Materials
|
||||
|
||||
Building geometry
|
||||
-----------------
|
||||
|
||||
.. autosummary::
|
||||
:toctree: generated
|
||||
:nosignatures:
|
||||
:template: myclass.rst
|
||||
|
||||
openmc.Plane
|
||||
openmc.XPlane
|
||||
openmc.YPlane
|
||||
openmc.ZPlane
|
||||
openmc.XCylinder
|
||||
openmc.YCylinder
|
||||
openmc.ZCylinder
|
||||
openmc.Sphere
|
||||
openmc.Cone
|
||||
openmc.XCone
|
||||
openmc.YCone
|
||||
openmc.ZCone
|
||||
openmc.Quadric
|
||||
openmc.Halfspace
|
||||
openmc.Intersection
|
||||
openmc.Union
|
||||
openmc.Complement
|
||||
openmc.Cell
|
||||
openmc.Universe
|
||||
openmc.RectLattice
|
||||
openmc.HexLattice
|
||||
openmc.Geometry
|
||||
|
||||
Many of the above classes are derived from several abstract classes:
|
||||
|
||||
.. autosummary::
|
||||
:toctree: generated
|
||||
:nosignatures:
|
||||
:template: myclass.rst
|
||||
|
||||
openmc.Surface
|
||||
openmc.Region
|
||||
openmc.Lattice
|
||||
|
||||
One function is also available to create a hexagonal region defined by the
|
||||
intersection of six surface half-spaces.
|
||||
|
||||
.. autosummary::
|
||||
:toctree: generated
|
||||
:nosignatures:
|
||||
:template: myfunction.rst
|
||||
|
||||
openmc.make_hexagon_region
|
||||
|
||||
Constructing Tallies
|
||||
--------------------
|
||||
|
||||
.. autosummary::
|
||||
:toctree: generated
|
||||
:nosignatures:
|
||||
:template: myclass.rst
|
||||
|
||||
openmc.Filter
|
||||
openmc.Mesh
|
||||
openmc.Trigger
|
||||
openmc.Tally
|
||||
openmc.Tallies
|
||||
|
||||
Coarse Mesh Finite Difference Acceleration
|
||||
------------------------------------------
|
||||
|
||||
.. autosummary::
|
||||
:toctree: generated
|
||||
:nosignatures:
|
||||
:template: myclass.rst
|
||||
|
||||
openmc.CMFDMesh
|
||||
openmc.CMFD
|
||||
|
||||
Plotting
|
||||
--------
|
||||
|
||||
.. autosummary::
|
||||
:toctree: generated
|
||||
:nosignatures:
|
||||
:template: myclass.rst
|
||||
|
||||
openmc.Plot
|
||||
openmc.Plots
|
||||
|
||||
Running OpenMC
|
||||
--------------
|
||||
|
||||
.. autosummary::
|
||||
:toctree: generated
|
||||
:nosignatures:
|
||||
:template: myfunction.rst
|
||||
|
||||
openmc.run
|
||||
openmc.plot_geometry
|
||||
|
||||
Post-processing
|
||||
---------------
|
||||
|
||||
.. autosummary::
|
||||
:toctree: generated
|
||||
:nosignatures:
|
||||
:template: myclass.rst
|
||||
|
||||
openmc.Particle
|
||||
openmc.StatePoint
|
||||
openmc.Summary
|
||||
|
||||
Various classes may be created when performing tally slicing and/or arithmetic:
|
||||
|
||||
.. autosummary::
|
||||
:toctree: generated
|
||||
:nosignatures:
|
||||
:template: myclass.rst
|
||||
|
||||
openmc.arithmetic.CrossScore
|
||||
openmc.arithmetic.CrossNuclide
|
||||
openmc.arithmetic.CrossFilter
|
||||
openmc.arithmetic.AggregateScore
|
||||
openmc.arithmetic.AggregateNuclide
|
||||
openmc.arithmetic.AggregateFilter
|
||||
|
||||
---------------------------------
|
||||
:mod:`openmc.stats` -- Statistics
|
||||
---------------------------------
|
||||
|
||||
Univariate Probability Distributions
|
||||
------------------------------------
|
||||
|
||||
.. autosummary::
|
||||
:toctree: generated
|
||||
:nosignatures:
|
||||
:template: myclass.rst
|
||||
|
||||
openmc.stats.Univariate
|
||||
openmc.stats.Discrete
|
||||
openmc.stats.Uniform
|
||||
openmc.stats.Maxwell
|
||||
openmc.stats.Watt
|
||||
openmc.stats.Tabular
|
||||
|
||||
Angular Distributions
|
||||
---------------------
|
||||
|
||||
.. autosummary::
|
||||
:toctree: generated
|
||||
:nosignatures:
|
||||
:template: myclass.rst
|
||||
|
||||
openmc.stats.UnitSphere
|
||||
openmc.stats.PolarAzimuthal
|
||||
openmc.stats.Isotropic
|
||||
openmc.stats.Monodirectional
|
||||
|
||||
Spatial Distributions
|
||||
---------------------
|
||||
|
||||
.. autosummary::
|
||||
:toctree: generated
|
||||
:nosignatures:
|
||||
:template: myclass.rst
|
||||
|
||||
openmc.stats.Spatial
|
||||
openmc.stats.CartesianIndependent
|
||||
openmc.stats.Box
|
||||
openmc.stats.Point
|
||||
|
||||
----------------------------------------------------------
|
||||
:mod:`openmc.mgxs` -- Multi-Group Cross Section Generation
|
||||
----------------------------------------------------------
|
||||
|
||||
Energy Groups
|
||||
-------------
|
||||
|
||||
.. autosummary::
|
||||
:toctree: generated
|
||||
:nosignatures:
|
||||
:template: myclass.rst
|
||||
|
||||
openmc.mgxs.EnergyGroups
|
||||
|
||||
Multi-group Cross Sections
|
||||
--------------------------
|
||||
|
||||
.. autosummary::
|
||||
:toctree: generated
|
||||
:nosignatures:
|
||||
:template: myclassinherit.rst
|
||||
|
||||
openmc.mgxs.MGXS
|
||||
openmc.mgxs.AbsorptionXS
|
||||
openmc.mgxs.CaptureXS
|
||||
openmc.mgxs.Chi
|
||||
openmc.mgxs.FissionXS
|
||||
openmc.mgxs.KappaFissionXS
|
||||
openmc.mgxs.MultiplicityMatrixXS
|
||||
openmc.mgxs.NuFissionXS
|
||||
openmc.mgxs.NuFissionMatrixXS
|
||||
openmc.mgxs.NuScatterXS
|
||||
openmc.mgxs.NuScatterMatrixXS
|
||||
openmc.mgxs.ScatterXS
|
||||
openmc.mgxs.ScatterMatrixXS
|
||||
openmc.mgxs.TotalXS
|
||||
openmc.mgxs.TransportXS
|
||||
|
||||
Multi-group Cross Section Libraries
|
||||
-----------------------------------
|
||||
|
||||
.. autosummary::
|
||||
:toctree: generated
|
||||
:nosignatures:
|
||||
:template: myclass.rst
|
||||
|
||||
openmc.mgxs.Library
|
||||
|
||||
.. _Jupyter: https://jupyter.org/
|
||||
.. _NumPy: http://www.numpy.org/
|
||||
|
|
|
|||
|
|
@ -1,8 +0,0 @@
|
|||
.. _pythonapi_material:
|
||||
|
||||
=========
|
||||
Materials
|
||||
=========
|
||||
|
||||
.. automodule:: openmc.material
|
||||
:members:
|
||||
|
|
@ -1,8 +0,0 @@
|
|||
.. _pythonapi_mesh:
|
||||
|
||||
====
|
||||
Mesh
|
||||
====
|
||||
|
||||
.. automodule:: openmc.mesh
|
||||
:members:
|
||||
|
|
@ -1,66 +0,0 @@
|
|||
.. _pythonapi_mgxs:
|
||||
|
||||
==========================
|
||||
Multi-Group Cross Sections
|
||||
==========================
|
||||
|
||||
.. currentmodule:: openmc.mgxs.mgxs
|
||||
|
||||
----------------------------
|
||||
Summary of Available Classes
|
||||
----------------------------
|
||||
|
||||
.. autosummary::
|
||||
|
||||
MGXS
|
||||
AbsorptionXS
|
||||
CaptureXS
|
||||
Chi
|
||||
FissionXS
|
||||
NuFissionXS
|
||||
NuScatterXS
|
||||
NuScatterMatrixXS
|
||||
ScatterXS
|
||||
ScatterMatrixXS
|
||||
TotalXS
|
||||
TransportXS
|
||||
|
||||
-------------------
|
||||
Class Documentation
|
||||
-------------------
|
||||
|
||||
.. autoclass:: MGXS
|
||||
:members:
|
||||
|
||||
.. autoclass:: AbsorptionXS
|
||||
:members:
|
||||
|
||||
.. autoclass:: CaptureXS
|
||||
:members:
|
||||
|
||||
.. autoclass:: Chi
|
||||
:members:
|
||||
|
||||
.. autoclass:: FissionXS
|
||||
:members:
|
||||
|
||||
.. autoclass:: NuFissionXS
|
||||
:members:
|
||||
|
||||
.. autoclass:: NuScatterXS
|
||||
:members:
|
||||
|
||||
.. autoclass:: NuScatterMatrixXS
|
||||
:members:
|
||||
|
||||
.. autoclass:: ScatterXS
|
||||
:members:
|
||||
|
||||
.. autoclass:: ScatterMatrixXS
|
||||
:members:
|
||||
|
||||
.. autoclass:: TotalXS
|
||||
:members:
|
||||
|
||||
.. autoclass:: TransportXS
|
||||
:members:
|
||||
|
|
@ -1,8 +0,0 @@
|
|||
.. _pythonapi_mgxs_library:
|
||||
|
||||
============
|
||||
MGXS Library
|
||||
============
|
||||
|
||||
.. automodule:: openmc.mgxs.library
|
||||
:members:
|
||||
|
|
@ -1,8 +0,0 @@
|
|||
.. _pythonapi_nuclide:
|
||||
|
||||
=======
|
||||
Nuclide
|
||||
=======
|
||||
|
||||
.. automodule:: openmc.nuclide
|
||||
:members:
|
||||
|
|
@ -1,8 +0,0 @@
|
|||
.. _pythonapi_particle_restart:
|
||||
|
||||
================
|
||||
Particle Restart
|
||||
================
|
||||
|
||||
.. automodule:: openmc.particle_restart
|
||||
:members:
|
||||
|
|
@ -1,8 +0,0 @@
|
|||
.. _pythonapi_plots:
|
||||
|
||||
=====
|
||||
Plots
|
||||
=====
|
||||
|
||||
.. automodule:: openmc.plots
|
||||
:members:
|
||||
|
|
@ -1,8 +0,0 @@
|
|||
.. _pythonapi_settings:
|
||||
|
||||
========
|
||||
Settings
|
||||
========
|
||||
|
||||
.. automodule:: openmc.settings
|
||||
:members:
|
||||
|
|
@ -1,8 +0,0 @@
|
|||
.. _pythonapi_source:
|
||||
|
||||
======
|
||||
Source
|
||||
======
|
||||
|
||||
.. automodule:: openmc.source
|
||||
:members:
|
||||
|
|
@ -1,8 +0,0 @@
|
|||
.. _pythonapi_statepoint:
|
||||
|
||||
==========
|
||||
Statepoint
|
||||
==========
|
||||
|
||||
.. automodule:: openmc.statepoint
|
||||
:members:
|
||||
|
|
@ -1,58 +0,0 @@
|
|||
.. _pythonapi_stats:
|
||||
|
||||
=====================
|
||||
Statistical Functions
|
||||
=====================
|
||||
|
||||
----------------------------
|
||||
Summary of Available Classes
|
||||
----------------------------
|
||||
|
||||
Univariate Probability Distributions
|
||||
------------------------------------
|
||||
|
||||
.. currentmodule:: openmc.stats.univariate
|
||||
|
||||
.. autosummary::
|
||||
|
||||
Univariate
|
||||
Discrete
|
||||
Uniform
|
||||
Maxwell
|
||||
Watt
|
||||
Tabular
|
||||
|
||||
Angular Distributions
|
||||
---------------------
|
||||
|
||||
.. currentmodule:: openmc.stats.multivariate
|
||||
|
||||
.. autosummary::
|
||||
|
||||
UnitSphere
|
||||
PolarAzimuthal
|
||||
Isotropic
|
||||
Monodirectional
|
||||
|
||||
Spatial Distributions
|
||||
---------------------
|
||||
|
||||
.. autosummary::
|
||||
|
||||
Spatial
|
||||
CartesianIndependent
|
||||
Box
|
||||
Point
|
||||
|
||||
|
||||
Univariate Probability Distributions
|
||||
------------------------------------
|
||||
|
||||
.. automodule:: openmc.stats.univariate
|
||||
:members:
|
||||
|
||||
Multivariate Probability Distributions
|
||||
--------------------------------------
|
||||
|
||||
.. automodule:: openmc.stats.multivariate
|
||||
:members:
|
||||
|
|
@ -1,8 +0,0 @@
|
|||
.. _pythonapi_summary:
|
||||
|
||||
=======
|
||||
Summary
|
||||
=======
|
||||
|
||||
.. automodule:: openmc.summary
|
||||
:members:
|
||||
|
|
@ -1,8 +0,0 @@
|
|||
.. _pythonapi_surface:
|
||||
|
||||
=======
|
||||
Surface
|
||||
=======
|
||||
|
||||
.. automodule:: openmc.surface
|
||||
:members:
|
||||
|
|
@ -1,8 +0,0 @@
|
|||
.. _pythonapi_tallies:
|
||||
|
||||
=======
|
||||
Tallies
|
||||
=======
|
||||
|
||||
.. automodule:: openmc.tallies
|
||||
:members:
|
||||
|
|
@ -1,8 +0,0 @@
|
|||
.. _pythonapi_trigger:
|
||||
|
||||
=======
|
||||
Trigger
|
||||
=======
|
||||
|
||||
.. automodule:: openmc.trigger
|
||||
:members:
|
||||
|
|
@ -1,8 +0,0 @@
|
|||
.. _pythonapi_universe:
|
||||
|
||||
========
|
||||
Universe
|
||||
========
|
||||
|
||||
.. automodule:: openmc.universe
|
||||
:members:
|
||||
|
|
@ -897,11 +897,19 @@ Each ``<surface>`` element can have the following attributes or sub-elements:
|
|||
*Default*: None
|
||||
|
||||
:boundary:
|
||||
The boundary condition for the surface. This can be "transmission",
|
||||
"vacuum", or "reflective".
|
||||
The boundary condition for the surface. This can be "transmission",
|
||||
"vacuum", "reflective", or "periodic". Periodic boundary conditions can
|
||||
only be applied to x-, y-, and z-planes. Only axis-aligned periodicity is
|
||||
supported, i.e., x-planes can only be paired with x-planes. Specify which
|
||||
planes are periodic and the code will automatically identify which planes
|
||||
are paired together.
|
||||
|
||||
*Default*: "transmission"
|
||||
|
||||
:periodic_surface_id:
|
||||
If a periodic boundary condition is applied, this attribute identifies the
|
||||
``id`` of the corresponding periodic sufrace.
|
||||
|
||||
The following quadratic surfaces can be modeled:
|
||||
|
||||
:x-plane:
|
||||
|
|
@ -1033,6 +1041,20 @@ Each ``<cell>`` element can have the following attributes or sub-elements:
|
|||
|
||||
<cell fill="..." rotation="0 0 90" />
|
||||
|
||||
The rotation applied is an intrinsic rotation whose Tait-Bryan angles are
|
||||
given as those specified about the x, y, and z axes respectively. That is to
|
||||
say, if the angles are :math:`(\phi, \theta, \psi)`, then the rotation
|
||||
matrix applied is :math:`R_z(\psi) R_y(\theta) R_x(\phi)` or
|
||||
|
||||
.. math::
|
||||
|
||||
\left [ \begin{array}{ccc} \cos\theta \cos\psi & -\cos\theta \sin\psi +
|
||||
\sin\phi \sin\theta \cos\psi & \sin\phi \sin\psi + \cos\phi \sin\theta
|
||||
\cos\psi \\ \cos\theta \sin\psi & \cos\phi \cos\psi + \sin\phi \sin\theta
|
||||
\sin\psi & -\sin\phi \cos\psi + \cos\phi \sin\theta \sin\psi \\
|
||||
-\sin\theta & \sin\phi \cos\theta & \cos\phi \cos\theta \end{array}
|
||||
\right ]
|
||||
|
||||
*Default*: None
|
||||
|
||||
:translation:
|
||||
|
|
@ -1215,11 +1237,10 @@ Each ``material`` element can have the following attributes or sub-elements:
|
|||
An element with attributes/sub-elements called ``value`` and ``units``. The
|
||||
``value`` attribute is the numeric value of the density while the ``units``
|
||||
can be "g/cm3", "kg/m3", "atom/b-cm", "atom/cm3", or "sum". The "sum" unit
|
||||
indicates that values appearing in ``ao`` attributes for ``<nuclide>`` and
|
||||
``<element>`` sub-elements are to be interpreted as nuclide/element
|
||||
densities in atom/b-cm, and the total density of the material is taken as
|
||||
the sum of all nuclides/elements. The "sum" option cannot be used in
|
||||
conjunction with weight percents. The "macro" unit is used with
|
||||
indicates that values appearing in ``ao`` or ``wo`` attributes for ``<nuclide>``
|
||||
and ``<element>`` sub-elements are to be interpreted as absolute nuclide/element
|
||||
densities in atom/b-cm or g/cm3, and the total density of the material is
|
||||
taken as the sum of all nuclides/elements. The "macro" unit is used with
|
||||
a ``macroscopic`` quantity to indicate that the density is already included
|
||||
in the library and thus not needed here. However, if a value is provided
|
||||
for the ``value``, then this is treated as a number density multiplier on
|
||||
|
|
@ -1258,6 +1279,9 @@ Each ``material`` element can have the following attributes or sub-elements:
|
|||
|
||||
*Default*: None
|
||||
|
||||
.. note:: The ``scattering`` attribute/sub-element is not used in the
|
||||
multi-group :ref:`energy_mode`.
|
||||
|
||||
:element:
|
||||
|
||||
Specifies that a natural element is present in the material. The natural
|
||||
|
|
@ -1293,6 +1317,9 @@ Each ``material`` element can have the following attributes or sub-elements:
|
|||
|
||||
*Default*: None
|
||||
|
||||
.. note:: The ``scattering`` attribute/sub-element is not used in the
|
||||
multi-group :ref:`energy_mode`.
|
||||
|
||||
:sab:
|
||||
Associates an S(a,b) table with the material. This element has
|
||||
attributes/sub-elements called ``name`` and ``xs``. The ``name`` attribute
|
||||
|
|
@ -1301,6 +1328,8 @@ Each ``material`` element can have the following attributes or sub-elements:
|
|||
|
||||
*Default*: None
|
||||
|
||||
.. note:: This element is not used in the multi-group :ref:`energy_mode`.
|
||||
|
||||
:macroscopic:
|
||||
The ``macroscopic`` element is similar to the ``nuclide`` element, but,
|
||||
recognizes that some multi-group libraries may be providing material
|
||||
|
|
@ -1569,7 +1598,8 @@ The ``<tally>`` element accepts the following sub-elements:
|
|||
|Score | Description |
|
||||
+======================+===================================================+
|
||||
|absorption |Total absorption rate. This accounts for all |
|
||||
| |reactions which do not produce secondary neutrons. |
|
||||
| |reactions which do not produce secondary neutrons |
|
||||
| |as well as fission. |
|
||||
+----------------------+---------------------------------------------------+
|
||||
|elastic |Elastic scattering reaction rate. |
|
||||
+----------------------+---------------------------------------------------+
|
||||
|
|
|
|||
|
|
@ -8,10 +8,10 @@ OpenMC can be run in continuous-energy mode or multi-group mode, provided the
|
|||
nuclear data is available. In continuous-energy mode, the
|
||||
``cross_sections.xml`` file contains necessary meta-data for each data set,
|
||||
including the name and a file system location where the complete library
|
||||
can be found. In multi-group mode, this ``cross_sections.xml`` file contains
|
||||
can be found. In multi-group mode, this ``mgxs.xml`` file contains
|
||||
this same meta-data describing the nuclide or material, but also contains the
|
||||
group-wise nuclear data. This portion of the manual describes the format of
|
||||
the multi-group data library required to be used in the ``cross_sections.xml``
|
||||
the multi-group data library required to be used in the ``mgxs.xml``
|
||||
file.
|
||||
|
||||
Similar to the other input file types, the multi-group library is provided in
|
||||
|
|
@ -22,9 +22,9 @@ materials.
|
|||
|
||||
.. _XML: http://www.w3.org/XML/
|
||||
|
||||
------------------------------------------------
|
||||
MGXS Library Specification -- cross_sections.xml
|
||||
------------------------------------------------
|
||||
--------------------------------------
|
||||
MGXS Library Specification -- mgxs.xml
|
||||
--------------------------------------
|
||||
|
||||
The multi-group library meta-data is contained within the groups_,
|
||||
group_structure_, and inverse_velocities_ elements.
|
||||
|
|
@ -33,7 +33,7 @@ The actual multi-group data itself is contained within the xsdata_ element.
|
|||
.. _groups:
|
||||
|
||||
``<groups>`` Element
|
||||
----------------------------------
|
||||
--------------------
|
||||
|
||||
The ``<groups>`` element has no attributes and simply provides the number of
|
||||
energy groups contained within the library.
|
||||
|
|
@ -172,7 +172,7 @@ attributes/sub-elements required to describe the meta-data:
|
|||
during the scattering process. Specifically, the options are to either
|
||||
convert the Legendre expansion to a tabular representation or leave it as
|
||||
a set of Legendre coefficients. Converting to a tabular representation will
|
||||
cost memory but is likely to decrease runtime compared to leaving as a
|
||||
cost memory but can allow for a decrease in runtime compared to leaving as a
|
||||
set of Legendre coefficients. This element has the following
|
||||
attributes/sub-elements:
|
||||
|
||||
|
|
@ -181,7 +181,7 @@ attributes/sub-elements required to describe the meta-data:
|
|||
tabular format should be performed or not. A value of "true" means
|
||||
the conversion should be performed, "false" means it should not.
|
||||
|
||||
*Default*: "true"
|
||||
*Default*: "false"
|
||||
|
||||
:num_points:
|
||||
If the conversion is to take place the number of tabular points is
|
||||
|
|
|
|||
|
|
@ -248,7 +248,7 @@ if run_mode == 'k-eigenvalue':
|
|||
Accumulated sum and sum-of-squares for each global tally. The compound type
|
||||
has fields named ``sum`` and ``sum_sq``.
|
||||
|
||||
**tallies_present** (*int*)
|
||||
**/tallies_present** (*int*)
|
||||
|
||||
Flag indicated if tallies are present in the file.
|
||||
|
||||
|
|
@ -260,3 +260,69 @@ if (run_mode == 'k-eigenvalue' and source_present > 0)
|
|||
``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.
|
||||
|
||||
**/runtime/total initialization** (*double*)
|
||||
|
||||
Time (in seconds on the master process) spent reading inputs, allocating
|
||||
arrays, etc.
|
||||
|
||||
**/runtime/reading cross sections** (*double*)
|
||||
|
||||
Time (in seconds on the master process) spent loading cross section
|
||||
libraries (this is a subset of initialization).
|
||||
|
||||
**/runtime/simulation** (*double*)
|
||||
|
||||
Time (in seconds on the master process) spent between initialization and
|
||||
finalization.
|
||||
|
||||
**/runtime/transport** (*double*)
|
||||
|
||||
Time (in seconds on the master process) spent transporting particles.
|
||||
|
||||
**/runtime/inactive batches** (*double*)
|
||||
|
||||
Time (in seconds on the master process) spent in the inactive batches
|
||||
(including non-transport activities like communcating sites).
|
||||
|
||||
**/runtime/active batches** (*double*)
|
||||
|
||||
Time (in seconds on the master process) spent in the active batches
|
||||
(including non-transport activities like communicating sites).
|
||||
|
||||
**/runtime/synchronizing fission bank** (*double*)
|
||||
|
||||
Time (in seconds on the master process) spent sampling source particles
|
||||
from fission sites and communicating them to other processes for load
|
||||
balancing.
|
||||
|
||||
**/runtime/sampling source sites** (*double*)
|
||||
|
||||
Time (in seconds on the master process) spent sampling source particles
|
||||
from fission sites.
|
||||
|
||||
**/runtime/SEND-RECV source sites** (*double*)
|
||||
|
||||
Time (in seconds on the master process) spent communicating source sites
|
||||
between processes for load balancing.
|
||||
|
||||
**/runtime/accumulating tallies** (*double*)
|
||||
|
||||
Time (in seconds on the master process) spent communicating tally results
|
||||
and evaluating their statistics.
|
||||
|
||||
**/runtime/CMFD** (*double*)
|
||||
|
||||
Time (in seconds on the master process) spent evaluating CMFD.
|
||||
|
||||
**/runtime/CMFD building matrices** (*double*)
|
||||
|
||||
Time (in seconds on the master process) spent buliding CMFD matrices.
|
||||
|
||||
**/runtime/CMFD solving matrices** (*double*)
|
||||
|
||||
Time (in seconds on the master process) spent solving CMFD matrices.
|
||||
|
||||
**/runtime/total** (*double*)
|
||||
|
||||
Total time spent (in seconds on the master process) in the program.
|
||||
|
|
|
|||
|
|
@ -293,6 +293,13 @@ The current revision of the summary file format is 1.
|
|||
|
||||
Filter offset (used for distribcell filter).
|
||||
|
||||
**/tallies/tally <uid>/filter <j>/paths** (*char[][]*)
|
||||
|
||||
The paths traversed through the CSG tree to reach each distribcell
|
||||
instance (for 'distribcell' filters only). This consists of the integer
|
||||
IDs for each universe, cell and lattice delimited by '->'. Each lattice
|
||||
cell is specified by its (x,y) or (x,y,z) indices.
|
||||
|
||||
**/tallies/tally <uid>/filter <j>/n_bins** (*int*)
|
||||
|
||||
Number of bins for the j-th filter.
|
||||
|
|
|
|||
|
|
@ -196,10 +196,10 @@ Data Extraction
|
|||
|
||||
A great deal of information is available in statepoint files (See
|
||||
:ref:`usersguide_statepoint`), all of which is accessible through the Python
|
||||
API. The ``openmc.statepoint`` module (see :ref:`pythonapi_statepoint`) provides
|
||||
a class to load statepoints and access data as requested; it is used in many of
|
||||
the provided plotting utilities, OpenMC's regression test suite, and can be used
|
||||
in user-created scripts to carry out manipulations of the data.
|
||||
API. The :class:`openmc.StatePoint` class can load statepoints and access data
|
||||
as requested; it is used in many of the provided plotting utilities, OpenMC's
|
||||
regression test suite, and can be used in user-created scripts to carry out
|
||||
manipulations of the data.
|
||||
|
||||
An :ref:`example IPython notebook <notebook_post_processing>` demonstrates how
|
||||
to extract data from a statepoint using the Python API.
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
import openmc
|
||||
from openmc.source import Source
|
||||
from openmc.stats import Box
|
||||
|
||||
|
||||
###############################################################################
|
||||
# Simulation Input File Parameters
|
||||
|
|
@ -13,7 +12,7 @@ particles = 10000
|
|||
|
||||
|
||||
###############################################################################
|
||||
# Exporting to OpenMC materials.xml File
|
||||
# Exporting to OpenMC materials.xml file
|
||||
###############################################################################
|
||||
|
||||
# Instantiate some Nuclides
|
||||
|
|
@ -32,15 +31,14 @@ fuel = openmc.Material(material_id=40, name='fuel')
|
|||
fuel.set_density('g/cc', 4.5)
|
||||
fuel.add_nuclide(u235, 1.)
|
||||
|
||||
# Instantiate a MaterialsFile, register all Materials, and export to XML
|
||||
materials_file = openmc.MaterialsFile()
|
||||
# Instantiate a Materials collection and export to XML
|
||||
materials_file = openmc.Materials([moderator, fuel])
|
||||
materials_file.default_xs = '71c'
|
||||
materials_file.add_materials([moderator, fuel])
|
||||
materials_file.export_to_xml()
|
||||
|
||||
|
||||
###############################################################################
|
||||
# Exporting to OpenMC geometry.xml File
|
||||
# Exporting to OpenMC geometry.xml file
|
||||
###############################################################################
|
||||
|
||||
# Instantiate ZCylinder surfaces
|
||||
|
|
@ -75,31 +73,31 @@ cell1.fill = universe1
|
|||
universe1.add_cells([cell2, cell3])
|
||||
root.add_cells([cell1, cell4])
|
||||
|
||||
# Instantiate a Geometry and register the root Universe
|
||||
geometry = openmc.Geometry()
|
||||
geometry.root_universe = root
|
||||
|
||||
# Instantiate a GeometryFile, register Geometry, and export to XML
|
||||
geometry_file = openmc.GeometryFile()
|
||||
geometry_file.geometry = geometry
|
||||
geometry_file.export_to_xml()
|
||||
# Instantiate a Geometry, register the root Universe, and export to XML
|
||||
geometry = openmc.Geometry(root)
|
||||
geometry.export_to_xml()
|
||||
|
||||
|
||||
###############################################################################
|
||||
# Exporting to OpenMC settings.xml File
|
||||
# Exporting to OpenMC settings.xml file
|
||||
###############################################################################
|
||||
|
||||
# Instantiate a SettingsFile, set all runtime parameters, and export to XML
|
||||
settings_file = openmc.SettingsFile()
|
||||
# Instantiate a Settings object, set all runtime parameters, and export to XML
|
||||
settings_file = openmc.Settings()
|
||||
settings_file.batches = batches
|
||||
settings_file.inactive = inactive
|
||||
settings_file.particles = particles
|
||||
settings_file.source = Source(space=Box([-4, -4, -4], [4, 4, 4]))
|
||||
|
||||
# Create an initial uniform spatial source distribution over fissionable zones
|
||||
bounds = [-4., -4., -4., 4., 4., 4.]
|
||||
uniform_dist = openmc.stats.Box(bounds[:3], bounds[3:], only_fissionable=True)
|
||||
settings_file.source = openmc.source.Source(space=uniform_dist)
|
||||
|
||||
settings_file.export_to_xml()
|
||||
|
||||
|
||||
###############################################################################
|
||||
# Exporting to OpenMC tallies.xml File
|
||||
# Exporting to OpenMC tallies.xml file
|
||||
###############################################################################
|
||||
|
||||
# Instantiate some tally Filters
|
||||
|
|
@ -109,33 +107,21 @@ energyout_filter = openmc.Filter(type='energyout', bins=[0., 20.])
|
|||
|
||||
# Instantiate the first Tally
|
||||
first_tally = openmc.Tally(tally_id=1, name='first tally')
|
||||
first_tally.add_filter(cell_filter)
|
||||
scores = ['total', 'scatter', 'nu-scatter', \
|
||||
first_tally.filters = [cell_filter]
|
||||
scores = ['total', 'scatter', 'nu-scatter',
|
||||
'absorption', 'fission', 'nu-fission']
|
||||
for score in scores:
|
||||
first_tally.add_score(score)
|
||||
first_tally.scores = scores
|
||||
|
||||
# Instantiate the second Tally
|
||||
second_tally = openmc.Tally(tally_id=2, name='second tally')
|
||||
second_tally.add_filter(cell_filter)
|
||||
second_tally.add_filter(energy_filter)
|
||||
scores = ['total', 'scatter', 'nu-scatter', \
|
||||
'absorption', 'fission', 'nu-fission']
|
||||
for score in scores:
|
||||
second_tally.add_score(score)
|
||||
second_tally.filters = [cell_filter, energy_filter]
|
||||
second_tally.scores = scores
|
||||
|
||||
# Instantiate the third Tally
|
||||
third_tally = openmc.Tally(tally_id=3, name='third tally')
|
||||
third_tally.add_filter(cell_filter)
|
||||
third_tally.add_filter(energy_filter)
|
||||
third_tally.add_filter(energyout_filter)
|
||||
scores = ['scatter', 'nu-scatter', 'nu-fission']
|
||||
for score in scores:
|
||||
third_tally.add_score(score)
|
||||
third_tally.filters = [cell_filter, energy_filter, energyout_filter]
|
||||
third_tally.scores = ['scatter', 'nu-scatter', 'nu-fission']
|
||||
|
||||
# Instantiate a TalliesFile, register all Tallies, and export to XML
|
||||
tallies_file = openmc.TalliesFile()
|
||||
tallies_file.add_tally(first_tally)
|
||||
tallies_file.add_tally(second_tally)
|
||||
tallies_file.add_tally(third_tally)
|
||||
# Instantiate a Tallies collection and export to XML
|
||||
tallies_file = openmc.Tallies((first_tally, second_tally, third_tally))
|
||||
tallies_file.export_to_xml()
|
||||
|
|
|
|||
|
|
@ -1,8 +1,5 @@
|
|||
import numpy as np
|
||||
|
||||
import openmc
|
||||
from openmc.source import Source
|
||||
from openmc.stats import Box
|
||||
|
||||
###############################################################################
|
||||
# Simulation Input File Parameters
|
||||
|
|
@ -39,15 +36,14 @@ moderator.add_nuclide(h1, 2.)
|
|||
moderator.add_nuclide(o16, 1.)
|
||||
moderator.add_s_alpha_beta('HH2O', '71t')
|
||||
|
||||
# Instantiate a MaterialsFile, register all Materials, and export to XML
|
||||
materials_file = openmc.MaterialsFile()
|
||||
# Instantiate a Materials collection and export to XML
|
||||
materials_file = openmc.Materials([fuel1, fuel2, moderator])
|
||||
materials_file.default_xs = '71c'
|
||||
materials_file.add_materials([fuel1, fuel2, moderator])
|
||||
materials_file.export_to_xml()
|
||||
|
||||
|
||||
###############################################################################
|
||||
# Exporting to OpenMC geometry.xml File
|
||||
# Exporting to OpenMC geometry.xml file
|
||||
###############################################################################
|
||||
|
||||
# Instantiate planar surfaces
|
||||
|
|
@ -100,26 +96,25 @@ outer_box.fill = moderator
|
|||
root = openmc.Universe(universe_id=0, name='root universe')
|
||||
root.add_cells([inner_box, middle_box, outer_box])
|
||||
|
||||
# Instantiate a Geometry and register the root Universe
|
||||
geometry = openmc.Geometry()
|
||||
geometry.root_universe = root
|
||||
|
||||
# Instantiate a GeometryFile, register Geometry, and export to XML
|
||||
geometry_file = openmc.GeometryFile()
|
||||
geometry_file.geometry = geometry
|
||||
geometry_file.export_to_xml()
|
||||
# Instantiate a Geometry, register the root Universe, and export to XML
|
||||
geometry = openmc.Geometry(root)
|
||||
geometry.export_to_xml()
|
||||
|
||||
|
||||
###############################################################################
|
||||
# Exporting to OpenMC settings.xml File
|
||||
###############################################################################
|
||||
|
||||
# Instantiate a SettingsFile, set all runtime parameters, and export to XML
|
||||
settings_file = openmc.SettingsFile()
|
||||
# Instantiate a Settings object, set all runtime parameters, and export to XML
|
||||
settings_file = openmc.Settings()
|
||||
settings_file.batches = batches
|
||||
settings_file.inactive = inactive
|
||||
settings_file.particles = particles
|
||||
settings_file.source = Source(space=Box(*outer_cube.bounding_box))
|
||||
|
||||
# Create an initial uniform spatial source distribution over fissionable zones
|
||||
uniform_dist = openmc.stats.Box(*outer_cube.bounding_box, only_fissionable=True)
|
||||
settings_file.source = openmc.source.Source(space=uniform_dist)
|
||||
|
||||
settings_file.export_to_xml()
|
||||
|
||||
###############################################################################
|
||||
|
|
@ -132,7 +127,6 @@ plot.width = [20, 20]
|
|||
plot.pixels = [200, 200]
|
||||
plot.color = 'cell'
|
||||
|
||||
# Instantiate a PlotsFile, add Plot, and export to XML
|
||||
plot_file = openmc.PlotsFile()
|
||||
plot_file.add_plot(plot)
|
||||
# Instantiate a Plots collection and export to XML
|
||||
plot_file = openmc.Plots([plot])
|
||||
plot_file.export_to_xml()
|
||||
|
|
|
|||
|
|
@ -1,6 +1,4 @@
|
|||
import openmc
|
||||
from openmc.source import Source
|
||||
from openmc.stats import Box
|
||||
|
||||
###############################################################################
|
||||
# Simulation Input File Parameters
|
||||
|
|
@ -37,15 +35,14 @@ iron = openmc.Material(material_id=3, name='iron')
|
|||
iron.set_density('g/cc', 7.9)
|
||||
iron.add_nuclide(fe56, 1.)
|
||||
|
||||
# Instantiate a MaterialsFile, register all Materials, and export to XML
|
||||
materials_file = openmc.MaterialsFile()
|
||||
# Instantiate a Materials collection and export to XML
|
||||
materials_file = openmc.Materials([moderator, fuel, iron])
|
||||
materials_file.default_xs = '71c'
|
||||
materials_file.add_materials([moderator, fuel, iron])
|
||||
materials_file.export_to_xml()
|
||||
|
||||
|
||||
###############################################################################
|
||||
# Exporting to OpenMC geometry.xml File
|
||||
# Exporting to OpenMC geometry.xml file
|
||||
###############################################################################
|
||||
|
||||
# Instantiate Surfaces
|
||||
|
|
@ -107,27 +104,26 @@ lattice.outer = univ2
|
|||
# Fill Cell with the Lattice
|
||||
cell1.fill = lattice
|
||||
|
||||
# Instantiate a Geometry and register the root Universe
|
||||
geometry = openmc.Geometry()
|
||||
geometry.root_universe = root
|
||||
|
||||
# Instantiate a GeometryFile, register Geometry, and export to XML
|
||||
geometry_file = openmc.GeometryFile()
|
||||
geometry_file.geometry = geometry
|
||||
geometry_file.export_to_xml()
|
||||
# Instantiate a Geometry, register the root Universe, and export to XML
|
||||
geometry = openmc.Geometry(root)
|
||||
geometry.export_to_xml()
|
||||
|
||||
|
||||
###############################################################################
|
||||
# Exporting to OpenMC settings.xml File
|
||||
# Exporting to OpenMC settings.xml file
|
||||
###############################################################################
|
||||
|
||||
# Instantiate a SettingsFile, set all runtime parameters, and export to XML
|
||||
settings_file = openmc.SettingsFile()
|
||||
# Instantiate a Settings object, set all runtime parameters, and export to XML
|
||||
settings_file = openmc.Settings()
|
||||
settings_file.batches = batches
|
||||
settings_file.inactive = inactive
|
||||
settings_file.particles = particles
|
||||
settings_file.source = Source(space=Box(
|
||||
[-1, -1, -1], [1, 1, 1]))
|
||||
|
||||
# Create an initial uniform spatial source distribution over fissionable zones
|
||||
bounds = [-1, -1, -1, 1, 1, 1]
|
||||
uniform_dist = openmc.stats.Box(bounds[:3], bounds[3:], only_fissionable=True)
|
||||
settings_file.source = openmc.source.Source(space=uniform_dist)
|
||||
|
||||
settings_file.keff_trigger = {'type' : 'std_dev', 'threshold' : 5E-4}
|
||||
settings_file.trigger_active = True
|
||||
settings_file.trigger_max_batches = 100
|
||||
|
|
@ -135,7 +131,7 @@ settings_file.export_to_xml()
|
|||
|
||||
|
||||
###############################################################################
|
||||
# Exporting to OpenMC plots.xml File
|
||||
# Exporting to OpenMC plots.xml file
|
||||
###############################################################################
|
||||
|
||||
plot_xy = openmc.Plot(plot_id=1)
|
||||
|
|
@ -153,10 +149,8 @@ plot_yz.width = [8, 8]
|
|||
plot_yz.pixels = [400, 400]
|
||||
plot_yz.color = 'mat'
|
||||
|
||||
# Instantiate a PlotsFile, add Plot, and export to XML
|
||||
plot_file = openmc.PlotsFile()
|
||||
plot_file.add_plot(plot_xy)
|
||||
plot_file.add_plot(plot_yz)
|
||||
# Instantiate a Plots collection, add plots, and export to XML
|
||||
plot_file = openmc.Plots((plot_xy, plot_yz))
|
||||
plot_file.export_to_xml()
|
||||
|
||||
|
||||
|
|
@ -166,10 +160,9 @@ plot_file.export_to_xml()
|
|||
|
||||
# Instantiate a distribcell Tally
|
||||
tally = openmc.Tally(tally_id=1)
|
||||
tally.add_filter(openmc.Filter(type='distribcell', bins=[cell2.id]))
|
||||
tally.add_score('total')
|
||||
tally.filters = [openmc.Filter(type='distribcell', bins=[cell2.id])]
|
||||
tally.scores = ['total']
|
||||
|
||||
# Instantiate a TalliesFile, register Tally/Mesh, and export to XML
|
||||
tallies_file = openmc.TalliesFile()
|
||||
tallies_file.add_tally(tally)
|
||||
# Instantiate a Tallies collection and export to XML
|
||||
tallies_file = openmc.Tallies([tally])
|
||||
tallies_file.export_to_xml()
|
||||
|
|
|
|||
|
|
@ -1,6 +1,4 @@
|
|||
import openmc
|
||||
from openmc.source import Source
|
||||
from openmc.stats import Box
|
||||
|
||||
###############################################################################
|
||||
# Simulation Input File Parameters
|
||||
|
|
@ -13,7 +11,7 @@ particles = 10000
|
|||
|
||||
|
||||
###############################################################################
|
||||
# Exporting to OpenMC materials.xml File
|
||||
# Exporting to OpenMC materials.xml file
|
||||
###############################################################################
|
||||
|
||||
# Instantiate some Nuclides
|
||||
|
|
@ -32,15 +30,14 @@ moderator.add_nuclide(h1, 2.)
|
|||
moderator.add_nuclide(o16, 1.)
|
||||
moderator.add_s_alpha_beta('HH2O', '71t')
|
||||
|
||||
# Instantiate a MaterialsFile, register all Materials, and export to XML
|
||||
materials_file = openmc.MaterialsFile()
|
||||
# Instantiate a Materials collection and export to XML
|
||||
materials_file = openmc.Materials((moderator, fuel))
|
||||
materials_file.default_xs = '71c'
|
||||
materials_file.add_materials([moderator, fuel])
|
||||
materials_file.export_to_xml()
|
||||
|
||||
|
||||
###############################################################################
|
||||
# Exporting to OpenMC geometry.xml File
|
||||
# Exporting to OpenMC geometry.xml file
|
||||
###############################################################################
|
||||
|
||||
# Instantiate Surfaces
|
||||
|
|
@ -101,14 +98,12 @@ univ4.add_cell(cell2)
|
|||
|
||||
# Instantiate nested Lattices
|
||||
lattice1 = openmc.RectLattice(lattice_id=4, name='4x4 assembly')
|
||||
lattice1.dimension = [2, 2]
|
||||
lattice1.lower_left = [-1., -1.]
|
||||
lattice1.pitch = [1., 1.]
|
||||
lattice1.universes = [[univ1, univ2],
|
||||
[univ2, univ3]]
|
||||
|
||||
lattice2 = openmc.RectLattice(lattice_id=6, name='4x4 core')
|
||||
lattice2.dimension = [2, 2]
|
||||
lattice2.lower_left = [-2., -2.]
|
||||
lattice2.pitch = [2., 2.]
|
||||
lattice2.universes = [[univ4, univ4],
|
||||
|
|
@ -118,32 +113,31 @@ lattice2.universes = [[univ4, univ4],
|
|||
cell1.fill = lattice2
|
||||
cell2.fill = lattice1
|
||||
|
||||
# Instantiate a Geometry and register the root Universe
|
||||
geometry = openmc.Geometry()
|
||||
geometry.root_universe = root
|
||||
|
||||
# Instantiate a GeometryFile, register Geometry, and export to XML
|
||||
geometry_file = openmc.GeometryFile()
|
||||
geometry_file.geometry = geometry
|
||||
geometry_file.export_to_xml()
|
||||
# Instantiate a Geometry, register the root Universe, and export to XML
|
||||
geometry = openmc.Geometry(root)
|
||||
geometry.export_to_xml()
|
||||
|
||||
|
||||
###############################################################################
|
||||
# Exporting to OpenMC settings.xml File
|
||||
# Exporting to OpenMC settings.xml file
|
||||
###############################################################################
|
||||
|
||||
# Instantiate a SettingsFile, set all runtime parameters, and export to XML
|
||||
settings_file = openmc.SettingsFile()
|
||||
# Instantiate a Settings object, set all runtime parameters, and export to XML
|
||||
settings_file = openmc.Settings()
|
||||
settings_file.batches = batches
|
||||
settings_file.inactive = inactive
|
||||
settings_file.particles = particles
|
||||
settings_file.source = Source(space=Box(
|
||||
[-1, -1, -1], [1, 1, 1]))
|
||||
|
||||
# Create an initial uniform spatial source distribution over fissionable zones
|
||||
bounds = [-1, -1, -1, 1, 1, 1]
|
||||
uniform_dist = openmc.stats.Box(bounds[:3], bounds[3:], only_fissionable=True)
|
||||
settings_file.source = openmc.source.Source(space=uniform_dist)
|
||||
|
||||
settings_file.export_to_xml()
|
||||
|
||||
|
||||
###############################################################################
|
||||
# Exporting to OpenMC plots.xml File
|
||||
# Exporting to OpenMC plots.xml file
|
||||
###############################################################################
|
||||
|
||||
plot = openmc.Plot(plot_id=1)
|
||||
|
|
@ -152,14 +146,13 @@ plot.width = [4, 4]
|
|||
plot.pixels = [400, 400]
|
||||
plot.color = 'mat'
|
||||
|
||||
# Instantiate a PlotsFile, add Plot, and export to XML
|
||||
plot_file = openmc.PlotsFile()
|
||||
plot_file.add_plot(plot)
|
||||
# Instantiate a Plots object and export to XML
|
||||
plot_file = openmc.Plots([plot])
|
||||
plot_file.export_to_xml()
|
||||
|
||||
|
||||
###############################################################################
|
||||
# Exporting to OpenMC tallies.xml File
|
||||
# Exporting to OpenMC tallies.xml file
|
||||
###############################################################################
|
||||
|
||||
# Instantiate a tally mesh
|
||||
|
|
@ -175,11 +168,9 @@ mesh_filter.mesh = mesh
|
|||
|
||||
# Instantiate the Tally
|
||||
tally = openmc.Tally(tally_id=1)
|
||||
tally.add_filter(mesh_filter)
|
||||
tally.add_score('total')
|
||||
tally.filters = [mesh_filter]
|
||||
tally.scores = ['total']
|
||||
|
||||
# Instantiate a TalliesFile, register Tally/Mesh, and export to XML
|
||||
tallies_file = openmc.TalliesFile()
|
||||
tallies_file.add_mesh(mesh)
|
||||
tallies_file.add_tally(tally)
|
||||
# Instantiate a Tallies collection, register Tally/Mesh, and export to XML
|
||||
tallies_file = openmc.Tallies([tally])
|
||||
tallies_file.export_to_xml()
|
||||
|
|
|
|||
|
|
@ -1,6 +1,4 @@
|
|||
import openmc
|
||||
from openmc.source import Source
|
||||
from openmc.stats import Box
|
||||
|
||||
###############################################################################
|
||||
# Simulation Input File Parameters
|
||||
|
|
@ -13,7 +11,7 @@ particles = 10000
|
|||
|
||||
|
||||
###############################################################################
|
||||
# Exporting to OpenMC materials.xml File
|
||||
# Exporting to OpenMC materials.xml file
|
||||
###############################################################################
|
||||
|
||||
# Instantiate some Nuclides
|
||||
|
|
@ -32,15 +30,14 @@ moderator.add_nuclide(h1, 2.)
|
|||
moderator.add_nuclide(o16, 1.)
|
||||
moderator.add_s_alpha_beta('HH2O', '71t')
|
||||
|
||||
# Instantiate a MaterialsFile, register all Materials, and export to XML
|
||||
materials_file = openmc.MaterialsFile()
|
||||
# Instantiate a Materials collection and export to XML
|
||||
materials_file = openmc.Materials([moderator, fuel])
|
||||
materials_file.default_xs = '71c'
|
||||
materials_file.add_materials([moderator, fuel])
|
||||
materials_file.export_to_xml()
|
||||
|
||||
|
||||
###############################################################################
|
||||
# Exporting to OpenMC geometry.xml File
|
||||
# Exporting to OpenMC geometry.xml file
|
||||
###############################################################################
|
||||
|
||||
# Instantiate Surfaces
|
||||
|
|
@ -97,7 +94,6 @@ root.add_cell(cell1)
|
|||
|
||||
# Instantiate a Lattice
|
||||
lattice = openmc.RectLattice(lattice_id=5)
|
||||
lattice.dimension = [4, 4]
|
||||
lattice.lower_left = [-2., -2.]
|
||||
lattice.pitch = [1., 1.]
|
||||
lattice.universes = [[univ1, univ2, univ1, univ2],
|
||||
|
|
@ -108,34 +104,33 @@ lattice.universes = [[univ1, univ2, univ1, univ2],
|
|||
# Fill Cell with the Lattice
|
||||
cell1.fill = lattice
|
||||
|
||||
# Instantiate a Geometry and register the root Universe
|
||||
geometry = openmc.Geometry()
|
||||
geometry.root_universe = root
|
||||
|
||||
# Instantiate a GeometryFile, register Geometry, and export to XML
|
||||
geometry_file = openmc.GeometryFile()
|
||||
geometry_file.geometry = geometry
|
||||
geometry_file.export_to_xml()
|
||||
# Instantiate a Geometry, register the root Universe, and export to XML
|
||||
geometry = openmc.Geometry(root)
|
||||
geometry.export_to_xml()
|
||||
|
||||
|
||||
###############################################################################
|
||||
# Exporting to OpenMC settings.xml File
|
||||
# Exporting to OpenMC settings.xml file
|
||||
###############################################################################
|
||||
|
||||
# Instantiate a SettingsFile, set all runtime parameters, and export to XML
|
||||
settings_file = openmc.SettingsFile()
|
||||
# Instantiate a Settings object, set all runtime parameters, and export to XML
|
||||
settings_file = openmc.Settings()
|
||||
settings_file.batches = batches
|
||||
settings_file.inactive = inactive
|
||||
settings_file.particles = particles
|
||||
settings_file.source = Source(space=Box(
|
||||
[-1, -1, -1], [1, 1, 1]))
|
||||
|
||||
# Create an initial uniform spatial source distribution over fissionable zones
|
||||
bounds = [-1, -1, -1, 1, 1, 1]
|
||||
uniform_dist = openmc.stats.Box(bounds[:3], bounds[3:], only_fissionable=True)
|
||||
settings_file.source = openmc.source.Source(space=uniform_dist)
|
||||
|
||||
settings_file.trigger_active = True
|
||||
settings_file.trigger_max_batches = 100
|
||||
settings_file.export_to_xml()
|
||||
|
||||
|
||||
###############################################################################
|
||||
# Exporting to OpenMC plots.xml File
|
||||
# Exporting to OpenMC plots.xml file
|
||||
###############################################################################
|
||||
|
||||
plot = openmc.Plot(plot_id=1)
|
||||
|
|
@ -144,14 +139,13 @@ plot.width = [4, 4]
|
|||
plot.pixels = [400, 400]
|
||||
plot.color = 'mat'
|
||||
|
||||
# Instantiate a PlotsFile, add Plot, and export to XML
|
||||
plot_file = openmc.PlotsFile()
|
||||
plot_file.add_plot(plot)
|
||||
# Instantiate a Plots collection and export to XML
|
||||
plot_file = openmc.Plots([plot])
|
||||
plot_file.export_to_xml()
|
||||
|
||||
|
||||
###############################################################################
|
||||
# Exporting to OpenMC tallies.xml File
|
||||
# Exporting to OpenMC tallies.xml file
|
||||
###############################################################################
|
||||
|
||||
# Instantiate a tally mesh
|
||||
|
|
@ -167,16 +161,14 @@ mesh_filter.mesh = mesh
|
|||
|
||||
# Instantiate tally Trigger
|
||||
trigger = openmc.Trigger(trigger_type='rel_err', threshold=1E-2)
|
||||
trigger.add_score('all')
|
||||
trigger.scores = ['all']
|
||||
|
||||
# Instantiate the Tally
|
||||
tally = openmc.Tally(tally_id=1)
|
||||
tally.add_filter(mesh_filter)
|
||||
tally.add_score('total')
|
||||
tally.add_trigger(trigger)
|
||||
tally.filters = [mesh_filter]
|
||||
tally.scores = ['total']
|
||||
tally.triggers = [trigger]
|
||||
|
||||
# Instantiate a TalliesFile, register Tally/Mesh, and export to XML
|
||||
tallies_file = openmc.TalliesFile()
|
||||
tallies_file.add_mesh(mesh)
|
||||
tallies_file.add_tally(tally)
|
||||
# Instantiate a Tallies collection and export to XML
|
||||
tallies_file = openmc.Tallies([tally])
|
||||
tallies_file.export_to_xml()
|
||||
|
|
|
|||
|
|
@ -1,6 +1,4 @@
|
|||
import openmc
|
||||
from openmc.source import Source
|
||||
from openmc.stats import Box
|
||||
|
||||
###############################################################################
|
||||
# Simulation Input File Parameters
|
||||
|
|
@ -13,7 +11,7 @@ particles = 1000
|
|||
|
||||
|
||||
###############################################################################
|
||||
# Exporting to OpenMC materials.xml File
|
||||
# Exporting to OpenMC materials.xml file
|
||||
###############################################################################
|
||||
|
||||
# Instantiate some Nuclides
|
||||
|
|
@ -102,15 +100,14 @@ borated_water.add_nuclide(o16, 2.4672e-2)
|
|||
borated_water.add_nuclide(o17, 6.0099e-5)
|
||||
borated_water.add_s_alpha_beta('HH2O', '71t')
|
||||
|
||||
# Instantiate a MaterialsFile, register all Materials, and export to XML
|
||||
materials_file = openmc.MaterialsFile()
|
||||
# Instantiate a Materials collection and export to XML
|
||||
materials_file = openmc.Materials([uo2, helium, zircaloy, borated_water])
|
||||
materials_file.default_xs = '71c'
|
||||
materials_file.add_materials([uo2, helium, zircaloy, borated_water])
|
||||
materials_file.export_to_xml()
|
||||
|
||||
|
||||
###############################################################################
|
||||
# Exporting to OpenMC geometry.xml File
|
||||
# Exporting to OpenMC geometry.xml file
|
||||
###############################################################################
|
||||
|
||||
# Instantiate ZCylinder surfaces
|
||||
|
|
@ -151,27 +148,26 @@ root = openmc.Universe(universe_id=0, name='root universe')
|
|||
# Register Cells with Universe
|
||||
root.add_cells([fuel, gap, clad, water])
|
||||
|
||||
# Instantiate a Geometry and register the root Universe
|
||||
geometry = openmc.Geometry()
|
||||
geometry.root_universe = root
|
||||
|
||||
# Instantiate a GeometryFile, register Geometry, and export to XML
|
||||
geometry_file = openmc.GeometryFile()
|
||||
geometry_file.geometry = geometry
|
||||
geometry_file.export_to_xml()
|
||||
# Instantiate a Geometry, register the root Universe, and export to XML
|
||||
geometry = openmc.Geometry(root)
|
||||
geometry.export_to_xml()
|
||||
|
||||
|
||||
###############################################################################
|
||||
# Exporting to OpenMC settings.xml File
|
||||
# Exporting to OpenMC settings.xml file
|
||||
###############################################################################
|
||||
|
||||
# Instantiate a SettingsFile, set all runtime parameters, and export to XML
|
||||
settings_file = openmc.SettingsFile()
|
||||
# Instantiate a Settings object, set all runtime parameters, and export to XML
|
||||
settings_file = openmc.Settings()
|
||||
settings_file.batches = batches
|
||||
settings_file.inactive = inactive
|
||||
settings_file.particles = particles
|
||||
settings_file.source = Source(space=Box(
|
||||
[-0.62992, -0.62992, -1], [0.62992, 0.62992, 1]))
|
||||
|
||||
# Create an initial uniform spatial source distribution over fissionable zones
|
||||
bounds = [-0.62992, -0.62992, -1, 0.62992, 0.62992, 1]
|
||||
uniform_dist = openmc.stats.Box(bounds[:3], bounds[3:], only_fissionable=True)
|
||||
settings_file.source = openmc.source.Source(space=uniform_dist)
|
||||
|
||||
settings_file.entropy_lower_left = [-0.39218, -0.39218, -1.e50]
|
||||
settings_file.entropy_upper_right = [0.39218, 0.39218, 1.e50]
|
||||
settings_file.entropy_dimension = [10, 10, 1]
|
||||
|
|
@ -179,7 +175,7 @@ settings_file.export_to_xml()
|
|||
|
||||
|
||||
###############################################################################
|
||||
# Exporting to OpenMC tallies.xml File
|
||||
# Exporting to OpenMC tallies.xml file
|
||||
###############################################################################
|
||||
|
||||
# Instantiate a tally mesh
|
||||
|
|
@ -196,14 +192,9 @@ mesh_filter.mesh = mesh
|
|||
|
||||
# Instantiate the Tally
|
||||
tally = openmc.Tally(tally_id=1, name='tally 1')
|
||||
tally.add_filter(energy_filter)
|
||||
tally.add_filter(mesh_filter)
|
||||
tally.add_score('flux')
|
||||
tally.add_score('fission')
|
||||
tally.add_score('nu-fission')
|
||||
tally.filters = [energy_filter, mesh_filter]
|
||||
tally.scores = ['flux', 'fission', 'nu-fission']
|
||||
|
||||
# Instantiate a TalliesFile, register all Tallies, and export to XML
|
||||
tallies_file = openmc.TalliesFile()
|
||||
tallies_file.add_mesh(mesh)
|
||||
tallies_file.add_tally(tally)
|
||||
# Instantiate a Tallies collection and export to XML
|
||||
tallies_file = openmc.Tallies([tally])
|
||||
tallies_file.export_to_xml()
|
||||
|
|
|
|||
|
|
@ -1,8 +1,5 @@
|
|||
import openmc
|
||||
import openmc.mgxs
|
||||
from openmc.source import Source
|
||||
from openmc.stats import Box
|
||||
import numpy as np
|
||||
|
||||
###############################################################################
|
||||
# Simulation Input File Parameters
|
||||
|
|
@ -14,7 +11,7 @@ inactive = 10
|
|||
particles = 1000
|
||||
|
||||
###############################################################################
|
||||
# Exporting to OpenMC mg_cross_sections.xml File
|
||||
# Exporting to OpenMC mgxs.xml file
|
||||
###############################################################################
|
||||
|
||||
# Instantiate the energy group data
|
||||
|
|
@ -24,50 +21,48 @@ groups = openmc.mgxs.EnergyGroups(group_edges=[1E-11, 0.0635E-6, 10.0E-6,
|
|||
# Instantiate the 7-group (C5G7) cross section data
|
||||
uo2_xsdata = openmc.XSdata('UO2.300K', groups)
|
||||
uo2_xsdata.order = 0
|
||||
uo2_xsdata.total = np.array([0.1779492, 0.3298048, 0.4803882, 0.5543674,
|
||||
0.3118013, 0.3951678, 0.5644058])
|
||||
uo2_xsdata.absorption = np.array([8.0248E-03, 3.7174E-03, 2.6769E-02, 9.6236E-02,
|
||||
3.0020E-02, 1.1126E-01, 2.8278E-01])
|
||||
scatter = [[[0.1275370, 0.0423780, 0.0000094, 0.0000000, 0.0000000, 0.0000000, 0.0000000],
|
||||
[0.0000000, 0.3244560, 0.0016314, 0.0000000, 0.0000000, 0.0000000, 0.0000000],
|
||||
[0.0000000, 0.0000000, 0.4509400, 0.0026792, 0.0000000, 0.0000000, 0.0000000],
|
||||
[0.0000000, 0.0000000, 0.0000000, 0.4525650, 0.0055664, 0.0000000, 0.0000000],
|
||||
[0.0000000, 0.0000000, 0.0000000, 0.0001253, 0.2714010, 0.0102550, 0.0000000],
|
||||
[0.0000000, 0.0000000, 0.0000000, 0.0000000, 0.0012968, 0.2658020, 0.0168090],
|
||||
[0.0000000, 0.0000000, 0.0000000, 0.0000000, 0.0000000, 0.0085458, 0.2730800]]]
|
||||
uo2_xsdata.scatter = np.array(scatter[:][:])
|
||||
uo2_xsdata.fission = np.array([7.21206E-03, 8.19301E-04, 6.45320E-03,
|
||||
1.85648E-02, 1.78084E-02, 8.30348E-02,
|
||||
2.16004E-01])
|
||||
uo2_xsdata.nu_fission = np.array([2.005998E-02, 2.027303E-03, 1.570599E-02,
|
||||
4.518301E-02, 4.334208E-02, 2.020901E-01,
|
||||
5.257105E-01])
|
||||
uo2_xsdata.chi = np.array([5.8791E-01, 4.1176E-01, 3.3906E-04, 1.1761E-07,
|
||||
0.0000E+00, 0.0000E+00, 0.0000E+00])
|
||||
uo2_xsdata.total = [0.1779492, 0.3298048, 0.4803882, 0.5543674,
|
||||
0.3118013, 0.3951678, 0.5644058]
|
||||
uo2_xsdata.absorption = [8.0248E-03, 3.7174E-03, 2.6769E-02, 9.6236E-02,
|
||||
3.0020E-02, 1.1126E-01, 2.8278E-01]
|
||||
uo2_xsdata.scatter = [[[0.1275370, 0.0423780, 0.0000094, 0.0000000, 0.0000000, 0.0000000, 0.0000000],
|
||||
[0.0000000, 0.3244560, 0.0016314, 0.0000000, 0.0000000, 0.0000000, 0.0000000],
|
||||
[0.0000000, 0.0000000, 0.4509400, 0.0026792, 0.0000000, 0.0000000, 0.0000000],
|
||||
[0.0000000, 0.0000000, 0.0000000, 0.4525650, 0.0055664, 0.0000000, 0.0000000],
|
||||
[0.0000000, 0.0000000, 0.0000000, 0.0001253, 0.2714010, 0.0102550, 0.0000000],
|
||||
[0.0000000, 0.0000000, 0.0000000, 0.0000000, 0.0012968, 0.2658020, 0.0168090],
|
||||
[0.0000000, 0.0000000, 0.0000000, 0.0000000, 0.0000000, 0.0085458, 0.2730800]]]
|
||||
uo2_xsdata.fission = [7.21206E-03, 8.19301E-04, 6.45320E-03,
|
||||
1.85648E-02, 1.78084E-02, 8.30348E-02,
|
||||
2.16004E-01]
|
||||
uo2_xsdata.nu_fission = [2.005998E-02, 2.027303E-03, 1.570599E-02,
|
||||
4.518301E-02, 4.334208E-02, 2.020901E-01,
|
||||
5.257105E-01]
|
||||
uo2_xsdata.chi = [5.8791E-01, 4.1176E-01, 3.3906E-04, 1.1761E-07,
|
||||
0.0000E+00, 0.0000E+00, 0.0000E+00]
|
||||
|
||||
h2o_xsdata = openmc.XSdata('LWTR.300K', groups)
|
||||
h2o_xsdata.order = 0
|
||||
h2o_xsdata.total = np.array([0.15920605, 0.412969593, 0.59030986, 0.58435,
|
||||
0.718, 1.2544497, 2.650379])
|
||||
h2o_xsdata.absorption = np.array([6.0105E-04, 1.5793E-05, 3.3716E-04,
|
||||
1.9406E-03, 5.7416E-03, 1.5001E-02,
|
||||
3.7239E-02])
|
||||
scatter = [[[0.0444777, 0.1134000, 0.0007235, 0.0000037, 0.0000001, 0.0000000, 0.0000000],
|
||||
[0.0000000, 0.2823340, 0.1299400, 0.0006234, 0.0000480, 0.0000074, 0.0000010],
|
||||
[0.0000000, 0.0000000, 0.3452560, 0.2245700, 0.0169990, 0.0026443, 0.0005034],
|
||||
[0.0000000, 0.0000000, 0.0000000, 0.0910284, 0.4155100, 0.0637320, 0.0121390],
|
||||
[0.0000000, 0.0000000, 0.0000000, 0.0000714, 0.1391380, 0.5118200, 0.0612290],
|
||||
[0.0000000, 0.0000000, 0.0000000, 0.0000000, 0.0022157, 0.6999130, 0.5373200],
|
||||
[0.0000000, 0.0000000, 0.0000000, 0.0000000, 0.0000000, 0.1324400, 2.4807000]]]
|
||||
h2o_xsdata.scatter = np.array(scatter)
|
||||
h2o_xsdata.total = [0.15920605, 0.412969593, 0.59030986, 0.58435,
|
||||
0.718, 1.2544497, 2.650379]
|
||||
h2o_xsdata.absorption = [6.0105E-04, 1.5793E-05, 3.3716E-04,
|
||||
1.9406E-03, 5.7416E-03, 1.5001E-02,
|
||||
3.7239E-02]
|
||||
h2o_xsdata.scatter = [[[0.0444777, 0.1134000, 0.0007235, 0.0000037, 0.0000001, 0.0000000, 0.0000000],
|
||||
[0.0000000, 0.2823340, 0.1299400, 0.0006234, 0.0000480, 0.0000074, 0.0000010],
|
||||
[0.0000000, 0.0000000, 0.3452560, 0.2245700, 0.0169990, 0.0026443, 0.0005034],
|
||||
[0.0000000, 0.0000000, 0.0000000, 0.0910284, 0.4155100, 0.0637320, 0.0121390],
|
||||
[0.0000000, 0.0000000, 0.0000000, 0.0000714, 0.1391380, 0.5118200, 0.0612290],
|
||||
[0.0000000, 0.0000000, 0.0000000, 0.0000000, 0.0022157, 0.6999130, 0.5373200],
|
||||
[0.0000000, 0.0000000, 0.0000000, 0.0000000, 0.0000000, 0.1324400, 2.4807000]]]
|
||||
|
||||
mg_cross_sections_file = openmc.MGXSLibraryFile(groups)
|
||||
mg_cross_sections_file.add_xsdatas([uo2_xsdata,h2o_xsdata])
|
||||
mg_cross_sections_file = openmc.MGXSLibrary(groups)
|
||||
mg_cross_sections_file.add_xsdatas([uo2_xsdata, h2o_xsdata])
|
||||
mg_cross_sections_file.export_to_xml()
|
||||
|
||||
|
||||
###############################################################################
|
||||
# Exporting to OpenMC materials.xml File
|
||||
# Exporting to OpenMC materials.xml file
|
||||
###############################################################################
|
||||
|
||||
# Instantiate some Macroscopic Data
|
||||
|
|
@ -83,15 +78,14 @@ water = openmc.Material(material_id=2, name='Water')
|
|||
water.set_density('macro', 1.0)
|
||||
water.add_macroscopic(h2o_data)
|
||||
|
||||
# Instantiate a MaterialsFile, register all Materials, and export to XML
|
||||
materials_file = openmc.MaterialsFile()
|
||||
# Instantiate a Materials collection and export to XML
|
||||
materials_file = openmc.Materials([uo2, water])
|
||||
materials_file.default_xs = '300K'
|
||||
materials_file.add_materials([uo2, water])
|
||||
materials_file.export_to_xml()
|
||||
|
||||
|
||||
###############################################################################
|
||||
# Exporting to OpenMC geometry.xml File
|
||||
# Exporting to OpenMC geometry.xml file
|
||||
###############################################################################
|
||||
|
||||
# Instantiate ZCylinder surfaces
|
||||
|
|
@ -124,31 +118,32 @@ root = openmc.Universe(universe_id=0, name='root universe')
|
|||
# Register Cells with Universe
|
||||
root.add_cells([fuel, moderator])
|
||||
|
||||
# Instantiate a Geometry and register the root Universe
|
||||
geometry = openmc.Geometry()
|
||||
geometry.root_universe = root
|
||||
|
||||
# Instantiate a GeometryFile, register Geometry, and export to XML
|
||||
geometry_file = openmc.GeometryFile()
|
||||
geometry_file.geometry = geometry
|
||||
geometry_file.export_to_xml()
|
||||
# Instantiate a Geometry, register the root Universe, and export to XML
|
||||
geometry = openmc.Geometry(root)
|
||||
geometry.export_to_xml()
|
||||
|
||||
|
||||
###############################################################################
|
||||
# Exporting to OpenMC settings.xml File
|
||||
# Exporting to OpenMC settings.xml file
|
||||
###############################################################################
|
||||
|
||||
# Instantiate a SettingsFile, set all runtime parameters, and export to XML
|
||||
settings_file = openmc.SettingsFile()
|
||||
# Instantiate a Settings object, set all runtime parameters, and export to XML
|
||||
settings_file = openmc.Settings()
|
||||
settings_file.energy_mode = "multi-group"
|
||||
settings_file.cross_sections = "./mg_cross_sections.xml"
|
||||
settings_file.cross_sections = "./mgxs.xml"
|
||||
settings_file.batches = batches
|
||||
settings_file.inactive = inactive
|
||||
settings_file.particles = particles
|
||||
settings_file.source = Source(space=Box([-0.63, -0.63, -1.], [0.63, 0.63, 1.]))
|
||||
|
||||
# Create an initial uniform spatial source distribution over fissionable zones
|
||||
bounds = [-0.63, -0.63, -1, 0.63, 0.63, 1]
|
||||
uniform_dist = openmc.stats.Box(bounds[:3], bounds[3:])
|
||||
settings_file.source = openmc.source.Source(space=uniform_dist)
|
||||
|
||||
settings_file.export_to_xml()
|
||||
|
||||
###############################################################################
|
||||
# Exporting to OpenMC tallies.xml File
|
||||
# Exporting to OpenMC tallies.xml file
|
||||
###############################################################################
|
||||
|
||||
# Instantiate a tally mesh
|
||||
|
|
@ -167,14 +162,9 @@ mesh_filter.mesh = mesh
|
|||
|
||||
# Instantiate the Tally
|
||||
tally = openmc.Tally(tally_id=1, name='tally 1')
|
||||
tally.add_filter(energy_filter)
|
||||
tally.add_filter(mesh_filter)
|
||||
tally.add_score('flux')
|
||||
tally.add_score('fission')
|
||||
tally.add_score('nu-fission')
|
||||
tally.filters = [energy_filter, mesh_filter]
|
||||
tally.scores = ['flux', 'fission', 'nu-fission']
|
||||
|
||||
# Instantiate a TalliesFile, register all Tallies, and export to XML
|
||||
tallies_file = openmc.TalliesFile()
|
||||
tallies_file.add_mesh(mesh)
|
||||
tallies_file.add_tally(tally)
|
||||
# Instantiate a Tallies collection, register all Tallies, and export to XML
|
||||
tallies_file = openmc.Tallies([tally])
|
||||
tallies_file.export_to_xml()
|
||||
|
|
|
|||
|
|
@ -1,8 +1,5 @@
|
|||
import numpy as np
|
||||
|
||||
import openmc
|
||||
from openmc.stats import Box
|
||||
from openmc.source import Source
|
||||
|
||||
###############################################################################
|
||||
# Simulation Input File Parameters
|
||||
|
|
@ -15,7 +12,7 @@ particles = 10000
|
|||
|
||||
|
||||
###############################################################################
|
||||
# Exporting to OpenMC materials.xml File
|
||||
# Exporting to OpenMC materials.xml file
|
||||
###############################################################################
|
||||
|
||||
# Instantiate a Nuclides
|
||||
|
|
@ -26,15 +23,14 @@ fuel = openmc.Material(material_id=1, name='fuel')
|
|||
fuel.set_density('g/cc', 4.5)
|
||||
fuel.add_nuclide(u235, 1.)
|
||||
|
||||
# Instantiate a MaterialsFile, register Material, and export to XML
|
||||
materials_file = openmc.MaterialsFile()
|
||||
# Instantiate a Materials collection and export to XML
|
||||
materials_file = openmc.Materials([fuel])
|
||||
materials_file.default_xs = '71c'
|
||||
materials_file.add_material(fuel)
|
||||
materials_file.export_to_xml()
|
||||
|
||||
|
||||
###############################################################################
|
||||
# Exporting to OpenMC geometry.xml File
|
||||
# Exporting to OpenMC geometry.xml file
|
||||
###############################################################################
|
||||
|
||||
# Instantiate Surfaces
|
||||
|
|
@ -67,24 +63,24 @@ root = openmc.Universe(universe_id=0, name='root universe')
|
|||
# Register Cell with Universe
|
||||
root.add_cell(cell)
|
||||
|
||||
# Instantiate a Geometry and register the root Universe
|
||||
geometry = openmc.Geometry()
|
||||
geometry.root_universe = root
|
||||
|
||||
# Instantiate a GeometryFile, register Geometry, and export to XML
|
||||
geometry_file = openmc.GeometryFile()
|
||||
geometry_file.geometry = geometry
|
||||
geometry_file.export_to_xml()
|
||||
# Instantiate a Geometry, register the root Universe, and export to XML
|
||||
geometry = openmc.Geometry(root)
|
||||
geometry.export_to_xml()
|
||||
|
||||
|
||||
###############################################################################
|
||||
# Exporting to OpenMC settings.xml File
|
||||
# Exporting to OpenMC settings.xml file
|
||||
###############################################################################
|
||||
|
||||
# Instantiate a SettingsFile, set all runtime parameters, and export to XML
|
||||
settings_file = openmc.SettingsFile()
|
||||
# Instantiate a Settings object, set all runtime parameters, and export to XML
|
||||
settings_file = openmc.Settings()
|
||||
settings_file.batches = batches
|
||||
settings_file.inactive = inactive
|
||||
settings_file.particles = particles
|
||||
settings_file.source = Source(space=Box(*cell.region.bounding_box))
|
||||
|
||||
# Create an initial uniform spatial source distribution over fissionable zones
|
||||
uniform_dist = openmc.stats.Box(*cell.region.bounding_box,
|
||||
only_fissionable=True)
|
||||
settings_file.source = openmc.source.Source(space=uniform_dist)
|
||||
|
||||
settings_file.export_to_xml()
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
from openmc.cell import *
|
||||
from openmc.lattice import *
|
||||
from openmc.element import *
|
||||
from openmc.geometry import *
|
||||
from openmc.nuclide import *
|
||||
|
|
@ -16,6 +18,9 @@ from openmc.cmfd import *
|
|||
from openmc.executor import *
|
||||
from openmc.statepoint import *
|
||||
from openmc.summary import *
|
||||
from openmc.region import *
|
||||
from openmc.source import *
|
||||
from openmc.particle_restart import *
|
||||
|
||||
try:
|
||||
from openmc.opencg_compatible import *
|
||||
|
|
|
|||
480
openmc/cell.py
Normal file
480
openmc/cell.py
Normal file
|
|
@ -0,0 +1,480 @@
|
|||
from collections import OrderedDict, Iterable
|
||||
from math import cos, sin, pi
|
||||
from numbers import Real, Integral
|
||||
from xml.etree import ElementTree as ET
|
||||
import sys
|
||||
import warnings
|
||||
|
||||
import numpy as np
|
||||
|
||||
import openmc
|
||||
import openmc.checkvalue as cv
|
||||
from openmc.surface import Halfspace
|
||||
from openmc.region import Region, Intersection, Complement
|
||||
|
||||
if sys.version_info[0] >= 3:
|
||||
basestring = str
|
||||
|
||||
|
||||
# A static variable for auto-generated Cell IDs
|
||||
AUTO_CELL_ID = 10000
|
||||
|
||||
|
||||
def reset_auto_cell_id():
|
||||
global AUTO_CELL_ID
|
||||
AUTO_CELL_ID = 10000
|
||||
|
||||
|
||||
class Cell(object):
|
||||
r"""A region of space defined as the intersection of half-space created by
|
||||
quadric surfaces.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
cell_id : int, optional
|
||||
Unique identifier for the cell. If not specified, an identifier will
|
||||
automatically be assigned.
|
||||
name : str, optional
|
||||
Name of the cell. If not specified, the name is the empty string.
|
||||
fill : openmc.Material or openmc.Universe or openmc.Lattice or None or iterable of openmc.Material, optional
|
||||
Indicates what the region of space is filled with
|
||||
region : openmc.Region, optional
|
||||
Region of space that is assigned to the cell.
|
||||
|
||||
Attributes
|
||||
----------
|
||||
id : int
|
||||
Unique identifier for the cell
|
||||
name : str
|
||||
Name of the cell
|
||||
fill : openmc.Material or openmc.Universe or openmc.Lattice or None or iterable of openmc.Material
|
||||
Indicates what the region of space is filled with. If None, the cell is
|
||||
treated as a void. An iterable of materials is used to fill repeated
|
||||
instances of a cell with different materials.
|
||||
fill_type : {'material', 'universe', 'lattice', 'distribmat', 'void'}
|
||||
Indicates what the cell is filled with.
|
||||
region : openmc.Region or None
|
||||
Region of space that is assigned to the cell.
|
||||
rotation : Iterable of float
|
||||
If the cell is filled with a universe, this array specifies the angles
|
||||
in degrees about the x, y, and z axes that the filled universe should be
|
||||
rotated. The rotation applied is an intrinsic rotation with specified
|
||||
Tait-Bryan angles. That is to say, if the angles are :math:`(\phi,
|
||||
\theta, \psi)`, then the rotation matrix applied is :math:`R_z(\psi)
|
||||
R_y(\theta) R_x(\phi)` or
|
||||
|
||||
.. math::
|
||||
|
||||
\left [ \begin{array}{ccc} \cos\theta \cos\psi & -\cos\theta \sin\psi
|
||||
+ \sin\phi \sin\theta \cos\psi & \sin\phi \sin\psi + \cos\phi
|
||||
\sin\theta \cos\psi \\ \cos\theta \sin\psi & \cos\phi \cos\psi +
|
||||
\sin\phi \sin\theta \sin\psi & -\sin\phi \cos\psi + \cos\phi
|
||||
\sin\theta \sin\psi \\ -\sin\theta & \sin\phi \cos\theta & \cos\phi
|
||||
\cos\theta \end{array} \right ]
|
||||
|
||||
rotation_matrix : numpy.ndarray
|
||||
The rotation matrix defined by the angles specified in the
|
||||
:attr:`Cell.rotation` property.
|
||||
translation : Iterable of float
|
||||
If the cell is filled with a universe, this array specifies a vector
|
||||
that is used to translate (shift) the universe.
|
||||
offsets : ndarray
|
||||
Array of offsets used for distributed cell searches
|
||||
distribcell_index : int
|
||||
Index of this cell in distribcell arrays
|
||||
|
||||
"""
|
||||
|
||||
def __init__(self, cell_id=None, name='', fill=None, region=None):
|
||||
# Initialize Cell class attributes
|
||||
self.id = cell_id
|
||||
self.name = name
|
||||
self.fill = fill
|
||||
self.region = region
|
||||
self._rotation = None
|
||||
self._rotation_matrix = None
|
||||
self._translation = None
|
||||
self._offsets = None
|
||||
self._distribcell_index = None
|
||||
|
||||
def __contains__(self, point):
|
||||
if self.region is None:
|
||||
return True
|
||||
else:
|
||||
return point in self.region
|
||||
|
||||
def __eq__(self, other):
|
||||
if not isinstance(other, Cell):
|
||||
return False
|
||||
elif self.id != other.id:
|
||||
return False
|
||||
elif self.name != other.name:
|
||||
return False
|
||||
elif self.fill != other.fill:
|
||||
return False
|
||||
elif self.region != other.region:
|
||||
return False
|
||||
elif self.rotation != other.rotation:
|
||||
return False
|
||||
elif self.translation != other.translation:
|
||||
return False
|
||||
else:
|
||||
return True
|
||||
|
||||
def __ne__(self, other):
|
||||
return not self == other
|
||||
|
||||
def __hash__(self):
|
||||
return hash(repr(self))
|
||||
|
||||
def __repr__(self):
|
||||
string = 'Cell\n'
|
||||
string += '{: <16}=\t{}\n'.format('\tID', self.id)
|
||||
string += '{: <16}=\t{}\n'.format('\tName', self.name)
|
||||
|
||||
if self.fill_type == 'material':
|
||||
string += '{: <16}=\tMaterial {}\n'.format('\tFill', self.fill.id)
|
||||
elif self.fill_type == 'void':
|
||||
string += '{: <16}=\tNone\n'.format('\tFill')
|
||||
elif self.fill_type == 'distribmat':
|
||||
string += '{: <16}=\t{}\n'.format('\tFill', list(map(
|
||||
lambda m: m if m is None else m.id, self.fill)))
|
||||
else:
|
||||
string += '{: <16}=\t{}\n'.format('\tFill', self.fill.id)
|
||||
|
||||
string += '{: <16}=\t{}\n'.format('\tRegion', self.region)
|
||||
string += '{: <16}=\t{}\n'.format('\tRotation', self.rotation)
|
||||
string += '{: <16}=\t{}\n'.format('\tTranslation', self.translation)
|
||||
string += '{: <16}=\t{}\n'.format('\tOffset', self.offsets)
|
||||
string += '{: <16}=\t{}\n'.format('\tDistribcell index', self.distribcell_index)
|
||||
|
||||
return string
|
||||
|
||||
@property
|
||||
def id(self):
|
||||
return self._id
|
||||
|
||||
@property
|
||||
def name(self):
|
||||
return self._name
|
||||
|
||||
@property
|
||||
def fill(self):
|
||||
return self._fill
|
||||
|
||||
@property
|
||||
def fill_type(self):
|
||||
if isinstance(self.fill, openmc.Material):
|
||||
return 'material'
|
||||
elif isinstance(self.fill, openmc.Universe):
|
||||
return 'universe'
|
||||
elif isinstance(self.fill, openmc.Lattice):
|
||||
return 'lattice'
|
||||
elif isinstance(self.fill, Iterable):
|
||||
return 'distribmat'
|
||||
else:
|
||||
return 'void'
|
||||
|
||||
@property
|
||||
def region(self):
|
||||
return self._region
|
||||
|
||||
@property
|
||||
def rotation(self):
|
||||
return self._rotation
|
||||
|
||||
@property
|
||||
def rotation_matrix(self):
|
||||
return self._rotation_matrix
|
||||
|
||||
@property
|
||||
def translation(self):
|
||||
return self._translation
|
||||
|
||||
@property
|
||||
def offsets(self):
|
||||
return self._offsets
|
||||
|
||||
@property
|
||||
def distribcell_index(self):
|
||||
return self._distribcell_index
|
||||
|
||||
@id.setter
|
||||
def id(self, cell_id):
|
||||
if cell_id is None:
|
||||
global AUTO_CELL_ID
|
||||
self._id = AUTO_CELL_ID
|
||||
AUTO_CELL_ID += 1
|
||||
else:
|
||||
cv.check_type('cell ID', cell_id, Integral)
|
||||
cv.check_greater_than('cell ID', cell_id, 0, equality=True)
|
||||
self._id = cell_id
|
||||
|
||||
@name.setter
|
||||
def name(self, name):
|
||||
if name is not None:
|
||||
cv.check_type('cell name', name, basestring)
|
||||
self._name = name
|
||||
else:
|
||||
self._name = ''
|
||||
|
||||
@fill.setter
|
||||
def fill(self, fill):
|
||||
if fill is not None:
|
||||
if isinstance(fill, basestring):
|
||||
if fill.strip().lower() != 'void':
|
||||
msg = 'Unable to set Cell ID="{0}" to use a non-Material ' \
|
||||
'or Universe fill "{1}"'.format(self._id, fill)
|
||||
raise ValueError(msg)
|
||||
fill = None
|
||||
|
||||
elif isinstance(fill, Iterable):
|
||||
for i, f in enumerate(fill):
|
||||
if f is not None:
|
||||
cv.check_type('cell.fill[i]', f, openmc.Material)
|
||||
|
||||
elif not isinstance(fill, (openmc.Material, openmc.Lattice,
|
||||
openmc.Universe)):
|
||||
msg = 'Unable to set Cell ID="{0}" to use a non-Material or ' \
|
||||
'Universe fill "{1}"'.format(self._id, fill)
|
||||
raise ValueError(msg)
|
||||
|
||||
self._fill = fill
|
||||
|
||||
@rotation.setter
|
||||
def rotation(self, rotation):
|
||||
if not isinstance(self.fill, openmc.Universe):
|
||||
raise RuntimeError('Cell rotation can only be applied if the cell '
|
||||
'is filled with a Universe')
|
||||
|
||||
cv.check_type('cell rotation', rotation, Iterable, Real)
|
||||
cv.check_length('cell rotation', rotation, 3)
|
||||
self._rotation = np.asarray(rotation)
|
||||
|
||||
# Save rotation matrix
|
||||
phi, theta, psi = self.rotation*(-pi/180.)
|
||||
c3, s3 = cos(phi), sin(phi)
|
||||
c2, s2 = cos(theta), sin(theta)
|
||||
c1, s1 = cos(psi), sin(psi)
|
||||
self._rotation_matrix = np.array([
|
||||
[c1*c2, c1*s2*s3 - c3*s1, s1*s3 + c1*c3*s2],
|
||||
[c2*s1, c1*c3 + s1*s2*s3, c3*s1*s2 - c1*s3],
|
||||
[-s2, c2*s3, c2*c3]])
|
||||
|
||||
@translation.setter
|
||||
def translation(self, translation):
|
||||
cv.check_type('cell translation', translation, Iterable, Real)
|
||||
cv.check_length('cell translation', translation, 3)
|
||||
self._translation = np.asarray(translation)
|
||||
|
||||
@offsets.setter
|
||||
def offsets(self, offsets):
|
||||
cv.check_type('cell offsets', offsets, Iterable)
|
||||
self._offsets = offsets
|
||||
|
||||
@region.setter
|
||||
def region(self, region):
|
||||
if region is not None:
|
||||
cv.check_type('cell region', region, Region)
|
||||
self._region = region
|
||||
|
||||
@distribcell_index.setter
|
||||
def distribcell_index(self, ind):
|
||||
cv.check_type('distribcell index', ind, Integral)
|
||||
self._distribcell_index = ind
|
||||
|
||||
def add_surface(self, surface, halfspace):
|
||||
"""Add a half-space to the list of half-spaces whose intersection defines the
|
||||
cell.
|
||||
|
||||
.. deprecated:: 0.7.1
|
||||
Use the :attr:`Cell.region` property to directly specify a Region
|
||||
expression.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
surface : openmc.Surface
|
||||
Quadric surface dividing space
|
||||
halfspace : {-1, 1}
|
||||
Indicate whether the negative or positive half-space is to be used
|
||||
|
||||
"""
|
||||
|
||||
warnings.warn("Cell.add_surface(...) has been deprecated and may be "
|
||||
"removed in a future version. The region for a Cell "
|
||||
"should be defined using the region property directly.",
|
||||
DeprecationWarning)
|
||||
|
||||
if not isinstance(surface, openmc.Surface):
|
||||
msg = 'Unable to add Surface "{0}" to Cell ID="{1}" since it is ' \
|
||||
'not a Surface object'.format(surface, self._id)
|
||||
raise ValueError(msg)
|
||||
|
||||
if halfspace not in [-1, +1]:
|
||||
msg = 'Unable to add Surface "{0}" to Cell ID="{1}" with halfspace ' \
|
||||
'"{2}" since it is not +/-1'.format(surface, self._id, halfspace)
|
||||
raise ValueError(msg)
|
||||
|
||||
# If no region has been assigned, simply use the half-space. Otherwise,
|
||||
# take the intersection of the current region and the half-space
|
||||
# specified
|
||||
region = +surface if halfspace == 1 else -surface
|
||||
if self.region is None:
|
||||
self.region = region
|
||||
else:
|
||||
if isinstance(self.region, Intersection):
|
||||
self.region.nodes.append(region)
|
||||
else:
|
||||
self.region = Intersection(self.region, region)
|
||||
|
||||
def get_cell_instance(self, path, distribcell_index):
|
||||
|
||||
# If the Cell is filled by a Material
|
||||
if self.fill_type in ('material', 'distribmat', 'void'):
|
||||
offset = 0
|
||||
|
||||
# If the Cell is filled by a Universe
|
||||
elif self.fill_type == 'universe':
|
||||
offset = self.offsets[distribcell_index-1]
|
||||
offset += self.fill.get_cell_instance(path, distribcell_index)
|
||||
|
||||
# If the Cell is filled by a Lattice
|
||||
else:
|
||||
offset = self.fill.get_cell_instance(path, distribcell_index)
|
||||
|
||||
return offset
|
||||
|
||||
def get_all_nuclides(self):
|
||||
"""Return all nuclides contained in the cell
|
||||
|
||||
Returns
|
||||
-------
|
||||
nuclides : dict
|
||||
Dictionary whose keys are nuclide names and values are 2-tuples of
|
||||
(nuclide, density)
|
||||
|
||||
"""
|
||||
|
||||
nuclides = OrderedDict()
|
||||
|
||||
if self.fill_type != 'void':
|
||||
nuclides.update(self.fill.get_all_nuclides())
|
||||
|
||||
return nuclides
|
||||
|
||||
def get_all_cells(self):
|
||||
"""Return all cells that are contained within this one if it is filled with a
|
||||
universe or lattice
|
||||
|
||||
Returns
|
||||
-------
|
||||
cells : dict
|
||||
Dictionary whose keys are cell IDs and values are :class:`Cell`
|
||||
instances
|
||||
|
||||
"""
|
||||
|
||||
cells = OrderedDict()
|
||||
|
||||
if self.fill_type in ('universe', 'lattice'):
|
||||
cells.update(self.fill.get_all_cells())
|
||||
|
||||
return cells
|
||||
|
||||
def get_all_materials(self):
|
||||
"""Return all materials that are contained within the cell
|
||||
|
||||
Returns
|
||||
-------
|
||||
materials : dict
|
||||
Dictionary whose keys are material IDs and values are
|
||||
:class:`Material` instances
|
||||
|
||||
"""
|
||||
|
||||
materials = OrderedDict()
|
||||
if self.fill_type == 'material':
|
||||
materials[self.fill.id] = self.fill
|
||||
|
||||
# Append all Cells in each Cell in the Universe to the dictionary
|
||||
cells = self.get_all_cells()
|
||||
for cell_id, cell in cells.items():
|
||||
materials.update(cell.get_all_materials())
|
||||
|
||||
return materials
|
||||
|
||||
def get_all_universes(self):
|
||||
"""Return all universes that are contained within this one if any of
|
||||
its cells are filled with a universe or lattice.
|
||||
|
||||
Returns
|
||||
-------
|
||||
universes : dict
|
||||
Dictionary whose keys are universe IDs and values are
|
||||
:class:`Universe` instances
|
||||
|
||||
"""
|
||||
|
||||
universes = OrderedDict()
|
||||
|
||||
if self.fill_type == 'universe':
|
||||
universes[self.fill.id] = self.fill
|
||||
universes.update(self.fill.get_all_universes())
|
||||
elif self.fill_type == 'lattice':
|
||||
universes.update(self.fill.get_all_universes())
|
||||
|
||||
return universes
|
||||
|
||||
def create_xml_subelement(self, xml_element):
|
||||
element = ET.Element("cell")
|
||||
element.set("id", str(self.id))
|
||||
|
||||
if len(self._name) > 0:
|
||||
element.set("name", str(self.name))
|
||||
|
||||
if self.fill_type == 'void':
|
||||
element.set("material", "void")
|
||||
|
||||
elif self.fill_type == 'material':
|
||||
element.set("material", str(self.fill.id))
|
||||
|
||||
elif self.fill_type == 'distribmat':
|
||||
element.set("material", ' '.join(['void' if m is None else str(m.id)
|
||||
for m in self.fill]))
|
||||
|
||||
elif self.fill_type in ('universe', 'lattice'):
|
||||
element.set("fill", str(self.fill.id))
|
||||
self.fill.create_xml_subelement(xml_element)
|
||||
|
||||
if self.region is not None:
|
||||
# Set the region attribute with the region specification
|
||||
element.set("region", str(self.region))
|
||||
|
||||
# Only surfaces that appear in a region are added to the geometry
|
||||
# file, so the appropriate check is performed here. First we create
|
||||
# a function which is called recursively to navigate through the CSG
|
||||
# tree. When it reaches a leaf (a Halfspace), it creates a <surface>
|
||||
# element for the corresponding surface if none has been created
|
||||
# thus far.
|
||||
def create_surface_elements(node, element):
|
||||
if isinstance(node, Halfspace):
|
||||
path = './surface[@id=\'{0}\']'.format(node.surface.id)
|
||||
if xml_element.find(path) is None:
|
||||
surface_subelement = node.surface.create_xml_subelement()
|
||||
xml_element.append(surface_subelement)
|
||||
elif isinstance(node, Complement):
|
||||
create_surface_elements(node.node, element)
|
||||
else:
|
||||
for subnode in node.nodes:
|
||||
create_surface_elements(subnode, element)
|
||||
|
||||
# Call the recursive function from the top node
|
||||
create_surface_elements(self.region, xml_element)
|
||||
|
||||
if self.translation is not None:
|
||||
element.set("translation", ' '.join(map(str, self.translation)))
|
||||
|
||||
if self.rotation is not None:
|
||||
element.set("rotation", ' '.join(map(str, self.rotation)))
|
||||
|
||||
return element
|
||||
|
|
@ -1,35 +1,9 @@
|
|||
import copy
|
||||
from collections import Iterable
|
||||
from numbers import Integral, Real
|
||||
|
||||
import numpy as np
|
||||
|
||||
def _isinstance(value, expected_type):
|
||||
"""A Numpy-aware replacement for isinstance
|
||||
|
||||
This function will be obsolete when Numpy v. >= 1.9 is established.
|
||||
"""
|
||||
|
||||
# Declare numpy numeric types.
|
||||
np_ints = (np.int_, np.intc, np.intp, np.int8, np.int16, np.int32, np.int64,
|
||||
np.uint8, np.uint16, np.uint32, np.uint64)
|
||||
np_floats = (np.float_, np.float16, np.float32, np.float64)
|
||||
|
||||
# Include numpy integers, if necessary.
|
||||
if type(expected_type) is tuple:
|
||||
if Integral in expected_type:
|
||||
expected_type = expected_type + np_ints
|
||||
elif expected_type is Integral:
|
||||
expected_type = (Integral, ) + np_ints
|
||||
|
||||
# Include numpy floats, if necessary.
|
||||
if type(expected_type) is tuple:
|
||||
if Real in expected_type:
|
||||
expected_type = expected_type + np_floats
|
||||
elif expected_type is Real:
|
||||
expected_type = (Real, ) + np_floats
|
||||
|
||||
# Now, make the instance check.
|
||||
return isinstance(value, expected_type)
|
||||
|
||||
def check_type(name, value, expected_type, expected_iter_type=None):
|
||||
"""Ensure that an object is of an expected type. Optionally, if the object is
|
||||
|
|
@ -41,26 +15,45 @@ def check_type(name, value, expected_type, expected_iter_type=None):
|
|||
Description of value being checked
|
||||
value : object
|
||||
Object to check type of
|
||||
expected_type : type
|
||||
expected_type : type or Iterable of type
|
||||
type to check object against
|
||||
expected_iter_type : type or None, optional
|
||||
expected_iter_type : type or Iterable of type or None, optional
|
||||
Expected type of each element in value, assuming it is iterable. If
|
||||
None, no check will be performed.
|
||||
|
||||
"""
|
||||
|
||||
if not _isinstance(value, expected_type):
|
||||
msg = 'Unable to set "{0}" to "{1}" which is not of type "{2}"'.format(
|
||||
name, value, expected_type.__name__)
|
||||
raise ValueError(msg)
|
||||
if not isinstance(value, expected_type):
|
||||
if isinstance(expected_type, Iterable):
|
||||
msg = 'Unable to set "{0}" to "{1}" which is not one of the ' \
|
||||
'following types: "{2}"'.format(name, value, ', '.join(
|
||||
[t.__name__ for t in expected_type]))
|
||||
else:
|
||||
msg = 'Unable to set "{0}" to "{1}" which is not of type "{2}"'.format(
|
||||
name, value, expected_type.__name__)
|
||||
raise TypeError(msg)
|
||||
|
||||
if expected_iter_type:
|
||||
for item in value:
|
||||
if not _isinstance(item, expected_iter_type):
|
||||
if isinstance(value, np.ndarray):
|
||||
if not issubclass(value.dtype.type, expected_iter_type):
|
||||
msg = 'Unable to set "{0}" to "{1}" since each item must be ' \
|
||||
'of type "{2}"'.format(name, value,
|
||||
expected_iter_type.__name__)
|
||||
raise ValueError(msg)
|
||||
expected_iter_type.__name__)
|
||||
else:
|
||||
return
|
||||
|
||||
for item in value:
|
||||
if not isinstance(item, expected_iter_type):
|
||||
if isinstance(expected_iter_type, Iterable):
|
||||
msg = 'Unable to set "{0}" to "{1}" since each item must be ' \
|
||||
'one of the following types: "{2}"'.format(
|
||||
name, value, ', '.join([t.__name__ for t in
|
||||
expected_iter_type]))
|
||||
else:
|
||||
msg = 'Unable to set "{0}" to "{1}" since each item must be ' \
|
||||
'of type "{2}"'.format(name, value,
|
||||
expected_iter_type.__name__)
|
||||
raise TypeError(msg)
|
||||
|
||||
|
||||
def check_iterable_type(name, value, expected_type, min_depth=1, max_depth=1):
|
||||
|
|
@ -106,12 +99,12 @@ def check_iterable_type(name, value, expected_type, min_depth=1, max_depth=1):
|
|||
|
||||
# If this item is of the expected type, then we've reached the bottom
|
||||
# level of this branch.
|
||||
if _isinstance(current_item, expected_type):
|
||||
if isinstance(current_item, expected_type):
|
||||
# Is this deep enough?
|
||||
if len(tree) < min_depth:
|
||||
msg = 'Error setting "{0}": The item at {1} does not meet the '\
|
||||
'minimum depth of {2}'.format(name, ind_str, min_depth)
|
||||
raise ValueError(msg)
|
||||
raise TypeError(msg)
|
||||
|
||||
# This item is okay. Move on to the next item.
|
||||
index[-1] += 1
|
||||
|
|
@ -129,7 +122,7 @@ def check_iterable_type(name, value, expected_type, min_depth=1, max_depth=1):
|
|||
msg = 'Error setting {0}: Found an iterable at {1}, items '\
|
||||
'in that iterable exceed the maximum depth of {2}' \
|
||||
.format(name, ind_str, max_depth)
|
||||
raise ValueError(msg)
|
||||
raise TypeError(msg)
|
||||
|
||||
else:
|
||||
# This item is completely unexpected.
|
||||
|
|
@ -137,7 +130,7 @@ def check_iterable_type(name, value, expected_type, min_depth=1, max_depth=1):
|
|||
"item at {2} is of type '{3}'"\
|
||||
.format(name, expected_type.__name__, ind_str,
|
||||
type(current_item).__name__)
|
||||
raise ValueError(msg)
|
||||
raise TypeError(msg)
|
||||
|
||||
|
||||
def check_length(name, value, length_min, length_max=None):
|
||||
|
|
@ -245,3 +238,65 @@ def check_greater_than(name, value, minimum, equality=False):
|
|||
msg = 'Unable to set "{0}" to "{1}" since it is less than ' \
|
||||
'or equal to "{2}"'.format(name, value, minimum)
|
||||
raise ValueError(msg)
|
||||
|
||||
|
||||
class CheckedList(list):
|
||||
"""A list for which each element is type-checked as it's added
|
||||
|
||||
Parameters
|
||||
----------
|
||||
expected_type : type or Iterable of type
|
||||
Type(s) which each element should be
|
||||
name : str
|
||||
Name of data being checked
|
||||
items : Iterable, optional
|
||||
Items to initialize the list with
|
||||
|
||||
"""
|
||||
|
||||
def __init__(self, expected_type, name, items=[]):
|
||||
self.expected_type = expected_type
|
||||
self.name = name
|
||||
for item in items:
|
||||
self.append(item)
|
||||
|
||||
def __add__(self, other):
|
||||
new_instance = copy.copy(self)
|
||||
new_instance += other
|
||||
return new_instance
|
||||
|
||||
def __radd__(self, other):
|
||||
return self + other
|
||||
|
||||
def __iadd__(self, other):
|
||||
check_type('CheckedList add operand', other, Iterable,
|
||||
self.expected_type)
|
||||
for item in other:
|
||||
self.append(item)
|
||||
return self
|
||||
|
||||
def append(self, item):
|
||||
"""Append item to list
|
||||
|
||||
Parameters
|
||||
----------
|
||||
item : object
|
||||
Item to append
|
||||
|
||||
"""
|
||||
check_type(self.name, item, self.expected_type)
|
||||
super(CheckedList, self).append(item)
|
||||
|
||||
def insert(self, index, item):
|
||||
"""Insert item before index
|
||||
|
||||
Parameters
|
||||
----------
|
||||
index : int
|
||||
Index in list
|
||||
item : object
|
||||
Item to insert
|
||||
|
||||
"""
|
||||
check_type(self.name, item, self.expected_type)
|
||||
super(CheckedList, self).insert(index, item)
|
||||
|
|
|
|||
|
|
@ -69,7 +69,7 @@ class CMFDMesh(object):
|
|||
to any tallies far away from fission source neutron regions. A ``2``
|
||||
must be used to identify any fission source region.
|
||||
|
||||
"""
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
self._lower_left = None
|
||||
|
|
@ -187,7 +187,7 @@ class CMFDMesh(object):
|
|||
return element
|
||||
|
||||
|
||||
class CMFDFile(object):
|
||||
class CMFD(object):
|
||||
"""Parameters that control the use of coarse-mesh finite difference acceleration
|
||||
in OpenMC. This corresponds directly to the cmfd.xml input file.
|
||||
|
||||
|
|
@ -219,7 +219,7 @@ class CMFDFile(object):
|
|||
inner tolerance for Gauss-Seidel iterations when performing CMFD.
|
||||
ktol : float
|
||||
Tolerance on the eigenvalue when performing CMFD power iteration
|
||||
cmfd_mesh : CMFDMesh
|
||||
cmfd_mesh : openmc.CMFDMesh
|
||||
Structured mesh to be used for acceleration
|
||||
norm : float
|
||||
Normalization factor applied to the CMFD fission source distribution
|
||||
|
|
|
|||
1
openmc/data/__init__.py
Normal file
1
openmc/data/__init__.py
Normal file
|
|
@ -0,0 +1 @@
|
|||
from .data import *
|
||||
101
openmc/data/data.py
Normal file
101
openmc/data/data.py
Normal file
|
|
@ -0,0 +1,101 @@
|
|||
# Isotopic abundances from M. Berglund and M. E. Wieser, "Isotopic compositions
|
||||
# of the elements 2009 (IUPAC Technical Report)", Pure. Appl. Chem. 83 (2),
|
||||
# pp. 397--410 (2011).
|
||||
natural_abundance = {
|
||||
'H-1': 0.999885, 'H-2': 0.000115, 'He-3': 1.34e-06,
|
||||
'He-4': 0.99999866, 'Li-6': 0.0759, 'Li-7': 0.9241,
|
||||
'Be-9': 1.0, 'B-10': 0.199, 'B-11': 0.801,
|
||||
'C-12': 0.9893, 'C-13': 0.0107, 'N-14': 0.99636,
|
||||
'N-15': 0.00364, 'O-16': 0.99757, 'O-17': 0.00038,
|
||||
'O-18': 0.00205, 'F-19': 1.0, 'Ne-20': 0.9048,
|
||||
'Ne-21': 0.0027, 'Ne-22': 0.0925, 'Na-23': 1.0,
|
||||
'Mg-24': 0.7899, 'Mg-25': 0.1, 'Mg-26': 0.1101,
|
||||
'Al-27': 1.0, 'Si-28': 0.92223, 'Si-29': 0.04685,
|
||||
'Si-30': 0.03092, 'P-31': 1.0, 'S-32': 0.9499,
|
||||
'S-33': 0.0075, 'S-34': 0.0425, 'S-36': 0.0001,
|
||||
'Cl-35': 0.7576, 'Cl-37': 0.2424, 'Ar-36': 0.003336,
|
||||
'Ar-38': 0.000629, 'Ar-40': 0.996035, 'K-39': 0.932581,
|
||||
'K-40': 0.000117, 'K-41': 0.067302, 'Ca-40': 0.96941,
|
||||
'Ca-42': 0.00647, 'Ca-43': 0.00135, 'Ca-44': 0.02086,
|
||||
'Ca-46': 4e-05, 'Ca-48': 0.00187, 'Sc-45': 1.0,
|
||||
'Ti-46': 0.0825, 'Ti-47': 0.0744, 'Ti-48': 0.7372,
|
||||
'Ti-49': 0.0541, 'Ti-50': 0.0518, 'V-50': 0.0025,
|
||||
'V-51': 0.9975, 'Cr-50': 0.04345, 'Cr-52': 0.83789,
|
||||
'Cr-53': 0.09501, 'Cr-54': 0.02365, 'Mn-55': 1.0,
|
||||
'Fe-54': 0.05845, 'Fe-56': 0.91754, 'Fe-57': 0.02119,
|
||||
'Fe-58': 0.00282, 'Co-59': 1.0, 'Ni-58': 0.68077,
|
||||
'Ni-60': 0.26223, 'Ni-61': 0.011399, 'Ni-62': 0.036346,
|
||||
'Ni-64': 0.009255, 'Cu-63': 0.6915, 'Cu-65': 0.3085,
|
||||
'Zn-64': 0.4917, 'Zn-66': 0.2773, 'Zn-67': 0.0404,
|
||||
'Zn-68': 0.1845, 'Zn-70': 0.0061, 'Ga-69': 0.60108,
|
||||
'Ga-71': 0.39892, 'Ge-70': 0.2057, 'Ge-72': 0.2745,
|
||||
'Ge-73': 0.0775, 'Ge-74': 0.365, 'Ge-76': 0.0773,
|
||||
'As-75': 1.0, 'Se-74': 0.0089, 'Se-76': 0.0937,
|
||||
'Se-77': 0.0763, 'Se-78': 0.2377, 'Se-80': 0.4961,
|
||||
'Se-82': 0.0873, 'Br-79': 0.5069, 'Br-81': 0.4931,
|
||||
'Kr-78': 0.00355, 'Kr-80': 0.02286, 'Kr-82': 0.11593,
|
||||
'Kr-83': 0.115, 'Kr-84': 0.56987, 'Kr-86': 0.17279,
|
||||
'Rb-85': 0.7217, 'Rb-87': 0.2783, 'Sr-84': 0.0056,
|
||||
'Sr-86': 0.0986, 'Sr-87': 0.07, 'Sr-88': 0.8258,
|
||||
'Y-89': 1.0, 'Zr-90': 0.5145, 'Zr-91': 0.1122,
|
||||
'Zr-92': 0.1715, 'Zr-94': 0.1738, 'Zr-96': 0.028,
|
||||
'Nb-93': 1.0, 'Mo-92': 0.1453, 'Mo-94': 0.0915,
|
||||
'Mo-95': 0.1584, 'Mo-96': 0.1667, 'Mo-97': 0.096,
|
||||
'Mo-98': 0.2439, 'Mo-100': 0.0982, 'Ru-96': 0.0554,
|
||||
'Ru-98': 0.0187, 'Ru-99': 0.1276, 'Ru-100': 0.126,
|
||||
'Ru-101': 0.1706, 'Ru-102': 0.3155, 'Ru-104': 0.1862,
|
||||
'Rh-103': 1.0, 'Pd-102': 0.0102, 'Pd-104': 0.1114,
|
||||
'Pd-105': 0.2233, 'Pd-106': 0.2733, 'Pd-108': 0.2646,
|
||||
'Pd-110': 0.1172, 'Ag-107': 0.51839, 'Ag-109': 0.48161,
|
||||
'Cd-106': 0.0125, 'Cd-108': 0.0089, 'Cd-110': 0.1249,
|
||||
'Cd-111': 0.128, 'Cd-112': 0.2413, 'Cd-113': 0.1222,
|
||||
'Cd-114': 0.2873, 'Cd-116': 0.0749, 'In-113': 0.0429,
|
||||
'In-115': 0.9571, 'Sn-112': 0.0097, 'Sn-114': 0.0066,
|
||||
'Sn-115': 0.0034, 'Sn-116': 0.1454, 'Sn-117': 0.0768,
|
||||
'Sn-118': 0.2422, 'Sn-119': 0.0859, 'Sn-120': 0.3258,
|
||||
'Sn-122': 0.0463, 'Sn-124': 0.0579, 'Sb-121': 0.5721,
|
||||
'Sb-123': 0.4279, 'Te-120': 0.0009, 'Te-122': 0.0255,
|
||||
'Te-123': 0.0089, 'Te-124': 0.0474, 'Te-125': 0.0707,
|
||||
'Te-126': 0.1884, 'Te-128': 0.3174, 'Te-130': 0.3408,
|
||||
'I-127': 1.0, 'Xe-124': 0.000952, 'Xe-126': 0.00089,
|
||||
'Xe-128': 0.019102, 'Xe-129': 0.264006, 'Xe-130': 0.04071,
|
||||
'Xe-131': 0.212324, 'Xe-132': 0.269086, 'Xe-134': 0.104357,
|
||||
'Xe-136': 0.088573, 'Cs-133': 1.0, 'Ba-130': 0.00106,
|
||||
'Ba-132': 0.00101, 'Ba-134': 0.02417, 'Ba-135': 0.06592,
|
||||
'Ba-136': 0.07854, 'Ba-137': 0.11232, 'Ba-138': 0.71698,
|
||||
'La-138': 0.0008881, 'La-139': 0.9991119, 'Ce-136': 0.00185,
|
||||
'Ce-138': 0.00251, 'Ce-140': 0.8845, 'Ce-142': 0.11114,
|
||||
'Pr-141': 1.0, 'Nd-142': 0.27152, 'Nd-143': 0.12174,
|
||||
'Nd-144': 0.23798, 'Nd-145': 0.08293, 'Nd-146': 0.17189,
|
||||
'Nd-148': 0.05756, 'Nd-150': 0.05638, 'Sm-144': 0.0307,
|
||||
'Sm-147': 0.1499, 'Sm-148': 0.1124, 'Sm-149': 0.1382,
|
||||
'Sm-150': 0.0738, 'Sm-152': 0.2675, 'Sm-154': 0.2275,
|
||||
'Eu-151': 0.4781, 'Eu-153': 0.5219, 'Gd-152': 0.002,
|
||||
'Gd-154': 0.0218, 'Gd-155': 0.148, 'Gd-156': 0.2047,
|
||||
'Gd-157': 0.1565, 'Gd-158': 0.2484, 'Gd-160': 0.2186,
|
||||
'Tb-159': 1.0, 'Dy-156': 0.00056, 'Dy-158': 0.00095,
|
||||
'Dy-160': 0.02329, 'Dy-161': 0.18889, 'Dy-162': 0.25475,
|
||||
'Dy-163': 0.24896, 'Dy-164': 0.2826, 'Ho-165': 1.0,
|
||||
'Er-162': 0.00139, 'Er-164': 0.01601, 'Er-166': 0.33503,
|
||||
'Er-167': 0.22869, 'Er-168': 0.26978, 'Er-170': 0.1491,
|
||||
'Tm-169': 1.0, 'Yb-168': 0.00123, 'Yb-170': 0.02982,
|
||||
'Yb-171': 0.1409, 'Yb-172': 0.2168, 'Yb-173': 0.16103,
|
||||
'Yb-174': 0.32026, 'Yb-176': 0.12996, 'Lu-175': 0.97401,
|
||||
'Lu-176': 0.02599, 'Hf-174': 0.0016, 'Hf-176': 0.0526,
|
||||
'Hf-177': 0.186, 'Hf-178': 0.2728, 'Hf-179': 0.1362,
|
||||
'Hf-180': 0.3508, 'Ta-180': 0.0001201, 'Ta-181': 0.9998799,
|
||||
'W-180': 0.0012, 'W-182': 0.265, 'W-183': 0.1431,
|
||||
'W-184': 0.3064, 'W-186': 0.2843, 'Re-185': 0.374,
|
||||
'Re-187': 0.626, 'Os-184': 0.0002, 'Os-186': 0.0159,
|
||||
'Os-187': 0.0196, 'Os-188': 0.1324, 'Os-189': 0.1615,
|
||||
'Os-190': 0.2626, 'Os-192': 0.4078, 'Ir-191': 0.373,
|
||||
'Ir-193': 0.627, 'Pt-190': 0.00012, 'Pt-192': 0.00782,
|
||||
'Pt-194': 0.3286, 'Pt-195': 0.3378, 'Pt-196': 0.2521,
|
||||
'Pt-198': 0.07356, 'Au-197': 1.0, 'Hg-196': 0.0015,
|
||||
'Hg-198': 0.0997, 'Hg-199': 0.1687, 'Hg-200': 0.231,
|
||||
'Hg-201': 0.1318, 'Hg-202': 0.2986, 'Hg-204': 0.0687,
|
||||
'Tl-203': 0.2952, 'Tl-205': 0.7048, 'Pb-204': 0.014,
|
||||
'Pb-206': 0.241, 'Pb-207': 0.221, 'Pb-208': 0.524,
|
||||
'Bi-209': 1.0, 'Th-232': 1.0, 'Pa-231': 1.0,
|
||||
'U-234': 5.4e-05, 'U-235': 0.007204, 'U-238': 0.992742
|
||||
}
|
||||
|
|
@ -1,6 +1,8 @@
|
|||
import sys
|
||||
|
||||
from openmc.checkvalue import check_type
|
||||
import openmc
|
||||
from openmc.checkvalue import check_type, check_length
|
||||
from openmc.data import natural_abundance
|
||||
|
||||
if sys.version_info[0] >= 3:
|
||||
basestring = str
|
||||
|
|
@ -24,7 +26,7 @@ class Element(object):
|
|||
Chemical symbol of the element, e.g. Pu
|
||||
xs : str
|
||||
Cross section identifier, e.g. 71c
|
||||
scattering : 'data' or 'iso-in-lab' or None
|
||||
scattering : {'data', 'iso-in-lab', None}
|
||||
The type of angular scattering distribution to use
|
||||
|
||||
"""
|
||||
|
|
@ -97,7 +99,8 @@ class Element(object):
|
|||
|
||||
@name.setter
|
||||
def name(self, name):
|
||||
check_type('name', name, basestring)
|
||||
check_type('element name', name, basestring)
|
||||
check_length('element name', name, 1, 2)
|
||||
self._name = name
|
||||
|
||||
@scattering.setter
|
||||
|
|
@ -109,3 +112,22 @@ class Element(object):
|
|||
raise ValueError(msg)
|
||||
|
||||
self._scattering = scattering
|
||||
|
||||
def expand(self):
|
||||
"""Expand natural element into its naturally-occurring isotopes.
|
||||
|
||||
Returns
|
||||
-------
|
||||
isotopes : list
|
||||
Naturally-occurring isotopes of the element. Each item of the list
|
||||
is a tuple consisting of an openmc.Nuclide instance and the natural
|
||||
abundance of the isotope.
|
||||
|
||||
"""
|
||||
|
||||
isotopes = []
|
||||
for isotope, abundance in natural_abundance.items():
|
||||
if isotope.startswith(self.name + '-'):
|
||||
nuc = openmc.Nuclide(isotope, self.xs)
|
||||
isotopes.append((nuc, abundance))
|
||||
return isotopes
|
||||
|
|
|
|||
|
|
@ -1,130 +1,103 @@
|
|||
from __future__ import print_function
|
||||
import subprocess
|
||||
from numbers import Integral
|
||||
import os
|
||||
import sys
|
||||
|
||||
from openmc.checkvalue import check_type
|
||||
|
||||
if sys.version_info[0] >= 3:
|
||||
basestring = str
|
||||
|
||||
|
||||
class Executor(object):
|
||||
"""Control execution of OpenMC
|
||||
def _run(command, output, cwd):
|
||||
# Launch a subprocess
|
||||
p = subprocess.Popen(command, shell=True, cwd=cwd, stdout=subprocess.PIPE,
|
||||
stderr=subprocess.STDOUT, universal_newlines=True)
|
||||
|
||||
Attributes
|
||||
# Capture and re-print OpenMC output in real-time
|
||||
while True:
|
||||
# If OpenMC is finished, break loop
|
||||
line = p.stdout.readline()
|
||||
if not line and p.poll() != None:
|
||||
break
|
||||
|
||||
# If user requested output, print to screen
|
||||
if output:
|
||||
print(line, end='')
|
||||
|
||||
# Return the returncode (integer, zero if no problems encountered)
|
||||
return p.returncode
|
||||
|
||||
|
||||
def plot_geometry(output=True, openmc_exec='openmc', cwd='.'):
|
||||
"""Run OpenMC in plotting mode
|
||||
|
||||
Parameters
|
||||
----------
|
||||
working_directory : str
|
||||
Path to working directory to run in
|
||||
output : bool
|
||||
Capture OpenMC output from standard out
|
||||
openmc_exec : str
|
||||
Path to OpenMC executable
|
||||
cwd : str, optional
|
||||
Path to working directory to run in. Defaults to the current working directory.
|
||||
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
self._working_directory = '.'
|
||||
return _run(openmc_exec + ' -p', output, cwd)
|
||||
|
||||
def _run_openmc(self, command, output):
|
||||
# Launch a subprocess to run OpenMC
|
||||
p = subprocess.Popen(command, shell=True,
|
||||
cwd=self._working_directory,
|
||||
stdout=subprocess.PIPE)
|
||||
|
||||
# Capture and re-print OpenMC output in real-time
|
||||
while True:
|
||||
# If OpenMC is finished, break loop
|
||||
line = p.stdout.readline()
|
||||
if not line and p.poll() != None:
|
||||
break
|
||||
def run(particles=None, threads=None, geometry_debug=False,
|
||||
restart_file=None, tracks=False, mpi_procs=1, output=True,
|
||||
openmc_exec='openmc', mpi_exec='mpiexec', cwd='.'):
|
||||
"""Run an OpenMC simulation.
|
||||
|
||||
# If user requested output, print to screen
|
||||
if output:
|
||||
print(line, end='')
|
||||
Parameters
|
||||
----------
|
||||
particles : int, optional
|
||||
Number of particles to simulate per generation.
|
||||
threads : int, optional
|
||||
Number of OpenMP threads. If OpenMC is compiled with OpenMP threading
|
||||
enabled, the default is implementation-dependent but is usually equal to
|
||||
the number of hardware threads available (or a value set by the
|
||||
OMP_NUM_THREADS environment variable).
|
||||
geometry_debug : bool, optional
|
||||
Turn on geometry debugging during simulation. Defaults to False.
|
||||
restart_file : str, optional
|
||||
Path to restart file to use
|
||||
tracks : bool, optional
|
||||
Write tracks for all particles. Defaults to False.
|
||||
mpi_procs : int, optional
|
||||
Number of MPI processes.
|
||||
output : bool, optional
|
||||
Capture OpenMC output from standard out. Defaults to True.
|
||||
openmc_exec : str, optional
|
||||
Path to OpenMC executable. Defaults to 'openmc'.
|
||||
mpi_exec : str, optional
|
||||
MPI execute command. Defaults to 'mpiexec'.
|
||||
cwd : str, optional
|
||||
Path to working directory to run in. Defaults to the current working directory.
|
||||
|
||||
# Return the returncode (integer, zero if no problems encountered)
|
||||
return p.returncode
|
||||
"""
|
||||
|
||||
@property
|
||||
def working_directory(self):
|
||||
return self._working_directory
|
||||
post_args = ' '
|
||||
pre_args = ''
|
||||
|
||||
@working_directory.setter
|
||||
def working_directory(self, working_directory):
|
||||
check_type("Executor's working directory", working_directory,
|
||||
basestring)
|
||||
if not os.path.isdir(working_directory):
|
||||
msg = 'Unable to set Executor\'s working directory to "{0}" ' \
|
||||
'which does not exist'.format(working_directory)
|
||||
raise ValueError(msg)
|
||||
if isinstance(particles, Integral) and particles > 0:
|
||||
post_args += '-n {0} '.format(particles)
|
||||
|
||||
self._working_directory = working_directory
|
||||
if isinstance(threads, Integral) and threads > 0:
|
||||
post_args += '-s {0} '.format(threads)
|
||||
|
||||
def plot_geometry(self, output=True, openmc_exec='openmc'):
|
||||
"""Run OpenMC in plotting mode"""
|
||||
if geometry_debug:
|
||||
post_args += '-g '
|
||||
|
||||
return self._run_openmc(openmc_exec + ' -p', output)
|
||||
if isinstance(restart_file, basestring):
|
||||
post_args += '-r {0} '.format(restart_file)
|
||||
|
||||
def run_simulation(self, particles=None, threads=None,
|
||||
geometry_debug=False, restart_file=None,
|
||||
tracks=False, mpi_procs=1, output=True,
|
||||
openmc_exec='openmc', mpi_exec=None):
|
||||
"""Run an OpenMC simulation.
|
||||
if tracks:
|
||||
post_args += '-t'
|
||||
|
||||
Parameters
|
||||
----------
|
||||
particles : int
|
||||
Number of particles to simulate per generation
|
||||
threads : int
|
||||
Number of OpenMP threads
|
||||
geometry_debug : bool
|
||||
Turn on geometry debugging during simulation
|
||||
restart_file : str
|
||||
Path to restart file to use
|
||||
tracks : bool
|
||||
Write tracks for all particles
|
||||
mpi_procs : int
|
||||
Number of MPI processes
|
||||
output : bool
|
||||
Capture OpenMC output from standard out
|
||||
openmc_exec : str
|
||||
Path to OpenMC executable
|
||||
if isinstance(mpi_procs, Integral) and mpi_procs > 1:
|
||||
pre_args += '{} -n {} '.format(mpi_exec, mpi_procs)
|
||||
|
||||
"""
|
||||
command = pre_args + openmc_exec + ' ' + post_args
|
||||
|
||||
post_args = ' '
|
||||
pre_args = ''
|
||||
|
||||
if isinstance(particles, Integral) and particles > 0:
|
||||
post_args += '-n {0} '.format(particles)
|
||||
|
||||
if isinstance(threads, Integral) and threads > 0:
|
||||
post_args += '-s {0} '.format(threads)
|
||||
|
||||
if geometry_debug:
|
||||
post_args += '-g '
|
||||
|
||||
if isinstance(restart_file, basestring):
|
||||
post_args += '-r {0} '.format(restart_file)
|
||||
|
||||
if tracks:
|
||||
post_args += '-t'
|
||||
|
||||
if isinstance(mpi_procs, Integral) and mpi_procs > 1:
|
||||
np_present = True
|
||||
else:
|
||||
np_present = False
|
||||
|
||||
if mpi_exec is not None and isinstance(mpi_exec, basestring):
|
||||
mpi_exec_present = True
|
||||
else:
|
||||
mpi_exec_present = False
|
||||
|
||||
if np_present or mpi_exec_present:
|
||||
if mpi_exec_present:
|
||||
pre_args += mpi_exec + ' '
|
||||
else:
|
||||
pre_args += 'mpirun '
|
||||
pre_args += '-n {0} '.format(mpi_procs)
|
||||
|
||||
command = pre_args + openmc_exec + ' ' + post_args
|
||||
|
||||
return self._run_openmc(command, output)
|
||||
return _run(command, output, cwd)
|
||||
|
|
|
|||
248
openmc/filter.py
248
openmc/filter.py
|
|
@ -1,4 +1,4 @@
|
|||
from collections import Iterable
|
||||
from collections import Iterable, OrderedDict
|
||||
import copy
|
||||
from numbers import Real, Integral
|
||||
import sys
|
||||
|
|
@ -27,7 +27,8 @@ class Filter(object):
|
|||
type : str
|
||||
The type of the tally filter. Acceptable values are "universe",
|
||||
"material", "cell", "cellborn", "surface", "mesh", "energy",
|
||||
"energyout", and "distribcell".
|
||||
"energyout", "distribcell", "mu", "polar", "azimuthal", and
|
||||
"delayedgroup".
|
||||
bins : Integral or Iterable of Integral or Iterable of Real
|
||||
The bins for the filter. This takes on different meaning for different
|
||||
filters. See the OpenMC online documentation for more details.
|
||||
|
|
@ -40,11 +41,14 @@ class Filter(object):
|
|||
The bins for the filter
|
||||
num_bins : Integral
|
||||
The number of filter bins
|
||||
mesh : Mesh or None
|
||||
mesh : openmc.Mesh or None
|
||||
A Mesh object for 'mesh' type filters.
|
||||
stride : Integral
|
||||
The number of filter, nuclide and score bins within each of this
|
||||
filter's bins.
|
||||
distribcell_paths : list of str
|
||||
The paths traversed through the CSG tree to reach each distribcell
|
||||
instance (for 'distribcell' filters only)
|
||||
|
||||
"""
|
||||
|
||||
|
|
@ -56,6 +60,7 @@ class Filter(object):
|
|||
self._bins = None
|
||||
self._mesh = None
|
||||
self._stride = None
|
||||
self._distribcell_paths = None
|
||||
|
||||
if type is not None:
|
||||
self.type = type
|
||||
|
|
@ -110,6 +115,7 @@ class Filter(object):
|
|||
clone._num_bins = self.num_bins
|
||||
clone._mesh = copy.deepcopy(self.mesh, memo)
|
||||
clone._stride = self.stride
|
||||
clone._distribcell_paths = copy.deepcopy(self.distribcell_paths)
|
||||
|
||||
memo[id(self)] = clone
|
||||
|
||||
|
|
@ -152,6 +158,10 @@ class Filter(object):
|
|||
def stride(self):
|
||||
return self._stride
|
||||
|
||||
@property
|
||||
def distribcell_paths(self):
|
||||
return self._distribcell_paths
|
||||
|
||||
@type.setter
|
||||
def type(self, type):
|
||||
if type is None:
|
||||
|
|
@ -186,7 +196,7 @@ class Filter(object):
|
|||
|
||||
elif self.type in ['energy', 'energyout']:
|
||||
for edge in bins:
|
||||
if not cv._isinstance(edge, Real):
|
||||
if not isinstance(edge, Real):
|
||||
msg = 'Unable to add bin edge "{0}" to a "{1}" Filter ' \
|
||||
'since it is a non-integer or floating point ' \
|
||||
'value'.format(edge, self.type)
|
||||
|
|
@ -210,7 +220,7 @@ class Filter(object):
|
|||
msg = 'Unable to add bins "{0}" to a mesh Filter since ' \
|
||||
'only a single mesh can be used per tally'.format(bins)
|
||||
raise ValueError(msg)
|
||||
elif not cv._isinstance(bins[0], Integral):
|
||||
elif not isinstance(bins[0], Integral):
|
||||
msg = 'Unable to add bin "{0}" to mesh Filter since it ' \
|
||||
'is a non-integer'.format(bins[0])
|
||||
raise ValueError(msg)
|
||||
|
|
@ -246,12 +256,17 @@ class Filter(object):
|
|||
|
||||
self._stride = stride
|
||||
|
||||
@distribcell_paths.setter
|
||||
def distribcell_paths(self, distribcell_paths):
|
||||
cv.check_iterable_type('distribcell_paths', distribcell_paths, str)
|
||||
self._distribcell_paths = distribcell_paths
|
||||
|
||||
def can_merge(self, other):
|
||||
"""Determine if filter can be merged with another.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
other : Filter
|
||||
other : openmc.Filter
|
||||
Filter to compare with
|
||||
|
||||
Returns
|
||||
|
|
@ -296,12 +311,12 @@ class Filter(object):
|
|||
|
||||
Parameters
|
||||
----------
|
||||
other : Filter
|
||||
other : openmc.Filter
|
||||
Filter to merge with
|
||||
|
||||
Returns
|
||||
-------
|
||||
merged_filter : Filter
|
||||
merged_filter : openmc.Filter
|
||||
Filter resulting from the merge
|
||||
|
||||
"""
|
||||
|
|
@ -341,7 +356,7 @@ class Filter(object):
|
|||
|
||||
Parameters
|
||||
----------
|
||||
other : Filter
|
||||
other : openmc.Filter
|
||||
The filter to query as a subset of this filter
|
||||
|
||||
Returns
|
||||
|
|
@ -501,12 +516,12 @@ class Filter(object):
|
|||
|
||||
return filter_bin
|
||||
|
||||
def get_pandas_dataframe(self, data_size, summary=None):
|
||||
def get_pandas_dataframe(self, data_size, distribcell_paths=True):
|
||||
"""Builds a Pandas DataFrame for the Filter's bins.
|
||||
|
||||
This method constructs a Pandas DataFrame object for the filter with
|
||||
columns annotated by filter bin information. This is a helper method
|
||||
for the Tally.get_pandas_dataframe(...) method.
|
||||
columns annotated by filter bin information. This is a helper method for
|
||||
:meth:`Tally.get_pandas_dataframe`.
|
||||
|
||||
This capability has been tested for Pandas >=0.13.1. However, it is
|
||||
recommended to use v0.16 or newer versions of Pandas since this method
|
||||
|
|
@ -516,12 +531,13 @@ class Filter(object):
|
|||
----------
|
||||
data_size : Integral
|
||||
The total number of bins in the tally corresponding to this filter
|
||||
summary : None or Summary
|
||||
An optional Summary object to be used to construct columns for
|
||||
distribcell tally filters (default is None). The geometric
|
||||
information in the Summary object is embedded into a Multi-index
|
||||
column with a geometric "path" to each distribcell instance.
|
||||
NOTE: This option requires the OpenCG Python package.
|
||||
distribcell_paths : bool, optional
|
||||
Construct columns for distribcell tally filters (default is True).
|
||||
The geometric information in the Summary object is embedded into a
|
||||
Multi-index column with a geometric "path" to each distribcell
|
||||
instance. NOTE: This option assumes that all distribcell paths are
|
||||
of the same length and do not have the same universes and cells but
|
||||
different lattice cell indices.
|
||||
|
||||
Returns
|
||||
-------
|
||||
|
|
@ -539,7 +555,7 @@ class Filter(object):
|
|||
|
||||
1. a single column with the cell instance IDs (without summary info)
|
||||
2. separate columns for the cell IDs, universe IDs, and lattice IDs
|
||||
and x,y,z cell indices corresponding to each (with summary info).
|
||||
and x,y,z cell indices corresponding to each (distribcell paths).
|
||||
|
||||
For 'energy' and 'energyout' filters, the DataFrame includes one
|
||||
column for the lower energy bound and one column for the upper
|
||||
|
|
@ -551,8 +567,7 @@ class Filter(object):
|
|||
Raises
|
||||
------
|
||||
ImportError
|
||||
When Pandas is not installed, or summary info is requested but
|
||||
OpenCG is not installed.
|
||||
When Pandas is not installed
|
||||
|
||||
See also
|
||||
--------
|
||||
|
|
@ -611,114 +626,117 @@ class Filter(object):
|
|||
elif self.type == 'distribcell':
|
||||
level_df = None
|
||||
|
||||
if isinstance(summary, Summary):
|
||||
# Attempt to import the OpenCG package
|
||||
try:
|
||||
import opencg
|
||||
except ImportError:
|
||||
msg = 'The OpenCG package must be installed ' \
|
||||
'to use a Summary for distribcell dataframes'
|
||||
raise ImportError(msg)
|
||||
# Create Pandas Multi-index columns for each level in CSG tree
|
||||
if distribcell_paths:
|
||||
|
||||
# Extract the OpenCG geometry from the Summary
|
||||
opencg_geometry = summary.opencg_geometry
|
||||
openmc_geometry = summary.openmc_geometry
|
||||
# Distribcell paths require linked metadata from the Summary
|
||||
if self.distribcell_paths is None:
|
||||
msg = 'Unable to construct distribcell paths since ' \
|
||||
'the Summary is not linked to the StatePoint'
|
||||
raise ValueError(msg)
|
||||
|
||||
# Use OpenCG to compute the number of regions
|
||||
opencg_geometry.initialize_cell_offsets()
|
||||
num_regions = opencg_geometry.num_regions
|
||||
# Make copy of array of distribcell paths to use in
|
||||
# Pandas Multi-index column construction
|
||||
distribcell_paths = copy.deepcopy(self.distribcell_paths)
|
||||
num_offsets = len(distribcell_paths)
|
||||
|
||||
# Initialize a dictionary mapping OpenMC distribcell
|
||||
# offsets to OpenCG LocalCoords linked lists
|
||||
offsets_to_coords = {}
|
||||
|
||||
# Use OpenCG to compute LocalCoords linked list for
|
||||
# each region and store in dictionary
|
||||
for region in range(num_regions):
|
||||
coords = opencg_geometry.find_region(region)
|
||||
path = opencg.get_path(coords)
|
||||
cell_id = path[-1]
|
||||
|
||||
# If this region is in Cell corresponding to the
|
||||
# distribcell filter bin, store it in dictionary
|
||||
if cell_id == self.bins[0]:
|
||||
offset = openmc_geometry.get_cell_instance(path)
|
||||
offsets_to_coords[offset] = coords
|
||||
|
||||
# Each distribcell offset is a DataFrame bin
|
||||
# Unravel the paths into DataFrame columns
|
||||
num_offsets = len(offsets_to_coords)
|
||||
|
||||
# Initialize termination condition for while loop
|
||||
# Loop over CSG levels in the distribcell paths
|
||||
level_counter = 0
|
||||
levels_remain = True
|
||||
counter = 0
|
||||
|
||||
# Iterate over each level in the CSG tree hierarchy
|
||||
while levels_remain:
|
||||
levels_remain = False
|
||||
|
||||
# Initialize dictionary to build Pandas Multi-index
|
||||
# column for this level in the CSG tree hierarchy
|
||||
level_dict = {}
|
||||
# Use level key as first index in Pandas Multi-index column
|
||||
level_counter += 1
|
||||
level_key = 'level {}'.format(level_counter)
|
||||
|
||||
# Initialize prefix Multi-index keys
|
||||
counter += 1
|
||||
level_key = 'level {0}'.format(counter)
|
||||
univ_key = (level_key, 'univ', 'id')
|
||||
cell_key = (level_key, 'cell', 'id')
|
||||
lat_id_key = (level_key, 'lat', 'id')
|
||||
lat_x_key = (level_key, 'lat', 'x')
|
||||
lat_y_key = (level_key, 'lat', 'y')
|
||||
lat_z_key = (level_key, 'lat', 'z')
|
||||
# Use the first distribcell path to determine if level
|
||||
# is a universe/cell or lattice level
|
||||
first_path = distribcell_paths[0]
|
||||
next_index = first_path.index('-')
|
||||
level = first_path[:next_index]
|
||||
|
||||
# Allocate NumPy arrays for each CSG level and
|
||||
# each Multi-index column in the DataFrame
|
||||
level_dict[univ_key] = np.empty(num_offsets)
|
||||
level_dict[cell_key] = np.empty(num_offsets)
|
||||
level_dict[lat_id_key] = np.empty(num_offsets)
|
||||
level_dict[lat_x_key] = np.empty(num_offsets)
|
||||
level_dict[lat_y_key] = np.empty(num_offsets)
|
||||
level_dict[lat_z_key] = np.empty(num_offsets)
|
||||
# Trim universe/lattice info from path
|
||||
first_path = first_path[next_index+2:]
|
||||
|
||||
# Initialize Multi-index columns to NaN - this is
|
||||
# necessary since some distribcell instances may
|
||||
# have very different LocalCoords linked lists
|
||||
level_dict[univ_key][:] = np.NAN
|
||||
level_dict[cell_key][:] = np.NAN
|
||||
level_dict[lat_id_key][:] = np.NAN
|
||||
level_dict[lat_x_key][:] = np.NAN
|
||||
level_dict[lat_y_key][:] = np.NAN
|
||||
level_dict[lat_z_key][:] = np.NAN
|
||||
# Create a dictionary for this level for Pandas Multi-index
|
||||
level_dict = OrderedDict()
|
||||
|
||||
# Iterate over all regions (distribcell instances)
|
||||
for offset in range(num_offsets):
|
||||
coords = offsets_to_coords[offset]
|
||||
# This level is a lattice (e.g., ID(x,y,z))
|
||||
if '(' in level:
|
||||
level_type = 'lattice'
|
||||
|
||||
# If entire LocalCoords has been unraveled into
|
||||
# Multi-index columns already, continue
|
||||
if coords is None:
|
||||
continue
|
||||
# Initialize prefix Multi-index keys
|
||||
lat_id_key = (level_key, 'lat', 'id')
|
||||
lat_x_key = (level_key, 'lat', 'x')
|
||||
lat_y_key = (level_key, 'lat', 'y')
|
||||
lat_z_key = (level_key, 'lat', 'z')
|
||||
|
||||
# Assign entry to Universe Multi-index column
|
||||
if coords._type == 'universe':
|
||||
level_dict[univ_key][offset] = coords._universe._id
|
||||
level_dict[cell_key][offset] = coords._cell._id
|
||||
# Allocate NumPy arrays for each CSG level and
|
||||
# each Multi-index column in the DataFrame
|
||||
level_dict[lat_id_key] = np.empty(num_offsets)
|
||||
level_dict[lat_x_key] = np.empty(num_offsets)
|
||||
level_dict[lat_y_key] = np.empty(num_offsets)
|
||||
level_dict[lat_z_key] = np.empty(num_offsets)
|
||||
|
||||
# This level is a universe / cell (e.g., ID->ID)
|
||||
else:
|
||||
level_type = 'universe'
|
||||
|
||||
# Initialize prefix Multi-index keys
|
||||
univ_key = (level_key, 'univ', 'id')
|
||||
cell_key = (level_key, 'cell', 'id')
|
||||
|
||||
# Allocate NumPy arrays for each CSG level and
|
||||
# each Multi-index column in the DataFrame
|
||||
level_dict[univ_key] = np.empty(num_offsets)
|
||||
level_dict[cell_key] = np.empty(num_offsets)
|
||||
|
||||
# Determine any levels remain in path
|
||||
if '-' not in first_path:
|
||||
levels_remain = False
|
||||
|
||||
# Populate Multi-index arrays with all distribcell paths
|
||||
for i, path in enumerate(distribcell_paths):
|
||||
|
||||
if level_type == 'lattice':
|
||||
# Extract lattice ID, indices from path
|
||||
next_index = path.index('-')
|
||||
lat_id_indices = path[:next_index]
|
||||
|
||||
# Trim lattice info from distribcell path
|
||||
distribcell_paths[i] = path[next_index+2:]
|
||||
|
||||
# Extract the lattice cell indices from the path
|
||||
i1 = lat_id_indices.index('(')
|
||||
i2 = lat_id_indices.index(')')
|
||||
i3 = lat_id_indices[i1+1:i2]
|
||||
|
||||
# Assign entry to Lattice Multi-index column
|
||||
level_dict[lat_id_key][i] = path[:i1]
|
||||
level_dict[lat_x_key][i] = int(i3.split(',')[0]) - 1
|
||||
level_dict[lat_y_key][i] = int(i3.split(',')[1]) - 1
|
||||
level_dict[lat_z_key][i] = int(i3.split(',')[2]) - 1
|
||||
|
||||
# Assign entry to Lattice Multi-index column
|
||||
else:
|
||||
# Reverse y index per lattice ordering in OpenCG
|
||||
level_dict[lat_id_key][offset] = coords._lattice._id
|
||||
level_dict[lat_x_key][offset] = coords._lat_x
|
||||
level_dict[lat_y_key][offset] = \
|
||||
coords._lattice.dimension[1] - coords._lat_y - 1
|
||||
level_dict[lat_z_key][offset] = coords._lat_z
|
||||
# Extract universe ID from path
|
||||
next_index = path.index('-')
|
||||
universe_id = int(path[:next_index])
|
||||
|
||||
# Move to next node in LocalCoords linked list
|
||||
if coords._next is None:
|
||||
offsets_to_coords[offset] = None
|
||||
else:
|
||||
offsets_to_coords[offset] = coords._next
|
||||
levels_remain = True
|
||||
# Trim universe info from distribcell path
|
||||
path = path[next_index+2:]
|
||||
|
||||
# Extract cell ID from path
|
||||
if '-' in path:
|
||||
next_index = path.index('-')
|
||||
cell_id = int(path[:next_index])
|
||||
distribcell_paths[i] = path[next_index+2:]
|
||||
else:
|
||||
cell_id = int(path)
|
||||
distribcell_paths[i] = ''
|
||||
|
||||
# Assign entry to Universe, Cell Multi-index columns
|
||||
level_dict[univ_key][i] = universe_id
|
||||
level_dict[cell_key][i] = cell_id
|
||||
|
||||
# Tile the Multi-index columns
|
||||
for level_key, level_bins in level_dict.items():
|
||||
|
|
@ -733,7 +751,7 @@ class Filter(object):
|
|||
else:
|
||||
level_df = pd.concat([level_df, pd.DataFrame(level_dict)], axis=1)
|
||||
|
||||
# Create DataFrame column for distribcell instances IDs
|
||||
# Create DataFrame column for distribcell instance IDs
|
||||
# NOTE: This is performed regardless of whether the user
|
||||
# requests Summary geometric information
|
||||
filter_bins = np.arange(self.num_bins)
|
||||
|
|
|
|||
|
|
@ -15,17 +15,23 @@ def reset_auto_ids():
|
|||
class Geometry(object):
|
||||
"""Geometry representing a collection of surfaces, cells, and universes.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
root_universe : openmc.Universe, optional
|
||||
Root universe which contains all others
|
||||
|
||||
Attributes
|
||||
----------
|
||||
root_universe : openmc.universe.Universe
|
||||
root_universe : openmc.Universe
|
||||
Root universe which contains all others
|
||||
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
# Initialize Geometry class attributes
|
||||
def __init__(self, root_universe=None):
|
||||
self._root_universe = None
|
||||
self._offsets = {}
|
||||
if root_universe is not None:
|
||||
self.root_universe = root_universe
|
||||
|
||||
@property
|
||||
def root_universe(self):
|
||||
|
|
@ -42,6 +48,44 @@ class Geometry(object):
|
|||
|
||||
self._root_universe = root_universe
|
||||
|
||||
def export_to_xml(self):
|
||||
"""Create a geometry.xml file that can be used for a simulation.
|
||||
|
||||
"""
|
||||
|
||||
# Clear OpenMC written IDs used to optimize XML generation
|
||||
openmc.universe.WRITTEN_IDS = {}
|
||||
|
||||
# Create XML representation
|
||||
geometry_file = ET.Element("geometry")
|
||||
self.root_universe.create_xml_subelement(geometry_file)
|
||||
|
||||
# Clean the indentation in the file to be user-readable
|
||||
sort_xml_elements(geometry_file)
|
||||
clean_xml_indentation(geometry_file)
|
||||
|
||||
# Write the XML Tree to the geometry.xml file
|
||||
tree = ET.ElementTree(geometry_file)
|
||||
tree.write("geometry.xml", xml_declaration=True, encoding='utf-8',
|
||||
method="xml")
|
||||
|
||||
def find(self, point):
|
||||
"""Find cells/universes/lattices which contain a given point
|
||||
|
||||
Parameters
|
||||
----------
|
||||
point : 3-tuple of float
|
||||
Cartesian coordinates of the point
|
||||
|
||||
Returns
|
||||
-------
|
||||
list
|
||||
Sequence of universes, cells, and lattices which are traversed to
|
||||
find the given point
|
||||
|
||||
"""
|
||||
return self.root_universe.find(point)
|
||||
|
||||
def get_cell_instance(self, path):
|
||||
"""Return the instance number for the final cell in a geometry path.
|
||||
|
||||
|
|
@ -63,15 +107,19 @@ class Geometry(object):
|
|||
|
||||
"""
|
||||
|
||||
# Extract the cell id from the path
|
||||
last_index = path.rfind('>')
|
||||
cell_id = int(path[last_index+1:])
|
||||
|
||||
# Find the distribcell index of the cell.
|
||||
cells = self.get_all_cells()
|
||||
for cell in cells:
|
||||
if cell.id == path[-1]:
|
||||
if cell.id == cell_id:
|
||||
distribcell_index = cell.distribcell_index
|
||||
break
|
||||
else:
|
||||
raise RuntimeError('Could not find cell {} specified in a \
|
||||
distribcell filter'.format(path[-1]))
|
||||
distribcell filter'.format(cell_id))
|
||||
|
||||
# Return memoize'd offset if possible
|
||||
if (path, distribcell_index) in self._offsets:
|
||||
|
|
@ -91,19 +139,13 @@ class Geometry(object):
|
|||
|
||||
Returns
|
||||
-------
|
||||
list of openmc.universe.Cell
|
||||
list of openmc.Cell
|
||||
Cells in the geometry
|
||||
|
||||
"""
|
||||
|
||||
all_cells = self._root_universe.get_all_cells()
|
||||
cells = set()
|
||||
|
||||
for cell in all_cells.values():
|
||||
if cell._type == 'normal':
|
||||
cells.add(cell)
|
||||
|
||||
cells = list(cells)
|
||||
all_cells = self.root_universe.get_all_cells()
|
||||
cells = list(set(all_cells.values()))
|
||||
cells.sort(key=lambda x: x.id)
|
||||
return cells
|
||||
|
||||
|
|
@ -112,18 +154,13 @@ class Geometry(object):
|
|||
|
||||
Returns
|
||||
-------
|
||||
list of openmc.universe.Universe
|
||||
list of openmc.Universe
|
||||
Universes in the geometry
|
||||
|
||||
"""
|
||||
|
||||
all_universes = self._root_universe.get_all_universes()
|
||||
universes = set()
|
||||
|
||||
for universe in all_universes.values():
|
||||
universes.add(universe)
|
||||
|
||||
universes = list(universes)
|
||||
universes = list(set(all_universes.values()))
|
||||
universes.sort(key=lambda x: x.id)
|
||||
return universes
|
||||
|
||||
|
|
@ -132,7 +169,7 @@ class Geometry(object):
|
|||
|
||||
Returns
|
||||
-------
|
||||
list of openmc.nuclide.Nuclide
|
||||
list of openmc.Nuclide
|
||||
Nuclides in the geometry
|
||||
|
||||
"""
|
||||
|
|
@ -150,21 +187,23 @@ class Geometry(object):
|
|||
|
||||
Returns
|
||||
-------
|
||||
list of openmc.material.Material
|
||||
list of openmc.Material
|
||||
Materials in the geometry
|
||||
|
||||
"""
|
||||
|
||||
material_cells = self.get_all_material_cells()
|
||||
materials = set()
|
||||
materials = []
|
||||
|
||||
for cell in material_cells:
|
||||
if isinstance(cell.fill, Iterable):
|
||||
for m in cell.fill: materials.add(m)
|
||||
else:
|
||||
materials.add(cell.fill)
|
||||
if cell.fill_type == 'distribmat':
|
||||
for m in cell.fill:
|
||||
if m is not None and m not in materials:
|
||||
materials.append(m)
|
||||
elif cell.fill_type == 'material':
|
||||
if cell.fill not in materials:
|
||||
materials.append(cell.fill)
|
||||
|
||||
materials = list(materials)
|
||||
materials.sort(key=lambda x: x.id)
|
||||
return materials
|
||||
|
||||
|
|
@ -173,19 +212,19 @@ class Geometry(object):
|
|||
|
||||
Returns
|
||||
-------
|
||||
list of openmc.universe.Cell
|
||||
list of openmc.Cell
|
||||
Cells filled by Materials in the geometry
|
||||
|
||||
"""
|
||||
|
||||
all_cells = self.get_all_cells()
|
||||
material_cells = set()
|
||||
material_cells = []
|
||||
|
||||
for cell in all_cells:
|
||||
if cell._type == 'normal':
|
||||
material_cells.add(cell)
|
||||
if cell.fill_type in ('material', 'distribmat'):
|
||||
if cell not in material_cells:
|
||||
material_cells.append(cell)
|
||||
|
||||
material_cells = list(material_cells)
|
||||
material_cells.sort(key=lambda x: x.id)
|
||||
return material_cells
|
||||
|
||||
|
|
@ -194,21 +233,21 @@ class Geometry(object):
|
|||
|
||||
Returns
|
||||
-------
|
||||
list of openmc.universe.Universe
|
||||
list of openmc.Universe
|
||||
Universes with non-fill cells
|
||||
|
||||
"""
|
||||
|
||||
all_universes = self.get_all_universes()
|
||||
material_universes = set()
|
||||
material_universes = []
|
||||
|
||||
for universe in all_universes:
|
||||
cells = universe.cells
|
||||
for cell in cells:
|
||||
if cell._type == 'normal':
|
||||
material_universes.add(universe)
|
||||
if cell.fill_type in ('material', 'distribmat', 'void'):
|
||||
if universe not in material_universes:
|
||||
material_universes.append(universe)
|
||||
|
||||
material_universes = list(material_universes)
|
||||
material_universes.sort(key=lambda x: x.id)
|
||||
return material_universes
|
||||
|
||||
|
|
@ -217,19 +256,19 @@ class Geometry(object):
|
|||
|
||||
Returns
|
||||
-------
|
||||
list of openmc.universe.Lattice
|
||||
list of openmc.Lattice
|
||||
Lattices in the geometry
|
||||
|
||||
"""
|
||||
|
||||
cells = self.get_all_cells()
|
||||
lattices = set()
|
||||
lattices = []
|
||||
|
||||
for cell in cells:
|
||||
if isinstance(cell.fill, openmc.Lattice):
|
||||
lattices.add(cell.fill)
|
||||
if cell.fill_type == 'lattice':
|
||||
if cell.fill not in lattices:
|
||||
lattices.append(cell.fill)
|
||||
|
||||
lattices = list(lattices)
|
||||
lattices.sort(key=lambda x: x.id)
|
||||
return lattices
|
||||
|
||||
|
|
@ -248,7 +287,7 @@ class Geometry(object):
|
|||
|
||||
Returns
|
||||
-------
|
||||
list of openmc.material.Material
|
||||
list of openmc.Material
|
||||
Materials matching the queried name
|
||||
|
||||
"""
|
||||
|
|
@ -288,7 +327,7 @@ class Geometry(object):
|
|||
|
||||
Returns
|
||||
-------
|
||||
list of openmc.universe.Cell
|
||||
list of openmc.Cell
|
||||
Cells matching the queried name
|
||||
|
||||
"""
|
||||
|
|
@ -328,7 +367,7 @@ class Geometry(object):
|
|||
|
||||
Returns
|
||||
-------
|
||||
list of openmc.universe.Cell
|
||||
list of openmc.Cell
|
||||
Cells with fills matching the queried name
|
||||
|
||||
"""
|
||||
|
|
@ -368,7 +407,7 @@ class Geometry(object):
|
|||
|
||||
Returns
|
||||
-------
|
||||
list of openmc.universe.Universe
|
||||
list of openmc.Universe
|
||||
Universes matching the queried name
|
||||
|
||||
"""
|
||||
|
|
@ -408,7 +447,7 @@ class Geometry(object):
|
|||
|
||||
Returns
|
||||
-------
|
||||
list of openmc.universe.Lattice
|
||||
list of openmc.Lattice
|
||||
Lattices matching the queried name
|
||||
|
||||
"""
|
||||
|
|
@ -432,52 +471,3 @@ class Geometry(object):
|
|||
lattices = list(lattices)
|
||||
lattices.sort(key=lambda x: x.id)
|
||||
return lattices
|
||||
|
||||
|
||||
class GeometryFile(object):
|
||||
"""Geometry file used for an OpenMC simulation. Corresponds directly to the
|
||||
geometry.xml input file.
|
||||
|
||||
Attributes
|
||||
----------
|
||||
geometry : Geometry
|
||||
The geometry to be used
|
||||
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
# Initialize GeometryFile class attributes
|
||||
self._geometry = None
|
||||
self._geometry_file = ET.Element("geometry")
|
||||
|
||||
@property
|
||||
def geometry(self):
|
||||
return self._geometry
|
||||
|
||||
@geometry.setter
|
||||
def geometry(self, geometry):
|
||||
check_type('the geometry', geometry, Geometry)
|
||||
self._geometry = geometry
|
||||
|
||||
def export_to_xml(self):
|
||||
"""Create a geometry.xml file that can be used for a simulation.
|
||||
|
||||
"""
|
||||
|
||||
# Clear OpenMC written IDs used to optimize XML generation
|
||||
openmc.universe.WRITTEN_IDS = {}
|
||||
|
||||
# Reset xml element tree
|
||||
self._geometry_file.clear()
|
||||
|
||||
root_universe = self.geometry.root_universe
|
||||
root_universe.create_xml_subelement(self._geometry_file)
|
||||
|
||||
# Clean the indentation in the file to be user-readable
|
||||
sort_xml_elements(self._geometry_file)
|
||||
clean_xml_indentation(self._geometry_file)
|
||||
|
||||
# Write the XML Tree to the geometry.xml file
|
||||
tree = ET.ElementTree(self._geometry_file)
|
||||
tree.write("geometry.xml", xml_declaration=True,
|
||||
encoding='utf-8', method="xml")
|
||||
|
|
|
|||
1328
openmc/lattice.py
Normal file
1328
openmc/lattice.py
Normal file
File diff suppressed because it is too large
Load diff
|
|
@ -8,8 +8,9 @@ if sys.version_info[0] >= 3:
|
|||
basestring = str
|
||||
|
||||
import openmc
|
||||
from openmc.checkvalue import check_type, check_value, check_greater_than
|
||||
import openmc.checkvalue as cv
|
||||
from openmc.clean_xml import *
|
||||
from openmc.data import natural_abundance
|
||||
|
||||
|
||||
# A static variable for auto-generated Material IDs
|
||||
|
|
@ -25,9 +26,6 @@ def reset_auto_material_id():
|
|||
DENSITY_UNITS = ['g/cm3', 'g/cc', 'kg/cm3', 'atom/b-cm', 'atom/cm3', 'sum',
|
||||
'macro']
|
||||
|
||||
# Constant for density when not needed
|
||||
NO_DENSITY = 99999.
|
||||
|
||||
|
||||
class Material(object):
|
||||
"""A material composed of a collection of nuclides/elements that can be
|
||||
|
|
@ -52,6 +50,14 @@ class Material(object):
|
|||
Units used for `density`. Can be one of 'g/cm3', 'g/cc', 'kg/cm3',
|
||||
'atom/b-cm', 'atom/cm3', 'sum', or 'macro'. The 'macro' unit only
|
||||
applies in the case of a multi-group calculation.
|
||||
elements : collections.OrderedDict
|
||||
Dictionary whose keys are element names and values are 3-tuples
|
||||
consisting of an :class:`openmc.Element` instance, the percent density,
|
||||
and the percent type (atom or weight fraction).
|
||||
nuclides : collections.OrderedDict
|
||||
Dictionary whose keys are nuclide names and values are 3-tuples
|
||||
consisting of an :class:`openmc.Nuclide` instance, the percent density,
|
||||
and the percent type (atom or weight fraction).
|
||||
|
||||
"""
|
||||
|
||||
|
|
@ -141,9 +147,9 @@ class Material(object):
|
|||
string += '{0: <16}\n'.format('\tElements')
|
||||
|
||||
for element in self._elements:
|
||||
percent = self._nuclides[element][1]
|
||||
percent_type = self._nuclides[element][2]
|
||||
string += '{0: >16}'.format('\t{0}'.format(element))
|
||||
percent = self._elements[element][1]
|
||||
percent_type = self._elements[element][2]
|
||||
string += '{0: <16}'.format('\t{0}'.format(element))
|
||||
string += '=\t{0: <12} [{1}]\n'.format(percent, percent_type)
|
||||
|
||||
return string
|
||||
|
|
@ -189,6 +195,14 @@ class Material(object):
|
|||
def density_units(self):
|
||||
return self._density_units
|
||||
|
||||
@property
|
||||
def elements(self):
|
||||
return self._elements
|
||||
|
||||
@property
|
||||
def nuclides(self):
|
||||
return self._nuclides
|
||||
|
||||
@property
|
||||
def convert_to_distrib_comps(self):
|
||||
return self._convert_to_distrib_comps
|
||||
|
|
@ -205,45 +219,51 @@ class Material(object):
|
|||
self._id = AUTO_MATERIAL_ID
|
||||
AUTO_MATERIAL_ID += 1
|
||||
else:
|
||||
check_type('material ID', material_id, Integral)
|
||||
check_greater_than('material ID', material_id, 0, equality=True)
|
||||
cv.check_type('material ID', material_id, Integral)
|
||||
cv.check_greater_than('material ID', material_id, 0, equality=True)
|
||||
self._id = material_id
|
||||
|
||||
@name.setter
|
||||
def name(self, name):
|
||||
if name is not None:
|
||||
check_type('name for Material ID="{0}"'.format(self._id),
|
||||
name, basestring)
|
||||
cv.check_type('name for Material ID="{0}"'.format(self._id),
|
||||
name, basestring)
|
||||
self._name = name
|
||||
else:
|
||||
self._name = ''
|
||||
|
||||
def set_density(self, units, density=NO_DENSITY):
|
||||
def set_density(self, units, density=None):
|
||||
"""Set the density of the material
|
||||
|
||||
Parameters
|
||||
----------
|
||||
units : str
|
||||
Physical units of density
|
||||
units : {'g/cm3', 'g/cc', 'km/cm3', 'atom/b-cm', 'atom/cm3', 'sum', 'macro'}
|
||||
Physical units of density.
|
||||
density : float, optional
|
||||
Value of the density. Must be specified unless units is given as
|
||||
'sum'.
|
||||
|
||||
"""
|
||||
|
||||
check_type('the density for Material ID="{0}"'.format(self._id),
|
||||
density, Real)
|
||||
check_value('density units', units, DENSITY_UNITS)
|
||||
|
||||
if density == NO_DENSITY and units is not 'sum':
|
||||
msg = 'Unable to set the density Material ID="{0}" ' \
|
||||
'because a density must be set when not using ' \
|
||||
'sum unit'.format(self._id)
|
||||
raise ValueError(msg)
|
||||
|
||||
self._density = density
|
||||
cv.check_value('density units', units, DENSITY_UNITS)
|
||||
self._density_units = units
|
||||
|
||||
if units is 'sum':
|
||||
if density is not None:
|
||||
msg = 'Density "{0}" for Material ID="{1}" is ignored ' \
|
||||
'because the unit is "sum"'.format(density, self.id)
|
||||
warnings.warn(msg)
|
||||
else:
|
||||
if density is None:
|
||||
msg = 'Unable to set the density for Material ID="{0}" ' \
|
||||
'because a density value must be given when not using ' \
|
||||
'"sum" unit'.format(self.id)
|
||||
raise ValueError(msg)
|
||||
|
||||
cv.check_type('the density for Material ID="{0}"'.format(self.id),
|
||||
density, Real)
|
||||
self._density = density
|
||||
|
||||
@distrib_otf_file.setter
|
||||
def distrib_otf_file(self, filename):
|
||||
# TODO: remove this when distributed materials are merged
|
||||
|
|
@ -270,11 +290,11 @@ class Material(object):
|
|||
|
||||
Parameters
|
||||
----------
|
||||
nuclide : str or openmc.nuclide.Nuclide
|
||||
nuclide : str or openmc.Nuclide
|
||||
Nuclide to add
|
||||
percent : float
|
||||
Atom or weight percent
|
||||
percent_type : str
|
||||
percent_type : {'ao', 'wo'}
|
||||
'ao' for atom percent and 'wo' for weight percent
|
||||
|
||||
"""
|
||||
|
|
@ -284,7 +304,7 @@ class Material(object):
|
|||
'macroscopic data-set has already been added'.format(self._id)
|
||||
raise ValueError(msg)
|
||||
|
||||
if not isinstance(nuclide, (openmc.Nuclide, str)):
|
||||
if not isinstance(nuclide, (openmc.Nuclide, basestring)):
|
||||
msg = 'Unable to add a Nuclide to Material ID="{0}" with a ' \
|
||||
'non-Nuclide value "{1}"'.format(self._id, nuclide)
|
||||
raise ValueError(msg)
|
||||
|
|
@ -313,7 +333,7 @@ class Material(object):
|
|||
|
||||
Parameters
|
||||
----------
|
||||
nuclide : openmc.nuclide.Nuclide
|
||||
nuclide : openmc.Nuclide
|
||||
Nuclide to remove
|
||||
|
||||
"""
|
||||
|
|
@ -328,11 +348,13 @@ class Material(object):
|
|||
del self._nuclides[nuclide._name]
|
||||
|
||||
def add_macroscopic(self, macroscopic):
|
||||
"""Add a macroscopic to the material
|
||||
"""Add a macroscopic to the material. This will also set the
|
||||
density of the material to 1.0, unless it has been otherwise set,
|
||||
as a default for Macroscopic cross sections.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
macroscopic : str or Macroscopic
|
||||
macroscopic : str or openmc.Macroscopic
|
||||
Macroscopic to add
|
||||
|
||||
"""
|
||||
|
|
@ -366,12 +388,20 @@ class Material(object):
|
|||
'Material!'.format(self._id, macroscopic)
|
||||
raise ValueError(msg)
|
||||
|
||||
# Generally speaking, the density for a macroscopic object will
|
||||
# be 1.0. Therefore, lets set density to 1.0 so that the user
|
||||
# doesnt need to set it unless its needed.
|
||||
# Of course, if the user has already set a value of density,
|
||||
# then we will not override it.
|
||||
if self._density is None:
|
||||
self.set_density('macro', 1.0)
|
||||
|
||||
def remove_macroscopic(self, macroscopic):
|
||||
"""Remove a macroscopic from the material
|
||||
|
||||
Parameters
|
||||
----------
|
||||
macroscopic : Macroscopic
|
||||
macroscopic : openmc.Macroscopic
|
||||
Macroscopic to remove
|
||||
|
||||
"""
|
||||
|
|
@ -385,17 +415,21 @@ class Material(object):
|
|||
if macroscopic._name == self._macroscopic.name:
|
||||
self._macroscopic = None
|
||||
|
||||
def add_element(self, element, percent, percent_type='ao'):
|
||||
def add_element(self, element, percent, percent_type='ao', expand=False):
|
||||
"""Add a natural element to the material
|
||||
|
||||
Parameters
|
||||
----------
|
||||
element : openmc.element.Element
|
||||
element : openmc.Element or str
|
||||
Element to add
|
||||
percent : float
|
||||
Atom or weight percent
|
||||
percent_type : str
|
||||
'ao' for atom percent and 'wo' for weight percent
|
||||
percent_type : {'ao', 'wo'}, optional
|
||||
'ao' for atom percent and 'wo' for weight percent. Defaults to atom
|
||||
percent.
|
||||
expand : bool, optional
|
||||
Whether to expand the natural element into its naturally-occurring
|
||||
isotopes. Defaults to False.
|
||||
|
||||
"""
|
||||
|
||||
|
|
@ -404,7 +438,7 @@ class Material(object):
|
|||
'macroscopic data-set has already been added'.format(self._id)
|
||||
raise ValueError(msg)
|
||||
|
||||
if not isinstance(element, openmc.Element):
|
||||
if not isinstance(element, (openmc.Element, basestring)):
|
||||
msg = 'Unable to add an Element to Material ID="{0}" with a ' \
|
||||
'non-Element value "{1}"'.format(self._id, element)
|
||||
raise ValueError(msg)
|
||||
|
|
@ -420,16 +454,27 @@ class Material(object):
|
|||
raise ValueError(msg)
|
||||
|
||||
# Copy this Element to separate it from same Element in other Materials
|
||||
element = deepcopy(element)
|
||||
if isinstance(element, openmc.Element):
|
||||
element = deepcopy(element)
|
||||
else:
|
||||
element = openmc.Element(element)
|
||||
|
||||
self._elements[element._name] = (element, percent, percent_type)
|
||||
if expand:
|
||||
if percent_type == 'wo':
|
||||
raise NotImplementedError('Expanding natural element based on '
|
||||
'weight percent is not yet supported.')
|
||||
for isotope, abundance in element.expand():
|
||||
self._nuclides[isotope.name] = (
|
||||
isotope, percent*abundance, percent_type)
|
||||
else:
|
||||
self._elements[element.name] = (element, percent, percent_type)
|
||||
|
||||
def remove_element(self, element):
|
||||
"""Remove a natural element from the material
|
||||
|
||||
Parameters
|
||||
----------
|
||||
element : openmc.element.Element
|
||||
element : openmc.Element
|
||||
Element to remove
|
||||
|
||||
"""
|
||||
|
|
@ -471,7 +516,7 @@ class Material(object):
|
|||
for nuclide_name in self._nuclides:
|
||||
self._nuclides[nuclide_name][0].scattering = 'iso-in-lab'
|
||||
for element_name in self._elements:
|
||||
self._element[element_name][0].scattering = 'iso-in-lab'
|
||||
self._elements[element_name][0].scattering = 'iso-in-lab'
|
||||
|
||||
def get_all_nuclides(self):
|
||||
"""Returns all nuclides in the material
|
||||
|
|
@ -491,6 +536,14 @@ class Material(object):
|
|||
density = nuclide_tuple[1]
|
||||
nuclides[nuclide._name] = (nuclide, density)
|
||||
|
||||
for element_name, element_tuple in self._elements.items():
|
||||
element = element_tuple[0]
|
||||
density = element_tuple[1]
|
||||
|
||||
# Expand natural element into isotopes
|
||||
for isotope, abundance in element.expand():
|
||||
nuclides[isotope.name] = (isotope, density*abundance)
|
||||
|
||||
return nuclides
|
||||
|
||||
def _get_nuclide_xml(self, nuclide, distrib=False):
|
||||
|
|
@ -498,7 +551,7 @@ class Material(object):
|
|||
xml_element.set("name", nuclide[0]._name)
|
||||
|
||||
if not distrib:
|
||||
if nuclide[2] is 'ao':
|
||||
if nuclide[2] == 'ao':
|
||||
xml_element.set("ao", str(nuclide[1]))
|
||||
else:
|
||||
xml_element.set("wo", str(nuclide[1]))
|
||||
|
|
@ -525,11 +578,14 @@ class Material(object):
|
|||
xml_element.set("name", str(element[0]._name))
|
||||
|
||||
if not distrib:
|
||||
if element[2] is 'ao':
|
||||
if element[2] == 'ao':
|
||||
xml_element.set("ao", str(element[1]))
|
||||
else:
|
||||
xml_element.set("wo", str(element[1]))
|
||||
|
||||
if element[0].xs is not None:
|
||||
xml_element.set("xs", element[0].xs)
|
||||
|
||||
if not element[0].scattering is None:
|
||||
xml_element.set("scattering", element[0].scattering)
|
||||
|
||||
|
|
@ -639,9 +695,25 @@ class Material(object):
|
|||
return element
|
||||
|
||||
|
||||
class MaterialsFile(object):
|
||||
"""Materials file used for an OpenMC simulation. Corresponds directly to the
|
||||
materials.xml input file.
|
||||
class Materials(cv.CheckedList):
|
||||
"""Collection of Materials used for an OpenMC simulation.
|
||||
|
||||
This class corresponds directly to the materials.xml input file. It can be
|
||||
thought of as a normal Python list where each member is a
|
||||
:class:`Material`. It behaves like a list as the following example
|
||||
demonstrates:
|
||||
|
||||
>>> fuel = openmc.Material()
|
||||
>>> clad = openmc.Material()
|
||||
>>> water = openmc.Material()
|
||||
>>> m = openmc.Materials([fuel])
|
||||
>>> m.append(water)
|
||||
>>> m += [clad]
|
||||
|
||||
Parameters
|
||||
----------
|
||||
materials : Iterable of openmc.Material
|
||||
Materials to add to the collection
|
||||
|
||||
Attributes
|
||||
----------
|
||||
|
|
@ -651,11 +723,12 @@ class MaterialsFile(object):
|
|||
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
# Initialize MaterialsFile class attributes
|
||||
self._materials = []
|
||||
def __init__(self, materials=None):
|
||||
super(Materials, self).__init__(Material, 'materials collection')
|
||||
self._default_xs = None
|
||||
self._materials_file = ET.Element("materials")
|
||||
if materials is not None:
|
||||
self += materials
|
||||
|
||||
@property
|
||||
def default_xs(self):
|
||||
|
|
@ -663,72 +736,95 @@ class MaterialsFile(object):
|
|||
|
||||
@default_xs.setter
|
||||
def default_xs(self, xs):
|
||||
check_type('default xs', xs, basestring)
|
||||
cv.check_type('default xs', xs, basestring)
|
||||
self._default_xs = xs
|
||||
|
||||
def add_material(self, material):
|
||||
"""Add a material to the file.
|
||||
"""Append material to collection
|
||||
|
||||
.. deprecated:: 0.8
|
||||
Use :meth:`Materials.append` instead.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
material : Material
|
||||
material : openmc.Material
|
||||
Material to add
|
||||
|
||||
"""
|
||||
|
||||
if not isinstance(material, Material):
|
||||
msg = 'Unable to add a non-Material "{0}" to the ' \
|
||||
'MaterialsFile'.format(material)
|
||||
raise ValueError(msg)
|
||||
|
||||
self._materials.append(material)
|
||||
warnings.warn("Materials.add_material(...) has been deprecated and may be "
|
||||
"removed in a future version. Use Material.append(...) "
|
||||
"instead.", DeprecationWarning)
|
||||
self.append(material)
|
||||
|
||||
def add_materials(self, materials):
|
||||
"""Add multiple materials to the file.
|
||||
"""Add multiple materials to the collection
|
||||
|
||||
.. deprecated:: 0.8
|
||||
Use compound assignment instead.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
materials : tuple or list of Material
|
||||
materials : Iterable of openmc.Material
|
||||
Materials to add
|
||||
|
||||
"""
|
||||
|
||||
if not isinstance(materials, Iterable):
|
||||
msg = 'Unable to create OpenMC materials.xml file from "{0}" which ' \
|
||||
'is not iterable'.format(materials)
|
||||
raise ValueError(msg)
|
||||
|
||||
warnings.warn("Materials.add_materials(...) has been deprecated and may be "
|
||||
"removed in a future version. Use compound assignment "
|
||||
"instead.", DeprecationWarning)
|
||||
for material in materials:
|
||||
self.add_material(material)
|
||||
self.append(material)
|
||||
|
||||
def append(self, material):
|
||||
"""Append material to collection
|
||||
|
||||
Parameters
|
||||
----------
|
||||
material : openmc.Material
|
||||
Material to append
|
||||
|
||||
"""
|
||||
super(Materials, self).append(material)
|
||||
|
||||
def insert(self, index, material):
|
||||
"""Insert material before index
|
||||
|
||||
Parameters
|
||||
----------
|
||||
index : int
|
||||
Index in list
|
||||
material : openmc.Material
|
||||
Material to insert
|
||||
|
||||
"""
|
||||
super(Materials, self).insert(index, material)
|
||||
|
||||
def remove_material(self, material):
|
||||
"""Remove a material from the file
|
||||
|
||||
.. deprecated:: 0.8
|
||||
Use :meth:`Materials.remove` instead.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
material : Material
|
||||
material : openmc.Material
|
||||
Material to remove
|
||||
|
||||
"""
|
||||
|
||||
if not isinstance(material, Material):
|
||||
msg = 'Unable to remove a non-Material "{0}" from the ' \
|
||||
'MaterialsFile'.format(material)
|
||||
raise ValueError(msg)
|
||||
|
||||
self._materials.remove(material)
|
||||
warnings.warn("Materials.remove_material(...) has been deprecated and "
|
||||
"may be removed in a future version. Use "
|
||||
"Materials.remove(...) instead.", DeprecationWarning)
|
||||
self.remove(material)
|
||||
|
||||
def make_isotropic_in_lab(self):
|
||||
for material in self._materials:
|
||||
for material in self:
|
||||
material.make_isotropic_in_lab()
|
||||
|
||||
def _create_material_subelements(self):
|
||||
subelement = ET.SubElement(self._materials_file, "default_xs")
|
||||
|
||||
if self._default_xs is not None:
|
||||
subelement = ET.SubElement(self._materials_file, "default_xs")
|
||||
subelement.text = self._default_xs
|
||||
|
||||
for material in self._materials:
|
||||
for material in self:
|
||||
xml_element = material.get_material_xml()
|
||||
self._materials_file.append(xml_element)
|
||||
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ class EnergyGroups(object):
|
|||
----------
|
||||
group_edges : Iterable of Real
|
||||
The energy group boundaries [MeV]
|
||||
num_groups : Integral
|
||||
num_groups : int
|
||||
The number of energy groups
|
||||
|
||||
"""
|
||||
|
|
@ -86,7 +86,7 @@ class EnergyGroups(object):
|
|||
|
||||
Parameters
|
||||
----------
|
||||
energy : Real
|
||||
energy : float
|
||||
The energy of interest in MeV
|
||||
|
||||
Returns
|
||||
|
|
@ -115,7 +115,7 @@ class EnergyGroups(object):
|
|||
|
||||
Parameters
|
||||
----------
|
||||
group : Integral
|
||||
group : int
|
||||
The energy group index, starting at 1 for the highest energies
|
||||
|
||||
Returns
|
||||
|
|
@ -153,7 +153,7 @@ class EnergyGroups(object):
|
|||
|
||||
Returns
|
||||
-------
|
||||
ndarray
|
||||
numpy.ndarray
|
||||
The ndarray array indices for each energy group of interest
|
||||
|
||||
Raises
|
||||
|
|
@ -200,7 +200,7 @@ class EnergyGroups(object):
|
|||
|
||||
Returns
|
||||
-------
|
||||
EnergyGroups
|
||||
openmc.mgxs.EnergyGroups
|
||||
A coarsened version of this EnergyGroups object.
|
||||
|
||||
Raises
|
||||
|
|
@ -244,7 +244,7 @@ class EnergyGroups(object):
|
|||
|
||||
Parameters
|
||||
----------
|
||||
other : EnergyGroups
|
||||
other : openmc.mgxs.EnergyGroups
|
||||
EnergyGroups to compare with
|
||||
|
||||
Returns
|
||||
|
|
@ -275,12 +275,12 @@ class EnergyGroups(object):
|
|||
|
||||
Parameters
|
||||
----------
|
||||
other : EnergyGroups
|
||||
other : openmc.mgxs.EnergyGroups
|
||||
EnergyGroups to merge with
|
||||
|
||||
Returns
|
||||
-------
|
||||
merged_groups : EnergyGroups
|
||||
merged_groups : openmc.mgxs.EnergyGroups
|
||||
EnergyGroups resulting from the merge
|
||||
|
||||
"""
|
||||
|
|
|
|||
|
|
@ -2,8 +2,12 @@ import sys
|
|||
import os
|
||||
import copy
|
||||
import pickle
|
||||
import warnings
|
||||
from numbers import Integral
|
||||
from collections import OrderedDict
|
||||
from warnings import warn
|
||||
|
||||
import numpy as np
|
||||
|
||||
import openmc
|
||||
import openmc.mgxs
|
||||
|
|
@ -30,7 +34,7 @@ class Library(object):
|
|||
Parameters
|
||||
----------
|
||||
openmc_geometry : openmc.Geometry
|
||||
An geometry which has been initialized with a root universe
|
||||
A geometry which has been initialized with a root universe
|
||||
by_nuclide : bool
|
||||
If true, computes cross sections for each nuclide in each domain
|
||||
mgxs_types : Iterable of str
|
||||
|
|
@ -53,22 +57,24 @@ class Library(object):
|
|||
The types of cross sections in the library (e.g., ['total', 'scatter'])
|
||||
domain_type : {'material', 'cell', 'distribcell', 'universe'}
|
||||
Domain type for spatial homogenization
|
||||
domains : Iterable of Material, Cell or Universe
|
||||
domains : Iterable of openmc.Material, openmc.Cell or openmc.Universe
|
||||
The spatial domain(s) for which MGXS in the Library are computed
|
||||
correction : 'P0' or None
|
||||
correction : {'P0', None}
|
||||
Apply the P0 correction to scattering matrices if set to 'P0'
|
||||
energy_groups : EnergyGroups
|
||||
legendre_order : int
|
||||
The highest legendre moment in the scattering matrices (default is 0)
|
||||
energy_groups : openmc.mgxs.EnergyGroups
|
||||
Energy group structure for energy condensation
|
||||
tally_trigger : Trigger
|
||||
tally_trigger : openmc.Trigger
|
||||
An (optional) tally precision trigger given to each tally used to
|
||||
compute the cross section
|
||||
all_mgxs : OrderedDict
|
||||
all_mgxs : collections.OrderedDict
|
||||
MGXS objects keyed by domain ID and cross section type
|
||||
sp_filename : str
|
||||
The filename of the statepoint with tally data used to the
|
||||
compute cross sections
|
||||
keff : Real or None
|
||||
The combined keff from the statepoint file with tally data used to
|
||||
The combined keff from the statepoint file with tally data used to
|
||||
compute cross sections (for eigenvalue calculations only)
|
||||
name : str, optional
|
||||
Name of the multi-group cross section library. Used as a label to
|
||||
|
|
@ -89,8 +95,9 @@ class Library(object):
|
|||
self._mgxs_types = []
|
||||
self._domain_type = None
|
||||
self._domains = 'all'
|
||||
self._correction = 'P0'
|
||||
self._energy_groups = None
|
||||
self._correction = 'P0'
|
||||
self._legendre_order = 0
|
||||
self._tally_trigger = None
|
||||
self._all_mgxs = OrderedDict()
|
||||
self._sp_filename = None
|
||||
|
|
@ -118,6 +125,7 @@ class Library(object):
|
|||
clone._domain_type = self.domain_type
|
||||
clone._domains = copy.deepcopy(self.domains)
|
||||
clone._correction = self.correction
|
||||
clone._legendre_order = self.legendre_order
|
||||
clone._energy_groups = copy.deepcopy(self.energy_groups, memo)
|
||||
clone._tally_trigger = copy.deepcopy(self.tally_trigger, memo)
|
||||
clone._all_mgxs = copy.deepcopy(self.all_mgxs)
|
||||
|
|
@ -185,13 +193,17 @@ class Library(object):
|
|||
else:
|
||||
return self._domains
|
||||
|
||||
@property
|
||||
def energy_groups(self):
|
||||
return self._energy_groups
|
||||
|
||||
@property
|
||||
def correction(self):
|
||||
return self._correction
|
||||
|
||||
@property
|
||||
def energy_groups(self):
|
||||
return self._energy_groups
|
||||
def legendre_order(self):
|
||||
return self._legendre_order
|
||||
|
||||
@property
|
||||
def tally_trigger(self):
|
||||
|
|
@ -245,7 +257,7 @@ class Library(object):
|
|||
|
||||
@domain_type.setter
|
||||
def domain_type(self, domain_type):
|
||||
cv.check_value('domain type', domain_type, tuple(openmc.mgxs.DOMAIN_TYPES))
|
||||
cv.check_value('domain type', domain_type, openmc.mgxs.DOMAIN_TYPES)
|
||||
self._domain_type = domain_type
|
||||
|
||||
@domains.setter
|
||||
|
|
@ -280,16 +292,36 @@ class Library(object):
|
|||
|
||||
self._domains = domains
|
||||
|
||||
@correction.setter
|
||||
def correction(self, correction):
|
||||
cv.check_value('correction', correction, ('P0', None))
|
||||
self._correction = correction
|
||||
|
||||
@energy_groups.setter
|
||||
def energy_groups(self, energy_groups):
|
||||
cv.check_type('energy groups', energy_groups, openmc.mgxs.EnergyGroups)
|
||||
self._energy_groups = energy_groups
|
||||
|
||||
@correction.setter
|
||||
def correction(self, correction):
|
||||
cv.check_value('correction', correction, ('P0', None))
|
||||
|
||||
if correction == 'P0' and self.legendre_order > 0:
|
||||
msg = 'The P0 correction will be ignored since the scattering ' \
|
||||
'order {} is greater than zero'.format(self.legendre_order)
|
||||
warnings.warn(msg)
|
||||
|
||||
self._correction = correction
|
||||
|
||||
@legendre_order.setter
|
||||
def legendre_order(self, legendre_order):
|
||||
cv.check_type('legendre_order', legendre_order, Integral)
|
||||
cv.check_greater_than('legendre_order', legendre_order, 0, equality=True)
|
||||
cv.check_less_than('legendre_order', legendre_order, 10, equality=True)
|
||||
|
||||
if self.correction == 'P0' and legendre_order > 0:
|
||||
msg = 'The P0 correction will be ignored since the scattering ' \
|
||||
'order {} is greater than zero'.format(self.legendre_order)
|
||||
warnings.warn(msg, RuntimeWarning)
|
||||
self.correction = None
|
||||
|
||||
self._legendre_order = legendre_order
|
||||
|
||||
@tally_trigger.setter
|
||||
def tally_trigger(self, tally_trigger):
|
||||
cv.check_type('tally trigger', tally_trigger, openmc.Trigger)
|
||||
|
|
@ -308,7 +340,7 @@ class Library(object):
|
|||
"""
|
||||
|
||||
cv.check_type('sparse', sparse, bool)
|
||||
|
||||
|
||||
# Sparsify or densify each MGXS in the Library
|
||||
for domain in self.domains:
|
||||
for mgxs_type in self.mgxs_types:
|
||||
|
|
@ -344,33 +376,34 @@ class Library(object):
|
|||
# Specify whether to use a transport ('P0') correction
|
||||
if isinstance(mgxs, openmc.mgxs.ScatterMatrixXS):
|
||||
mgxs.correction = self.correction
|
||||
mgxs.legendre_order = self.legendre_order
|
||||
|
||||
self.all_mgxs[domain.id][mgxs_type] = mgxs
|
||||
|
||||
def add_to_tallies_file(self, tallies_file, merge=True):
|
||||
"""Add all tallies from all MGXS objects to a tallies file.
|
||||
|
||||
NOTE: This assumes that build_library() has been called
|
||||
NOTE: This assumes that :meth:`Library.build_library` has been called
|
||||
|
||||
Parameters
|
||||
----------
|
||||
tallies_file : openmc.TalliesFile
|
||||
A TalliesFile object to add each MGXS' tallies to generate a
|
||||
"tallies.xml" input file for OpenMC
|
||||
tallies_file : openmc.Tallies
|
||||
A Tallies collection to add each MGXS' tallies to generate a
|
||||
'tallies.xml' input file for OpenMC
|
||||
merge : bool
|
||||
Indicate whether tallies should be merged when possible. Defaults
|
||||
to True.
|
||||
|
||||
"""
|
||||
|
||||
cv.check_type('tallies_file', tallies_file, openmc.TalliesFile)
|
||||
cv.check_type('tallies_file', tallies_file, openmc.Tallies)
|
||||
|
||||
# Add tallies from each MGXS for each domain and mgxs type
|
||||
for domain in self.domains:
|
||||
for mgxs_type in self.mgxs_types:
|
||||
mgxs = self.get_mgxs(domain, mgxs_type)
|
||||
for tally_id, tally in mgxs.tallies.items():
|
||||
tallies_file.add_tally(tally, merge=merge)
|
||||
tallies_file.append(tally, merge=merge)
|
||||
|
||||
def load_from_statepoint(self, statepoint):
|
||||
"""Extracts tallies in an OpenMC StatePoint with the data needed to
|
||||
|
|
@ -403,6 +436,7 @@ class Library(object):
|
|||
|
||||
self._sp_filename = statepoint._f.filename
|
||||
self._openmc_geometry = statepoint.summary.openmc_geometry
|
||||
self._nuclides = statepoint.summary.nuclides
|
||||
|
||||
if statepoint.run_mode == 'k-eigenvalue':
|
||||
self._keff = statepoint.k_combined[0]
|
||||
|
|
@ -426,7 +460,7 @@ class Library(object):
|
|||
----------
|
||||
domain : Material or Cell or Universe or Integral
|
||||
The material, cell, or universe object of interest (or its ID)
|
||||
mgxs_type : {'total', 'transport', 'absorption', 'capture', 'fission', 'nu-fission', 'scatter', 'nu-scatter', 'scatter matrix', 'nu-scatter matrix', 'chi'}
|
||||
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'}
|
||||
The type of multi-group cross section object to return
|
||||
|
||||
Returns
|
||||
|
|
@ -450,14 +484,14 @@ class Library(object):
|
|||
cv.check_type('domain', domain, (openmc.Universe, Integral))
|
||||
|
||||
# Check that requested domain is included in library
|
||||
if cv._isinstance(domain, Integral):
|
||||
if isinstance(domain, Integral):
|
||||
domain_id = domain
|
||||
for domain in self.domains:
|
||||
if domain_id == domain.id:
|
||||
break
|
||||
else:
|
||||
msg = 'Unable to find MGXS for {0} "{1}" in ' \
|
||||
'library'.format(self.domain_type, domain)
|
||||
msg = 'Unable to find MGXS for "{0}" "{1}" in ' \
|
||||
'library'.format(self.domain_type, domain_id)
|
||||
raise ValueError(msg)
|
||||
else:
|
||||
domain_id = domain.id
|
||||
|
|
@ -537,7 +571,7 @@ class Library(object):
|
|||
|
||||
Returns
|
||||
-------
|
||||
Library
|
||||
openmc.mgxs.Library
|
||||
A new multi-group cross section library averaged across subdomains
|
||||
|
||||
Raises
|
||||
|
|
@ -575,7 +609,8 @@ class Library(object):
|
|||
return subdomain_avg_library
|
||||
|
||||
def build_hdf5_store(self, filename='mgxs.h5', directory='mgxs',
|
||||
subdomains='all', nuclides='all', xs_type='macro'):
|
||||
subdomains='all', nuclides='all', xs_type='macro',
|
||||
row_column='inout'):
|
||||
"""Export the multi-group cross section library to an HDF5 binary file.
|
||||
|
||||
This method constructs an HDF5 file which stores the library's
|
||||
|
|
@ -605,6 +640,10 @@ class Library(object):
|
|||
xs_type: {'macro', 'micro'}
|
||||
Store the macro or micro cross section in units of cm^-1 or barns.
|
||||
Defaults to 'macro'.
|
||||
row_column: {'inout', 'outin'}
|
||||
Store scattering matrices indexed first by incoming group and
|
||||
second by outgoing group ('inout'), or vice versa ('outin').
|
||||
Defaults to 'inout'.
|
||||
|
||||
Raises
|
||||
------
|
||||
|
|
@ -635,7 +674,7 @@ class Library(object):
|
|||
full_filename = os.path.join(directory, filename)
|
||||
full_filename = full_filename.replace(' ', '-')
|
||||
f = h5py.File(full_filename, 'w')
|
||||
f.attrs["# groups"] = self.num_groups
|
||||
f.attrs['# groups'] = self.num_groups
|
||||
f.close()
|
||||
|
||||
# Export MGXS for each domain and mgxs type to an HDF5 file
|
||||
|
|
@ -646,8 +685,8 @@ class Library(object):
|
|||
if subdomains == 'avg':
|
||||
mgxs = mgxs.get_subdomain_avg_xs()
|
||||
|
||||
mgxs.build_hdf5_store(filename, directory,
|
||||
xs_type=xs_type, nuclides=nuclides)
|
||||
mgxs.build_hdf5_store(filename, directory, xs_type=xs_type,
|
||||
nuclides=nuclides, row_column=row_column)
|
||||
|
||||
def dump_to_file(self, filename='mgxs', directory='mgxs'):
|
||||
"""Store this Library object in a pickle binary file.
|
||||
|
|
@ -712,3 +751,419 @@ class Library(object):
|
|||
|
||||
# Load and return pickled Library object
|
||||
return pickle.load(open(full_filename, 'rb'))
|
||||
|
||||
def get_xsdata(self, domain, xsdata_name, nuclide='total', xs_type='macro',
|
||||
xs_id='1m', order=None):
|
||||
"""Generates an openmc.XSdata object describing a multi-group cross section
|
||||
data set for eventual combination in to an openmc.MGXSLibrary object
|
||||
(i.e., the library).
|
||||
|
||||
Parameters
|
||||
----------
|
||||
domain : openmc.Material or openmc.Cell or openmc.Universe
|
||||
The domain for spatial homogenization
|
||||
xsdata_name : str
|
||||
Name to apply to the "xsdata" entry produced by this method
|
||||
nuclide : str
|
||||
A nuclide name string (e.g., 'U-235'). Defaults to 'total' to
|
||||
obtain a material-wise macroscopic cross section.
|
||||
xs_type: {'macro', 'micro'}
|
||||
Provide the macro or micro cross section in units of cm^-1 or
|
||||
barns. Defaults to 'macro'. If the Library object is not tallied by
|
||||
nuclide this will be set to 'macro' regardless.
|
||||
xs_ids : str
|
||||
Cross section set identifier. Defaults to '1m'.
|
||||
order : Scattering order for this data entry. Default is None,
|
||||
which will set the XSdata object to use the order of the
|
||||
Library.
|
||||
|
||||
Returns
|
||||
-------
|
||||
xsdata : openmc.XSdata
|
||||
Multi-Group Cross Section data set object.
|
||||
|
||||
Raises
|
||||
------
|
||||
ValueError
|
||||
When the Library object is initialized with insufficient types of
|
||||
cross sections for the Library.
|
||||
|
||||
See also
|
||||
--------
|
||||
Library.create_mg_library()
|
||||
|
||||
"""
|
||||
|
||||
cv.check_type('domain', domain, (openmc.Material, openmc.Cell,
|
||||
openmc.Cell))
|
||||
cv.check_type('xsdata_name', xsdata_name, basestring)
|
||||
cv.check_type('nuclide', nuclide, basestring)
|
||||
cv.check_value('xs_type', xs_type, ['macro', 'micro'])
|
||||
cv.check_type('xs_id', xs_id, basestring)
|
||||
cv.check_type('order', order, (type(None), Integral))
|
||||
if order is not None:
|
||||
cv.check_greater_than('order', order, 0, equality=True)
|
||||
cv.check_less_than('order', order, 10, equality=True)
|
||||
|
||||
# Make sure statepoint has been loaded
|
||||
if self._sp_filename is None:
|
||||
msg = 'A StatePoint must be loaded before calling ' \
|
||||
'the create_mg_library() function'
|
||||
raise ValueError(msg)
|
||||
|
||||
# If gathering material-specific data, set the xs_type to macro
|
||||
if not self.by_nuclide:
|
||||
xs_type = 'macro'
|
||||
|
||||
# Build & add metadata to XSdata object
|
||||
name = xsdata_name
|
||||
if nuclide is not 'total':
|
||||
name += '_' + nuclide
|
||||
name += '.' + xs_id
|
||||
xsdata = openmc.XSdata(name, self.energy_groups)
|
||||
|
||||
if order is None:
|
||||
# Set the order to the Library's order (the defualt behavior)
|
||||
xsdata.order = self.legendre_order
|
||||
else:
|
||||
# Set the order of the xsdata object to the minimum of
|
||||
# the provided order or the Library's order.
|
||||
xsdata.order = min(order, self.legendre_order)
|
||||
|
||||
if nuclide is not 'total':
|
||||
xsdata.zaid = self._nuclides[nuclide][0]
|
||||
xsdata.awr = self._nuclides[nuclide][1]
|
||||
|
||||
# Now get xs data itself
|
||||
if 'nu-transport' in self.mgxs_types and self.correction == 'P0':
|
||||
mymgxs = self.get_mgxs(domain, 'nu-transport')
|
||||
xsdata.set_total_mgxs(mymgxs, xs_type=xs_type, nuclide=[nuclide])
|
||||
elif 'total' in self.mgxs_types:
|
||||
mymgxs = self.get_mgxs(domain, 'total')
|
||||
xsdata.set_total_mgxs(mymgxs, xs_type=xs_type, nuclide=[nuclide])
|
||||
if 'absorption' in self.mgxs_types:
|
||||
mymgxs = self.get_mgxs(domain, 'absorption')
|
||||
xsdata.set_absorption_mgxs(mymgxs, xs_type=xs_type,
|
||||
nuclide=[nuclide])
|
||||
if 'fission' in self.mgxs_types:
|
||||
mymgxs = self.get_mgxs(domain, 'fission')
|
||||
xsdata.set_fission_mgxs(mymgxs, xs_type=xs_type,
|
||||
nuclide=[nuclide])
|
||||
if 'kappa-fission' in self.mgxs_types:
|
||||
mymgxs = self.get_mgxs(domain, 'kappa-fission')
|
||||
xsdata.set_kappa_fission_mgxs(mymgxs, xs_type=xs_type,
|
||||
nuclide=[nuclide])
|
||||
# For chi and nu-fission we can either have only a nu-fission matrix
|
||||
# provided, or vectors of chi and nu-fission provided
|
||||
if 'nu-fission matrix' in self.mgxs_types:
|
||||
mymgxs = self.get_mgxs(domain, 'nu-fission matrix')
|
||||
xsdata.set_nu_fission_mgxs(mymgxs, xs_type=xs_type,
|
||||
nuclide=[nuclide])
|
||||
else:
|
||||
if 'chi' in self.mgxs_types:
|
||||
mymgxs = self.get_mgxs(domain, 'chi')
|
||||
xsdata.set_chi_mgxs(mymgxs, xs_type=xs_type, nuclide=[nuclide])
|
||||
if 'nu-fission' in self.mgxs_types:
|
||||
mymgxs = self.get_mgxs(domain, 'nu-fission')
|
||||
xsdata.set_nu_fission_mgxs(mymgxs, xs_type=xs_type,
|
||||
nuclide=[nuclide])
|
||||
# If multiplicity matrix is available, prefer that
|
||||
if 'multiplicity matrix' in self.mgxs_types:
|
||||
mymgxs = self.get_mgxs(domain, 'multiplicity matrix')
|
||||
xsdata.set_multiplicity_mgxs(mymgxs, xs_type=xs_type,
|
||||
nuclide=[nuclide])
|
||||
using_multiplicity = True
|
||||
# multiplicity wil fall back to using scatter and nu-scatter
|
||||
elif ((('scatter matrix' in self.mgxs_types) and
|
||||
('nu-scatter matrix' in self.mgxs_types))):
|
||||
scatt_mgxs = self.get_mgxs(domain, 'scatter matrix')
|
||||
nuscatt_mgxs = self.get_mgxs(domain, 'nu-scatter matrix')
|
||||
xsdata.set_multiplicity_mgxs(nuscatt_mgxs, scatt_mgxs,
|
||||
xs_type=xs_type, nuclide=[nuclide])
|
||||
using_multiplicity = True
|
||||
else:
|
||||
using_multiplicity = False
|
||||
|
||||
if using_multiplicity:
|
||||
nuscatt_mgxs = self.get_mgxs(domain, 'nu-scatter matrix')
|
||||
xsdata.set_scatter_mgxs(nuscatt_mgxs, xs_type=xs_type,
|
||||
nuclide=[nuclide])
|
||||
else:
|
||||
if 'nu-scatter matrix' in self.mgxs_types:
|
||||
nuscatt_mgxs = self.get_mgxs(domain, 'nu-scatter matrix')
|
||||
xsdata.set_scatter_mgxs(nuscatt_mgxs, xs_type=xs_type,
|
||||
nuclide=[nuclide])
|
||||
|
||||
# Since we are not using multiplicity, then
|
||||
# scattering multiplication (nu-scatter) must be
|
||||
# accounted for approximately by using an adjusted
|
||||
# absorption cross section.
|
||||
if 'total' in self.mgxs_types:
|
||||
xsdata._absorption = \
|
||||
np.subtract(xsdata.total,
|
||||
np.sum(xsdata.scatter[0, :, :], axis=1))
|
||||
|
||||
return xsdata
|
||||
|
||||
def create_mg_library(self, xs_type='macro', xsdata_names=None,
|
||||
xs_ids=None):
|
||||
"""Creates an openmc.MGXSLibrary object to contain the MGXS data for the
|
||||
Multi-Group mode of OpenMC.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
xs_type: {'macro', 'micro'}
|
||||
Provide the macro or micro cross section in units of cm^-1 or
|
||||
barns. Defaults to 'macro'. If the Library object is not tallied by
|
||||
nuclide this will be set to 'macro' regardless.
|
||||
xsdata_names : Iterable of str
|
||||
List of names to apply to the "xsdata" entries in the
|
||||
resultant mgxs data file. Defaults to 'set1', 'set2', ...
|
||||
xs_ids : str or Iterable of str
|
||||
Cross section set identifier (i.e., '71c') for all
|
||||
data sets (if only str) or for each individual one
|
||||
(if iterable of str). Defaults to '1m'.
|
||||
|
||||
Returns
|
||||
-------
|
||||
mgxs_file : openmc.MGXSLibrary
|
||||
Multi-Group Cross Section File that is ready to be printed to the
|
||||
file of choice by the user.
|
||||
|
||||
Raises
|
||||
------
|
||||
ValueError
|
||||
When the Library object is initialized with insufficient types of
|
||||
cross sections for the Library.
|
||||
|
||||
See also
|
||||
--------
|
||||
Library.dump_to_file()
|
||||
Library.create_mg_mode()
|
||||
|
||||
"""
|
||||
|
||||
# Check to ensure the Library contains the correct
|
||||
# multi-group cross section types
|
||||
self.check_library_for_openmc_mgxs()
|
||||
|
||||
cv.check_value('xs_type', xs_type, ['macro', 'micro'])
|
||||
if xsdata_names is not None:
|
||||
cv.check_iterable_type('xsdata_names', xsdata_names, basestring)
|
||||
if xs_ids is not None:
|
||||
if isinstance(xs_ids, basestring):
|
||||
# If we only have a string lets convert it now to a list
|
||||
# of strings.
|
||||
xs_ids = [xs_ids for i in range(len(self.domains))]
|
||||
else:
|
||||
cv.check_iterable_type('xs_ids', xs_ids, basestring)
|
||||
else:
|
||||
xs_ids = ['1m' for i in range(len(self.domains))]
|
||||
|
||||
# If gathering material-specific data, set the xs_type to macro
|
||||
if not self.by_nuclide:
|
||||
xs_type = 'macro'
|
||||
|
||||
# Initialize file
|
||||
mgxs_file = openmc.MGXSLibrary(self.energy_groups)
|
||||
|
||||
# Create the xsdata object and add it to the mgxs_file
|
||||
for i, domain in enumerate(self.domains):
|
||||
if self.by_nuclide:
|
||||
nuclides = list(domain.get_all_nuclides().keys())
|
||||
else:
|
||||
nuclides = ['total']
|
||||
for nuclide in nuclides:
|
||||
# Build & add metadata to XSdata object
|
||||
if xsdata_names is None:
|
||||
xsdata_name = 'set' + str(i + 1)
|
||||
else:
|
||||
xsdata_name = xsdata_names[i]
|
||||
if nuclide is not 'total':
|
||||
xsdata_name += '_' + nuclide
|
||||
|
||||
xsdata = self.get_xsdata(domain, xsdata_name, nuclide=nuclide,
|
||||
xs_type=xs_type, xs_id=xs_ids[i])
|
||||
|
||||
mgxs_file.add_xsdata(xsdata)
|
||||
|
||||
return mgxs_file
|
||||
|
||||
def create_mg_mode(self, xsdata_names=None, xs_ids=None):
|
||||
"""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. The created Geometry is the same as that
|
||||
used to generate the MGXS data, with the only differences being
|
||||
modifications to point to newly-created Materials which point to the
|
||||
multi-group data. This method only creates a macroscopic
|
||||
MGXS Library even if nuclidic tallies are specified in the Library.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
xsdata_names : Iterable of str
|
||||
List of names to apply to the "xsdata" entries in the
|
||||
resultant mgxs data file. Defaults to 'set1', 'set2', ...
|
||||
xs_ids : str or Iterable of str
|
||||
Cross section set identifier (i.e., '71c') for all
|
||||
data sets (if only str) or for each individual one
|
||||
(if iterable of str). Defaults to '1m'.
|
||||
|
||||
Returns
|
||||
-------
|
||||
mgxs_file : openmc.MGXSLibrary
|
||||
Multi-Group Cross Section File that is ready to be printed to the
|
||||
file of choice by the user.
|
||||
materials : openmc.Materials
|
||||
Materials file ready to be printed with all the macroscopic data
|
||||
present within this Library.
|
||||
geometry : openmc.Geometry
|
||||
Materials file ready to be printed with all the macroscopic data
|
||||
present within this Library.
|
||||
|
||||
Raises
|
||||
------
|
||||
ValueError
|
||||
When the Library object is initialized with insufficient types of
|
||||
cross sections for the Library.
|
||||
|
||||
See also
|
||||
--------
|
||||
Library.create_mg_library()
|
||||
Library.dump_to_file()
|
||||
|
||||
"""
|
||||
|
||||
# Check to ensure the Library contains the correct
|
||||
# multi-group cross section types
|
||||
self.check_library_for_openmc_mgxs()
|
||||
|
||||
if xsdata_names is not None:
|
||||
cv.check_iterable_type('xsdata_names', xsdata_names, basestring)
|
||||
if xs_ids is not None:
|
||||
if isinstance(xs_ids, basestring):
|
||||
# If we only have a string lets convert it now to a list
|
||||
# of strings.
|
||||
xs_ids = [xs_ids for i in range(len(self.domains))]
|
||||
else:
|
||||
cv.check_iterable_type('xs_ids', xs_ids, basestring)
|
||||
else:
|
||||
xs_ids = ['1m' for i in range(len(self.domains))]
|
||||
xs_type = 'macro'
|
||||
|
||||
# Initialize MGXS File
|
||||
mgxs_file = openmc.MGXSLibrary(self.energy_groups)
|
||||
|
||||
# Create a copy of the Geometry to differentiate for these Macroscopics
|
||||
geometry = copy.deepcopy(self.openmc_geometry)
|
||||
materials = openmc.Materials()
|
||||
|
||||
# Get all Cells from the Geometry for differentiation
|
||||
all_cells = geometry.get_all_material_cells()
|
||||
|
||||
# Create the xsdata object and add it to the mgxs_file
|
||||
for i, domain in enumerate(self.domains):
|
||||
|
||||
# Build & add metadata to XSdata object
|
||||
if xsdata_names is None:
|
||||
xsdata_name = 'set' + str(i + 1)
|
||||
else:
|
||||
xsdata_name = xsdata_names[i]
|
||||
|
||||
# Create XSdata and Macroscopic for this domain
|
||||
xsdata = self.get_xsdata(domain, xsdata_name, nuclide='total',
|
||||
xs_type=xs_type, xs_id=xs_ids[i])
|
||||
mgxs_file.add_xsdata(xsdata)
|
||||
macroscopic = openmc.Macroscopic(name=xsdata_name, xs=xs_ids[i])
|
||||
|
||||
# Create Material and add to collection
|
||||
material = openmc.Material(name=xsdata_name + '.' + xs_ids[i])
|
||||
material.add_macroscopic(macroscopic)
|
||||
materials.append(material)
|
||||
|
||||
# Differentiate Geometry with new Material
|
||||
if self.domain_type == 'material':
|
||||
# Fill all appropriate Cells with new Material
|
||||
for cell in all_cells:
|
||||
if cell.fill.id == domain.id:
|
||||
cell.fill = material
|
||||
|
||||
elif self.domain_type == 'cell':
|
||||
for cell in all_cells:
|
||||
if cell.id == domain.id:
|
||||
cell.fill = material
|
||||
|
||||
return mgxs_file, materials, geometry
|
||||
|
||||
def check_library_for_openmc_mgxs(self):
|
||||
"""This routine will check the MGXS Types within a Library
|
||||
to ensure the MGXS types provided can be used to create
|
||||
a MGXS Library for OpenMC's Multi-Group mode.
|
||||
|
||||
The rules to check include:
|
||||
|
||||
- Either total or transport should be present.
|
||||
|
||||
- Both can be available if one wants, but we should
|
||||
use whatever corresponds to Library.correction (if P0: transport)
|
||||
|
||||
- Absorption and total (or transport) are required.
|
||||
- A nu-fission cross section and chi values are not required as a
|
||||
fixed source problem could be the target.
|
||||
- Fission and kappa-fission are not required as they are only
|
||||
needed to support tallies the user may wish to request.
|
||||
- A nu-scatter matrix is required.
|
||||
|
||||
- Having a multiplicity matrix is preferred.
|
||||
- Having both nu-scatter (of any order) and scatter
|
||||
(at least isotropic) matrices is the second choice.
|
||||
- If only nu-scatter, need total (not transport), to
|
||||
be used in adjusting absorption
|
||||
(i.e., reduced_abs = tot - nuscatt)
|
||||
|
||||
See also
|
||||
--------
|
||||
Library.create_mg_library()
|
||||
Library.create_mg_mode()
|
||||
|
||||
"""
|
||||
|
||||
error_flag = False
|
||||
# Ensure absorption is present
|
||||
if 'absorption' not in self.mgxs_types:
|
||||
error_flag = True
|
||||
msg = '"absorption" MGXS type is required but not provided.'
|
||||
warn(msg)
|
||||
# Ensure nu-scattering matrix is required
|
||||
if 'nu-scatter matrix' not in self.mgxs_types:
|
||||
error_flag = True
|
||||
msg = '"nu-scatter matrix" MGXS type is required but not provided.'
|
||||
warn(msg)
|
||||
else:
|
||||
# Ok, now see the status of scatter and/or multiplicity
|
||||
if ((('scatter matrix' not in self.mgxs_types) and
|
||||
('multiplicity matrix' not in self.mgxs_types))):
|
||||
# We dont have data needed for multiplicity matrix, therefore
|
||||
# we need total, and not transport.
|
||||
if 'total' not in self.mgxs_types:
|
||||
error_flag = True
|
||||
msg = '"total" MGXS type is required if a ' \
|
||||
'scattering matrix is not provided.'
|
||||
warn(msg)
|
||||
# Total or transport can be present, but if using
|
||||
# self.correction=="P0", then we should use transport.
|
||||
if (((self.correction is "P0") and
|
||||
('nu-transport' not in self.mgxs_types))):
|
||||
error_flag = True
|
||||
msg = 'A "nu-transport" MGXS type is required since a "P0" ' \
|
||||
'correction is applied, but a "nu-transport" MGXS is ' \
|
||||
'not provided.'
|
||||
warn(msg)
|
||||
elif (((self.correction is None) and
|
||||
('total' not in self.mgxs_types))):
|
||||
error_flag = True
|
||||
msg = '"total" MGXS type is required, but not provided.'
|
||||
warn(msg)
|
||||
|
||||
if error_flag:
|
||||
msg = 'Invalid MGXS configuration encountered.'
|
||||
raise ValueError(msg)
|
||||
|
|
|
|||
3432
openmc/mgxs/mgxs.py
3432
openmc/mgxs/mgxs.py
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
|
@ -1,4 +1,5 @@
|
|||
import copy
|
||||
import operator
|
||||
|
||||
import numpy as np
|
||||
|
||||
|
|
@ -9,8 +10,7 @@ except ImportError:
|
|||
raise ImportError(msg)
|
||||
|
||||
import openmc
|
||||
from openmc.region import Intersection
|
||||
from openmc.surface import Halfspace
|
||||
import openmc.checkvalue as cv
|
||||
|
||||
|
||||
# A dictionary of all OpenMC Materials created
|
||||
|
|
@ -79,10 +79,7 @@ def get_opencg_material(openmc_material):
|
|||
|
||||
"""
|
||||
|
||||
if not isinstance(openmc_material, openmc.Material):
|
||||
msg = 'Unable to create an OpenCG Material from "{0}" ' \
|
||||
'which is not an OpenMC Material'.format(openmc_material)
|
||||
raise ValueError(msg)
|
||||
cv.check_type('openmc_material', openmc_material, openmc.Material)
|
||||
|
||||
global OPENCG_MATERIALS
|
||||
material_id = openmc_material.id
|
||||
|
|
@ -119,10 +116,7 @@ def get_openmc_material(opencg_material):
|
|||
|
||||
"""
|
||||
|
||||
if not isinstance(opencg_material, opencg.Material):
|
||||
msg = 'Unable to create an OpenMC Material from "{0}" ' \
|
||||
'which is not an OpenCG Material'.format(opencg_material)
|
||||
raise ValueError(msg)
|
||||
cv.check_type('opencg_material', opencg_material, opencg.Material)
|
||||
|
||||
global OPENMC_MATERIALS
|
||||
material_id = opencg_material.id
|
||||
|
|
@ -165,10 +159,7 @@ def is_opencg_surface_compatible(opencg_surface):
|
|||
|
||||
"""
|
||||
|
||||
if not isinstance(opencg_surface, opencg.Surface):
|
||||
msg = 'Unable to check if OpenCG Surface is compatible' \
|
||||
'since "{0}" is not a Surface'.format(opencg_surface)
|
||||
raise ValueError(msg)
|
||||
cv.check_type('opencg_surface', opencg_surface, opencg.Surface)
|
||||
|
||||
if opencg_surface.type in ['x-squareprism',
|
||||
'y-squareprism', 'z-squareprism']:
|
||||
|
|
@ -192,10 +183,7 @@ def get_opencg_surface(openmc_surface):
|
|||
|
||||
"""
|
||||
|
||||
if not isinstance(openmc_surface, openmc.Surface):
|
||||
msg = 'Unable to create an OpenCG Surface from "{0}" ' \
|
||||
'which is not an OpenMC Surface'.format(openmc_surface)
|
||||
raise ValueError(msg)
|
||||
cv.check_type('openmc_surface', openmc_surface, openmc.Surface)
|
||||
|
||||
global OPENCG_SURFACES
|
||||
surface_id = openmc_surface.id
|
||||
|
|
@ -278,10 +266,7 @@ def get_openmc_surface(opencg_surface):
|
|||
|
||||
"""
|
||||
|
||||
if not isinstance(opencg_surface, opencg.Surface):
|
||||
msg = 'Unable to create an OpenMC Surface from "{0}" which ' \
|
||||
'is not an OpenCG Surface'.format(opencg_surface)
|
||||
raise ValueError(msg)
|
||||
cv.check_type('opencg_surface', opencg_surface, opencg.Surface)
|
||||
|
||||
global openmc_surface
|
||||
surface_id = opencg_surface.id
|
||||
|
|
@ -369,10 +354,7 @@ def get_compatible_opencg_surfaces(opencg_surface):
|
|||
|
||||
"""
|
||||
|
||||
if not isinstance(opencg_surface, opencg.Surface):
|
||||
msg = 'Unable to create an OpenMC Surface from "{0}" which ' \
|
||||
'is not an OpenCG Surface'.format(opencg_surface)
|
||||
raise ValueError(msg)
|
||||
cv.check_type('opencg_surface', opencg_surface, opencg.Surface)
|
||||
|
||||
global OPENMC_SURFACES
|
||||
surface_id = opencg_surface.id
|
||||
|
|
@ -410,9 +392,9 @@ def get_compatible_opencg_surfaces(opencg_surface):
|
|||
surfaces = [left, right, bottom, top]
|
||||
|
||||
elif opencg_surface.type == 'z-squareprism':
|
||||
x0 = opencg_surface.x0['x0']
|
||||
y0 = opencg_surface.y0['y0']
|
||||
R = opencg_surface.r['R']
|
||||
x0 = opencg_surface.x0
|
||||
y0 = opencg_surface.y0
|
||||
R = opencg_surface.r
|
||||
|
||||
# Create a list of the four planes we need
|
||||
left = opencg.XPlane(name=name, boundary=boundary, x0=x0-R)
|
||||
|
|
@ -451,10 +433,7 @@ def get_opencg_cell(openmc_cell):
|
|||
|
||||
"""
|
||||
|
||||
if not isinstance(openmc_cell, openmc.Cell):
|
||||
msg = 'Unable to create an OpenCG Cell from "{0}" which ' \
|
||||
'is not an OpenMC Cell'.format(openmc_cell)
|
||||
raise ValueError(msg)
|
||||
cv.check_type('openmc_cell', openmc_cell, openmc.Cell)
|
||||
|
||||
global OPENCG_CELLS
|
||||
cell_id = openmc_cell.id
|
||||
|
|
@ -469,9 +448,9 @@ def get_opencg_cell(openmc_cell):
|
|||
|
||||
fill = openmc_cell.fill
|
||||
|
||||
if (openmc_cell.fill_type == 'material'):
|
||||
if openmc_cell.fill_type == 'material':
|
||||
opencg_cell.fill = get_opencg_material(fill)
|
||||
elif (openmc_cell.fill_type == 'universe'):
|
||||
elif openmc_cell.fill_type == 'universe':
|
||||
opencg_cell.fill = get_opencg_universe(fill)
|
||||
else:
|
||||
opencg_cell.fill = get_opencg_lattice(fill)
|
||||
|
|
@ -487,13 +466,13 @@ def get_opencg_cell(openmc_cell):
|
|||
# half-spaces, i.e., no complex cells.
|
||||
region = openmc_cell.region
|
||||
if region is not None:
|
||||
if isinstance(region, Halfspace):
|
||||
if isinstance(region, openmc.Halfspace):
|
||||
surface = region.surface
|
||||
halfspace = -1 if region.side == '-' else 1
|
||||
opencg_cell.add_surface(get_opencg_surface(surface), halfspace)
|
||||
elif isinstance(region, Intersection):
|
||||
elif isinstance(region, openmc.Intersection):
|
||||
for node in region.nodes:
|
||||
if not isinstance(node, Halfspace):
|
||||
if not isinstance(node, openmc.Halfspace):
|
||||
raise NotImplementedError("Complex cells not yet "
|
||||
"supported in OpenCG.")
|
||||
surface = node.surface
|
||||
|
|
@ -533,20 +512,10 @@ def get_compatible_opencg_cells(opencg_cell, opencg_surface, halfspace):
|
|||
OpenMC
|
||||
|
||||
"""
|
||||
if not isinstance(opencg_cell, opencg.Cell):
|
||||
msg = 'Unable to create compatible OpenMC Cell from "{0}" which ' \
|
||||
'is not an OpenCG Cell'.format(opencg_cell)
|
||||
raise ValueError(msg)
|
||||
|
||||
elif not isinstance(opencg_surface, opencg.Surface):
|
||||
msg = 'Unable to create compatible OpenMC Cell since "{0}" is ' \
|
||||
'not an OpenCG Surface'.format(opencg_surface)
|
||||
raise ValueError(msg)
|
||||
|
||||
elif halfspace not in [-1, +1]:
|
||||
msg = 'Unable to create compatible Cell since "{0}"' \
|
||||
'is not a +/-1 halfspace'.format(halfspace)
|
||||
raise ValueError(msg)
|
||||
cv.check_type('opencg_cell', opencg_cell, opencg.Cell)
|
||||
cv.check_type('opencg_surface', opencg_surface, opencg.Surface)
|
||||
cv.check_value('halfspace', halfspace, (-1, +1))
|
||||
|
||||
# Initialize an empty list for the new compatible cells
|
||||
compatible_cells = []
|
||||
|
|
@ -558,7 +527,7 @@ def get_compatible_opencg_cells(opencg_cell, opencg_surface, halfspace):
|
|||
# Get the compatible Surfaces (XPlanes and YPlanes)
|
||||
compatible_surfaces = get_compatible_opencg_surfaces(opencg_surface)
|
||||
|
||||
opencg_cell.removeSurface(opencg_surface)
|
||||
opencg_cell.remove_surface(opencg_surface)
|
||||
|
||||
# If Cell is inside SquarePrism, add "inside" of Surface halfspaces
|
||||
if halfspace == -1:
|
||||
|
|
@ -575,7 +544,7 @@ def get_compatible_opencg_cells(opencg_cell, opencg_surface, halfspace):
|
|||
num_clones = 8
|
||||
|
||||
for clone_id in range(num_clones):
|
||||
# Create a cloned OpenCG Cell with Surfaces compatible with OpenMC
|
||||
# Create cloned OpenCG Cell with Surfaces compatible with OpenMC
|
||||
clone = opencg_cell.clone()
|
||||
compatible_cells.append(clone)
|
||||
|
||||
|
|
@ -625,7 +594,7 @@ def get_compatible_opencg_cells(opencg_cell, opencg_surface, halfspace):
|
|||
|
||||
# Remove redundant Surfaces from the Cells
|
||||
for cell in compatible_cells:
|
||||
cell.removeRedundantSurfaces()
|
||||
cell.remove_redundant_surfaces()
|
||||
|
||||
# Return the list of OpenMC compatible OpenCG Cells
|
||||
return compatible_cells
|
||||
|
|
@ -641,10 +610,7 @@ def make_opencg_cells_compatible(opencg_universe):
|
|||
|
||||
"""
|
||||
|
||||
if not isinstance(opencg_universe, opencg.Universe):
|
||||
msg = 'Unable to make compatible OpenCG Cells for "{0}" which ' \
|
||||
'is not an OpenCG Universe'.format(opencg_universe)
|
||||
raise ValueError(msg)
|
||||
cv.check_type('opencg_universe', opencg_universe, opencg.Universe)
|
||||
|
||||
# Check all OpenCG Cells in this Universe for compatibility with OpenMC
|
||||
opencg_cells = opencg_universe.cells
|
||||
|
|
@ -672,7 +638,7 @@ def make_opencg_cells_compatible(opencg_universe):
|
|||
surface, halfspace)
|
||||
|
||||
# Remove the non-compatible OpenCG Cell from the Universe
|
||||
opencg_universe.removeCell(opencg_cell)
|
||||
opencg_universe.remove_cell(opencg_cell)
|
||||
|
||||
# Add the compatible OpenCG Cells to the Universe
|
||||
opencg_universe.add_cells(cells)
|
||||
|
|
@ -700,10 +666,7 @@ def get_openmc_cell(opencg_cell):
|
|||
|
||||
"""
|
||||
|
||||
if not isinstance(opencg_cell, opencg.Cell):
|
||||
msg = 'Unable to create an OpenMC Cell from "{0}" which ' \
|
||||
'is not an OpenCG Cell'.format(opencg_cell)
|
||||
raise ValueError(msg)
|
||||
cv.check_type('opencg_cell', opencg_cell, opencg.Cell)
|
||||
|
||||
global OPENMC_CELLS
|
||||
cell_id = opencg_cell.id
|
||||
|
|
@ -718,9 +681,9 @@ def get_openmc_cell(opencg_cell):
|
|||
|
||||
fill = opencg_cell.fill
|
||||
|
||||
if (opencg_cell.type == 'universe'):
|
||||
if opencg_cell.type == 'universe':
|
||||
openmc_cell.fill = get_openmc_universe(fill)
|
||||
elif (opencg_cell.type == 'lattice'):
|
||||
elif opencg_cell.type == 'lattice':
|
||||
openmc_cell.fill = get_openmc_lattice(fill)
|
||||
else:
|
||||
openmc_cell.fill = get_openmc_material(fill)
|
||||
|
|
@ -733,12 +696,13 @@ def get_openmc_cell(opencg_cell):
|
|||
translation = np.asarray(opencg_cell.translation, dtype=np.float64)
|
||||
openmc_cell.translation = translation
|
||||
|
||||
surfaces = opencg_cell.surfaces
|
||||
|
||||
for surface_id in surfaces:
|
||||
surface = surfaces[surface_id][0]
|
||||
halfspace = surfaces[surface_id][1]
|
||||
openmc_cell.add_surface(get_openmc_surface(surface), halfspace)
|
||||
surfaces = []
|
||||
operators = []
|
||||
for surface, halfspace in opencg_cell.surfaces.values():
|
||||
surfaces.append(get_openmc_surface(surface))
|
||||
operators.append(operator.neg if halfspace == -1 else operator.pos)
|
||||
openmc_cell.region = openmc.Intersection(
|
||||
*[op(s) for op, s in zip(operators, surfaces)])
|
||||
|
||||
# Add the OpenMC Cell to the global collection of all OpenMC Cells
|
||||
OPENMC_CELLS[cell_id] = openmc_cell
|
||||
|
|
@ -764,10 +728,7 @@ def get_opencg_universe(openmc_universe):
|
|||
|
||||
"""
|
||||
|
||||
if not isinstance(openmc_universe, openmc.Universe):
|
||||
msg = 'Unable to create an OpenCG Universe from "{0}" which ' \
|
||||
'is not an OpenMC Universe'.format(openmc_universe)
|
||||
raise ValueError(msg)
|
||||
cv.check_type('openmc_universe', openmc_universe, openmc.Universe)
|
||||
|
||||
global OPENCG_UNIVERSES
|
||||
universe_id = openmc_universe.id
|
||||
|
|
@ -811,10 +772,7 @@ def get_openmc_universe(opencg_universe):
|
|||
|
||||
"""
|
||||
|
||||
if not isinstance(opencg_universe, opencg.Universe):
|
||||
msg = 'Unable to create an OpenMC Universe from "{0}" which ' \
|
||||
'is not an OpenCG Universe'.format(opencg_universe)
|
||||
raise ValueError(msg)
|
||||
cv.check_type('opencg_universe', opencg_universe, opencg.Universe)
|
||||
|
||||
global OPENMC_UNIVERSES
|
||||
universe_id = opencg_universe.id
|
||||
|
|
@ -861,10 +819,7 @@ def get_opencg_lattice(openmc_lattice):
|
|||
|
||||
"""
|
||||
|
||||
if not isinstance(openmc_lattice, openmc.Lattice):
|
||||
msg = 'Unable to create an OpenCG Lattice from "{0}" which ' \
|
||||
'is not an OpenMC Lattice'.format(openmc_lattice)
|
||||
raise ValueError(msg)
|
||||
cv.check_type('openmc_lattice', openmc_lattice, openmc.Lattice)
|
||||
|
||||
global OPENCG_LATTICES
|
||||
lattice_id = openmc_lattice.id
|
||||
|
|
@ -906,8 +861,8 @@ def get_opencg_lattice(openmc_lattice):
|
|||
universes = new_universes
|
||||
|
||||
# Initialize an empty array for the OpenCG nested Universes in this Lattice
|
||||
universe_array = np.ndarray(tuple(np.array(dimension)[::-1]),
|
||||
dtype=opencg.Universe)
|
||||
universe_array = np.empty(tuple(np.array(dimension)[::-1]),
|
||||
dtype=opencg.Universe)
|
||||
|
||||
# Create OpenCG Universes for each unique nested Universe in this Lattice
|
||||
unique_universes = openmc_lattice.get_unique_universes()
|
||||
|
|
@ -958,10 +913,7 @@ def get_openmc_lattice(opencg_lattice):
|
|||
|
||||
"""
|
||||
|
||||
if not isinstance(opencg_lattice, opencg.Lattice):
|
||||
msg = 'Unable to create an OpenMC Lattice from "{0}" which ' \
|
||||
'is not an OpenCG Lattice'.format(opencg_lattice)
|
||||
raise ValueError(msg)
|
||||
cv.check_type('opencg_lattice', opencg_lattice, opencg.Lattice)
|
||||
|
||||
global OPENMC_LATTICES
|
||||
lattice_id = opencg_lattice.id
|
||||
|
|
@ -977,8 +929,8 @@ def get_openmc_lattice(opencg_lattice):
|
|||
outer = opencg_lattice.outside
|
||||
|
||||
# Initialize an empty array for the OpenMC nested Universes in this Lattice
|
||||
universe_array = np.ndarray(tuple(np.array(dimension)[::-1]),
|
||||
dtype=openmc.Universe)
|
||||
universe_array = np.empty(tuple(np.array(dimension)[::-1]),
|
||||
dtype=openmc.Universe)
|
||||
|
||||
# Create OpenMC Universes for each unique nested Universe in this Lattice
|
||||
unique_universes = opencg_lattice.get_unique_universes()
|
||||
|
|
@ -1001,7 +953,6 @@ def get_openmc_lattice(opencg_lattice):
|
|||
np.array(dimension, dtype=np.float64))) / -2.0
|
||||
|
||||
openmc_lattice = openmc.RectLattice(lattice_id=lattice_id)
|
||||
openmc_lattice.dimension = dimension
|
||||
openmc_lattice.pitch = width
|
||||
openmc_lattice.universes = universe_array
|
||||
openmc_lattice.lower_left = lower_left
|
||||
|
|
@ -1032,10 +983,7 @@ def get_opencg_geometry(openmc_geometry):
|
|||
|
||||
"""
|
||||
|
||||
if not isinstance(openmc_geometry, openmc.Geometry):
|
||||
msg = 'Unable to get OpenCG geometry from "{0}" which is ' \
|
||||
'not an OpenMC Geometry object'.format(openmc_geometry)
|
||||
raise ValueError(msg)
|
||||
cv.check_type('openmc_geometry', openmc_geometry, openmc.Geometry)
|
||||
|
||||
# Clear dictionaries and auto-generated IDs
|
||||
OPENMC_SURFACES.clear()
|
||||
|
|
@ -1053,6 +1001,7 @@ def get_opencg_geometry(openmc_geometry):
|
|||
opencg_geometry = opencg.Geometry()
|
||||
opencg_geometry.root_universe = opencg_root_universe
|
||||
opencg_geometry.initialize_cell_offsets()
|
||||
opencg_geometry.assign_auto_ids()
|
||||
|
||||
return opencg_geometry
|
||||
|
||||
|
|
@ -1072,10 +1021,7 @@ def get_openmc_geometry(opencg_geometry):
|
|||
|
||||
"""
|
||||
|
||||
if not isinstance(opencg_geometry, opencg.Geometry):
|
||||
msg = 'Unable to get OpenMC geometry from "{0}" which is ' \
|
||||
'not an OpenCG Geometry object'.format(opencg_geometry)
|
||||
raise ValueError(msg)
|
||||
cv.check_type('opencg_geometry', opencg_geometry, opencg.Geometry)
|
||||
|
||||
# Deep copy the goemetry since it may be modified to make all Surfaces
|
||||
# compatible with OpenMC's specifications
|
||||
|
|
|
|||
|
|
@ -37,6 +37,11 @@ class Particle(object):
|
|||
|
||||
def __init__(self, filename):
|
||||
import h5py
|
||||
if h5py.__version__ == '2.6.0':
|
||||
raise ImportError("h5py 2.6.0 has a known bug which makes it "
|
||||
"incompatible with OpenMC's HDF5 files. "
|
||||
"Please switch to a different version.")
|
||||
|
||||
self._f = h5py.File(filename, 'r')
|
||||
|
||||
# Ensure filetype and revision are correct
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ from collections import Iterable
|
|||
from numbers import Real, Integral
|
||||
from xml.etree import ElementTree as ET
|
||||
import sys
|
||||
import warnings
|
||||
|
||||
import numpy as np
|
||||
|
||||
|
|
@ -125,7 +126,7 @@ class Plot(object):
|
|||
return self._background
|
||||
|
||||
@property
|
||||
def mask_componenets(self):
|
||||
def mask_components(self):
|
||||
return self._mask_components
|
||||
|
||||
@property
|
||||
|
|
@ -227,7 +228,7 @@ class Plot(object):
|
|||
|
||||
self._col_spec = col_spec
|
||||
|
||||
@mask_componenets.setter
|
||||
@mask_components.setter
|
||||
def mask_components(self, mask_components):
|
||||
cv.check_type('plot mask_components', mask_components, Iterable, Integral)
|
||||
for component in mask_components:
|
||||
|
|
@ -275,7 +276,7 @@ class Plot(object):
|
|||
The random number seed used to generate the color scheme
|
||||
|
||||
"""
|
||||
|
||||
|
||||
cv.check_type('geometry', geometry, openmc.Geometry)
|
||||
cv.check_type('seed', seed, Integral)
|
||||
cv.check_greater_than('seed', seed, 1, equality=True)
|
||||
|
|
@ -401,44 +402,90 @@ class Plot(object):
|
|||
return element
|
||||
|
||||
|
||||
class PlotsFile(object):
|
||||
"""Plots file used for an OpenMC simulation. Corresponds directly to the
|
||||
plots.xml input file.
|
||||
class Plots(cv.CheckedList):
|
||||
"""Collection of Plots used for an OpenMC simulation.
|
||||
|
||||
This class corresponds directly to the plots.xml input file. It can be
|
||||
thought of as a normal Python list where each member is a :class:`Plot`. It
|
||||
behaves like a list as the following example demonstrates:
|
||||
|
||||
>>> xz_plot = openmc.Plot()
|
||||
>>> big_plot = openmc.Plot()
|
||||
>>> small_plot = openmc.Plot()
|
||||
>>> p = openmc.Plots((xz_plot, big_plot))
|
||||
>>> p.append(small_plot)
|
||||
>>> small_plot = p.pop()
|
||||
|
||||
Parameters
|
||||
----------
|
||||
plots : Iterable of openmc.Plot
|
||||
Plots to add to the collection
|
||||
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
# Initialize PlotsFile class attributes
|
||||
self._plots = []
|
||||
def __init__(self, plots=None):
|
||||
super(Plots, self).__init__(Plot, 'plots collection')
|
||||
self._plots_file = ET.Element("plots")
|
||||
if plots is not None:
|
||||
self += plots
|
||||
|
||||
def add_plot(self, plot):
|
||||
"""Add a plot to the file.
|
||||
|
||||
.. deprecated:: 0.8
|
||||
Use :meth:`Plots.append` instead.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
plot : Plot
|
||||
plot : openmc.Plot
|
||||
Plot to add
|
||||
|
||||
"""
|
||||
warnings.warn("Plots.add_plot(...) has been deprecated and may be "
|
||||
"removed in a future version. Use Plots.append(...) "
|
||||
"instead.", DeprecationWarning)
|
||||
self.append(plot)
|
||||
|
||||
if not isinstance(plot, Plot):
|
||||
msg = 'Unable to add a non-Plot "{0}" to the PlotsFile'.format(plot)
|
||||
raise ValueError(msg)
|
||||
def append(self, plot):
|
||||
"""Append plot to collection
|
||||
|
||||
self._plots.append(plot)
|
||||
Parameters
|
||||
----------
|
||||
plot : openmc.Plot
|
||||
Plot to append
|
||||
|
||||
"""
|
||||
super(Plots, self).append(plot)
|
||||
|
||||
def insert(self, index, plot):
|
||||
"""Insert plot before index
|
||||
|
||||
Parameters
|
||||
----------
|
||||
index : int
|
||||
Index in list
|
||||
plot : openmc.Plot
|
||||
Plot to insert
|
||||
|
||||
"""
|
||||
super(Plots, self).insert(index, plot)
|
||||
|
||||
def remove_plot(self, plot):
|
||||
"""Remove a plot from the file.
|
||||
|
||||
.. deprecated:: 0.8
|
||||
Use :meth:`Plots.remove` instead.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
plot : Plot
|
||||
plot : openmc.Plot
|
||||
Plot to remove
|
||||
|
||||
"""
|
||||
|
||||
self._plots.remove(plot)
|
||||
warnings.warn("Plots.remove_plot(...) has been deprecated and may be "
|
||||
"removed in a future version. Use Plots.remove(...) "
|
||||
"instead.", DeprecationWarning)
|
||||
self.remove(plot)
|
||||
|
||||
def colorize(self, geometry, seed=1):
|
||||
"""Generate a consistent color scheme for each domain in each plot.
|
||||
|
|
@ -456,7 +503,7 @@ class PlotsFile(object):
|
|||
|
||||
"""
|
||||
|
||||
for plot in self._plots:
|
||||
for plot in self:
|
||||
plot.colorize(geometry, seed)
|
||||
|
||||
|
||||
|
|
@ -482,11 +529,11 @@ class PlotsFile(object):
|
|||
|
||||
"""
|
||||
|
||||
for plot in self._plots:
|
||||
for plot in self:
|
||||
plot.highlight_domains(geometry, domains, seed, alpha, background)
|
||||
|
||||
def _create_plot_subelements(self):
|
||||
for plot in self._plots:
|
||||
for plot in self:
|
||||
xml_element = plot.get_plot_xml()
|
||||
|
||||
if len(plot._name) > 0:
|
||||
|
|
|
|||
108
openmc/region.py
108
openmc/region.py
|
|
@ -9,10 +9,11 @@ from openmc.checkvalue import check_type
|
|||
class Region(object):
|
||||
"""Region of space that can be assigned to a cell.
|
||||
|
||||
Region is an abstract base class that is inherited by Halfspace,
|
||||
Intersection, Union, and Complement. Each of those respective classes are
|
||||
typically not instantiated directly but rather are created through operators
|
||||
of the Surface and Region classes.
|
||||
Region is an abstract base class that is inherited by
|
||||
:class:`openmc.Halfspace`, :class:`openmc.Intersection`,
|
||||
:class:`openmc.Union`, and :class:`openmc.Complement`. Each of those
|
||||
respective classes are typically not instantiated directly but rather are
|
||||
created through operators of the Surface and Region classes.
|
||||
|
||||
"""
|
||||
|
||||
|
|
@ -27,6 +28,10 @@ class Region(object):
|
|||
def __invert__(self):
|
||||
return Complement(self)
|
||||
|
||||
@abstractmethod
|
||||
def __contains__(self, point):
|
||||
return False
|
||||
|
||||
@abstractmethod
|
||||
def __str__(self):
|
||||
return ''
|
||||
|
|
@ -201,11 +206,11 @@ class Intersection(Region):
|
|||
"""Intersection of two or more regions.
|
||||
|
||||
Instances of Intersection are generally created via the __and__ operator
|
||||
applied to two instances of Region. This is illustrated in the following
|
||||
example:
|
||||
applied to two instances of :class:`openmc.Region`. This is illustrated in
|
||||
the following example:
|
||||
|
||||
>>> equator = openmc.surface.ZPlane(z0=0.0)
|
||||
>>> earth = openmc.surface.Sphere(R=637.1e6)
|
||||
>>> equator = openmc.ZPlane(z0=0.0)
|
||||
>>> earth = openmc.Sphere(R=637.1e6)
|
||||
>>> northern_hemisphere = -earth & +equator
|
||||
>>> southern_hemisphere = -earth & -equator
|
||||
>>> type(northern_hemisphere)
|
||||
|
|
@ -213,12 +218,12 @@ class Intersection(Region):
|
|||
|
||||
Parameters
|
||||
----------
|
||||
*nodes
|
||||
\*nodes
|
||||
Regions to take the intersection of
|
||||
|
||||
Attributes
|
||||
----------
|
||||
nodes : tuple of Region
|
||||
nodes : list of openmc.Region
|
||||
Regions to take the intersection of
|
||||
bounding_box : tuple of numpy.array
|
||||
Lower-left and upper-right coordinates of an axis-aligned bounding box
|
||||
|
|
@ -228,6 +233,26 @@ class Intersection(Region):
|
|||
def __init__(self, *nodes):
|
||||
self.nodes = list(nodes)
|
||||
|
||||
def __iter__(self):
|
||||
for n in self.nodes:
|
||||
yield n
|
||||
|
||||
def __contains__(self, point):
|
||||
"""Check whether a point is contained in the region.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
point : 3-tuple of float
|
||||
Cartesian coordinates, :math:`(x',y',z')`, of the point
|
||||
|
||||
Returns
|
||||
-------
|
||||
bool
|
||||
Whether the point is in the region
|
||||
|
||||
"""
|
||||
return all(point in n for n in self.nodes)
|
||||
|
||||
def __str__(self):
|
||||
return '(' + ' '.join(map(str, self.nodes)) + ')'
|
||||
|
||||
|
|
@ -255,21 +280,22 @@ class Union(Region):
|
|||
"""Union of two or more regions.
|
||||
|
||||
Instances of Union are generally created via the __or__ operator applied to
|
||||
two instances of Region. This is illustrated in the following example:
|
||||
two instances of :class:`openmc.Region`. This is illustrated in the
|
||||
following example:
|
||||
|
||||
>>> s1 = openmc.surface.ZPlane(z0=0.0)
|
||||
>>> s2 = openmc.surface.Sphere(R=637.1e6)
|
||||
>>> s1 = openmc.ZPlane(z0=0.0)
|
||||
>>> s2 = openmc.Sphere(R=637.1e6)
|
||||
>>> type(-s2 | +s1)
|
||||
<class 'openmc.region.Union'>
|
||||
|
||||
Parameters
|
||||
----------
|
||||
*nodes
|
||||
\*nodes
|
||||
Regions to take the union of
|
||||
|
||||
Attributes
|
||||
----------
|
||||
nodes : tuple of Region
|
||||
nodes : tuple of openmc.Region
|
||||
Regions to take the union of
|
||||
bounding_box : tuple of numpy.array
|
||||
Lower-left and upper-right coordinates of an axis-aligned bounding box
|
||||
|
|
@ -279,6 +305,26 @@ class Union(Region):
|
|||
def __init__(self, *nodes):
|
||||
self.nodes = list(nodes)
|
||||
|
||||
def __iter__(self):
|
||||
for n in self.nodes:
|
||||
yield n
|
||||
|
||||
def __contains__(self, point):
|
||||
"""Check whether a point is contained in the region.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
point : 3-tuple of float
|
||||
Cartesian coordinates, :math:`(x',y',z')`, of the point
|
||||
|
||||
Returns
|
||||
-------
|
||||
bool
|
||||
Whether the point is in the region
|
||||
|
||||
"""
|
||||
return any(point in n for n in self.nodes)
|
||||
|
||||
def __str__(self):
|
||||
return '(' + ' | '.join(map(str, self.nodes)) + ')'
|
||||
|
||||
|
|
@ -305,13 +351,13 @@ class Union(Region):
|
|||
class Complement(Region):
|
||||
"""Complement of a region.
|
||||
|
||||
The Complement of an existing Region can be created by using the __invert__
|
||||
operator as the following example demonstrates:
|
||||
The Complement of an existing :class:`openmc.Region` can be created by using
|
||||
the __invert__ operator as the following example demonstrates:
|
||||
|
||||
>>> xl = openmc.surface.XPlane(x0=-10.0)
|
||||
>>> xr = openmc.surface.XPlane(x0=10.0)
|
||||
>>> yl = openmc.surface.YPlane(y0=-10.0)
|
||||
>>> yr = openmc.surface.YPlane(y0=10.0)
|
||||
>>> xl = openmc.XPlane(x0=-10.0)
|
||||
>>> xr = openmc.XPlane(x0=10.0)
|
||||
>>> yl = openmc.YPlane(y0=-10.0)
|
||||
>>> yr = openmc.YPlane(y0=10.0)
|
||||
>>> inside_box = +xl & -xr & +yl & -yl
|
||||
>>> outside_box = ~inside_box
|
||||
>>> type(outside_box)
|
||||
|
|
@ -319,12 +365,12 @@ class Complement(Region):
|
|||
|
||||
Parameters
|
||||
----------
|
||||
node : Region
|
||||
node : openmc.Region
|
||||
Region to take the complement of
|
||||
|
||||
Attributes
|
||||
----------
|
||||
node : Region
|
||||
node : openmc.Region
|
||||
Regions to take the complement of
|
||||
bounding_box : tuple of numpy.array
|
||||
Lower-left and upper-right coordinates of an axis-aligned bounding box
|
||||
|
|
@ -334,6 +380,22 @@ class Complement(Region):
|
|||
def __init__(self, node):
|
||||
self.node = node
|
||||
|
||||
def __contains__(self, point):
|
||||
"""Check whether a point is contained in the region.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
point : 3-tuple of float
|
||||
Cartesian coordinates, :math:`(x',y',z')`, of the point
|
||||
|
||||
Returns
|
||||
-------
|
||||
bool
|
||||
Whether the point is in the region
|
||||
|
||||
"""
|
||||
return point not in self.node
|
||||
|
||||
def __str__(self):
|
||||
return '~' + str(self.node)
|
||||
|
||||
|
|
|
|||
|
|
@ -9,13 +9,14 @@ import numpy as np
|
|||
from openmc.clean_xml import *
|
||||
from openmc.checkvalue import (check_type, check_length, check_value,
|
||||
check_greater_than, check_less_than)
|
||||
from openmc import Nuclide
|
||||
from openmc.source import Source
|
||||
|
||||
if sys.version_info[0] >= 3:
|
||||
basestring = str
|
||||
|
||||
|
||||
class SettingsFile(object):
|
||||
class Settings(object):
|
||||
"""Settings file used for an OpenMC simulation. Corresponds directly to the
|
||||
settings.xml input file.
|
||||
|
||||
|
|
@ -37,7 +38,7 @@ class SettingsFile(object):
|
|||
type are 'variance', 'std_dev', and 'rel_err'. The threshold value
|
||||
should be a float indicating the variance, standard deviation, or
|
||||
relative error used.
|
||||
source : Iterable of openmc.source.Source
|
||||
source : Iterable of openmc.Source
|
||||
Distribution of source sites in space, angle, and energy
|
||||
output : dict
|
||||
Dictionary indicating what files to output. Valid keys are 'summary',
|
||||
|
|
@ -69,9 +70,10 @@ class SettingsFile(object):
|
|||
deviation.
|
||||
cross_sections : str
|
||||
Indicates the path to an XML cross section listing file (usually named
|
||||
cross_sections.xml). If it is not set, the :envvar:`CROSS_SECTIONS`
|
||||
environment variable will be used for continuous-energy calculations
|
||||
and :envvar:`MG_CROSS_SECTIONS` will be used for multi-group
|
||||
cross_sections.xml). If it is not set, the
|
||||
:envvar:`OPENMC_CROSS_SECTIONS` environment variable will be used for
|
||||
continuous-energy calculations and
|
||||
:envvar:`OPENMC_MG_CROSS_SECTIONS` will be used for multi-group
|
||||
calculations to find the path to the XML cross section file.
|
||||
energy_grid : {'nuclide', 'logarithm', 'material-union'}
|
||||
Set the method used to search energy grids.
|
||||
|
|
@ -125,6 +127,8 @@ class SettingsFile(object):
|
|||
Coordinates of the lower-left point of the UFS mesh
|
||||
ufs_upper_right : tuple or list
|
||||
Coordinates of the upper-right point of the UFS mesh
|
||||
resonance_scattering : ResonanceScattering or iterable of ResonanceScattering
|
||||
The elastic scattering model to use for resonant isotopes
|
||||
|
||||
"""
|
||||
|
||||
|
|
@ -205,6 +209,8 @@ class SettingsFile(object):
|
|||
self._run_mode_subelement = None
|
||||
self._source_element = None
|
||||
|
||||
self._resonance_scattering = None
|
||||
|
||||
@property
|
||||
def run_mode(self):
|
||||
return self._run_mode
|
||||
|
|
@ -393,9 +399,13 @@ class SettingsFile(object):
|
|||
def dd_count_interactions(self):
|
||||
return self._dd_count_interactions
|
||||
|
||||
@property
|
||||
def resonance_scattering(self):
|
||||
return self._resonance_scattering
|
||||
|
||||
@run_mode.setter
|
||||
def run_mode(self, run_mode):
|
||||
if 'run_mode' not in ['eigenvalue', 'fixed source']:
|
||||
if run_mode not in ['eigenvalue', 'fixed source']:
|
||||
msg = 'Unable to set run mode to "{0}". Only "eigenvalue" ' \
|
||||
'and "fixed source" are supported."'.format(run_mode)
|
||||
raise ValueError(msg)
|
||||
|
|
@ -764,6 +774,16 @@ class SettingsFile(object):
|
|||
|
||||
self._dd_count_interactions = interactions
|
||||
|
||||
@resonance_scattering.setter
|
||||
def resonance_scattering(self, res):
|
||||
if isinstance(res, Iterable):
|
||||
check_type('resonance_scattering', res, Iterable,
|
||||
ResonanceScattering)
|
||||
self._resonance_scattering = res
|
||||
else:
|
||||
check_type('resonance_scattering', res, ResonanceScattering)
|
||||
self._resonance_scattering = [res]
|
||||
|
||||
def _create_run_mode_subelement(self):
|
||||
|
||||
if self.run_mode == 'eigenvalue':
|
||||
|
|
@ -1043,6 +1063,17 @@ class SettingsFile(object):
|
|||
subelement = ET.SubElement(element, "count_interactions")
|
||||
subelement.text = str(self._dd_count_interactions).lower()
|
||||
|
||||
def _create_resonance_scattering_element(self):
|
||||
if self.resonance_scattering is None: return
|
||||
|
||||
element = ET.SubElement(self._settings_file, "resonance_scattering")
|
||||
|
||||
for r in self.resonance_scattering:
|
||||
if r.nuclide.name != r.nuclide_0K.name:
|
||||
raise ValueError("The nuclide and nuclide_0K attributes of "
|
||||
"a ResonantScattering object must have identical names.")
|
||||
r.create_xml_subelement(element)
|
||||
|
||||
def export_to_xml(self):
|
||||
"""Create a settings.xml file that can be used for a simulation.
|
||||
|
||||
|
|
@ -1079,6 +1110,7 @@ class SettingsFile(object):
|
|||
self._create_track_subelement()
|
||||
self._create_ufs_subelement()
|
||||
self._create_dd_subelement()
|
||||
self._create_resonance_scattering_element()
|
||||
|
||||
# Clean the indentation in the file to be user-readable
|
||||
clean_xml_indentation(self._settings_file)
|
||||
|
|
@ -1087,3 +1119,104 @@ class SettingsFile(object):
|
|||
tree = ET.ElementTree(self._settings_file)
|
||||
tree.write("settings.xml", xml_declaration=True,
|
||||
encoding='utf-8', method="xml")
|
||||
|
||||
|
||||
class ResonanceScattering(object):
|
||||
"""Specification of the elastic scattering model for resonant isotopes
|
||||
|
||||
Attributes
|
||||
----------
|
||||
nuclide : openmc.Nuclide
|
||||
The nuclide affected by this resonance scattering treatment.
|
||||
nuclide_0K : openmc.Nuclide
|
||||
This should be the same isotope as the nuclide attribute above, but it
|
||||
should have an xs attribute that identifies 0 Kelvin data.
|
||||
method : str
|
||||
The method used to sample outgoing scattering energies. Valid options
|
||||
are 'ARES', 'CXS' (constant cross section), 'DBRC' (Doppler broadening
|
||||
rejection correction), and 'WCM' (weight correction method).
|
||||
E_min : float
|
||||
The minimum energy above which the specified method is applied. By
|
||||
default, CXS will be used below E_min.
|
||||
E_max : float
|
||||
The maximum energy below which the specified method is applied. By
|
||||
default, the asymptotic target-at-rest model is applied above E_max.
|
||||
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
self._nuclide = None
|
||||
self._nuclide_0K = None
|
||||
self._method = None
|
||||
self._E_min = None
|
||||
self._E_max = None
|
||||
|
||||
@property
|
||||
def nuclide(self):
|
||||
return self._nuclide
|
||||
|
||||
@property
|
||||
def nuclide_0K(self):
|
||||
return self._nuclide_0K
|
||||
|
||||
@property
|
||||
def method(self):
|
||||
return self._method
|
||||
|
||||
@property
|
||||
def E_min(self):
|
||||
return self._E_min
|
||||
|
||||
@property
|
||||
def E_max(self):
|
||||
return self._E_max
|
||||
|
||||
@nuclide.setter
|
||||
def nuclide(self, nuc):
|
||||
check_type('nuclide', nuc, Nuclide)
|
||||
if nuc.zaid == None: raise ValueError("The nuclide must have an "
|
||||
"explicitly defined zaid attribute.")
|
||||
self._nuclide = nuc
|
||||
|
||||
@nuclide_0K.setter
|
||||
def nuclide_0K(self, nuc):
|
||||
check_type('nuclide_0K', nuc, Nuclide)
|
||||
if nuc.zaid == None: raise ValueError("The nuclide_0K must have an "
|
||||
"explicitly defined zaid attribute.")
|
||||
self._nuclide_0K = nuc
|
||||
|
||||
@method.setter
|
||||
def method(self, m):
|
||||
check_value('method', m, ('ARES', 'CXS', 'DBRC', 'WCM'))
|
||||
self._method = m
|
||||
|
||||
@E_min.setter
|
||||
def E_min(self, E):
|
||||
check_type('E_min', E, Real)
|
||||
check_greater_than('E_min', E, 0, True)
|
||||
self._E_min = E
|
||||
|
||||
@E_max.setter
|
||||
def E_max(self, E):
|
||||
check_type('E_max', E, Real)
|
||||
check_greater_than('E_max', E, 0, True)
|
||||
self._E_max = E
|
||||
|
||||
def create_xml_subelement(self, xml_element):
|
||||
scatterer = ET.SubElement(xml_element, "scatterer")
|
||||
subelement = ET.SubElement(scatterer, 'nuclide')
|
||||
subelement.text = self.nuclide.name
|
||||
if self.method is not None:
|
||||
subelement = ET.SubElement(scatterer, 'method')
|
||||
subelement.text = self.method
|
||||
subelement = ET.SubElement(scatterer, 'xs_label')
|
||||
subelement.text = str(self.nuclide.zaid) + '.' + str(self.nuclide.xs)
|
||||
subelement = ET.SubElement(scatterer, 'xs_label_0K')
|
||||
subelement.text = str(self.nuclide_0K.zaid) + '.' \
|
||||
+ str(self.nuclide_0K.xs)
|
||||
if self.E_min is not None:
|
||||
subelement = ET.SubElement(scatterer, 'E_min')
|
||||
subelement.text = str(self.E_min)
|
||||
if self.E_max is not None:
|
||||
subelement = ET.SubElement(scatterer, 'E_max')
|
||||
subelement.text = str(self.E_max)
|
||||
|
|
|
|||
|
|
@ -1,5 +1,8 @@
|
|||
import sys
|
||||
import re
|
||||
import os
|
||||
import warnings
|
||||
|
||||
import numpy as np
|
||||
|
||||
import openmc
|
||||
|
|
@ -14,63 +17,74 @@ class StatePoint(object):
|
|||
of a given batch). Statepoints can be used to analyze tally results as well
|
||||
as restart a simulation.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
filename : str
|
||||
Path to file to load
|
||||
autolink : bool, optional
|
||||
Whether to automatically link in metadata from a summary.h5
|
||||
file. Defaults to True.
|
||||
|
||||
Attributes
|
||||
----------
|
||||
cmfd_on : bool
|
||||
Indicate whether CMFD is active
|
||||
cmfd_balance : ndarray
|
||||
cmfd_balance : numpy.ndarray
|
||||
Residual neutron balance for each batch
|
||||
cmfd_dominance
|
||||
Dominance ratio for each batch
|
||||
cmfd_entropy : ndarray
|
||||
cmfd_entropy : numpy.ndarray
|
||||
Shannon entropy of CMFD fission source for each batch
|
||||
cmfd_indices : ndarray
|
||||
cmfd_indices : numpy.ndarray
|
||||
Number of CMFD mesh cells and energy groups. The first three indices
|
||||
correspond to the x-, y-, and z- spatial directions and the fourth index
|
||||
is the number of energy groups.
|
||||
cmfd_srccmp : ndarray
|
||||
cmfd_srccmp : numpy.ndarray
|
||||
Root-mean-square difference between OpenMC and CMFD fission source for
|
||||
each batch
|
||||
cmfd_src : ndarray
|
||||
cmfd_src : numpy.ndarray
|
||||
CMFD fission source distribution over all mesh cells and energy groups.
|
||||
current_batch : Integral
|
||||
current_batch : int
|
||||
Number of batches simulated
|
||||
date_and_time : str
|
||||
Date and time when simulation began
|
||||
entropy : ndarray
|
||||
entropy : numpy.ndarray
|
||||
Shannon entropy of fission source at each batch
|
||||
gen_per_batch : Integral
|
||||
Number of fission generations per batch
|
||||
global_tallies : ndarray of compound datatype
|
||||
global_tallies : numpy.ndarray of compound datatype
|
||||
Global tallies for k-effective estimates and leakage. The compound
|
||||
datatype has fields 'name', 'sum', 'sum_sq', 'mean', and 'std_dev'.
|
||||
k_combined : list
|
||||
Combined estimator for k-effective and its uncertainty
|
||||
k_col_abs : Real
|
||||
k_col_abs : float
|
||||
Cross-product of collision and absorption estimates of k-effective
|
||||
k_col_tra : Real
|
||||
k_col_tra : float
|
||||
Cross-product of collision and tracklength estimates of k-effective
|
||||
k_abs_tra : Real
|
||||
k_abs_tra : float
|
||||
Cross-product of absorption and tracklength estimates of k-effective
|
||||
k_generation : ndarray
|
||||
k_generation : numpy.ndarray
|
||||
Estimate of k-effective for each batch/generation
|
||||
meshes : dict
|
||||
Dictionary whose keys are mesh IDs and whose values are Mesh objects
|
||||
n_batches : Integral
|
||||
n_batches : int
|
||||
Number of batches
|
||||
n_inactive : Integral
|
||||
n_inactive : int
|
||||
Number of inactive batches
|
||||
n_particles : Integral
|
||||
n_particles : int
|
||||
Number of particles per generation
|
||||
n_realizations : Integral
|
||||
n_realizations : int
|
||||
Number of tally realizations
|
||||
path : str
|
||||
Working directory for simulation
|
||||
run_mode : str
|
||||
Simulation run mode, e.g. 'k-eigenvalue'
|
||||
seed : Integral
|
||||
runtime : dict
|
||||
Dictionary whose keys are strings describing various runtime metrics
|
||||
and whose values are time values in seconds.
|
||||
seed : int
|
||||
Pseudorandom number generator seed
|
||||
source : ndarray of compound datatype
|
||||
source : numpy.ndarray of compound datatype
|
||||
Array of source sites. The compound datatype has fields 'wgt', 'xyz',
|
||||
'uvw', and 'E' corresponding to the weight, position, direction, and
|
||||
energy of the source site.
|
||||
|
|
@ -85,13 +99,18 @@ class StatePoint(object):
|
|||
Indicate whether user-defined tallies are present
|
||||
version: tuple of Integral
|
||||
Version of OpenMC
|
||||
summary : None or openmc.summary.Summary
|
||||
summary : None or openmc.Summary
|
||||
A summary object if the statepoint has been linked with a summary file
|
||||
|
||||
"""
|
||||
|
||||
def __init__(self, filename):
|
||||
def __init__(self, filename, autolink=True):
|
||||
import h5py
|
||||
if h5py.__version__ == '2.6.0':
|
||||
raise ImportError("h5py 2.6.0 has a known bug which makes it "
|
||||
"incompatible with OpenMC's HDF5 files. "
|
||||
"Please switch to a different version.")
|
||||
|
||||
self._f = h5py.File(filename, 'r')
|
||||
|
||||
# Ensure filetype and revision are correct
|
||||
|
|
@ -101,8 +120,9 @@ class StatePoint(object):
|
|||
raise IOError('{} is not a statepoint file.'.format(filename))
|
||||
except AttributeError:
|
||||
raise IOError('Could not read statepoint file. This most likely '
|
||||
'means the statepoint file was produced by a different '
|
||||
'version of OpenMC than the one you are using.')
|
||||
'means the statepoint file was produced by a '
|
||||
'different version of OpenMC than the one you are '
|
||||
'using.')
|
||||
if self._f['revision'].value != 15:
|
||||
raise IOError('Statepoint file has a file revision of {} '
|
||||
'which is not consistent with the revision this '
|
||||
|
|
@ -112,10 +132,17 @@ class StatePoint(object):
|
|||
# Set flags for what data has been read
|
||||
self._meshes_read = False
|
||||
self._tallies_read = False
|
||||
self._summary = False
|
||||
self._summary = None
|
||||
self._global_tallies = None
|
||||
self._sparse = False
|
||||
|
||||
# Automatically link in a summary file if one exists
|
||||
if autolink:
|
||||
path_summary = os.path.join(os.path.dirname(filename), 'summary.h5')
|
||||
if os.path.exists(path_summary):
|
||||
su = openmc.Summary(path_summary)
|
||||
self.link_with_summary(su)
|
||||
|
||||
def close(self):
|
||||
self._f.close()
|
||||
|
||||
|
|
@ -311,6 +338,11 @@ class StatePoint(object):
|
|||
def run_mode(self):
|
||||
return self._f['run_mode'].value.decode()
|
||||
|
||||
@property
|
||||
def runtime(self):
|
||||
return {name: dataset.value
|
||||
for name, dataset in self._f['runtime'].items()}
|
||||
|
||||
@property
|
||||
def seed(self):
|
||||
return self._f['seed'].value
|
||||
|
|
@ -389,7 +421,7 @@ class StatePoint(object):
|
|||
new_filter.mesh = self.meshes[key]
|
||||
|
||||
# Add Filter to the Tally
|
||||
tally.add_filter(new_filter)
|
||||
tally.filters.append(new_filter)
|
||||
|
||||
# Read Nuclide bins
|
||||
nuclide_names = \
|
||||
|
|
@ -398,7 +430,7 @@ class StatePoint(object):
|
|||
# Add all Nuclides to the Tally
|
||||
for name in nuclide_names:
|
||||
nuclide = openmc.Nuclide(name.decode().strip())
|
||||
tally.add_nuclide(nuclide)
|
||||
tally.nuclides.append(nuclide)
|
||||
|
||||
scores = self._f['{0}{1}/score_bins'.format(
|
||||
base, tally_key)].value
|
||||
|
|
@ -425,7 +457,7 @@ class StatePoint(object):
|
|||
pattern = r'-n$|-pn$|-yn$'
|
||||
score = re.sub(pattern, '-' + moments[j].decode(), score)
|
||||
|
||||
tally.add_score(score)
|
||||
tally.scores.append(score)
|
||||
|
||||
# Add Tally to the global dictionary of all Tallies
|
||||
tally.sparse = self.sparse
|
||||
|
|
@ -470,13 +502,18 @@ class StatePoint(object):
|
|||
self.tallies[tally_id].sparse = self.sparse
|
||||
|
||||
def get_tally(self, scores=[], filters=[], nuclides=[],
|
||||
name=None, id=None, estimator=None):
|
||||
name=None, id=None, estimator=None, exact_filters=False,
|
||||
exact_nuclides=False, exact_scores=False):
|
||||
"""Finds and returns a Tally object with certain properties.
|
||||
|
||||
This routine searches the list of Tallies and returns the first Tally
|
||||
found which satisfies all of the input parameters.
|
||||
NOTE: The input parameters do not need to match the complete Tally
|
||||
specification and may only represent a subset of the Tally's properties.
|
||||
|
||||
NOTE: If any of the "exact" parameters are False (default), the input
|
||||
parameters do not need to match the complete Tally specification and
|
||||
may only represent a subset of the Tally's properties. If an "exact"
|
||||
parameter is True then number of scores, filters, or nuclides in the
|
||||
parameters must precisely match those of any matching Tally.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
|
|
@ -492,10 +529,22 @@ class StatePoint(object):
|
|||
The id specified for the Tally (default is None).
|
||||
estimator: str, optional
|
||||
The type of estimator ('tracklength', 'analog'; default is None).
|
||||
exact_filters : bool
|
||||
If True, the number of filters in the parameters must be identical
|
||||
to those in the matching Tally. If False (default), the filters in
|
||||
the parameters may be a subset of those in the matching Tally.
|
||||
exact_nuclides : bool
|
||||
If True, the number of nuclides in the parameters must be identical
|
||||
to those in the matching Tally. If False (default), the nuclides in
|
||||
the parameters may be a subset of those in the matching Tally.
|
||||
exact_scores : bool
|
||||
If True, the number of scores in the parameters must be identical
|
||||
to those in the matching Tally. If False (default), the scores
|
||||
in the parameters may be a subset of those in the matching Tally.
|
||||
|
||||
Returns
|
||||
-------
|
||||
tally : Tally
|
||||
tally : openmc.Tally
|
||||
A tally matching the specified criteria
|
||||
|
||||
Raises
|
||||
|
|
@ -520,7 +569,15 @@ class StatePoint(object):
|
|||
continue
|
||||
|
||||
# Determine if Tally has queried estimator
|
||||
if estimator and not estimator == test_tally.estimator:
|
||||
if estimator and estimator != test_tally.estimator:
|
||||
continue
|
||||
|
||||
# The number of filters, nuclides and scores must exactly match
|
||||
if exact_scores and len(scores) != test_tally.num_scores:
|
||||
continue
|
||||
if exact_nuclides and len(nuclides) != test_tally.num_nuclides:
|
||||
continue
|
||||
if exact_filters and len(filters) != test_tally.num_filters:
|
||||
continue
|
||||
|
||||
# Determine if Tally has the queried score(s)
|
||||
|
|
@ -592,7 +649,7 @@ class StatePoint(object):
|
|||
|
||||
Parameters
|
||||
----------
|
||||
summary : Summary
|
||||
summary : openmc.Summary
|
||||
A Summary object.
|
||||
|
||||
Raises
|
||||
|
|
@ -603,17 +660,24 @@ class StatePoint(object):
|
|||
|
||||
"""
|
||||
|
||||
if self.summary is not None:
|
||||
warnings.warn('A Summary object has already been linked.',
|
||||
RuntimeWarning)
|
||||
return
|
||||
|
||||
if not isinstance(summary, openmc.summary.Summary):
|
||||
msg = 'Unable to link statepoint with "{0}" which ' \
|
||||
'is not a Summary object'.format(summary)
|
||||
raise ValueError(msg)
|
||||
|
||||
for tally_id, tally in self.tallies.items():
|
||||
# Get the Tally name from the summary file
|
||||
tally.name = summary.tallies[tally_id].name
|
||||
summary_tally = summary.tallies[tally_id]
|
||||
tally.name = summary_tally.name
|
||||
tally.with_summary = True
|
||||
|
||||
for tally_filter in tally.filters:
|
||||
summary_filter = summary_tally.find_filter(tally_filter.type)
|
||||
|
||||
if tally_filter.type == 'surface':
|
||||
surface_ids = []
|
||||
for bin in tally_filter.bins:
|
||||
|
|
@ -626,6 +690,10 @@ class StatePoint(object):
|
|||
distribcell_ids.append(summary.cells[bin].id)
|
||||
tally_filter.bins = distribcell_ids
|
||||
|
||||
if tally_filter.type == 'distribcell':
|
||||
tally_filter.distribcell_paths = \
|
||||
summary_filter.distribcell_paths
|
||||
|
||||
if tally_filter.type == 'universe':
|
||||
universe_ids = []
|
||||
for bin in tally_filter.bins:
|
||||
|
|
|
|||
|
|
@ -22,12 +22,12 @@ class UnitSphere(object):
|
|||
|
||||
Parameters
|
||||
----------
|
||||
reference_uvw : Iterable of Real
|
||||
reference_uvw : Iterable of float
|
||||
Direction from which polar angle is measured
|
||||
|
||||
Attributes
|
||||
----------
|
||||
reference_uvw : Iterable of Real
|
||||
reference_uvw : Iterable of float
|
||||
Direction from which polar angle is measured
|
||||
|
||||
"""
|
||||
|
|
@ -62,19 +62,19 @@ class PolarAzimuthal(UnitSphere):
|
|||
|
||||
Parameters
|
||||
----------
|
||||
mu : Univariate
|
||||
mu : openmc.stats.Univariate
|
||||
Distribution of the cosine of the polar angle
|
||||
phi : Univariate
|
||||
phi : openmc.stats.Univariate
|
||||
Distribution of the azimuthal angle in radians
|
||||
reference_uvw : Iterable of Real
|
||||
reference_uvw : Iterable of float
|
||||
Direction from which polar angle is measured. Defaults to the positive
|
||||
z-direction.
|
||||
|
||||
Attributes
|
||||
----------
|
||||
mu : Univariate
|
||||
mu : openmc.stats.Univariate
|
||||
Distribution of the cosine of the polar angle
|
||||
phi : Univariate
|
||||
phi : openmc.stats.Univariate
|
||||
Distribution of the azimuthal angle in radians
|
||||
|
||||
"""
|
||||
|
|
@ -142,7 +142,7 @@ class Monodirectional(UnitSphere):
|
|||
|
||||
Parameters
|
||||
----------
|
||||
reference_uvw : Iterable of Real
|
||||
reference_uvw : Iterable of float
|
||||
Direction from which polar angle is measured. Defaults to the positive
|
||||
x-direction.
|
||||
|
||||
|
|
@ -186,20 +186,20 @@ class CartesianIndependent(Spatial):
|
|||
|
||||
Parameters
|
||||
----------
|
||||
x : Univariate
|
||||
x : openmc.stats.Univariate
|
||||
Distribution of x-coordinates
|
||||
y : Univariate
|
||||
y : openmc.stats.Univariate
|
||||
Distribution of y-coordinates
|
||||
z : Univariate
|
||||
z : openmc.stats.Univariate
|
||||
Distribution of z-coordinates
|
||||
|
||||
Attributes
|
||||
----------
|
||||
x : Univariate
|
||||
x : openmc.stats.Univariate
|
||||
Distribution of x-coordinates
|
||||
y : Univariate
|
||||
y : openmc.stats.Univariate
|
||||
Distribution of y-coordinates
|
||||
z : Univariate
|
||||
z : openmc.stats.Univariate
|
||||
Distribution of z-coordinates
|
||||
|
||||
"""
|
||||
|
|
@ -252,9 +252,9 @@ class Box(Spatial):
|
|||
|
||||
Parameters
|
||||
----------
|
||||
lower_left : Iterable of Real
|
||||
lower_left : Iterable of float
|
||||
Lower-left coordinates of cuboid
|
||||
upper_right : Iterable of Real
|
||||
upper_right : Iterable of float
|
||||
Upper-right coordinates of cuboid
|
||||
only_fissionable : bool, optional
|
||||
Whether spatial sites should only be accepted if they occur in
|
||||
|
|
@ -262,9 +262,9 @@ class Box(Spatial):
|
|||
|
||||
Attributes
|
||||
----------
|
||||
lower_left : Iterable of Real
|
||||
lower_left : Iterable of float
|
||||
Lower-left coordinates of cuboid
|
||||
upper_right : Iterable of Real
|
||||
upper_right : Iterable of float
|
||||
Upper-right coordinates of cuboid
|
||||
only_fissionable : bool, optional
|
||||
Whether spatial sites should only be accepted if they occur in
|
||||
|
|
@ -328,17 +328,17 @@ class Point(Spatial):
|
|||
|
||||
Parameters
|
||||
----------
|
||||
xyz : Iterable of Real
|
||||
Cartesian coordinates of location
|
||||
xyz : Iterable of float, optional
|
||||
Cartesian coordinates of location. Defaults to (0., 0., 0.).
|
||||
|
||||
Attributes
|
||||
----------
|
||||
xyz : Iterable of Real
|
||||
xyz : Iterable of float
|
||||
Cartesian coordinates of location
|
||||
|
||||
"""
|
||||
|
||||
def __init__(self, xyz):
|
||||
def __init__(self, xyz=(0., 0., 0.)):
|
||||
super(Point, self).__init__()
|
||||
self.xyz = xyz
|
||||
|
||||
|
|
|
|||
|
|
@ -37,16 +37,16 @@ class Discrete(Univariate):
|
|||
|
||||
Parameters
|
||||
----------
|
||||
x : Iterable of Real
|
||||
x : Iterable of float
|
||||
Values of the random variable
|
||||
p : Iterable of Real
|
||||
p : Iterable of float
|
||||
Discrete probability for each value
|
||||
|
||||
Attributes
|
||||
----------
|
||||
x : Iterable of Real
|
||||
x : Iterable of float
|
||||
Values of the random variable
|
||||
p : Iterable of Real
|
||||
p : Iterable of float
|
||||
Discrete probability for each value
|
||||
|
||||
"""
|
||||
|
|
@ -66,14 +66,14 @@ class Discrete(Univariate):
|
|||
|
||||
@x.setter
|
||||
def x(self, x):
|
||||
if cv._isinstance(x, Real):
|
||||
if isinstance(x, Real):
|
||||
x = [x]
|
||||
cv.check_type('discrete values', x, Iterable, Real)
|
||||
self._x = x
|
||||
|
||||
@p.setter
|
||||
def p(self, p):
|
||||
if cv._isinstance(p, Real):
|
||||
if isinstance(p, Real):
|
||||
p = [p]
|
||||
cv.check_type('discrete probabilities', p, Iterable, Real)
|
||||
for pk in p:
|
||||
|
|
@ -243,9 +243,9 @@ class Tabular(Univariate):
|
|||
|
||||
Parameters
|
||||
----------
|
||||
x : Iterable of Real
|
||||
x : Iterable of float
|
||||
Tabulated values of the random variable
|
||||
p : Iterable of Real
|
||||
p : Iterable of float
|
||||
Tabulated probabilities
|
||||
interpolation : {'histogram', 'linear-linear'}, optional
|
||||
Indicate whether the density function is constant between tabulated
|
||||
|
|
@ -253,9 +253,9 @@ class Tabular(Univariate):
|
|||
|
||||
Attributes
|
||||
----------
|
||||
x : Iterable of Real
|
||||
x : Iterable of float
|
||||
Tabulated values of the random variable
|
||||
p : Iterable of Real
|
||||
p : Iterable of float
|
||||
Tabulated probabilities
|
||||
interpolation : {'histogram', 'linear-linear'}, optional
|
||||
Indicate whether the density function is constant between tabulated
|
||||
|
|
|
|||
|
|
@ -26,6 +26,10 @@ class Summary(object):
|
|||
# Python API so we'll only try to import h5py if the user actually inits
|
||||
# a Summary object.
|
||||
import h5py
|
||||
if h5py.__version__ == '2.6.0':
|
||||
raise ImportError("h5py 2.6.0 has a known bug which makes it "
|
||||
"incompatible with OpenMC's HDF5 files. "
|
||||
"Please switch to a different version.")
|
||||
|
||||
openmc.reset_auto_ids()
|
||||
|
||||
|
|
@ -38,8 +42,10 @@ class Summary(object):
|
|||
self._opencg_geometry = None
|
||||
|
||||
self._read_metadata()
|
||||
self._read_nuclides()
|
||||
self._read_geometry()
|
||||
self._read_tallies()
|
||||
self._f.close()
|
||||
|
||||
@property
|
||||
def openmc_geometry(self):
|
||||
|
|
@ -55,8 +61,8 @@ class Summary(object):
|
|||
def _read_metadata(self):
|
||||
# Read OpenMC version
|
||||
self.version = [self._f['version_major'].value,
|
||||
self._f['version_minor'].value,
|
||||
self._f['version_release'].value]
|
||||
self._f['version_minor'].value,
|
||||
self._f['version_release'].value]
|
||||
# Read date and time
|
||||
self.date_and_time = self._f['date_and_time'][...]
|
||||
|
||||
|
|
@ -65,11 +71,23 @@ class Summary(object):
|
|||
|
||||
self.n_batches = self._f['n_batches'].value
|
||||
self.n_particles = self._f['n_particles'].value
|
||||
self.n_active = self._f['n_active'].value
|
||||
self.n_inactive = self._f['n_inactive'].value
|
||||
self.gen_per_batch = self._f['gen_per_batch'].value
|
||||
if 'n_inactive' in self._f:
|
||||
self.n_active = self._f['n_active'].value
|
||||
self.n_inactive = self._f['n_inactive'].value
|
||||
self.gen_per_batch = self._f['gen_per_batch'].value
|
||||
self.n_procs = self._f['n_procs'].value
|
||||
|
||||
def _read_nuclides(self):
|
||||
self.nuclides = {}
|
||||
n_nuclides = self._f['nuclides/n_nuclides_total'].value
|
||||
names = self._f['nuclides/names'].value
|
||||
awrs = self._f['nuclides/awrs'].value
|
||||
zaids = self._f['nuclides/zaids'].value
|
||||
for n in range(n_nuclides):
|
||||
name = names[n].decode()
|
||||
name = name[:name.find('.')]
|
||||
self.nuclides[name] = (zaids[n], awrs[n])
|
||||
|
||||
def _read_geometry(self):
|
||||
# Read in and initialize the Materials and Geometry
|
||||
self._read_materials()
|
||||
|
|
@ -266,7 +284,7 @@ class Summary(object):
|
|||
rotation = \
|
||||
self._f['geometry/cells'][key]['rotation'][...]
|
||||
rotation = np.asarray(rotation, dtype=np.int)
|
||||
cell.rotation = rotation
|
||||
cell._rotation = rotation
|
||||
|
||||
# Store Cell fill information for after Universe/Lattice creation
|
||||
self._cell_fills[index] = (fill_type, fill)
|
||||
|
|
@ -344,7 +362,6 @@ class Summary(object):
|
|||
|
||||
# Create the Lattice
|
||||
lattice = openmc.RectLattice(lattice_id=lattice_id, name=name)
|
||||
lattice.dimension = tuple(dimension)
|
||||
lattice.lower_left = lower_left
|
||||
lattice.pitch = pitch
|
||||
|
||||
|
|
@ -354,7 +371,7 @@ class Summary(object):
|
|||
|
||||
# Build array of Universe pointers for the Lattice
|
||||
universes = \
|
||||
np.ndarray(tuple(universe_ids.shape), dtype=openmc.Universe)
|
||||
np.empty(tuple(universe_ids.shape), dtype=openmc.Universe)
|
||||
|
||||
for z in range(universe_ids.shape[0]):
|
||||
for y in range(universe_ids.shape[1]):
|
||||
|
|
@ -378,19 +395,17 @@ class Summary(object):
|
|||
self.lattices[index] = lattice
|
||||
|
||||
if lattice_type == 'hexagonal':
|
||||
n_rings = self._f['geometry/lattices'][key]['n_rings'][0]
|
||||
n_axial = self._f['geometry/lattices'][key]['n_axial'][0]
|
||||
n_rings = self._f['geometry/lattices'][key]['n_rings'].value
|
||||
n_axial = self._f['geometry/lattices'][key]['n_axial'].value
|
||||
center = self._f['geometry/lattices'][key]['center'][...]
|
||||
pitch = self._f['geometry/lattices'][key]['pitch'][...]
|
||||
outer = self._f['geometry/lattices'][key]['outer'][0]
|
||||
outer = self._f['geometry/lattices'][key]['outer'].value
|
||||
|
||||
universe_ids = self._f[
|
||||
'geometry/lattices'][key]['universes'][...]
|
||||
|
||||
# Create the Lattice
|
||||
lattice = openmc.HexLattice(lattice_id=lattice_id, name=name)
|
||||
lattice.num_rings = n_rings
|
||||
lattice.num_axial = n_axial
|
||||
lattice.center = center
|
||||
lattice.pitch = pitch
|
||||
|
||||
|
|
@ -403,12 +418,12 @@ class Summary(object):
|
|||
# (x, alpha, z) to the Python API's format of a ragged nested
|
||||
# list of (z, ring, theta).
|
||||
universes = []
|
||||
for z in range(lattice.num_axial):
|
||||
for z in range(n_axial):
|
||||
# Add a list for this axial level.
|
||||
universes.append([])
|
||||
x = lattice.num_rings - 1
|
||||
a = 2*lattice.num_rings - 2
|
||||
for r in range(lattice.num_rings - 1, 0, -1):
|
||||
x = n_rings - 1
|
||||
a = 2*n_rings - 2
|
||||
for r in range(n_rings - 1, 0, -1):
|
||||
# Add a list for this ring.
|
||||
universes[-1].append([])
|
||||
|
||||
|
|
@ -482,13 +497,13 @@ class Summary(object):
|
|||
# Retrieve the object corresponding to the fill type and ID
|
||||
if fill_type == 'normal':
|
||||
if isinstance(fill_id, Iterable):
|
||||
fill = [self.get_material_by_id(mat) if mat > 0 else 'void'
|
||||
fill = [self.get_material_by_id(mat) if mat > 0 else None
|
||||
for mat in fill_id]
|
||||
else:
|
||||
if fill_id > 0:
|
||||
fill = self.get_material_by_id(fill_id)
|
||||
else:
|
||||
fill = 'void'
|
||||
fill = None
|
||||
elif fill_type == 'universe':
|
||||
fill = self.get_universe_by_id(fill_id)
|
||||
else:
|
||||
|
|
@ -542,7 +557,7 @@ class Summary(object):
|
|||
# If this is a moment, use generic moment order
|
||||
pattern = r'-n$|-pn$|-yn$'
|
||||
score = re.sub(pattern, '-' + moments[j].decode(), score)
|
||||
tally.add_score(score)
|
||||
tally.scores.append(score)
|
||||
|
||||
# Read filter metadata
|
||||
num_filters = self._f['{0}/n_filters'.format(subbase)].value
|
||||
|
|
@ -562,8 +577,14 @@ class Summary(object):
|
|||
new_filter = openmc.Filter(filter_type, bins)
|
||||
new_filter.num_bins = num_bins
|
||||
|
||||
# Read in distribcell paths
|
||||
if filter_type == 'distribcell':
|
||||
paths = self._f['{0}/paths'.format(subsubbase)][...]
|
||||
paths = [str(path.decode()) for path in paths]
|
||||
new_filter.distribcell_paths = paths
|
||||
|
||||
# Add Filter to the Tally
|
||||
tally.add_filter(new_filter)
|
||||
tally.filters.append(new_filter)
|
||||
|
||||
# Add Tally to the global dictionary of all Tallies
|
||||
self.tallies[tally_id] = tally
|
||||
|
|
@ -578,7 +599,7 @@ class Summary(object):
|
|||
|
||||
Returns
|
||||
-------
|
||||
material : openmc.material.Material
|
||||
material : openmc.Material
|
||||
Material with given id
|
||||
|
||||
"""
|
||||
|
|
@ -599,7 +620,7 @@ class Summary(object):
|
|||
|
||||
Returns
|
||||
-------
|
||||
surface : openmc.surface.Surface
|
||||
surface : openmc.Surface
|
||||
Surface with given id
|
||||
|
||||
"""
|
||||
|
|
@ -620,7 +641,7 @@ class Summary(object):
|
|||
|
||||
Returns
|
||||
-------
|
||||
cell : openmc.universe.Cell
|
||||
cell : openmc.Cell
|
||||
Cell with given id
|
||||
|
||||
"""
|
||||
|
|
@ -641,7 +662,7 @@ class Summary(object):
|
|||
|
||||
Returns
|
||||
-------
|
||||
universe : openmc.universe.Universe
|
||||
universe : openmc.Universe
|
||||
Universe with given id
|
||||
|
||||
"""
|
||||
|
|
@ -662,7 +683,7 @@ class Summary(object):
|
|||
|
||||
Returns
|
||||
-------
|
||||
lattice : openmc.universe.Lattice
|
||||
lattice : openmc.Lattice
|
||||
Lattice with given id
|
||||
|
||||
"""
|
||||
|
|
|
|||
1126
openmc/surface.py
1126
openmc/surface.py
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
|
@ -1,8 +1,10 @@
|
|||
from numbers import Real
|
||||
from xml.etree import ElementTree as ET
|
||||
import sys
|
||||
import warnings
|
||||
from collections import Iterable
|
||||
|
||||
from openmc.checkvalue import check_type, check_value
|
||||
import openmc.checkvalue as cv
|
||||
|
||||
if sys.version_info[0] >= 3:
|
||||
basestring = str
|
||||
|
|
@ -46,9 +48,7 @@ class Trigger(object):
|
|||
clone._trigger_type = self._trigger_type
|
||||
clone._threshold = self._threshold
|
||||
|
||||
clone._scores = []
|
||||
for score in self._scores:
|
||||
clone.add_score(score)
|
||||
clone.scores = self.scores
|
||||
|
||||
memo[id(self)] = clone
|
||||
|
||||
|
|
@ -88,15 +88,26 @@ class Trigger(object):
|
|||
|
||||
@trigger_type.setter
|
||||
def trigger_type(self, trigger_type):
|
||||
check_value('tally trigger type', trigger_type,
|
||||
cv.check_value('tally trigger type', trigger_type,
|
||||
['variance', 'std_dev', 'rel_err'])
|
||||
self._trigger_type = trigger_type
|
||||
|
||||
@threshold.setter
|
||||
def threshold(self, threshold):
|
||||
check_type('tally trigger threshold', threshold, Real)
|
||||
cv.check_type('tally trigger threshold', threshold, Real)
|
||||
self._threshold = threshold
|
||||
|
||||
@scores.setter
|
||||
def scores(self, scores):
|
||||
cv.check_type('trigger scores', scores, Iterable, basestring)
|
||||
|
||||
# Set scores making sure not to have duplicates
|
||||
self._scores = []
|
||||
for score in scores:
|
||||
if score not in self._scores:
|
||||
self._scores.append(score)
|
||||
|
||||
|
||||
def add_score(self, score):
|
||||
"""Add a score to the list of scores to be checked against the trigger.
|
||||
|
||||
|
|
@ -107,16 +118,11 @@ class Trigger(object):
|
|||
|
||||
"""
|
||||
|
||||
if not isinstance(score, basestring):
|
||||
msg = 'Unable to add score "{0}" to tally trigger since ' \
|
||||
'it is not a string'.format(score)
|
||||
raise ValueError(msg)
|
||||
|
||||
# If the score is already in the Tally, don't add it again
|
||||
if score in self._scores:
|
||||
return
|
||||
else:
|
||||
self._scores.append(score)
|
||||
warnings.warn('Trigger.add_score(...) has been deprecated and may be '
|
||||
'removed in a future version. Tally trigger scores should '
|
||||
'be defined using the scores property directly.',
|
||||
DeprecationWarning)
|
||||
self.scores.append(score)
|
||||
|
||||
def get_trigger_xml(self, element):
|
||||
"""Return XML representation of the trigger
|
||||
|
|
|
|||
1458
openmc/universe.py
1458
openmc/universe.py
File diff suppressed because it is too large
Load diff
4
setup.py
4
setup.py
|
|
@ -11,7 +11,7 @@ except ImportError:
|
|||
|
||||
kwargs = {'name': 'openmc',
|
||||
'version': '0.7.1',
|
||||
'packages': ['openmc', 'openmc.mgxs', 'openmc.stats'],
|
||||
'packages': ['openmc', 'openmc.data', 'openmc.mgxs', 'openmc.stats'],
|
||||
'scripts': glob.glob('scripts/openmc-*'),
|
||||
|
||||
# Metadata
|
||||
|
|
@ -36,7 +36,7 @@ if have_setuptools:
|
|||
|
||||
# Optional dependencies
|
||||
'extras_require': {
|
||||
'pandas': ['pandas'],
|
||||
'pandas': ['pandas>=0.17.0'],
|
||||
'sparse' : ['scipy'],
|
||||
'vtk': ['vtk', 'silomesh'],
|
||||
'validate': ['lxml']
|
||||
|
|
|
|||
763
src/ace.F90
763
src/ace.F90
File diff suppressed because it is too large
Load diff
|
|
@ -1,58 +0,0 @@
|
|||
module ace_header
|
||||
|
||||
use constants, only: MAX_FILE_LEN, ZERO
|
||||
use dict_header, only: DictIntInt
|
||||
use endf_header, only: Tab1
|
||||
use secondary_header, only: SecondaryDistribution, AngleEnergyContainer
|
||||
use stl_vector, only: VectorInt
|
||||
|
||||
implicit none
|
||||
|
||||
!===============================================================================
|
||||
! REACTION contains the cross-section and secondary energy and angle
|
||||
! distributions for a single reaction in a continuous-energy ACE-format table
|
||||
!===============================================================================
|
||||
|
||||
type Reaction
|
||||
integer :: MT ! ENDF MT value
|
||||
real(8) :: Q_value ! Reaction Q value
|
||||
integer :: multiplicity ! Number of secondary particles released
|
||||
type(Tab1), pointer :: multiplicity_E => null() ! Energy-dependent neutron yield
|
||||
integer :: threshold ! Energy grid index of threshold
|
||||
logical :: scatter_in_cm ! scattering system in center-of-mass?
|
||||
logical :: multiplicity_with_E = .false. ! Flag to indicate E-dependent multiplicity
|
||||
real(8), allocatable :: sigma(:) ! Cross section values
|
||||
type(SecondaryDistribution) :: secondary
|
||||
|
||||
contains
|
||||
procedure :: clear => reaction_clear ! Deallocates Reaction
|
||||
end type Reaction
|
||||
|
||||
!===============================================================================
|
||||
! URRDATA contains probability tables for the unresolved resonance range.
|
||||
!===============================================================================
|
||||
|
||||
type UrrData
|
||||
integer :: n_energy ! # of incident neutron energies
|
||||
integer :: n_prob ! # of probabilities
|
||||
integer :: interp ! inteprolation (2=lin-lin, 5=log-log)
|
||||
integer :: inelastic_flag ! inelastic competition flag
|
||||
integer :: absorption_flag ! other absorption flag
|
||||
logical :: multiply_smooth ! multiply by smooth cross section?
|
||||
real(8), allocatable :: energy(:) ! incident energies
|
||||
real(8), allocatable :: prob(:,:,:) ! actual probabibility tables
|
||||
end type UrrData
|
||||
|
||||
contains
|
||||
|
||||
!===============================================================================
|
||||
! REACTION_CLEAR resets and deallocates data in Reaction.
|
||||
!===============================================================================
|
||||
|
||||
subroutine reaction_clear(this)
|
||||
class(Reaction), intent(inout) :: this ! The Reaction object to clear
|
||||
|
||||
if (associated(this % multiplicity_E)) deallocate(this % multiplicity_E)
|
||||
end subroutine reaction_clear
|
||||
|
||||
end module ace_header
|
||||
29
src/angleenergy_header.F90
Normal file
29
src/angleenergy_header.F90
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
module angleenergy_header
|
||||
|
||||
!===============================================================================
|
||||
! ANGLEENERGY (abstract) defines a correlated or uncorrelated angle-energy
|
||||
! distribution that is a function of incoming energy. Each derived type must
|
||||
! implement a sample() subroutine that returns an outgoing energy and scattering
|
||||
! cosine given an incoming energy.
|
||||
!===============================================================================
|
||||
|
||||
type, abstract :: AngleEnergy
|
||||
contains
|
||||
procedure(angleenergy_sample_), deferred :: sample
|
||||
end type AngleEnergy
|
||||
|
||||
abstract interface
|
||||
subroutine angleenergy_sample_(this, E_in, E_out, mu)
|
||||
import AngleEnergy
|
||||
class(AngleEnergy), intent(in) :: this
|
||||
real(8), intent(in) :: E_in
|
||||
real(8), intent(out) :: E_out
|
||||
real(8), intent(out) :: mu
|
||||
end subroutine angleenergy_sample_
|
||||
end interface
|
||||
|
||||
type :: AngleEnergyContainer
|
||||
class(AngleEnergy), allocatable :: obj
|
||||
end type AngleEnergyContainer
|
||||
|
||||
end module angleenergy_header
|
||||
|
|
@ -70,7 +70,7 @@ contains
|
|||
inquire(FILE=filename, EXIST=file_exists)
|
||||
if (.not. file_exists) then
|
||||
! CMFD is optional unless it is in on from settings
|
||||
if (cmfd_on) then
|
||||
if (cmfd_run) then
|
||||
call fatal_error("No CMFD XML file, '" // trim(filename) // "' does not&
|
||||
& exist!")
|
||||
end if
|
||||
|
|
|
|||
|
|
@ -37,7 +37,7 @@ module constants
|
|||
real(8), parameter :: FP_COINCIDENT = 1e-12_8
|
||||
|
||||
! Maximum number of collisions/crossings
|
||||
integer, parameter :: MAX_EVENTS = 10000
|
||||
integer, parameter :: MAX_EVENTS = 1000000
|
||||
integer, parameter :: MAX_SAMPLE = 100000
|
||||
|
||||
! Maximum number of secondary particles created
|
||||
|
|
@ -223,6 +223,12 @@ module constants
|
|||
NU_POLYNOMIAL = 1, & ! Nu values given by polynomial
|
||||
NU_TABULAR = 2 ! Nu values given by tabular distribution
|
||||
|
||||
! Secondary particle emission type
|
||||
integer, parameter :: &
|
||||
EMISSION_PROMPT = 1, & ! Prompt emission of secondary particle
|
||||
EMISSION_DELAYED = 2, & ! Delayed emission of secondary particle
|
||||
EMISSION_TOTAL = 3 ! Yield represents total emission (prompt + delayed)
|
||||
|
||||
! Cross section filetypes
|
||||
integer, parameter :: &
|
||||
ASCII = 1, & ! ASCII cross section file
|
||||
|
|
@ -273,7 +279,7 @@ module constants
|
|||
EVENT_ABSORB = 2
|
||||
|
||||
! Tally score type
|
||||
integer, parameter :: N_SCORE_TYPES = 22
|
||||
integer, parameter :: N_SCORE_TYPES = 20
|
||||
integer, parameter :: &
|
||||
SCORE_FLUX = -1, & ! flux
|
||||
SCORE_TOTAL = -2, & ! total reaction rate
|
||||
|
|
@ -283,20 +289,18 @@ module constants
|
|||
SCORE_SCATTER_PN = -6, & ! system for scoring 0th through nth moment
|
||||
SCORE_NU_SCATTER_N = -7, & ! arbitrary nu-scattering moment
|
||||
SCORE_NU_SCATTER_PN = -8, & ! system for scoring 0th through nth nu-scatter moment
|
||||
SCORE_TRANSPORT = -9, & ! transport reaction rate
|
||||
SCORE_N_1N = -10, & ! (n,1n) rate
|
||||
SCORE_ABSORPTION = -11, & ! absorption rate
|
||||
SCORE_FISSION = -12, & ! fission rate
|
||||
SCORE_NU_FISSION = -13, & ! neutron production rate
|
||||
SCORE_KAPPA_FISSION = -14, & ! fission energy production rate
|
||||
SCORE_CURRENT = -15, & ! partial current
|
||||
SCORE_FLUX_YN = -16, & ! angular moment of flux
|
||||
SCORE_TOTAL_YN = -17, & ! angular moment of total reaction rate
|
||||
SCORE_SCATTER_YN = -18, & ! angular flux-weighted scattering moment (0:N)
|
||||
SCORE_NU_SCATTER_YN = -19, & ! angular flux-weighted nu-scattering moment (0:N)
|
||||
SCORE_EVENTS = -20, & ! number of events
|
||||
SCORE_DELAYED_NU_FISSION = -21, & ! delayed neutron production rate
|
||||
SCORE_INVERSE_VELOCITY = -22 ! flux-weighted inverse velocity
|
||||
SCORE_ABSORPTION = -9, & ! absorption rate
|
||||
SCORE_FISSION = -10, & ! fission rate
|
||||
SCORE_NU_FISSION = -11, & ! neutron production rate
|
||||
SCORE_KAPPA_FISSION = -12, & ! fission energy production rate
|
||||
SCORE_CURRENT = -13, & ! partial current
|
||||
SCORE_FLUX_YN = -14, & ! angular moment of flux
|
||||
SCORE_TOTAL_YN = -15, & ! angular moment of total reaction rate
|
||||
SCORE_SCATTER_YN = -16, & ! angular flux-weighted scattering moment (0:N)
|
||||
SCORE_NU_SCATTER_YN = -17, & ! angular flux-weighted nu-scattering moment (0:N)
|
||||
SCORE_EVENTS = -18, & ! number of events
|
||||
SCORE_DELAYED_NU_FISSION = -19, & ! delayed neutron production rate
|
||||
SCORE_INVERSE_VELOCITY = -20 ! flux-weighted inverse velocity
|
||||
|
||||
! Maximum scattering order supported
|
||||
integer, parameter :: MAX_ANG_ORDER = 10
|
||||
|
|
@ -365,10 +369,11 @@ module constants
|
|||
! ============================================================================
|
||||
! RANDOM NUMBER STREAM CONSTANTS
|
||||
|
||||
integer, parameter :: N_STREAMS = 3
|
||||
integer, parameter :: STREAM_TRACKING = 1
|
||||
integer, parameter :: STREAM_TALLIES = 2
|
||||
integer, parameter :: STREAM_SOURCE = 3
|
||||
integer, parameter :: N_STREAMS = 4
|
||||
integer, parameter :: STREAM_TRACKING = 1
|
||||
integer, parameter :: STREAM_TALLIES = 2
|
||||
integer, parameter :: STREAM_SOURCE = 3
|
||||
integer, parameter :: STREAM_URR_PTABLE = 4
|
||||
|
||||
! ============================================================================
|
||||
! MISCELLANEOUS CONSTANTS
|
||||
|
|
|
|||
|
|
@ -1,16 +1,14 @@
|
|||
module cross_section
|
||||
|
||||
use ace_header, only: Reaction, UrrData
|
||||
use constants
|
||||
use energy_grid, only: grid_method, log_spacing
|
||||
use error, only: fatal_error
|
||||
use fission, only: nu_total
|
||||
use global
|
||||
use list_header, only: ListElemInt
|
||||
use material_header, only: Material
|
||||
use nuclide_header
|
||||
use particle_header, only: Particle
|
||||
use random_lcg, only: prn
|
||||
use random_lcg, only: prn, future_prn, prn_set_stream
|
||||
use sab_header, only: SAlphaBeta
|
||||
use search, only: binary_search
|
||||
|
||||
|
|
@ -148,7 +146,7 @@ contains
|
|||
integer :: i_low ! lower logarithmic mapping index
|
||||
integer :: i_high ! upper logarithmic mapping index
|
||||
real(8) :: f ! interp factor on nuclide energy grid
|
||||
type(NuclideCE), pointer :: nuc
|
||||
type(Nuclide), pointer :: nuc
|
||||
type(Material), pointer :: mat
|
||||
|
||||
! Set pointer to nuclide and material
|
||||
|
|
@ -354,154 +352,136 @@ contains
|
|||
integer, intent(in) :: i_nuclide ! index into nuclides array
|
||||
real(8), intent(in) :: E ! energy
|
||||
|
||||
integer :: i ! loop index
|
||||
integer :: i_energy ! index for energy
|
||||
integer :: i_low ! band index at lower bounding energy
|
||||
integer :: i_up ! band index at upper bounding energy
|
||||
integer :: same_nuc_idx ! index of same nuclide
|
||||
real(8) :: f ! interpolation factor
|
||||
real(8) :: r ! pseudo-random number
|
||||
real(8) :: elastic ! elastic cross section
|
||||
real(8) :: capture ! (n,gamma) cross section
|
||||
real(8) :: fission ! fission cross section
|
||||
real(8) :: inelastic ! inelastic cross section
|
||||
logical :: same_nuc ! do we know the xs for this nuclide at this energy?
|
||||
type(UrrData), pointer :: urr
|
||||
type(NuclideCE), pointer :: nuc
|
||||
|
||||
micro_xs(i_nuclide) % use_ptable = .true.
|
||||
|
||||
! get pointer to probability table
|
||||
nuc => nuclides(i_nuclide)
|
||||
urr => nuc % urr_data
|
||||
associate (nuc => nuclides(i_nuclide), urr => nuclides(i_nuclide) % urr_data)
|
||||
! determine energy table
|
||||
i_energy = 1
|
||||
do
|
||||
if (E < urr % energy(i_energy + 1)) exit
|
||||
i_energy = i_energy + 1
|
||||
end do
|
||||
|
||||
! determine energy table
|
||||
i_energy = 1
|
||||
do
|
||||
if (E < urr % energy(i_energy + 1)) exit
|
||||
i_energy = i_energy + 1
|
||||
end do
|
||||
! determine interpolation factor on table
|
||||
f = (E - urr % energy(i_energy)) / &
|
||||
(urr % energy(i_energy + 1) - urr % energy(i_energy))
|
||||
|
||||
! determine interpolation factor on table
|
||||
f = (E - urr % energy(i_energy)) / &
|
||||
(urr % energy(i_energy + 1) - urr % energy(i_energy))
|
||||
! sample probability table using the cumulative distribution
|
||||
|
||||
! sample probability table using the cumulative distribution
|
||||
! Random numbers for xs calculation are sampled from a separated stream.
|
||||
! This guarantees the randomness and, at the same time, makes sure we reuse
|
||||
! random number for the same nuclide at different temperatures, therefore
|
||||
! preserving correlation of temperature in probability tables.
|
||||
call prn_set_stream(STREAM_URR_PTABLE)
|
||||
r = future_prn(int(nuc_zaid_dict % get_key(nuc % zaid), 8))
|
||||
call prn_set_stream(STREAM_TRACKING)
|
||||
|
||||
! if we're dealing with a nuclide that we've previously encountered at
|
||||
! this energy but a different temperature, use the original random number to
|
||||
! preserve correlation of temperature in probability tables
|
||||
same_nuc = .false.
|
||||
do i = 1, nuc % nuc_list % size()
|
||||
if (E /= ZERO .and. E == micro_xs(nuc % nuc_list % data(i)) % last_E) then
|
||||
same_nuc = .true.
|
||||
same_nuc_idx = i
|
||||
exit
|
||||
end if
|
||||
end do
|
||||
i_low = 1
|
||||
do
|
||||
if (urr % prob(i_energy, URR_CUM_PROB, i_low) > r) exit
|
||||
i_low = i_low + 1
|
||||
end do
|
||||
i_up = 1
|
||||
do
|
||||
if (urr % prob(i_energy + 1, URR_CUM_PROB, i_up) > r) exit
|
||||
i_up = i_up + 1
|
||||
end do
|
||||
|
||||
if (same_nuc) then
|
||||
r = micro_xs(nuc % nuc_list % data(same_nuc_idx)) % last_prn
|
||||
else
|
||||
r = prn()
|
||||
micro_xs(i_nuclide) % last_prn = r
|
||||
end if
|
||||
! determine elastic, fission, and capture cross sections from probability
|
||||
! table
|
||||
if (urr % interp == LINEAR_LINEAR) then
|
||||
elastic = (ONE - f) * urr % prob(i_energy, URR_ELASTIC, i_low) + &
|
||||
f * urr % prob(i_energy + 1, URR_ELASTIC, i_up)
|
||||
fission = (ONE - f) * urr % prob(i_energy, URR_FISSION, i_low) + &
|
||||
f * urr % prob(i_energy + 1, URR_FISSION, i_up)
|
||||
capture = (ONE - f) * urr % prob(i_energy, URR_N_GAMMA, i_low) + &
|
||||
f * urr % prob(i_energy + 1, URR_N_GAMMA, i_up)
|
||||
elseif (urr % interp == LOG_LOG) then
|
||||
! Get logarithmic interpolation factor
|
||||
f = log(E / urr % energy(i_energy)) / &
|
||||
log(urr % energy(i_energy + 1) / urr % energy(i_energy))
|
||||
|
||||
i_low = 1
|
||||
do
|
||||
if (urr % prob(i_energy, URR_CUM_PROB, i_low) > r) exit
|
||||
i_low = i_low + 1
|
||||
end do
|
||||
i_up = 1
|
||||
do
|
||||
if (urr % prob(i_energy + 1, URR_CUM_PROB, i_up) > r) exit
|
||||
i_up = i_up + 1
|
||||
end do
|
||||
|
||||
! determine elastic, fission, and capture cross sections from probability
|
||||
! table
|
||||
if (urr % interp == LINEAR_LINEAR) then
|
||||
elastic = (ONE - f) * urr % prob(i_energy, URR_ELASTIC, i_low) + &
|
||||
f * urr % prob(i_energy + 1, URR_ELASTIC, i_up)
|
||||
fission = (ONE - f) * urr % prob(i_energy, URR_FISSION, i_low) + &
|
||||
f * urr % prob(i_energy + 1, URR_FISSION, i_up)
|
||||
capture = (ONE - f) * urr % prob(i_energy, URR_N_GAMMA, i_low) + &
|
||||
f * urr % prob(i_energy + 1, URR_N_GAMMA, i_up)
|
||||
elseif (urr % interp == LOG_LOG) then
|
||||
! Get logarithmic interpolation factor
|
||||
f = log(E / urr % energy(i_energy)) / &
|
||||
log(urr % energy(i_energy + 1) / urr % energy(i_energy))
|
||||
|
||||
! Calculate elastic cross section/factor
|
||||
elastic = ZERO
|
||||
if (urr % prob(i_energy, URR_ELASTIC, i_low) > ZERO .and. &
|
||||
urr % prob(i_energy + 1, URR_ELASTIC, i_up) > ZERO) then
|
||||
elastic = exp((ONE - f) * log(urr % prob(i_energy, URR_ELASTIC, &
|
||||
i_low)) + f * log(urr % prob(i_energy + 1, URR_ELASTIC, &
|
||||
i_up)))
|
||||
end if
|
||||
|
||||
! Calculate fission cross section/factor
|
||||
fission = ZERO
|
||||
if (urr % prob(i_energy, URR_FISSION, i_low) > ZERO .and. &
|
||||
urr % prob(i_energy + 1, URR_FISSION, i_up) > ZERO) then
|
||||
fission = exp((ONE - f) * log(urr % prob(i_energy, URR_FISSION, &
|
||||
i_low)) + f * log(urr % prob(i_energy + 1, URR_FISSION, &
|
||||
i_up)))
|
||||
end if
|
||||
|
||||
! Calculate capture cross section/factor
|
||||
capture = ZERO
|
||||
if (urr % prob(i_energy, URR_N_GAMMA, i_low) > ZERO .and. &
|
||||
urr % prob(i_energy + 1, URR_N_GAMMA, i_up) > ZERO) then
|
||||
capture = exp((ONE - f) * log(urr % prob(i_energy, URR_N_GAMMA, &
|
||||
i_low)) + f * log(urr % prob(i_energy + 1, URR_N_GAMMA, &
|
||||
i_up)))
|
||||
end if
|
||||
end if
|
||||
|
||||
! Determine treatment of inelastic scattering
|
||||
inelastic = ZERO
|
||||
if (urr % inelastic_flag > 0) then
|
||||
! Get index on energy grid and interpolation factor
|
||||
i_energy = micro_xs(i_nuclide) % index_grid
|
||||
f = micro_xs(i_nuclide) % interp_factor
|
||||
|
||||
! Determine inelastic scattering cross section
|
||||
associate (rxn => nuc % reactions(nuc % urr_inelastic))
|
||||
if (i_energy >= rxn % threshold) then
|
||||
inelastic = (ONE - f) * rxn % sigma(i_energy - rxn%threshold + 1) + &
|
||||
f * rxn % sigma(i_energy - rxn%threshold + 2)
|
||||
! Calculate elastic cross section/factor
|
||||
elastic = ZERO
|
||||
if (urr % prob(i_energy, URR_ELASTIC, i_low) > ZERO .and. &
|
||||
urr % prob(i_energy + 1, URR_ELASTIC, i_up) > ZERO) then
|
||||
elastic = exp((ONE - f) * log(urr % prob(i_energy, URR_ELASTIC, &
|
||||
i_low)) + f * log(urr % prob(i_energy + 1, URR_ELASTIC, &
|
||||
i_up)))
|
||||
end if
|
||||
end associate
|
||||
end if
|
||||
|
||||
! Multiply by smooth cross-section if needed
|
||||
if (urr % multiply_smooth) then
|
||||
elastic = elastic * micro_xs(i_nuclide) % elastic
|
||||
capture = capture * (micro_xs(i_nuclide) % absorption - &
|
||||
micro_xs(i_nuclide) % fission)
|
||||
fission = fission * micro_xs(i_nuclide) % fission
|
||||
end if
|
||||
! Calculate fission cross section/factor
|
||||
fission = ZERO
|
||||
if (urr % prob(i_energy, URR_FISSION, i_low) > ZERO .and. &
|
||||
urr % prob(i_energy + 1, URR_FISSION, i_up) > ZERO) then
|
||||
fission = exp((ONE - f) * log(urr % prob(i_energy, URR_FISSION, &
|
||||
i_low)) + f * log(urr % prob(i_energy + 1, URR_FISSION, &
|
||||
i_up)))
|
||||
end if
|
||||
|
||||
! Check for negative values
|
||||
if (elastic < ZERO) elastic = ZERO
|
||||
if (fission < ZERO) fission = ZERO
|
||||
if (capture < ZERO) capture = ZERO
|
||||
! Calculate capture cross section/factor
|
||||
capture = ZERO
|
||||
if (urr % prob(i_energy, URR_N_GAMMA, i_low) > ZERO .and. &
|
||||
urr % prob(i_energy + 1, URR_N_GAMMA, i_up) > ZERO) then
|
||||
capture = exp((ONE - f) * log(urr % prob(i_energy, URR_N_GAMMA, &
|
||||
i_low)) + f * log(urr % prob(i_energy + 1, URR_N_GAMMA, &
|
||||
i_up)))
|
||||
end if
|
||||
end if
|
||||
|
||||
! Set elastic, absorption, fission, and total cross sections. Note that the
|
||||
! total cross section is calculated as sum of partials rather than using the
|
||||
! table-provided value
|
||||
micro_xs(i_nuclide) % elastic = elastic
|
||||
micro_xs(i_nuclide) % absorption = capture + fission
|
||||
micro_xs(i_nuclide) % fission = fission
|
||||
micro_xs(i_nuclide) % total = elastic + inelastic + capture + fission
|
||||
! Determine treatment of inelastic scattering
|
||||
inelastic = ZERO
|
||||
if (urr % inelastic_flag > 0) then
|
||||
! Get index on energy grid and interpolation factor
|
||||
i_energy = micro_xs(i_nuclide) % index_grid
|
||||
f = micro_xs(i_nuclide) % interp_factor
|
||||
|
||||
! Determine nu-fission cross section
|
||||
if (nuc % fissionable) then
|
||||
micro_xs(i_nuclide) % nu_fission = nu_total(nuc, E) * &
|
||||
micro_xs(i_nuclide) % fission
|
||||
end if
|
||||
! Determine inelastic scattering cross section
|
||||
associate (rxn => nuc % reactions(nuc % urr_inelastic))
|
||||
if (i_energy >= rxn % threshold) then
|
||||
inelastic = (ONE - f) * rxn % sigma(i_energy - rxn%threshold + 1) + &
|
||||
f * rxn % sigma(i_energy - rxn%threshold + 2)
|
||||
end if
|
||||
end associate
|
||||
end if
|
||||
|
||||
! Multiply by smooth cross-section if needed
|
||||
if (urr % multiply_smooth) then
|
||||
elastic = elastic * micro_xs(i_nuclide) % elastic
|
||||
capture = capture * (micro_xs(i_nuclide) % absorption - &
|
||||
micro_xs(i_nuclide) % fission)
|
||||
fission = fission * micro_xs(i_nuclide) % fission
|
||||
end if
|
||||
|
||||
! Check for negative values
|
||||
if (elastic < ZERO) elastic = ZERO
|
||||
if (fission < ZERO) fission = ZERO
|
||||
if (capture < ZERO) capture = ZERO
|
||||
|
||||
! Set elastic, absorption, fission, and total cross sections. Note that the
|
||||
! total cross section is calculated as sum of partials rather than using the
|
||||
! table-provided value
|
||||
micro_xs(i_nuclide) % elastic = elastic
|
||||
micro_xs(i_nuclide) % absorption = capture + fission
|
||||
micro_xs(i_nuclide) % fission = fission
|
||||
micro_xs(i_nuclide) % total = elastic + inelastic + capture + fission
|
||||
|
||||
! Determine nu-fission cross section
|
||||
if (nuc % fissionable) then
|
||||
micro_xs(i_nuclide) % nu_fission = nuc % nu(E, EMISSION_TOTAL) * &
|
||||
micro_xs(i_nuclide) % fission
|
||||
end if
|
||||
end associate
|
||||
|
||||
end subroutine calculate_urr_xs
|
||||
|
||||
|
|
@ -533,9 +513,9 @@ contains
|
|||
!===============================================================================
|
||||
|
||||
pure function elastic_xs_0K(E, nuc) result(xs_out)
|
||||
real(8), intent(in) :: E ! trial energy
|
||||
type(NuclideCE), intent(in) :: nuc ! target nuclide at temperature
|
||||
real(8) :: xs_out ! 0K xs at trial energy
|
||||
real(8), intent(in) :: E ! trial energy
|
||||
type(Nuclide), intent(in) :: nuc ! target nuclide at temperature
|
||||
real(8) :: xs_out ! 0K xs at trial energy
|
||||
|
||||
integer :: i_grid ! index on nuclide energy grid
|
||||
real(8) :: f ! interp factor on nuclide energy grid
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ module eigenvalue
|
|||
use math, only: t_percentile
|
||||
use mesh, only: count_bank_sites
|
||||
use mesh_header, only: RegularMesh
|
||||
use random_lcg, only: prn, set_particle_seed, prn_skip
|
||||
use random_lcg, only: prn, set_particle_seed, advance_prn_seed
|
||||
use search, only: binary_search
|
||||
use string, only: to_str
|
||||
|
||||
|
|
@ -99,7 +99,7 @@ contains
|
|||
|
||||
call set_particle_seed(int((current_batch - 1)*gen_per_batch + &
|
||||
current_gen,8))
|
||||
call prn_skip(start)
|
||||
call advance_prn_seed(start)
|
||||
|
||||
! Determine how many fission sites we need to sample from the source bank
|
||||
! and the probability for selecting a site.
|
||||
|
|
|
|||
|
|
@ -34,10 +34,6 @@ contains
|
|||
string = "nu-scatter-n"
|
||||
case (SCORE_NU_SCATTER_PN)
|
||||
string = "nu-scatter-pn"
|
||||
case (SCORE_TRANSPORT)
|
||||
string = "transport"
|
||||
case (SCORE_N_1N)
|
||||
string = "n1n"
|
||||
case (SCORE_ABSORPTION)
|
||||
string = "absorption"
|
||||
case (SCORE_FISSION)
|
||||
|
|
|
|||
|
|
@ -1,12 +1,51 @@
|
|||
module endf_header
|
||||
|
||||
implicit none
|
||||
use constants, only: ZERO, HISTOGRAM, LINEAR_LINEAR, LINEAR_LOG, &
|
||||
LOG_LINEAR, LOG_LOG
|
||||
use search, only: binary_search
|
||||
|
||||
implicit none
|
||||
|
||||
type, abstract :: Function1D
|
||||
contains
|
||||
procedure(function1d_evaluate_), deferred :: evaluate
|
||||
end type Function1D
|
||||
|
||||
abstract interface
|
||||
pure function function1d_evaluate_(this, x) result(y)
|
||||
import Function1D
|
||||
class(Function1D), intent(in) :: this
|
||||
real(8), intent(in) :: x
|
||||
real(8) :: y
|
||||
end function function1d_evaluate_
|
||||
end interface
|
||||
|
||||
!===============================================================================
|
||||
! TAB1 represents a one-dimensional interpolable function
|
||||
! CONSTANT1D represents a constant one-dimensional function
|
||||
!===============================================================================
|
||||
|
||||
type Tab1
|
||||
type, extends(Function1D) :: Constant1D
|
||||
real(8) :: y
|
||||
contains
|
||||
procedure :: evaluate => constant1d_evaluate
|
||||
end type Constant1D
|
||||
|
||||
!===============================================================================
|
||||
! POLYNOMIAL represents a one-dimensional function expressed as a polynomial
|
||||
!===============================================================================
|
||||
|
||||
type, extends(Function1D) :: Polynomial
|
||||
real(8), allocatable :: coef(:) ! coefficients
|
||||
contains
|
||||
procedure :: evaluate => polynomial_evaluate
|
||||
procedure :: from_ace => polynomial_from_ace
|
||||
end type Polynomial
|
||||
|
||||
!===============================================================================
|
||||
! TABULATED1D represents a one-dimensional interpolable function
|
||||
!===============================================================================
|
||||
|
||||
type, extends(Function1D) :: Tabulated1D
|
||||
integer :: n_regions = 0 ! # of interpolation regions
|
||||
integer, allocatable :: nbt(:) ! values separating interpolation regions
|
||||
integer, allocatable :: int(:) ! interpolation scheme
|
||||
|
|
@ -14,18 +53,78 @@ module endf_header
|
|||
real(8), allocatable :: x(:) ! values of abscissa
|
||||
real(8), allocatable :: y(:) ! values of ordinate
|
||||
contains
|
||||
procedure :: from_ace
|
||||
end type Tab1
|
||||
procedure :: from_ace => tabulated1d_from_ace
|
||||
procedure :: evaluate => tabulated1d_evaluate
|
||||
end type Tabulated1D
|
||||
|
||||
contains
|
||||
|
||||
subroutine from_ace(this, xss, idx)
|
||||
class(Tab1), intent(inout) :: this
|
||||
!===============================================================================
|
||||
! Constant1D implementation
|
||||
!===============================================================================
|
||||
|
||||
pure function constant1d_evaluate(this, x) result(y)
|
||||
class(Constant1D), intent(in) :: this
|
||||
real(8), intent(in) :: x
|
||||
real(8) :: y
|
||||
|
||||
y = this % y
|
||||
end function constant1d_evaluate
|
||||
|
||||
!===============================================================================
|
||||
! Polynomial implementation
|
||||
!===============================================================================
|
||||
|
||||
subroutine polynomial_from_ace(this, xss, idx)
|
||||
class(Polynomial), intent(inout) :: this
|
||||
real(8), intent(in) :: xss(:)
|
||||
integer, intent(in) :: idx
|
||||
|
||||
integer :: nc ! number of coefficients (order - 1)
|
||||
|
||||
! Clear space
|
||||
if (allocated(this % coef)) deallocate(this % coef)
|
||||
|
||||
! Determine number of coefficients
|
||||
nc = nint(xss(idx))
|
||||
|
||||
! Allocate space for and read coefficients
|
||||
allocate(this % coef(nc))
|
||||
this % coef(:) = xss(idx + 1 : idx + nc)
|
||||
end subroutine polynomial_from_ace
|
||||
|
||||
pure function polynomial_evaluate(this, x) result(y)
|
||||
class(Polynomial), intent(in) :: this
|
||||
real(8), intent(in) :: x
|
||||
real(8) :: y
|
||||
|
||||
integer :: i
|
||||
|
||||
! Use Horner's rule to evaluate polynomial. Note that coefficients are
|
||||
! ordered in increasing powers of x.
|
||||
y = ZERO
|
||||
do i = size(this % coef), 1, -1
|
||||
y = y*x + this % coef(i)
|
||||
end do
|
||||
end function polynomial_evaluate
|
||||
|
||||
!===============================================================================
|
||||
! Tabulated1D implementation
|
||||
!===============================================================================
|
||||
|
||||
subroutine tabulated1d_from_ace(this, xss, idx)
|
||||
class(Tabulated1D), intent(inout) :: this
|
||||
real(8), intent(in) :: xss(:)
|
||||
integer, intent(in) :: idx
|
||||
|
||||
integer :: nr, ne
|
||||
|
||||
! Clear space
|
||||
if (allocated(this % nbt)) deallocate(this % nbt)
|
||||
if (allocated(this % int)) deallocate(this % int)
|
||||
if (allocated(this % x)) deallocate(this % x)
|
||||
if (allocated(this % y)) deallocate(this % y)
|
||||
|
||||
! Determine number of regions
|
||||
nr = nint(xss(idx))
|
||||
this%n_regions = nr
|
||||
|
|
@ -47,6 +146,81 @@ contains
|
|||
allocate(this%y(ne))
|
||||
this%x(:) = xss(idx + 2*nr + 2 : idx + 2*nr + 1 + ne)
|
||||
this%y(:) = xss(idx + 2*nr + 2 + ne : idx + 2*nr + 1 + 2*ne)
|
||||
end subroutine from_ace
|
||||
end subroutine tabulated1d_from_ace
|
||||
|
||||
pure function tabulated1d_evaluate(this, x) result(y)
|
||||
class(Tabulated1D), intent(in) :: this
|
||||
real(8), intent(in) :: x ! x value to find y at
|
||||
real(8) :: y ! y(x)
|
||||
|
||||
integer :: i ! bin in which to interpolate
|
||||
integer :: j ! index for interpolation region
|
||||
integer :: n_regions ! number of interpolation regions
|
||||
integer :: n_pairs ! number of tabulated values
|
||||
integer :: interp ! ENDF interpolation scheme
|
||||
real(8) :: r ! interpolation factor
|
||||
real(8) :: x0, x1 ! bounding x values
|
||||
real(8) :: y0, y1 ! bounding y values
|
||||
|
||||
! determine number of interpolation regions and pairs
|
||||
n_regions = this % n_regions
|
||||
n_pairs = this % n_pairs
|
||||
|
||||
! find which bin the abscissa is in -- if the abscissa is outside the
|
||||
! tabulated range, the first or last point is chosen, i.e. no interpolation
|
||||
! is done outside the energy range
|
||||
if (x < this % x(1)) then
|
||||
y = this % y(1)
|
||||
return
|
||||
elseif (x > this % x(n_pairs)) then
|
||||
y = this % y(n_pairs)
|
||||
return
|
||||
else
|
||||
i = binary_search(this % x, n_pairs, x)
|
||||
end if
|
||||
|
||||
! determine interpolation scheme
|
||||
if (n_regions == 0) then
|
||||
interp = LINEAR_LINEAR
|
||||
elseif (n_regions == 1) then
|
||||
interp = this % int(1)
|
||||
elseif (n_regions > 1) then
|
||||
do j = 1, n_regions
|
||||
if (i < this % nbt(j)) then
|
||||
interp = this % int(j)
|
||||
exit
|
||||
end if
|
||||
end do
|
||||
end if
|
||||
|
||||
! handle special case of histogram interpolation
|
||||
if (interp == HISTOGRAM) then
|
||||
y = this % y(i)
|
||||
return
|
||||
end if
|
||||
|
||||
! determine bounding values
|
||||
x0 = this % x(i)
|
||||
x1 = this % x(i + 1)
|
||||
y0 = this % y(i)
|
||||
y1 = this % y(i + 1)
|
||||
|
||||
! determine interpolation factor and interpolated value
|
||||
select case (interp)
|
||||
case (LINEAR_LINEAR)
|
||||
r = (x - x0)/(x1 - x0)
|
||||
y = y0 + r*(y1 - y0)
|
||||
case (LINEAR_LOG)
|
||||
r = log(x/x0)/log(x1/x0)
|
||||
y = y0 + r*(y1 - y0)
|
||||
case (LOG_LINEAR)
|
||||
r = (x - x0)/(x1 - x0)
|
||||
y = y0*exp(r*log(y1/y0))
|
||||
case (LOG_LOG)
|
||||
r = log(x/x0)/log(x1/x0)
|
||||
y = y0*exp(r*log(y1/y0))
|
||||
end select
|
||||
|
||||
end function tabulated1d_evaluate
|
||||
|
||||
end module endf_header
|
||||
|
|
|
|||
|
|
@ -1,8 +1,7 @@
|
|||
module energy_distribution
|
||||
|
||||
use constants, only: ZERO, ONE, TWO, PI, HISTOGRAM, LINEAR_LINEAR
|
||||
use endf_header, only: Tab1
|
||||
use interpolation, only: interpolate_tab1
|
||||
use endf_header, only: Tabulated1D
|
||||
use math, only: maxwell_spectrum, watt_spectrum
|
||||
use random_lcg, only: prn
|
||||
use search, only: binary_search
|
||||
|
|
@ -83,8 +82,8 @@ module energy_distribution
|
|||
integer :: n_region
|
||||
integer, allocatable :: breakpoints(:)
|
||||
integer, allocatable :: interpolation(:)
|
||||
real(8), allocatable :: energy_in(:)
|
||||
type(CTTable), allocatable :: energy_out(:)
|
||||
real(8), allocatable :: energy(:)
|
||||
type(CTTable), allocatable :: distribution(:)
|
||||
contains
|
||||
procedure :: sample => continuous_sample
|
||||
end type ContinuousTabular
|
||||
|
|
@ -95,7 +94,7 @@ module energy_distribution
|
|||
!===============================================================================
|
||||
|
||||
type, extends(EnergyDistribution) :: MaxwellEnergy
|
||||
type(Tab1) :: theta ! incoming-energy-dependent parameter
|
||||
type(Tabulated1D) :: theta ! incoming-energy-dependent parameter
|
||||
real(8) :: u ! restriction energy
|
||||
contains
|
||||
procedure :: sample => maxwellenergy_sample
|
||||
|
|
@ -107,7 +106,7 @@ module energy_distribution
|
|||
!===============================================================================
|
||||
|
||||
type, extends(EnergyDistribution) :: Evaporation
|
||||
type(Tab1) :: theta
|
||||
type(Tabulated1D) :: theta
|
||||
real(8) :: u
|
||||
contains
|
||||
procedure :: sample => evaporation_sample
|
||||
|
|
@ -119,28 +118,13 @@ module energy_distribution
|
|||
!===============================================================================
|
||||
|
||||
type, extends(EnergyDistribution) :: WattEnergy
|
||||
type(Tab1) :: a
|
||||
type(Tab1) :: b
|
||||
type(Tabulated1D) :: a
|
||||
type(Tabulated1D) :: b
|
||||
real(8) :: u
|
||||
contains
|
||||
procedure :: sample => watt_sample
|
||||
end type WattEnergy
|
||||
|
||||
!===============================================================================
|
||||
! NBODYPHASESPACE gives the energy distribution for particles emitted from
|
||||
! neutron and charged-particle reactions. This corresponds to ACE law 66 and
|
||||
! ENDF File 6, LAW=6.
|
||||
!===============================================================================
|
||||
|
||||
type, extends(EnergyDistribution) :: NBodyPhaseSpace
|
||||
integer :: n_bodies
|
||||
real(8) :: mass_ratio
|
||||
real(8) :: A
|
||||
real(8) :: Q
|
||||
contains
|
||||
procedure :: sample => nbody_sample
|
||||
end type NBodyPhaseSpace
|
||||
|
||||
contains
|
||||
|
||||
function equiprobable_sample(this, E_in) result(E_out)
|
||||
|
|
@ -202,6 +186,7 @@ contains
|
|||
end if
|
||||
end function equiprobable_sample
|
||||
|
||||
|
||||
function level_inelastic_sample(this, E_in) result(E_out)
|
||||
class(LevelInelastic), intent(in) :: this
|
||||
real(8), intent(in) :: E_in
|
||||
|
|
@ -210,6 +195,7 @@ contains
|
|||
E_out = this%mass_ratio*(E_in - this%threshold)
|
||||
end function level_inelastic_sample
|
||||
|
||||
|
||||
function continuous_sample(this, E_in) result(E_out)
|
||||
class(ContinuousTabular), intent(in) :: this
|
||||
real(8), intent(in) :: E_in ! incoming energy
|
||||
|
|
@ -238,17 +224,17 @@ contains
|
|||
|
||||
! Find energy bin and calculate interpolation factor -- if the energy is
|
||||
! outside the range of the tabulated energies, choose the first or last bins
|
||||
n_energy_in = size(this%energy_in)
|
||||
if (E_in < this%energy_in(1)) then
|
||||
n_energy_in = size(this%energy)
|
||||
if (E_in < this%energy(1)) then
|
||||
i = 1
|
||||
r = ZERO
|
||||
elseif (E_in > this%energy_in(n_energy_in)) then
|
||||
elseif (E_in > this%energy(n_energy_in)) then
|
||||
i = n_energy_in - 1
|
||||
r = ONE
|
||||
else
|
||||
i = binary_search(this%energy_in, n_energy_in, E_in)
|
||||
r = (E_in - this%energy_in(i)) / &
|
||||
(this%energy_in(i+1) - this%energy_in(i))
|
||||
i = binary_search(this%energy, n_energy_in, E_in)
|
||||
r = (E_in - this%energy(i)) / &
|
||||
(this%energy(i+1) - this%energy(i))
|
||||
end if
|
||||
|
||||
! Sample between the ith and (i+1)th bin
|
||||
|
|
@ -263,23 +249,23 @@ contains
|
|||
end if
|
||||
|
||||
! Interpolation for energy E1 and EK
|
||||
n_energy_out = size(this%energy_out(i)%e_out)
|
||||
E_i_1 = this%energy_out(i)%e_out(1)
|
||||
E_i_K = this%energy_out(i)%e_out(n_energy_out)
|
||||
n_energy_out = size(this%distribution(i)%e_out)
|
||||
E_i_1 = this%distribution(i)%e_out(1)
|
||||
E_i_K = this%distribution(i)%e_out(n_energy_out)
|
||||
|
||||
n_energy_out = size(this%energy_out(i+1)%e_out)
|
||||
E_i1_1 = this%energy_out(i+1)%e_out(1)
|
||||
E_i1_K = this%energy_out(i+1)%e_out(n_energy_out)
|
||||
n_energy_out = size(this%distribution(i+1)%e_out)
|
||||
E_i1_1 = this%distribution(i+1)%e_out(1)
|
||||
E_i1_K = this%distribution(i+1)%e_out(n_energy_out)
|
||||
|
||||
E_1 = E_i_1 + r*(E_i1_1 - E_i_1)
|
||||
E_K = E_i_K + r*(E_i1_K - E_i_K)
|
||||
|
||||
! Determine outgoing energy bin
|
||||
n_energy_out = size(this%energy_out(l)%e_out)
|
||||
n_energy_out = size(this%distribution(l)%e_out)
|
||||
r1 = prn()
|
||||
c_k = this%energy_out(l)%c(1)
|
||||
c_k = this%distribution(l)%c(1)
|
||||
do k = 1, n_energy_out - 1
|
||||
c_k1 = this%energy_out(l)%c(k+1)
|
||||
c_k1 = this%distribution(l)%c(k+1)
|
||||
if (r1 < c_k1) exit
|
||||
c_k = c_k1
|
||||
end do
|
||||
|
|
@ -287,9 +273,9 @@ contains
|
|||
! Check to make sure k is <= NP - 1
|
||||
k = min(k, n_energy_out - 1)
|
||||
|
||||
E_l_k = this%energy_out(l)%e_out(k)
|
||||
p_l_k = this%energy_out(l)%p(k)
|
||||
if (this%energy_out(l)%interpolation == HISTOGRAM) then
|
||||
E_l_k = this%distribution(l)%e_out(k)
|
||||
p_l_k = this%distribution(l)%p(k)
|
||||
if (this%distribution(l)%interpolation == HISTOGRAM) then
|
||||
! Histogram interpolation
|
||||
if (p_l_k > ZERO) then
|
||||
E_out = E_l_k + (r1 - c_k)/p_l_k
|
||||
|
|
@ -297,10 +283,10 @@ contains
|
|||
E_out = E_l_k
|
||||
end if
|
||||
|
||||
elseif (this%energy_out(l)%interpolation == LINEAR_LINEAR) then
|
||||
elseif (this%distribution(l)%interpolation == LINEAR_LINEAR) then
|
||||
! Linear-linear interpolation
|
||||
E_l_k1 = this%energy_out(l)%e_out(k+1)
|
||||
p_l_k1 = this%energy_out(l)%p(k+1)
|
||||
E_l_k1 = this%distribution(l)%e_out(k+1)
|
||||
p_l_k1 = this%distribution(l)%p(k+1)
|
||||
|
||||
frac = (p_l_k1 - p_l_k)/(E_l_k1 - E_l_k)
|
||||
if (frac == ZERO) then
|
||||
|
|
@ -321,6 +307,7 @@ contains
|
|||
end if
|
||||
end function continuous_sample
|
||||
|
||||
|
||||
function maxwellenergy_sample(this, E_in) result(E_out)
|
||||
class(MaxwellEnergy), intent(in) :: this
|
||||
real(8), intent(in) :: E_in ! incoming energy
|
||||
|
|
@ -329,7 +316,7 @@ contains
|
|||
real(8) :: theta ! Maxwell distribution parameter
|
||||
|
||||
! Get temperature corresponding to incoming energy
|
||||
theta = interpolate_tab1(this%theta, E_in)
|
||||
theta = this % theta % evaluate(E_in)
|
||||
|
||||
do
|
||||
! Sample maxwell fission spectrum
|
||||
|
|
@ -349,9 +336,9 @@ contains
|
|||
real(8) :: x, y, v
|
||||
|
||||
! Get temperature corresponding to incoming energy
|
||||
theta = interpolate_tab1(this%theta, E_in)
|
||||
theta = this % theta % evaluate(E_in)
|
||||
|
||||
y = (E_in - this%U)/theta
|
||||
y = (E_in - this%u)/theta
|
||||
v = 1 - exp(-y)
|
||||
|
||||
! Sample outgoing energy based on evaporation spectrum probability
|
||||
|
|
@ -372,10 +359,10 @@ contains
|
|||
real(8) :: a, b ! Watt spectrum parameters
|
||||
|
||||
! Determine Watt parameter 'a' from tabulated function
|
||||
a = interpolate_tab1(this%a, E_in)
|
||||
a = this % a % evaluate(E_in)
|
||||
|
||||
! Determine Watt parameter 'b' from tabulated function
|
||||
b = interpolate_tab1(this%b, E_in)
|
||||
b = this % b % evaluate(E_in)
|
||||
|
||||
do
|
||||
! Sample energy-dependent Watt fission spectrum
|
||||
|
|
@ -386,44 +373,4 @@ contains
|
|||
end do
|
||||
end function watt_sample
|
||||
|
||||
function nbody_sample(this, E_in) result(E_out)
|
||||
class(NBodyPhaseSpace), intent(in) :: this
|
||||
real(8), intent(in) :: E_in ! incoming energy
|
||||
real(8) :: E_out ! sampled outgoing energy
|
||||
|
||||
real(8) :: Ap ! total mass of particles in neutron masses
|
||||
real(8) :: E_max ! maximum possible COM energy
|
||||
real(8) :: x, y, v
|
||||
real(8) :: r1, r2, r3, r4, r5, r6
|
||||
|
||||
! Determine E_max parameter
|
||||
Ap = this%mass_ratio
|
||||
E_max = (Ap - ONE)/Ap * (this%A/(this%A + ONE)*E_in + this%Q)
|
||||
|
||||
! x is essentially a Maxwellian distribution
|
||||
x = maxwell_spectrum(ONE)
|
||||
|
||||
select case (this%n_bodies)
|
||||
case (3)
|
||||
y = maxwell_spectrum(ONE)
|
||||
case (4)
|
||||
r1 = prn()
|
||||
r2 = prn()
|
||||
r3 = prn()
|
||||
y = -log(r1*r2*r3)
|
||||
case (5)
|
||||
r1 = prn()
|
||||
r2 = prn()
|
||||
r3 = prn()
|
||||
r4 = prn()
|
||||
r5 = prn()
|
||||
r6 = prn()
|
||||
y = -log(r1*r2*r3*r4) - log(r5) * cos(PI/TWO*r6)**2
|
||||
end select
|
||||
|
||||
! Now determine v and E_out
|
||||
v = x/(x+y)
|
||||
E_out = E_max * v
|
||||
end function nbody_sample
|
||||
|
||||
end module energy_distribution
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@ contains
|
|||
integer :: i ! index in nuclides array
|
||||
integer :: j ! index in materials array
|
||||
type(ListReal) :: list
|
||||
type(NuclideCE), pointer :: nuc
|
||||
type(Nuclide), pointer :: nuc
|
||||
type(Material), pointer :: mat
|
||||
|
||||
call write_message("Creating unionized energy grid...", 5)
|
||||
|
|
@ -70,7 +70,7 @@ contains
|
|||
real(8) :: E_max ! Maximum energy in MeV
|
||||
real(8) :: E_min ! Minimum energy in MeV
|
||||
real(8), allocatable :: umesh(:) ! Equally log-spaced energy grid
|
||||
type(NuclideCE), pointer :: nuc
|
||||
type(Nuclide), pointer :: nuc
|
||||
|
||||
! Set minimum/maximum energies
|
||||
E_max = energy_max_neutron
|
||||
|
|
@ -179,7 +179,7 @@ contains
|
|||
integer :: index_e ! index on union energy grid
|
||||
real(8) :: union_energy ! energy on union grid
|
||||
real(8) :: energy ! energy on nuclide grid
|
||||
type(NuclideCE), pointer :: nuc
|
||||
type(Nuclide), pointer :: nuc
|
||||
type(Material), pointer :: mat
|
||||
|
||||
do k = 1, n_materials
|
||||
|
|
|
|||
161
src/fission.F90
161
src/fission.F90
|
|
@ -1,161 +0,0 @@
|
|||
module fission
|
||||
|
||||
use nuclide_header, only: NuclideCE
|
||||
use constants
|
||||
use error, only: fatal_error
|
||||
use interpolation, only: interpolate_tab1
|
||||
use search, only: binary_search
|
||||
|
||||
implicit none
|
||||
|
||||
contains
|
||||
|
||||
!===============================================================================
|
||||
! NU_TOTAL calculates the total number of neutrons emitted per fission for a
|
||||
! given nuclide and incoming neutron energy
|
||||
!===============================================================================
|
||||
|
||||
pure function nu_total(nuc, E) result(nu)
|
||||
type(NuclideCE), intent(in) :: nuc ! nuclide from which to find nu
|
||||
real(8), intent(in) :: E ! energy of incoming neutron
|
||||
real(8) :: nu ! number of total neutrons emitted per fission
|
||||
|
||||
integer :: i ! loop index
|
||||
integer :: NC ! number of polynomial coefficients
|
||||
real(8) :: c ! polynomial coefficient
|
||||
|
||||
if (nuc % nu_t_type == NU_NONE) then
|
||||
nu = ERROR_REAL
|
||||
elseif (nuc % nu_t_type == NU_POLYNOMIAL) then
|
||||
! determine number of coefficients
|
||||
NC = int(nuc % nu_t_data(1))
|
||||
|
||||
! sum up polynomial in energy
|
||||
nu = ZERO
|
||||
do i = 0, NC - 1
|
||||
c = nuc % nu_t_data(i+2)
|
||||
nu = nu + c * E**i
|
||||
end do
|
||||
elseif (nuc % nu_t_type == NU_TABULAR) then
|
||||
! use ENDF interpolation laws to determine nu
|
||||
nu = interpolate_tab1(nuc % nu_t_data, E)
|
||||
end if
|
||||
|
||||
end function nu_total
|
||||
|
||||
!===============================================================================
|
||||
! NU_PROMPT calculates the total number of prompt neutrons emitted per fission
|
||||
! for a given nuclide and incoming neutron energy
|
||||
!===============================================================================
|
||||
|
||||
pure function nu_prompt(nuc, E) result(nu)
|
||||
type(NuclideCE), intent(in) :: nuc ! nuclide from which to find nu
|
||||
real(8), intent(in) :: E ! energy of incoming neutron
|
||||
real(8) :: nu ! number of prompt neutrons emitted per fission
|
||||
|
||||
integer :: i ! loop index
|
||||
integer :: NC ! number of polynomial coefficients
|
||||
real(8) :: c ! polynomial coefficient
|
||||
|
||||
if (nuc % nu_p_type == NU_NONE) then
|
||||
! since no prompt or delayed data is present, this means all neutron
|
||||
! emission is prompt -- WARNING: This currently returns zero. The calling
|
||||
! routine needs to know this situation is occurring since we don't want
|
||||
! to call nu_total unnecessarily if it has already been called.
|
||||
nu = ZERO
|
||||
elseif (nuc % nu_p_type == NU_POLYNOMIAL) then
|
||||
! determine number of coefficients
|
||||
NC = int(nuc % nu_p_data(1))
|
||||
|
||||
! sum up polynomial in energy
|
||||
nu = ZERO
|
||||
do i = 0, NC - 1
|
||||
c = nuc % nu_p_data(i+2)
|
||||
nu = nu + c * E**i
|
||||
end do
|
||||
elseif (nuc % nu_p_type == NU_TABULAR) then
|
||||
! use ENDF interpolation laws to determine nu
|
||||
nu = interpolate_tab1(nuc % nu_p_data, E)
|
||||
end if
|
||||
|
||||
end function nu_prompt
|
||||
|
||||
!===============================================================================
|
||||
! NU_DELAYED calculates the total number of delayed neutrons emitted per fission
|
||||
! for a given nuclide and incoming neutron energy
|
||||
!===============================================================================
|
||||
|
||||
pure function nu_delayed(nuc, E) result(nu)
|
||||
type(NuclideCE), intent(in) :: nuc ! nuclide from which to find nu
|
||||
real(8), intent(in) :: E ! energy of incoming neutron
|
||||
real(8) :: nu ! number of delayed neutrons emitted per fission
|
||||
|
||||
if (nuc % nu_d_type == NU_NONE) then
|
||||
! since no prompt or delayed data is present, this means all neutron
|
||||
! emission is prompt -- WARNING: This currently returns zero. The calling
|
||||
! routine needs to know this situation is occurring since we don't want
|
||||
! to call nu_delayed unnecessarily if it has already been called.
|
||||
nu = ZERO
|
||||
elseif (nuc % nu_d_type == NU_TABULAR) then
|
||||
! use ENDF interpolation laws to determine nu
|
||||
nu = interpolate_tab1(nuc % nu_d_data, E)
|
||||
end if
|
||||
|
||||
end function nu_delayed
|
||||
|
||||
!===============================================================================
|
||||
! YIELD_DELAYED calculates the fractional yield of delayed neutrons emitted for
|
||||
! a given nuclide and incoming neutron energy in a given delayed group.
|
||||
!===============================================================================
|
||||
|
||||
pure function yield_delayed(nuc, E, g) result(yield)
|
||||
type(NuclideCE), intent(in) :: nuc ! nuclide from which to find nu
|
||||
real(8), intent(in) :: E ! energy of incoming neutron
|
||||
real(8) :: yield ! delayed neutron precursor yield
|
||||
integer, intent(in) :: g ! the delayed neutron precursor group
|
||||
integer :: d ! precursor group
|
||||
integer :: lc ! index before start of energies/nu values
|
||||
integer :: NR ! number of interpolation regions
|
||||
integer :: NE ! number of energies tabulated
|
||||
|
||||
yield = ZERO
|
||||
|
||||
if (g > nuc % n_precursor .or. g < 1) then
|
||||
! if the precursor group is outside the range of precursor groups for
|
||||
! the input nuclide, return ZERO.
|
||||
yield = ZERO
|
||||
else if (nuc % nu_d_type == NU_NONE) then
|
||||
! since no prompt or delayed data is present, this means all neutron
|
||||
! emission is prompt -- WARNING: This currently returns zero. The calling
|
||||
! routine needs to know this situation is occurring since we don't want
|
||||
! to call yield_delayed unnecessarily if it has already been called.
|
||||
yield = ZERO
|
||||
else if (nuc % nu_d_type == NU_TABULAR) then
|
||||
|
||||
lc = 1
|
||||
|
||||
! loop over delayed groups and determine the yield for the desired group
|
||||
do d = 1, nuc % n_precursor
|
||||
|
||||
! determine number of interpolation regions and energies
|
||||
NR = int(nuc % nu_d_precursor_data(lc + 1))
|
||||
NE = int(nuc % nu_d_precursor_data(lc + 2 + 2*NR))
|
||||
|
||||
! check if this is the desired group
|
||||
if (d == g) then
|
||||
|
||||
! determine delayed neutron precursor yield for group g
|
||||
yield = interpolate_tab1(nuc % nu_d_precursor_data( &
|
||||
lc+1:lc+2+2*NR+2*NE), E)
|
||||
|
||||
exit
|
||||
end if
|
||||
|
||||
! advance pointer
|
||||
lc = lc + 2 + 2*NR + 2*NE + 1
|
||||
end do
|
||||
end if
|
||||
|
||||
end function yield_delayed
|
||||
|
||||
end module fission
|
||||
|
|
@ -378,6 +378,7 @@ contains
|
|||
real(8) :: v ! y-component of direction
|
||||
real(8) :: w ! z-component of direction
|
||||
real(8) :: norm ! "norm" of surface normal
|
||||
real(8) :: xyz(3) ! Saved global coordinate
|
||||
integer :: i_surface ! index in surfaces
|
||||
logical :: found ! particle found in universe?
|
||||
class(Surface), pointer :: surf
|
||||
|
|
@ -432,12 +433,13 @@ contains
|
|||
|
||||
! Score surface currents since reflection causes the direction of the
|
||||
! particle to change -- artificially move the particle slightly back in
|
||||
! case the surface crossing in coincident with a mesh boundary
|
||||
! case the surface crossing is coincident with a mesh boundary
|
||||
|
||||
if (active_current_tallies % size() > 0) then
|
||||
xyz = p % coord(1) % xyz
|
||||
p % coord(1) % xyz = p % coord(1) % xyz - TINY_BIT * p % coord(1) % uvw
|
||||
call score_surface_current(p)
|
||||
p % coord(1) % xyz = p % coord(1) % xyz + TINY_BIT * p % coord(1) % uvw
|
||||
p % coord(1) % xyz = xyz
|
||||
end if
|
||||
|
||||
! Reflect particle off surface
|
||||
|
|
@ -475,6 +477,70 @@ contains
|
|||
&// trim(to_str(surf%id)))
|
||||
end if
|
||||
return
|
||||
elseif (surf % bc == BC_PERIODIC .and. run_mode /= MODE_PLOTTING) then
|
||||
! =======================================================================
|
||||
! PERIODIC BOUNDARY
|
||||
|
||||
! Do not handle periodic boundary conditions on lower universes
|
||||
if (p % n_coord /= 1) then
|
||||
call handle_lost_particle(p, "Cannot transfer particle " &
|
||||
// trim(to_str(p % id)) // " across surface in a lower universe.&
|
||||
& Boundary conditions must be applied to universe 0.")
|
||||
return
|
||||
end if
|
||||
|
||||
! Score surface currents since reflection causes the direction of the
|
||||
! particle to change -- artificially move the particle slightly back in
|
||||
! case the surface crossing is coincident with a mesh boundary
|
||||
|
||||
if (active_current_tallies % size() > 0) then
|
||||
xyz = p % coord(1) % xyz
|
||||
p % coord(1) % xyz = p % coord(1) % xyz - TINY_BIT * p % coord(1) % uvw
|
||||
call score_surface_current(p)
|
||||
p % coord(1) % xyz = xyz
|
||||
end if
|
||||
|
||||
select type (surf)
|
||||
type is (SurfaceXPlane)
|
||||
select type (opposite => surfaces(surf % i_periodic) % obj)
|
||||
type is (SurfaceXPlane)
|
||||
p % coord(1) % xyz(1) = opposite % x0
|
||||
end select
|
||||
|
||||
type is (SurfaceYPlane)
|
||||
select type (opposite => surfaces(surf % i_periodic) % obj)
|
||||
type is (SurfaceYPlane)
|
||||
p % coord(1) % xyz(2) = opposite % y0
|
||||
end select
|
||||
|
||||
type is (SurfaceZPlane)
|
||||
select type (opposite => surfaces(surf % i_periodic) % obj)
|
||||
type is (SurfaceZPlane)
|
||||
p % coord(1) % xyz(3) = opposite % z0
|
||||
end select
|
||||
end select
|
||||
|
||||
! Reassign particle's surface
|
||||
p % surface = sign(surf % i_periodic, p % surface)
|
||||
|
||||
! Figure out what cell particle is in now
|
||||
p % n_coord = 1
|
||||
call find_cell(p, found)
|
||||
if (.not. found) then
|
||||
call handle_lost_particle(p, "Couldn't find particle after hitting &
|
||||
&periodic boundary on surface " // trim(to_str(surf%id)) // ".")
|
||||
return
|
||||
end if
|
||||
|
||||
! Set previous coordinate going slightly past surface crossing
|
||||
p % last_xyz = p % coord(1) % xyz + TINY_BIT * p % coord(1) % uvw
|
||||
|
||||
! Diagnostic message
|
||||
if (verbosity >= 10 .or. trace) then
|
||||
call write_message(" Hit periodic boundary on surface " &
|
||||
// trim(to_str(surf%id)))
|
||||
end if
|
||||
return
|
||||
end if
|
||||
|
||||
! ==========================================================================
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
module geometry_header
|
||||
|
||||
use constants, only: HALF, TWO, THREE
|
||||
use constants, only: HALF, TWO, THREE, INFINITY
|
||||
|
||||
implicit none
|
||||
|
||||
|
|
@ -201,20 +201,22 @@ contains
|
|||
real(8), intent(in) :: global_xyz(3)
|
||||
integer :: i_xyz(3)
|
||||
|
||||
real(8) :: xyz(3) ! global_xyz alias
|
||||
real(8) :: xyz(3) ! global xyz relative to the center
|
||||
real(8) :: alpha ! Skewed coord axis
|
||||
real(8) :: xyz_t(3) ! Local xyz
|
||||
real(8) :: dists(4) ! Squared distances from cell centers
|
||||
real(8) :: d, d_min ! Squared distance from cell centers
|
||||
integer :: i, j, k ! Iterators
|
||||
integer :: loc(1) ! Minimum distance index
|
||||
integer :: k_min ! Minimum distance index
|
||||
|
||||
xyz = global_xyz
|
||||
xyz(1) = global_xyz(1) - this % center(1)
|
||||
xyz(2) = global_xyz(2) - this % center(2)
|
||||
|
||||
! Index z direction.
|
||||
if (this % is_3d) then
|
||||
i_xyz(3) = ceiling((xyz(3) - this % center(3))/this % pitch(2) + HALF)&
|
||||
+ this % n_axial/2
|
||||
xyz(3) = global_xyz(3) - this % center(3)
|
||||
i_xyz(3) = ceiling(xyz(3)/this % pitch(2) + HALF*this % n_axial)
|
||||
else
|
||||
xyz(3) = global_xyz(3)
|
||||
i_xyz(3) = 1
|
||||
end if
|
||||
|
||||
|
|
@ -233,28 +235,33 @@ contains
|
|||
! the four possible cells. Regular hexagonal tiles form a centroidal
|
||||
! Voronoi tessellation so the global xyz should be in the hexagonal cell
|
||||
! that it is closest to the center of. This method is used over a
|
||||
! method that uses the remainders of the floor divisions above becasue it
|
||||
! method that uses the remainders of the floor divisions above because it
|
||||
! provides better finite precision performance. Squared distances are
|
||||
! used becasue they are more computationally efficient than normal
|
||||
! distances.
|
||||
k = 1
|
||||
do i=0,1
|
||||
do j=0,1
|
||||
xyz_t = this % get_local_xyz(xyz, i_xyz + (/j, i, 0/))
|
||||
dists(k) = xyz_t(1)**2 + xyz_t(2)**2
|
||||
d_min = INFINITY
|
||||
do i = 0, 1
|
||||
do j = 0, 1
|
||||
xyz_t = this % get_local_xyz(global_xyz, i_xyz + [j, i, 0])
|
||||
d = xyz_t(1)**2 + xyz_t(2)**2
|
||||
if (d < d_min) then
|
||||
d_min = d
|
||||
k_min = k
|
||||
end if
|
||||
k = k + 1
|
||||
end do
|
||||
end do
|
||||
|
||||
! Select the minimum squared distance which corresponds to the cell the
|
||||
! coordinates are in.
|
||||
loc = minloc(dists)
|
||||
if (loc(1) == 2) then
|
||||
i_xyz = i_xyz + (/1, 0, 0/)
|
||||
else if (loc(1) == 3) then
|
||||
i_xyz = i_xyz + (/0, 1, 0/)
|
||||
else if (loc(1) == 4) then
|
||||
i_xyz = i_xyz + (/1, 1, 0/)
|
||||
if (k_min == 2) then
|
||||
i_xyz(1) = i_xyz(1) + 1
|
||||
else if (k_min == 3) then
|
||||
i_xyz(2) = i_xyz(2) + 1
|
||||
else if (k_min == 4) then
|
||||
i_xyz(1) = i_xyz(1) + 1
|
||||
i_xyz(2) = i_xyz(2) + 1
|
||||
end if
|
||||
end function get_inds_hex
|
||||
|
||||
|
|
@ -303,7 +310,7 @@ contains
|
|||
(i_xyz(1) - this % n_rings) * this % pitch(1) / TWO)
|
||||
if (this % is_3d) then
|
||||
local_xyz(3) = xyz(3) - this % center(3) &
|
||||
+ (this % n_axial/2 - i_xyz(3) + 1) * this % pitch(2)
|
||||
+ (HALF*this % n_axial - i_xyz(3) + HALF) * this % pitch(2)
|
||||
else
|
||||
local_xyz(3) = xyz(3)
|
||||
end if
|
||||
|
|
|
|||
|
|
@ -5,9 +5,9 @@ module global
|
|||
use constants
|
||||
use dict_header, only: DictCharInt, DictIntInt
|
||||
use geometry_header, only: Cell, Universe, Lattice, LatticeContainer
|
||||
use macroxs_header, only: MacroXSContainer
|
||||
use material_header, only: Material
|
||||
use mesh_header, only: RegularMesh
|
||||
use mgxs_header, only: Mgxs, MgxsContainer
|
||||
use nuclide_header
|
||||
use plot_header, only: ObjectPlot
|
||||
use sab_header, only: SAlphaBeta
|
||||
|
|
@ -86,7 +86,7 @@ module global
|
|||
! CONTINUOUS-ENERGY CROSS SECTION RELATED VARIABLES
|
||||
|
||||
! Cross section arrays
|
||||
type(NuclideCE), allocatable, target :: nuclides(:) ! Nuclide cross-sections
|
||||
type(Nuclide), allocatable, target :: nuclides(:) ! Nuclide cross-sections
|
||||
type(SAlphaBeta), allocatable, target :: sab_tables(:) ! S(a,b) tables
|
||||
|
||||
integer :: n_sab_tables ! Number of S(a,b) thermal scattering tables
|
||||
|
|
@ -104,14 +104,18 @@ module global
|
|||
! What to assume for expanding natural elements
|
||||
integer :: default_expand = ENDF_BVII1
|
||||
|
||||
! Total amount of nuclide ZAID and dictionary of nuclide ZAID and index
|
||||
integer(8) :: n_nuc_zaid_total
|
||||
type(DictIntInt) :: nuc_zaid_dict
|
||||
|
||||
! ============================================================================
|
||||
! MULTI-GROUP CROSS SECTION RELATED VARIABLES
|
||||
|
||||
! Cross section arrays
|
||||
type(NuclideMGContainer), allocatable, target :: nuclides_MG(:)
|
||||
type(MgxsContainer), allocatable, target :: nuclides_MG(:)
|
||||
|
||||
! Cross section caches
|
||||
type(MacroXSContainer), target, allocatable :: macro_xs(:)
|
||||
type(MgxsContainer), target, allocatable :: macro_xs(:)
|
||||
|
||||
! Number of energy groups
|
||||
integer :: energy_groups
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue