mirror of
https://github.com/openmc-dev/openmc.git
synced 2026-07-27 13:45:36 -04:00
Merge pull request #471 from wbinventor/mgxs
Multi-Group Cross Section Generation Module
This commit is contained in:
commit
96e92e4306
48 changed files with 10809 additions and 1955 deletions
7
.gitignore
vendored
7
.gitignore
vendored
|
|
@ -64,3 +64,10 @@ data/nndc
|
|||
|
||||
# IPython notebook checkpoints
|
||||
.ipynb_checkpoints
|
||||
|
||||
# Multi-group cross section IPython Notebook
|
||||
docs/source/pythonapi/examples/*.xml
|
||||
docs/source/pythonapi/examples/*.png
|
||||
docs/source/pythonapi/examples/*.xls
|
||||
docs/source/pythonapi/examples/mgxs
|
||||
docs/source/pythonapi/examples/tracks
|
||||
|
|
@ -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
|
||||
- conda create -q -n test-environment python=$TRAVIS_PYTHON_VERSION numpy scipy h5py pandas
|
||||
- source activate test-environment
|
||||
|
||||
# Install GCC, MPICH, HDF5, PHDF5
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@ sys.path.insert(0, os.path.abspath('../..'))
|
|||
extensions = ['sphinx.ext.autodoc',
|
||||
'sphinx.ext.napoleon',
|
||||
'sphinx.ext.pngmath',
|
||||
'sphinx.ext.autosummary',
|
||||
'sphinxcontrib.tikz',
|
||||
'sphinx_numfig',
|
||||
'notebook_sphinxext']
|
||||
|
|
|
|||
8
docs/source/pythonapi/energy_groups.rst
Normal file
8
docs/source/pythonapi/energy_groups.rst
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
.. _pythonapi_energy_groups:
|
||||
|
||||
=============
|
||||
Energy Groups
|
||||
=============
|
||||
|
||||
.. automodule:: openmc.mgxs.groups
|
||||
:members:
|
||||
2461
docs/source/pythonapi/examples/multi-group-cross-sections.ipynb
Normal file
2461
docs/source/pythonapi/examples/multi-group-cross-sections.ipynb
Normal file
File diff suppressed because one or more lines are too long
|
|
@ -0,0 +1,11 @@
|
|||
====================================
|
||||
Multi-Group Cross Section Generation
|
||||
====================================
|
||||
|
||||
.. only:: html
|
||||
|
||||
.. notebook:: multi-group-cross-sections.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
|
|
@ -336,7 +336,18 @@
|
|||
"metadata": {
|
||||
"collapsed": false
|
||||
},
|
||||
"outputs": [],
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"0"
|
||||
]
|
||||
},
|
||||
"execution_count": 13,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"# Run openmc in plotting mode\n",
|
||||
"executor = openmc.Executor()\n",
|
||||
|
|
@ -352,7 +363,7 @@
|
|||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
"image/png": "iVBORw0KGgoAAAANSUhEUgAAAPoAAAD6AgMAAAD1grKuAAAABGdBTUEAALGPC/xhBQAAACBjSFJN\nAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAADFBMVEX///9yEhLpgJFNv8Tq\nQYT7AAAAAWJLR0QAiAUdSAAAAAd0SU1FB98KAwI1HbUKyRQAAAPZSURBVGje7Zs7buMwEIZ9iey5\n0gyNjQpXKTYudIScgkdQYTfut1idwkdQkQNsYQO2Qj0sPiVK+mlQDmwgwIcgg8Cc4fCTSK5W4OeF\nkM8rHv+2I/rgxPZEPZgR7XtQxKdXYuUXJSUnBQ/9WCgo4vOSJ+WFUvF7E08mlia+rn7VcKXP8sRs\nzFX8b2MdX2y6v1Tw6MZUw4H4ojfIjD8mvn/qRL5p4+vvlMqvp2EhR8WBzfiz20hXORmP9fi/bM9E\neUFvV5H/0yRkeSbiGRfFJErxD9ENdz7Mbhig/h89fvtFdMiI/ePUIXV4lXju8K3DKv9NThOZ3q2K\nmUy6grxFES8rjeyic+FFQav+ncg3fXjH+Ts+/iibztFqOiZuZP/Z3OafPX40NGgST2r+uvQkXXp6\ncKvmr+r0e1Eef5um3+JHP3IFF1D/seNZJgaDmvY0Gav1s+2f1fqpIcublfKGt6apotG/NVx3SInW\ntLX+7Vg/Pv1YqOsnun6JSVdOXT/X7vk75f938QP+8OmSBs0fXtymMhJbf8qlPynYmpKCh7OB1fzN\nalOj1sl0ZAruHLiA+RM73pDe/VjMVP89+aTXwjyc/x5n+u991895/utrJTy8/06TXh0r/5JOa2Jm\nYmqi4r/vUm/H4wLmT+z4anhr05X+q6KUXhtzr/9qSff5L5uMT//V/NdU4YuBTPa/8P67l/6r44ds\n+hYuoP5jx9ciy6XTWlibBrmx8V/TdMfjkP+6pOsu/lvM9N90sf7r+f6m/65n+S8p/itN15v0UkW3\n/+48+PRfJX6S9Joo4g+G/1qYG9KroqP/WypcuvyXPf13wH89/hHef7MB6R3Cqn55U4rv4kfH3zaS\ngQuYP7HjVf89tXrbO+hfLdr+Ozv/SP1dgtQ/Ov8C+i/3+q/Zf2D/HWi6bjT6rym9I/v/03/b+LHS\n4cTg/utTsV7/net/Afzz4f0XGX84/2j9xZ4/sePR/of2X7D/o+vPo/sv6h9B/Bfxr9j1Hz2eN/hO\n8/wfff4A848+f/1A/530/I0+/8PvH9D3H9HnT+R49P0b+v4PfP/4E/wXfP8Mvf9G37/D/ovuP8Se\nP7Hj0f0vdP8tqP9O339cyv7p3P1fdP8Z3v9G999j13/seMax8x/o+ZN7+O+E8zdP/8XOf8Hnz9Dz\nb7HnT+x49PxlCp7/BM+fOv13wvnXBfivt2lMvD8TyH/Hnb+Gz3+j589jz5/Y8ej9h4D+W7qQmf57\nefqv239n3T+C7z+h969i13/seMax+3/o/cMcu/8Y2H9n3p+J6r98pv8m4fwXuH+M3n+OO3++AX9c\nlR+4PhbRAAAAJXRFWHRkYXRlOmNyZWF0ZQAyMDE1LTEwLTAzVDA5OjUxOjU5KzA3OjAwJPCZIQAA\nACV0RVh0ZGF0ZTptb2RpZnkAMjAxNS0xMC0wM1QwOTo1MTo1OSswNzowMFWtIZ0AAAAASUVORK5C\nYII=\n",
|
||||
"image/png": "iVBORw0KGgoAAAANSUhEUgAAAPoAAAD6AgMAAAD1grKuAAAABGdBTUEAALGPC/xhBQAAAAFzUkdC\nAK7OHOkAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAAAAxQTFRF\n////chIS6YCRTb/E6kGE+wAAAAFiS0dEAIgFHUgAAAAJcEhZcwAAAEgAAABIAEbJaz4AAALKSURB\nVGje7dpLcqQwDAbgHHE2YeEj+D4cwQucBUfo+3CEXoSp8OhuhF70T4qpKXmdr21LogK2Pj7A8QmN\nP+HDhw8fPnz48Kf6VH9G+66vy+je8k19jnf8C5dXIPv86ms56lPdjvaYbyodx3ze+XLE76cXFiD4\nzPji99z0/AJ4n1lfvJ6fnl0A6x+578efMSg1wPr172/jPO5yFXM+Ef78gdblM+WPHyguP//t1/g6\npA0wfln+ho/fwgYYn19C/xwDvwHGc9OvC+hs37DTrwuwfWanXxdQTC9Mvyygs3wjTL8uwPJpn/tN\nDbSGz7T0SBEWw4vLXzbQ6b6RoveIoO6TvPxlA63qs7z8ZQPF9F+SH22vbX8OQKf5Rtv+EgDNJ3X5\n8wZaxWd1+fMGiuFvir8bvjp8J/tGy/6jAmRvhW8fwL3vVT+o3grfPoB7r/IpALI3tz8FoJN84/NV\n873hB8UnM3xzANtf8nb4dwmg3grfFEDJO8JPE0i9Ff4pAYL3pI8mkHor/HMCeO9JH00g9SafEsh7\nT/ppARBvp48UwJnelT5SACd7O31TAlnvKx9SQCd7B58KgPO+8iMFuPWe9E8F8BveWX7bAjzX9y4/\n/Jve+fhsH6Ctv7n8PTzjvY/v9gEOHz58+PBX+6v/f/wPvnd54f3j6venE/yl769Xv7+j3x/o98/V\n32/o9+fl389Xnx+g5x/o+Qt6/oOeP6HnX+j5G3z+h54/ouefV5/foufP6Pk3ev4On/+j9w/o/Qd6\n/4Le/6D3T/D9V67Y/ZsVQBq+s+8f0ftP+P41axXguP9NWgDuu/Cdfv+N3r/D9/9TAID+A7T/Ae2/\ngPs/0P4TtP8F7r9J3AIO9P+g/Udw/9Oygbf7r9D+L7j/DO1/Q/vv4P4/tP8Q7n9E+y/h/k+0/xTu\nf4X7b+H+X7T/+BPuf3aM8OHDhw8fPnz4w/4vzcvgeY10sY0AAAAldEVYdGRhdGU6Y3JlYXRlADIw\nMTUtMTAtMTJUMjM6NTI6MDgtMDQ6MDAXQ5NYAAAAJXRFWHRkYXRlOm1vZGlmeQAyMDE1LTEwLTEy\nVDIzOjUyOjA4LTA0OjAwZh4r5AAAAABJRU5ErkJggg==\n",
|
||||
"text/plain": [
|
||||
"<IPython.core.display.Image object>"
|
||||
]
|
||||
|
|
@ -381,13 +392,12 @@
|
|||
"cell_type": "code",
|
||||
"execution_count": 15,
|
||||
"metadata": {
|
||||
"collapsed": true
|
||||
"collapsed": false
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"# Instantiate an empty TalliesFile\n",
|
||||
"tallies_file = openmc.TalliesFile()\n",
|
||||
"tallies_file.tallies = []"
|
||||
"tallies_file = openmc.TalliesFile()"
|
||||
]
|
||||
},
|
||||
{
|
||||
|
|
@ -563,9 +573,9 @@
|
|||
" Copyright: 2011-2015 Massachusetts Institute of Technology\n",
|
||||
" License: http://mit-crpg.github.io/openmc/license.html\n",
|
||||
" Version: 0.7.0\n",
|
||||
" Git SHA1: 71dfde8d12942170a9a8d91796ab40a6e9becaaf\n",
|
||||
" Date/Time: 2015-10-03 09:53:29\n",
|
||||
" OpenMP Threads: 4\n",
|
||||
" Git SHA1: 170155e8d7935b57fad57bfad6aff1034a80206e\n",
|
||||
" Date/Time: 2015-10-12 23:52:08\n",
|
||||
" MPI Processes: 1\n",
|
||||
"\n",
|
||||
" ===========================================================================\n",
|
||||
" ========================> INITIALIZATION <=========================\n",
|
||||
|
|
@ -577,11 +587,11 @@
|
|||
" Reading materials XML file...\n",
|
||||
" Reading tallies XML file...\n",
|
||||
" Building neighboring cells lists for each surface...\n",
|
||||
" Loading ACE cross section table: 92235.71c\n",
|
||||
" Loading ACE cross section table: 92238.71c\n",
|
||||
" Loading ACE cross section table: 8016.71c\n",
|
||||
" Loading ACE cross section table: 92235.71c\n",
|
||||
" Loading ACE cross section table: 5010.71c\n",
|
||||
" Loading ACE cross section table: 1001.71c\n",
|
||||
" Loading ACE cross section table: 5010.71c\n",
|
||||
" Loading ACE cross section table: 40090.71c\n",
|
||||
" Initializing source particles...\n",
|
||||
"\n",
|
||||
|
|
@ -591,26 +601,26 @@
|
|||
"\n",
|
||||
" Bat./Gen. k Average k \n",
|
||||
" ========= ======== ==================== \n",
|
||||
" 1/1 1.00279 \n",
|
||||
" 2/1 1.03320 \n",
|
||||
" 3/1 1.04467 \n",
|
||||
" 4/1 1.09693 \n",
|
||||
" 5/1 1.05008 \n",
|
||||
" 6/1 1.08426 \n",
|
||||
" 7/1 1.05363 1.06894 +/- 0.01531\n",
|
||||
" 8/1 0.97961 1.03917 +/- 0.03106\n",
|
||||
" 9/1 1.06444 1.04549 +/- 0.02285\n",
|
||||
" 10/1 1.08345 1.05308 +/- 0.01926\n",
|
||||
" 11/1 1.06871 1.05568 +/- 0.01594\n",
|
||||
" 12/1 1.03183 1.05228 +/- 0.01390\n",
|
||||
" 13/1 1.04486 1.05135 +/- 0.01207\n",
|
||||
" 14/1 1.06468 1.05283 +/- 0.01075\n",
|
||||
" 15/1 1.04185 1.05173 +/- 0.00968\n",
|
||||
" 16/1 1.01268 1.04818 +/- 0.00944\n",
|
||||
" 17/1 1.04129 1.04761 +/- 0.00864\n",
|
||||
" 18/1 1.01127 1.04481 +/- 0.00843\n",
|
||||
" 19/1 1.03738 1.04428 +/- 0.00782\n",
|
||||
" 20/1 1.04410 1.04427 +/- 0.00728\n",
|
||||
" 1/1 1.05992 \n",
|
||||
" 2/1 1.05251 \n",
|
||||
" 3/1 1.05204 \n",
|
||||
" 4/1 1.02100 \n",
|
||||
" 5/1 1.07784 \n",
|
||||
" 6/1 1.04814 \n",
|
||||
" 7/1 1.02335 1.03574 +/- 0.01239\n",
|
||||
" 8/1 1.02415 1.03188 +/- 0.00813\n",
|
||||
" 9/1 1.10331 1.04974 +/- 0.01876\n",
|
||||
" 10/1 1.05452 1.05069 +/- 0.01456\n",
|
||||
" 11/1 1.07867 1.05536 +/- 0.01277\n",
|
||||
" 12/1 1.04203 1.05345 +/- 0.01096\n",
|
||||
" 13/1 1.04482 1.05237 +/- 0.00955\n",
|
||||
" 14/1 1.04117 1.05113 +/- 0.00852\n",
|
||||
" 15/1 1.07581 1.05360 +/- 0.00801\n",
|
||||
" 16/1 1.04235 1.05257 +/- 0.00731\n",
|
||||
" 17/1 1.02710 1.05045 +/- 0.00701\n",
|
||||
" 18/1 1.01970 1.04809 +/- 0.00687\n",
|
||||
" 19/1 1.01022 1.04538 +/- 0.00691\n",
|
||||
" 20/1 1.01449 1.04332 +/- 0.00675\n",
|
||||
" Creating state point statepoint.20.h5...\n",
|
||||
"\n",
|
||||
" ===========================================================================\n",
|
||||
|
|
@ -620,27 +630,27 @@
|
|||
"\n",
|
||||
" =======================> TIMING STATISTICS <=======================\n",
|
||||
"\n",
|
||||
" Total time for initialization = 3.7200E-01 seconds\n",
|
||||
" Reading cross sections = 1.2400E-01 seconds\n",
|
||||
" Total time in simulation = 4.7110E+00 seconds\n",
|
||||
" Time in transport only = 4.6510E+00 seconds\n",
|
||||
" Time in inactive batches = 6.1900E-01 seconds\n",
|
||||
" Time in active batches = 4.0920E+00 seconds\n",
|
||||
" Time synchronizing fission bank = 2.0000E-03 seconds\n",
|
||||
" Sampling source sites = 2.0000E-03 seconds\n",
|
||||
" Total time for initialization = 4.1300E-01 seconds\n",
|
||||
" Reading cross sections = 9.6000E-02 seconds\n",
|
||||
" Total time in simulation = 1.6248E+01 seconds\n",
|
||||
" Time in transport only = 1.6236E+01 seconds\n",
|
||||
" Time in inactive batches = 2.3150E+00 seconds\n",
|
||||
" Time in active batches = 1.3933E+01 seconds\n",
|
||||
" Time synchronizing fission bank = 0.0000E+00 seconds\n",
|
||||
" Sampling source sites = 0.0000E+00 seconds\n",
|
||||
" SEND/RECV source sites = 0.0000E+00 seconds\n",
|
||||
" Time accumulating tallies = 0.0000E+00 seconds\n",
|
||||
" Total time for finalization = 2.0000E-03 seconds\n",
|
||||
" Total time elapsed = 5.0950E+00 seconds\n",
|
||||
" Calculation Rate (inactive) = 20193.9 neutrons/second\n",
|
||||
" Calculation Rate (active) = 9164.22 neutrons/second\n",
|
||||
" Total time elapsed = 1.6672E+01 seconds\n",
|
||||
" Calculation Rate (inactive) = 5399.57 neutrons/second\n",
|
||||
" Calculation Rate (active) = 2691.45 neutrons/second\n",
|
||||
"\n",
|
||||
" ============================> RESULTS <============================\n",
|
||||
"\n",
|
||||
" k-effective (Collision) = 1.04044 +/- 0.00527\n",
|
||||
" k-effective (Track-length) = 1.04427 +/- 0.00728\n",
|
||||
" k-effective (Absorption) = 1.04794 +/- 0.00535\n",
|
||||
" Combined k-effective = 1.04628 +/- 0.00467\n",
|
||||
" k-effective (Collision) = 1.03935 +/- 0.00682\n",
|
||||
" k-effective (Track-length) = 1.04332 +/- 0.00675\n",
|
||||
" k-effective (Absorption) = 1.03845 +/- 0.00598\n",
|
||||
" Combined k-effective = 1.04024 +/- 0.00523\n",
|
||||
" Leakage Fraction = 0.00000 +/- 0.00000\n",
|
||||
"\n"
|
||||
]
|
||||
|
|
@ -741,30 +751,22 @@
|
|||
" <th>mean</th>\n",
|
||||
" <th>std. dev.</th>\n",
|
||||
" </tr>\n",
|
||||
" <tr>\n",
|
||||
" <th>bin</th>\n",
|
||||
" <th></th>\n",
|
||||
" <th></th>\n",
|
||||
" <th></th>\n",
|
||||
" <th></th>\n",
|
||||
" </tr>\n",
|
||||
" </thead>\n",
|
||||
" <tbody>\n",
|
||||
" <tr>\n",
|
||||
" <th>0</th>\n",
|
||||
" <td>total</td>\n",
|
||||
" <td>(nu-fission / absorption)</td>\n",
|
||||
" <td>1.046353</td>\n",
|
||||
" <td>0.00935</td>\n",
|
||||
" <td>1.040166</td>\n",
|
||||
" <td>0.009069</td>\n",
|
||||
" </tr>\n",
|
||||
" </tbody>\n",
|
||||
"</table>\n",
|
||||
"</div>"
|
||||
],
|
||||
"text/plain": [
|
||||
" nuclide score mean std. dev.\n",
|
||||
"bin \n",
|
||||
"0 total (nu-fission / absorption) 1.046353 0.00935"
|
||||
" nuclide score mean std. dev.\n",
|
||||
"0 total (nu-fission / absorption) 1.040166 0.009069"
|
||||
]
|
||||
},
|
||||
"execution_count": 26,
|
||||
|
|
@ -804,35 +806,29 @@
|
|||
" <thead>\n",
|
||||
" <tr style=\"text-align: right;\">\n",
|
||||
" <th></th>\n",
|
||||
" <th>energy [MeV]</th>\n",
|
||||
" <th>nuclide</th>\n",
|
||||
" <th>score</th>\n",
|
||||
" <th>mean</th>\n",
|
||||
" <th>std. dev.</th>\n",
|
||||
" </tr>\n",
|
||||
" <tr>\n",
|
||||
" <th>bin</th>\n",
|
||||
" <th></th>\n",
|
||||
" <th></th>\n",
|
||||
" <th></th>\n",
|
||||
" <th></th>\n",
|
||||
" </tr>\n",
|
||||
" </thead>\n",
|
||||
" <tbody>\n",
|
||||
" <tr>\n",
|
||||
" <th>0</th>\n",
|
||||
" <td>(0.0e+00 - 6.2e-01)</td>\n",
|
||||
" <td>total</td>\n",
|
||||
" <td>absorption</td>\n",
|
||||
" <td>0.95873</td>\n",
|
||||
" <td>0.00774</td>\n",
|
||||
" <td>0.95938</td>\n",
|
||||
" <td>0.008187</td>\n",
|
||||
" </tr>\n",
|
||||
" </tbody>\n",
|
||||
"</table>\n",
|
||||
"</div>"
|
||||
],
|
||||
"text/plain": [
|
||||
" nuclide score mean std. dev.\n",
|
||||
"bin \n",
|
||||
"0 total absorption 0.95873 0.00774"
|
||||
" energy [MeV] nuclide score mean std. dev.\n",
|
||||
"0 (0.0e+00 - 6.2e-01) total absorption 0.95938 0.008187"
|
||||
]
|
||||
},
|
||||
"execution_count": 27,
|
||||
|
|
@ -875,30 +871,22 @@
|
|||
" <th>mean</th>\n",
|
||||
" <th>std. dev.</th>\n",
|
||||
" </tr>\n",
|
||||
" <tr>\n",
|
||||
" <th>bin</th>\n",
|
||||
" <th></th>\n",
|
||||
" <th></th>\n",
|
||||
" <th></th>\n",
|
||||
" <th></th>\n",
|
||||
" </tr>\n",
|
||||
" </thead>\n",
|
||||
" <tbody>\n",
|
||||
" <tr>\n",
|
||||
" <th>0</th>\n",
|
||||
" <td>total</td>\n",
|
||||
" <td>nu-fission</td>\n",
|
||||
" <td>1.091622</td>\n",
|
||||
" <td>0.011163</td>\n",
|
||||
" <td>1.090899</td>\n",
|
||||
" <td>0.010602</td>\n",
|
||||
" </tr>\n",
|
||||
" </tbody>\n",
|
||||
"</table>\n",
|
||||
"</div>"
|
||||
],
|
||||
"text/plain": [
|
||||
" nuclide score mean std. dev.\n",
|
||||
"bin \n",
|
||||
"0 total nu-fission 1.091622 0.011163"
|
||||
" nuclide score mean std. dev.\n",
|
||||
"0 total nu-fission 1.090899 0.010602"
|
||||
]
|
||||
},
|
||||
"execution_count": 28,
|
||||
|
|
@ -944,25 +932,16 @@
|
|||
" <th>mean</th>\n",
|
||||
" <th>std. dev.</th>\n",
|
||||
" </tr>\n",
|
||||
" <tr>\n",
|
||||
" <th>bin</th>\n",
|
||||
" <th></th>\n",
|
||||
" <th></th>\n",
|
||||
" <th></th>\n",
|
||||
" <th></th>\n",
|
||||
" <th></th>\n",
|
||||
" <th></th>\n",
|
||||
" </tr>\n",
|
||||
" </thead>\n",
|
||||
" <tbody>\n",
|
||||
" <tr>\n",
|
||||
" <th>0</th>\n",
|
||||
" <td>0.0e+00 - 6.2e-01</td>\n",
|
||||
" <td>(0.0e+00 - 6.2e-01)</td>\n",
|
||||
" <td>10000</td>\n",
|
||||
" <td>total</td>\n",
|
||||
" <td>absorption</td>\n",
|
||||
" <td>0.802012</td>\n",
|
||||
" <td>0.006609</td>\n",
|
||||
" <td>0.803413</td>\n",
|
||||
" <td>0.007031</td>\n",
|
||||
" </tr>\n",
|
||||
" </tbody>\n",
|
||||
"</table>\n",
|
||||
|
|
@ -970,8 +949,7 @@
|
|||
],
|
||||
"text/plain": [
|
||||
" energy [MeV] cell nuclide score mean std. dev.\n",
|
||||
"bin \n",
|
||||
"0 0.0e+00 - 6.2e-01 10000 total absorption 0.802012 0.006609"
|
||||
"0 (0.0e+00 - 6.2e-01) 10000 total absorption 0.803413 0.007031"
|
||||
]
|
||||
},
|
||||
"execution_count": 29,
|
||||
|
|
@ -1009,44 +987,28 @@
|
|||
" <tr style=\"text-align: right;\">\n",
|
||||
" <th></th>\n",
|
||||
" <th>energy [MeV]</th>\n",
|
||||
" <th>cell</th>\n",
|
||||
" <th>nuclide</th>\n",
|
||||
" <th>score</th>\n",
|
||||
" <th>mean</th>\n",
|
||||
" <th>std. dev.</th>\n",
|
||||
" </tr>\n",
|
||||
" <tr>\n",
|
||||
" <th>bin</th>\n",
|
||||
" <th></th>\n",
|
||||
" <th></th>\n",
|
||||
" <th></th>\n",
|
||||
" <th></th>\n",
|
||||
" <th></th>\n",
|
||||
" <th></th>\n",
|
||||
" </tr>\n",
|
||||
" </thead>\n",
|
||||
" <tbody>\n",
|
||||
" <tr>\n",
|
||||
" <th>0</th>\n",
|
||||
" <td>0.0e+00 - 6.2e-01</td>\n",
|
||||
" <td>10000</td>\n",
|
||||
" <td>(0.0e+00 - 6.2e-01)</td>\n",
|
||||
" <td>total</td>\n",
|
||||
" <td>(nu-fission / absorption)</td>\n",
|
||||
" <td>1.246604</td>\n",
|
||||
" <td>0.011825</td>\n",
|
||||
" <td>1.237053</td>\n",
|
||||
" <td>0.011765</td>\n",
|
||||
" </tr>\n",
|
||||
" </tbody>\n",
|
||||
"</table>\n",
|
||||
"</div>"
|
||||
],
|
||||
"text/plain": [
|
||||
" energy [MeV] cell nuclide score mean \\\n",
|
||||
"bin \n",
|
||||
"0 0.0e+00 - 6.2e-01 10000 total (nu-fission / absorption) 1.246604 \n",
|
||||
"\n",
|
||||
" std. dev. \n",
|
||||
"bin \n",
|
||||
"0 0.011825 "
|
||||
" energy [MeV] nuclide score mean std. dev.\n",
|
||||
"0 (0.0e+00 - 6.2e-01) total (nu-fission / absorption) 1.237053 0.011765"
|
||||
]
|
||||
},
|
||||
"execution_count": 30,
|
||||
|
|
@ -1082,39 +1044,32 @@
|
|||
" <thead>\n",
|
||||
" <tr style=\"text-align: right;\">\n",
|
||||
" <th></th>\n",
|
||||
" <th>energy [MeV]</th>\n",
|
||||
" <th>nuclide</th>\n",
|
||||
" <th>score</th>\n",
|
||||
" <th>mean</th>\n",
|
||||
" <th>std. dev.</th>\n",
|
||||
" </tr>\n",
|
||||
" <tr>\n",
|
||||
" <th>bin</th>\n",
|
||||
" <th></th>\n",
|
||||
" <th></th>\n",
|
||||
" <th></th>\n",
|
||||
" <th></th>\n",
|
||||
" </tr>\n",
|
||||
" </thead>\n",
|
||||
" <tbody>\n",
|
||||
" <tr>\n",
|
||||
" <th>0</th>\n",
|
||||
" <td>(0.0e+00 - 6.2e-01)</td>\n",
|
||||
" <td>total</td>\n",
|
||||
" <td>(((absorption * nu-fission) * absorption) * (n...</td>\n",
|
||||
" <td>1.046353</td>\n",
|
||||
" <td>0.01894</td>\n",
|
||||
" <td>1.040166</td>\n",
|
||||
" <td>0.019018</td>\n",
|
||||
" </tr>\n",
|
||||
" </tbody>\n",
|
||||
"</table>\n",
|
||||
"</div>"
|
||||
],
|
||||
"text/plain": [
|
||||
" nuclide score mean \\\n",
|
||||
"bin \n",
|
||||
"0 total (((absorption * nu-fission) * absorption) * (n... 1.046353 \n",
|
||||
" energy [MeV] nuclide \\\n",
|
||||
"0 (0.0e+00 - 6.2e-01) total \n",
|
||||
"\n",
|
||||
" std. dev. \n",
|
||||
"bin \n",
|
||||
"0 0.01894 "
|
||||
" score mean std. dev. \n",
|
||||
"0 (((absorption * nu-fission) * absorption) * (n... 1.040166 0.019018 "
|
||||
]
|
||||
},
|
||||
"execution_count": 31,
|
||||
|
|
@ -1174,115 +1129,104 @@
|
|||
" <th>mean</th>\n",
|
||||
" <th>std. dev.</th>\n",
|
||||
" </tr>\n",
|
||||
" <tr>\n",
|
||||
" <th>bin</th>\n",
|
||||
" <th></th>\n",
|
||||
" <th></th>\n",
|
||||
" <th></th>\n",
|
||||
" <th></th>\n",
|
||||
" <th></th>\n",
|
||||
" <th></th>\n",
|
||||
" </tr>\n",
|
||||
" </thead>\n",
|
||||
" <tbody>\n",
|
||||
" <tr>\n",
|
||||
" <th>0</th>\n",
|
||||
" <td>10000</td>\n",
|
||||
" <td>0.0e+00 - 6.3e-07</td>\n",
|
||||
" <td>(0.0e+00 - 6.3e-07)</td>\n",
|
||||
" <td>(U-238 / total)</td>\n",
|
||||
" <td>(nu-fission / flux)</td>\n",
|
||||
" <td>0.000001</td>\n",
|
||||
" <td>6.859257e-09</td>\n",
|
||||
" <td>6.657029e-07</td>\n",
|
||||
" <td>7.377419e-09</td>\n",
|
||||
" </tr>\n",
|
||||
" <tr>\n",
|
||||
" <th>1</th>\n",
|
||||
" <td>10000</td>\n",
|
||||
" <td>0.0e+00 - 6.3e-07</td>\n",
|
||||
" <td>(0.0e+00 - 6.3e-07)</td>\n",
|
||||
" <td>(U-238 / total)</td>\n",
|
||||
" <td>(scatter / flux)</td>\n",
|
||||
" <td>0.209986</td>\n",
|
||||
" <td>1.966887e-03</td>\n",
|
||||
" <td>2.099891e-01</td>\n",
|
||||
" <td>2.303838e-03</td>\n",
|
||||
" </tr>\n",
|
||||
" <tr>\n",
|
||||
" <th>2</th>\n",
|
||||
" <td>10000</td>\n",
|
||||
" <td>0.0e+00 - 6.3e-07</td>\n",
|
||||
" <td>(0.0e+00 - 6.3e-07)</td>\n",
|
||||
" <td>(U-235 / total)</td>\n",
|
||||
" <td>(nu-fission / flux)</td>\n",
|
||||
" <td>0.355667</td>\n",
|
||||
" <td>3.717881e-03</td>\n",
|
||||
" <td>3.564204e-01</td>\n",
|
||||
" <td>3.951669e-03</td>\n",
|
||||
" </tr>\n",
|
||||
" <tr>\n",
|
||||
" <th>3</th>\n",
|
||||
" <td>10000</td>\n",
|
||||
" <td>0.0e+00 - 6.3e-07</td>\n",
|
||||
" <td>(0.0e+00 - 6.3e-07)</td>\n",
|
||||
" <td>(U-235 / total)</td>\n",
|
||||
" <td>(scatter / flux)</td>\n",
|
||||
" <td>0.005555</td>\n",
|
||||
" <td>5.218094e-05</td>\n",
|
||||
" <td>5.555330e-03</td>\n",
|
||||
" <td>6.101004e-05</td>\n",
|
||||
" </tr>\n",
|
||||
" <tr>\n",
|
||||
" <th>4</th>\n",
|
||||
" <td>10000</td>\n",
|
||||
" <td>6.3e-07 - 2.0e+01</td>\n",
|
||||
" <td>(6.3e-07 - 2.0e+01)</td>\n",
|
||||
" <td>(U-238 / total)</td>\n",
|
||||
" <td>(nu-fission / flux)</td>\n",
|
||||
" <td>0.007165</td>\n",
|
||||
" <td>5.625590e-05</td>\n",
|
||||
" <td>7.154887e-03</td>\n",
|
||||
" <td>8.053460e-05</td>\n",
|
||||
" </tr>\n",
|
||||
" <tr>\n",
|
||||
" <th>5</th>\n",
|
||||
" <td>10000</td>\n",
|
||||
" <td>6.3e-07 - 2.0e+01</td>\n",
|
||||
" <td>(6.3e-07 - 2.0e+01)</td>\n",
|
||||
" <td>(U-238 / total)</td>\n",
|
||||
" <td>(scatter / flux)</td>\n",
|
||||
" <td>0.227653</td>\n",
|
||||
" <td>8.544314e-04</td>\n",
|
||||
" <td>2.277701e-01</td>\n",
|
||||
" <td>1.079289e-03</td>\n",
|
||||
" </tr>\n",
|
||||
" <tr>\n",
|
||||
" <th>6</th>\n",
|
||||
" <td>10000</td>\n",
|
||||
" <td>6.3e-07 - 2.0e+01</td>\n",
|
||||
" <td>(6.3e-07 - 2.0e+01)</td>\n",
|
||||
" <td>(U-235 / total)</td>\n",
|
||||
" <td>(nu-fission / flux)</td>\n",
|
||||
" <td>0.008089</td>\n",
|
||||
" <td>5.080374e-05</td>\n",
|
||||
" <td>8.066738e-03</td>\n",
|
||||
" <td>5.254797e-05</td>\n",
|
||||
" </tr>\n",
|
||||
" <tr>\n",
|
||||
" <th>7</th>\n",
|
||||
" <td>10000</td>\n",
|
||||
" <td>6.3e-07 - 2.0e+01</td>\n",
|
||||
" <td>(6.3e-07 - 2.0e+01)</td>\n",
|
||||
" <td>(U-235 / total)</td>\n",
|
||||
" <td>(scatter / flux)</td>\n",
|
||||
" <td>0.003370</td>\n",
|
||||
" <td>1.361116e-05</td>\n",
|
||||
" <td>3.366802e-03</td>\n",
|
||||
" <td>1.647058e-05</td>\n",
|
||||
" </tr>\n",
|
||||
" </tbody>\n",
|
||||
"</table>\n",
|
||||
"</div>"
|
||||
],
|
||||
"text/plain": [
|
||||
" cell energy [MeV] nuclide score mean \\\n",
|
||||
"bin \n",
|
||||
"0 10000 0.0e+00 - 6.3e-07 (U-238 / total) (nu-fission / flux) 0.000001 \n",
|
||||
"1 10000 0.0e+00 - 6.3e-07 (U-238 / total) (scatter / flux) 0.209986 \n",
|
||||
"2 10000 0.0e+00 - 6.3e-07 (U-235 / total) (nu-fission / flux) 0.355667 \n",
|
||||
"3 10000 0.0e+00 - 6.3e-07 (U-235 / total) (scatter / flux) 0.005555 \n",
|
||||
"4 10000 6.3e-07 - 2.0e+01 (U-238 / total) (nu-fission / flux) 0.007165 \n",
|
||||
"5 10000 6.3e-07 - 2.0e+01 (U-238 / total) (scatter / flux) 0.227653 \n",
|
||||
"6 10000 6.3e-07 - 2.0e+01 (U-235 / total) (nu-fission / flux) 0.008089 \n",
|
||||
"7 10000 6.3e-07 - 2.0e+01 (U-235 / total) (scatter / flux) 0.003370 \n",
|
||||
" cell energy [MeV] nuclide score \\\n",
|
||||
"0 10000 (0.0e+00 - 6.3e-07) (U-238 / total) (nu-fission / flux) \n",
|
||||
"1 10000 (0.0e+00 - 6.3e-07) (U-238 / total) (scatter / flux) \n",
|
||||
"2 10000 (0.0e+00 - 6.3e-07) (U-235 / total) (nu-fission / flux) \n",
|
||||
"3 10000 (0.0e+00 - 6.3e-07) (U-235 / total) (scatter / flux) \n",
|
||||
"4 10000 (6.3e-07 - 2.0e+01) (U-238 / total) (nu-fission / flux) \n",
|
||||
"5 10000 (6.3e-07 - 2.0e+01) (U-238 / total) (scatter / flux) \n",
|
||||
"6 10000 (6.3e-07 - 2.0e+01) (U-235 / total) (nu-fission / flux) \n",
|
||||
"7 10000 (6.3e-07 - 2.0e+01) (U-235 / total) (scatter / flux) \n",
|
||||
"\n",
|
||||
" std. dev. \n",
|
||||
"bin \n",
|
||||
"0 6.859257e-09 \n",
|
||||
"1 1.966887e-03 \n",
|
||||
"2 3.717881e-03 \n",
|
||||
"3 5.218094e-05 \n",
|
||||
"4 5.625590e-05 \n",
|
||||
"5 8.544314e-04 \n",
|
||||
"6 5.080374e-05 \n",
|
||||
"7 1.361116e-05 "
|
||||
" mean std. dev. \n",
|
||||
"0 6.657029e-07 7.377419e-09 \n",
|
||||
"1 2.099891e-01 2.303838e-03 \n",
|
||||
"2 3.564204e-01 3.951669e-03 \n",
|
||||
"3 5.555330e-03 6.101004e-05 \n",
|
||||
"4 7.154887e-03 8.053460e-05 \n",
|
||||
"5 2.277701e-01 1.079289e-03 \n",
|
||||
"6 8.066738e-03 5.254797e-05 \n",
|
||||
"7 3.366802e-03 1.647058e-05 "
|
||||
]
|
||||
},
|
||||
"execution_count": 33,
|
||||
|
|
@ -1313,11 +1257,11 @@
|
|||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"[[[ 6.64174599e-07]\n",
|
||||
" [ 3.55666541e-01]]\n",
|
||||
"[[[ 6.65702880e-07]\n",
|
||||
" [ 3.56420449e-01]]\n",
|
||||
"\n",
|
||||
" [[ 7.16505734e-03]\n",
|
||||
" [ 8.08949336e-03]]]\n"
|
||||
" [[ 7.15488656e-03]\n",
|
||||
" [ 8.06673774e-03]]]\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
|
|
@ -1345,9 +1289,9 @@
|
|||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"[[[ 0.00555465]]\n",
|
||||
"[[[ 0.00555533]]\n",
|
||||
"\n",
|
||||
" [[ 0.00337011]]]\n"
|
||||
" [[ 0.0033668 ]]]\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
|
|
@ -1369,8 +1313,8 @@
|
|||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"[[[ 0.22765348]\n",
|
||||
" [ 0.00337011]]]\n"
|
||||
"[[[ 0.22777006]\n",
|
||||
" [ 0.0033668 ]]]\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
|
|
@ -1411,64 +1355,54 @@
|
|||
" <th>mean</th>\n",
|
||||
" <th>std. dev.</th>\n",
|
||||
" </tr>\n",
|
||||
" <tr>\n",
|
||||
" <th>bin</th>\n",
|
||||
" <th></th>\n",
|
||||
" <th></th>\n",
|
||||
" <th></th>\n",
|
||||
" <th></th>\n",
|
||||
" <th></th>\n",
|
||||
" <th></th>\n",
|
||||
" </tr>\n",
|
||||
" </thead>\n",
|
||||
" <tbody>\n",
|
||||
" <tr>\n",
|
||||
" <th>0</th>\n",
|
||||
" <td>10000</td>\n",
|
||||
" <td>0.0e+00 - 6.3e-07</td>\n",
|
||||
" <td>(0.0e+00 - 6.3e-07)</td>\n",
|
||||
" <td>U-238</td>\n",
|
||||
" <td>nu-fission</td>\n",
|
||||
" <td>0.000002</td>\n",
|
||||
" <td>1.284890e-08</td>\n",
|
||||
" <td>1.283958e-08</td>\n",
|
||||
" </tr>\n",
|
||||
" <tr>\n",
|
||||
" <th>1</th>\n",
|
||||
" <td>10000</td>\n",
|
||||
" <td>0.0e+00 - 6.3e-07</td>\n",
|
||||
" <td>(0.0e+00 - 6.3e-07)</td>\n",
|
||||
" <td>U-235</td>\n",
|
||||
" <td>nu-fission</td>\n",
|
||||
" <td>0.867982</td>\n",
|
||||
" <td>7.022256e-03</td>\n",
|
||||
" <td>0.868553</td>\n",
|
||||
" <td>6.880390e-03</td>\n",
|
||||
" </tr>\n",
|
||||
" <tr>\n",
|
||||
" <th>2</th>\n",
|
||||
" <td>10000</td>\n",
|
||||
" <td>6.3e-07 - 2.0e+01</td>\n",
|
||||
" <td>(6.3e-07 - 2.0e+01)</td>\n",
|
||||
" <td>U-238</td>\n",
|
||||
" <td>nu-fission</td>\n",
|
||||
" <td>0.082801</td>\n",
|
||||
" <td>6.087096e-04</td>\n",
|
||||
" <td>0.082149</td>\n",
|
||||
" <td>8.837250e-04</td>\n",
|
||||
" </tr>\n",
|
||||
" <tr>\n",
|
||||
" <th>3</th>\n",
|
||||
" <td>10000</td>\n",
|
||||
" <td>6.3e-07 - 2.0e+01</td>\n",
|
||||
" <td>(6.3e-07 - 2.0e+01)</td>\n",
|
||||
" <td>U-235</td>\n",
|
||||
" <td>nu-fission</td>\n",
|
||||
" <td>0.093484</td>\n",
|
||||
" <td>5.275039e-04</td>\n",
|
||||
" <td>0.092618</td>\n",
|
||||
" <td>5.195308e-04</td>\n",
|
||||
" </tr>\n",
|
||||
" </tbody>\n",
|
||||
"</table>\n",
|
||||
"</div>"
|
||||
],
|
||||
"text/plain": [
|
||||
" cell energy [MeV] nuclide score mean std. dev.\n",
|
||||
"bin \n",
|
||||
"0 10000 0.0e+00 - 6.3e-07 U-238 nu-fission 0.000002 1.284890e-08\n",
|
||||
"1 10000 0.0e+00 - 6.3e-07 U-235 nu-fission 0.867982 7.022256e-03\n",
|
||||
"2 10000 6.3e-07 - 2.0e+01 U-238 nu-fission 0.082801 6.087096e-04\n",
|
||||
"3 10000 6.3e-07 - 2.0e+01 U-235 nu-fission 0.093484 5.275039e-04"
|
||||
" cell energy [MeV] nuclide score mean std. dev.\n",
|
||||
"0 10000 (0.0e+00 - 6.3e-07) U-238 nu-fission 0.000002 1.283958e-08\n",
|
||||
"1 10000 (0.0e+00 - 6.3e-07) U-235 nu-fission 0.868553 6.880390e-03\n",
|
||||
"2 10000 (6.3e-07 - 2.0e+01) U-238 nu-fission 0.082149 8.837250e-04\n",
|
||||
"3 10000 (6.3e-07 - 2.0e+01) U-235 nu-fission 0.092618 5.195308e-04"
|
||||
]
|
||||
},
|
||||
"execution_count": 37,
|
||||
|
|
@ -1504,114 +1438,104 @@
|
|||
" <th>mean</th>\n",
|
||||
" <th>std. dev.</th>\n",
|
||||
" </tr>\n",
|
||||
" <tr>\n",
|
||||
" <th>bin</th>\n",
|
||||
" <th></th>\n",
|
||||
" <th></th>\n",
|
||||
" <th></th>\n",
|
||||
" <th></th>\n",
|
||||
" <th></th>\n",
|
||||
" <th></th>\n",
|
||||
" </tr>\n",
|
||||
" </thead>\n",
|
||||
" <tbody>\n",
|
||||
" <tr>\n",
|
||||
" <th>0</th>\n",
|
||||
" <td>10002</td>\n",
|
||||
" <td>1.0e-08 - 1.1e-07</td>\n",
|
||||
" <td>(1.0e-08 - 1.1e-07)</td>\n",
|
||||
" <td>H-1</td>\n",
|
||||
" <td>scatter</td>\n",
|
||||
" <td>4.620525</td>\n",
|
||||
" <td>0.038249</td>\n",
|
||||
" <td>4.619398</td>\n",
|
||||
" <td>0.040124</td>\n",
|
||||
" </tr>\n",
|
||||
" <tr>\n",
|
||||
" <th>1</th>\n",
|
||||
" <td>10002</td>\n",
|
||||
" <td>1.1e-07 - 1.2e-06</td>\n",
|
||||
" <td>(1.1e-07 - 1.2e-06)</td>\n",
|
||||
" <td>H-1</td>\n",
|
||||
" <td>scatter</td>\n",
|
||||
" <td>2.036841</td>\n",
|
||||
" <td>0.013203</td>\n",
|
||||
" <td>2.030757</td>\n",
|
||||
" <td>0.011239</td>\n",
|
||||
" </tr>\n",
|
||||
" <tr>\n",
|
||||
" <th>2</th>\n",
|
||||
" <td>10002</td>\n",
|
||||
" <td>1.2e-06 - 1.3e-05</td>\n",
|
||||
" <td>(1.2e-06 - 1.3e-05)</td>\n",
|
||||
" <td>H-1</td>\n",
|
||||
" <td>scatter</td>\n",
|
||||
" <td>1.659916</td>\n",
|
||||
" <td>0.010107</td>\n",
|
||||
" <td>1.658488</td>\n",
|
||||
" <td>0.009777</td>\n",
|
||||
" </tr>\n",
|
||||
" <tr>\n",
|
||||
" <th>3</th>\n",
|
||||
" <td>10002</td>\n",
|
||||
" <td>1.3e-05 - 1.4e-04</td>\n",
|
||||
" <td>(1.3e-05 - 1.4e-04)</td>\n",
|
||||
" <td>H-1</td>\n",
|
||||
" <td>scatter</td>\n",
|
||||
" <td>1.861546</td>\n",
|
||||
" <td>0.013328</td>\n",
|
||||
" <td>1.853002</td>\n",
|
||||
" <td>0.007378</td>\n",
|
||||
" </tr>\n",
|
||||
" <tr>\n",
|
||||
" <th>4</th>\n",
|
||||
" <td>10002</td>\n",
|
||||
" <td>1.4e-04 - 1.5e-03</td>\n",
|
||||
" <td>(1.4e-04 - 1.5e-03)</td>\n",
|
||||
" <td>H-1</td>\n",
|
||||
" <td>scatter</td>\n",
|
||||
" <td>2.049664</td>\n",
|
||||
" <td>0.008215</td>\n",
|
||||
" <td>2.050773</td>\n",
|
||||
" <td>0.012484</td>\n",
|
||||
" </tr>\n",
|
||||
" <tr>\n",
|
||||
" <th>5</th>\n",
|
||||
" <td>10002</td>\n",
|
||||
" <td>1.5e-03 - 1.6e-02</td>\n",
|
||||
" <td>(1.5e-03 - 1.6e-02)</td>\n",
|
||||
" <td>H-1</td>\n",
|
||||
" <td>scatter</td>\n",
|
||||
" <td>2.162157</td>\n",
|
||||
" <td>0.010245</td>\n",
|
||||
" <td>2.131759</td>\n",
|
||||
" <td>0.007821</td>\n",
|
||||
" </tr>\n",
|
||||
" <tr>\n",
|
||||
" <th>6</th>\n",
|
||||
" <td>10002</td>\n",
|
||||
" <td>1.6e-02 - 1.7e-01</td>\n",
|
||||
" <td>(1.6e-02 - 1.7e-01)</td>\n",
|
||||
" <td>H-1</td>\n",
|
||||
" <td>scatter</td>\n",
|
||||
" <td>2.224496</td>\n",
|
||||
" <td>0.013796</td>\n",
|
||||
" <td>2.213710</td>\n",
|
||||
" <td>0.015159</td>\n",
|
||||
" </tr>\n",
|
||||
" <tr>\n",
|
||||
" <th>7</th>\n",
|
||||
" <td>10002</td>\n",
|
||||
" <td>1.7e-01 - 1.9e+00</td>\n",
|
||||
" <td>(1.7e-01 - 1.9e+00)</td>\n",
|
||||
" <td>H-1</td>\n",
|
||||
" <td>scatter</td>\n",
|
||||
" <td>1.997585</td>\n",
|
||||
" <td>0.009161</td>\n",
|
||||
" <td>2.011925</td>\n",
|
||||
" <td>0.009406</td>\n",
|
||||
" </tr>\n",
|
||||
" <tr>\n",
|
||||
" <th>8</th>\n",
|
||||
" <td>10002</td>\n",
|
||||
" <td>1.9e+00 - 2.0e+01</td>\n",
|
||||
" <td>(1.9e+00 - 2.0e+01)</td>\n",
|
||||
" <td>H-1</td>\n",
|
||||
" <td>scatter</td>\n",
|
||||
" <td>0.373472</td>\n",
|
||||
" <td>0.003922</td>\n",
|
||||
" <td>0.371280</td>\n",
|
||||
" <td>0.003949</td>\n",
|
||||
" </tr>\n",
|
||||
" </tbody>\n",
|
||||
"</table>\n",
|
||||
"</div>"
|
||||
],
|
||||
"text/plain": [
|
||||
" cell energy [MeV] nuclide score mean std. dev.\n",
|
||||
"bin \n",
|
||||
"0 10002 1.0e-08 - 1.1e-07 H-1 scatter 4.620525 0.038249\n",
|
||||
"1 10002 1.1e-07 - 1.2e-06 H-1 scatter 2.036841 0.013203\n",
|
||||
"2 10002 1.2e-06 - 1.3e-05 H-1 scatter 1.659916 0.010107\n",
|
||||
"3 10002 1.3e-05 - 1.4e-04 H-1 scatter 1.861546 0.013328\n",
|
||||
"4 10002 1.4e-04 - 1.5e-03 H-1 scatter 2.049664 0.008215\n",
|
||||
"5 10002 1.5e-03 - 1.6e-02 H-1 scatter 2.162157 0.010245\n",
|
||||
"6 10002 1.6e-02 - 1.7e-01 H-1 scatter 2.224496 0.013796\n",
|
||||
"7 10002 1.7e-01 - 1.9e+00 H-1 scatter 1.997585 0.009161\n",
|
||||
"8 10002 1.9e+00 - 2.0e+01 H-1 scatter 0.373472 0.003922"
|
||||
" cell energy [MeV] nuclide score mean std. dev.\n",
|
||||
"0 10002 (1.0e-08 - 1.1e-07) H-1 scatter 4.619398 0.040124\n",
|
||||
"1 10002 (1.1e-07 - 1.2e-06) H-1 scatter 2.030757 0.011239\n",
|
||||
"2 10002 (1.2e-06 - 1.3e-05) H-1 scatter 1.658488 0.009777\n",
|
||||
"3 10002 (1.3e-05 - 1.4e-04) H-1 scatter 1.853002 0.007378\n",
|
||||
"4 10002 (1.4e-04 - 1.5e-03) H-1 scatter 2.050773 0.012484\n",
|
||||
"5 10002 (1.5e-03 - 1.6e-02) H-1 scatter 2.131759 0.007821\n",
|
||||
"6 10002 (1.6e-02 - 1.7e-01) H-1 scatter 2.213710 0.015159\n",
|
||||
"7 10002 (1.7e-01 - 1.9e+00) H-1 scatter 2.011925 0.009406\n",
|
||||
"8 10002 (1.9e+00 - 2.0e+01) H-1 scatter 0.371280 0.003949"
|
||||
]
|
||||
},
|
||||
"execution_count": 38,
|
||||
|
|
@ -1644,7 +1568,7 @@
|
|||
"name": "python",
|
||||
"nbconvert_exporter": "python",
|
||||
"pygments_lexer": "ipython2",
|
||||
"version": "2.7.9"
|
||||
"version": "2.7.6"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
|
|
|
|||
|
|
@ -57,6 +57,15 @@ on a given module or class.
|
|||
summary
|
||||
tallies
|
||||
|
||||
**Multi-Group Cross Section Generation**
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 1
|
||||
|
||||
mgxs
|
||||
energy_groups
|
||||
mgxs_library
|
||||
|
||||
**Example Jupyter Notebooks:**
|
||||
|
||||
.. toctree::
|
||||
|
|
@ -65,6 +74,7 @@ on a given module or class.
|
|||
examples/post-processing
|
||||
examples/pandas-dataframes
|
||||
examples/tally-arithmetic
|
||||
examples/multi-group-cross-sections
|
||||
|
||||
.. _Jupyter: https://jupyter.org/
|
||||
.. _NumPy: http://www.numpy.org/
|
||||
|
|
|
|||
66
docs/source/pythonapi/mgxs.rst
Normal file
66
docs/source/pythonapi/mgxs.rst
Normal file
|
|
@ -0,0 +1,66 @@
|
|||
.. _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:
|
||||
8
docs/source/pythonapi/mgxs_library.rst
Normal file
8
docs/source/pythonapi/mgxs_library.rst
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
.. _pythonapi_mgxs_library:
|
||||
|
||||
============
|
||||
MGXS Library
|
||||
============
|
||||
|
||||
.. automodule:: openmc.mgxs.library
|
||||
:members:
|
||||
|
|
@ -12,6 +12,8 @@ from openmc.trigger import *
|
|||
from openmc.tallies import *
|
||||
from openmc.cmfd import *
|
||||
from openmc.executor import *
|
||||
from openmc.statepoint import *
|
||||
from openmc.summary import *
|
||||
|
||||
try:
|
||||
from openmc.opencg_compatible import *
|
||||
|
|
|
|||
277
openmc/cross.py
277
openmc/cross.py
|
|
@ -1,9 +1,20 @@
|
|||
import sys
|
||||
|
||||
from openmc import Filter, Nuclide
|
||||
from openmc.filter import _FILTER_TYPES
|
||||
import openmc.checkvalue as cv
|
||||
|
||||
|
||||
if sys.version_info[0] >= 3:
|
||||
basestring = str
|
||||
|
||||
# Acceptable tally arithmetic binary operations
|
||||
_TALLY_ARITHMETIC_OPS = ['+', '-', '*', '/', '^']
|
||||
|
||||
|
||||
class CrossScore(object):
|
||||
"""A special-purpose tally score used to encapsulate all combinations of two
|
||||
tally's scores as a outer product for tally arithmetic.
|
||||
tally's scores as an outer product for tally arithmetic.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
|
|
@ -40,6 +51,38 @@ class CrossScore(object):
|
|||
if binary_op is not None:
|
||||
self.binary_op = binary_op
|
||||
|
||||
def __hash__(self):
|
||||
return hash(str(self))
|
||||
|
||||
def __eq__(self, other):
|
||||
return str(other) == str(self)
|
||||
|
||||
def __ne__(self, other):
|
||||
return not self == other
|
||||
|
||||
def __deepcopy__(self, memo):
|
||||
existing = memo.get(id(self))
|
||||
|
||||
# If this is the first time we have tried to copy this object, create a copy
|
||||
if existing is None:
|
||||
clone = type(self).__new__(type(self))
|
||||
clone._left_score = self.left_score
|
||||
clone._right_score = self.right_score
|
||||
clone._binary_op = self.binary_op
|
||||
|
||||
memo[id(self)] = clone
|
||||
|
||||
return clone
|
||||
|
||||
# If this object has been copied before, return the first copy made
|
||||
else:
|
||||
return existing
|
||||
|
||||
def __repr__(self):
|
||||
string = '({0} {1} {2})'.format(self.left_score,
|
||||
self.binary_op, self.right_score)
|
||||
return string
|
||||
|
||||
@property
|
||||
def left_score(self):
|
||||
return self._left_score
|
||||
|
|
@ -54,28 +97,24 @@ class CrossScore(object):
|
|||
|
||||
@left_score.setter
|
||||
def left_score(self, left_score):
|
||||
cv.check_type('left_score', left_score, (basestring, CrossScore))
|
||||
self._left_score = left_score
|
||||
|
||||
@right_score.setter
|
||||
def right_score(self, right_score):
|
||||
cv.check_type('right_score', right_score, (basestring, CrossScore))
|
||||
self._right_score = right_score
|
||||
|
||||
@binary_op.setter
|
||||
def binary_op(self, binary_op):
|
||||
cv.check_type('binary_op', binary_op, (basestring, CrossScore))
|
||||
cv.check_value('binary_op', binary_op, _TALLY_ARITHMETIC_OPS)
|
||||
self._binary_op = binary_op
|
||||
|
||||
def __eq__(self, other):
|
||||
return str(other) == str(self)
|
||||
|
||||
def __repr__(self):
|
||||
string = '({0} {1} {2})'.format(self.left_score,
|
||||
self.binary_op, self.right_score)
|
||||
return string
|
||||
|
||||
|
||||
class CrossNuclide(object):
|
||||
"""A special-purpose nuclide used to encapsulate all combinations of two
|
||||
tally's nuclides as a outer product for tally arithmetic.
|
||||
tally's nuclides as an outer product for tally arithmetic.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
|
|
@ -112,33 +151,33 @@ class CrossNuclide(object):
|
|||
if binary_op is not None:
|
||||
self.binary_op = binary_op
|
||||
|
||||
@property
|
||||
def left_nuclide(self):
|
||||
return self._left_nuclide
|
||||
|
||||
@property
|
||||
def right_nuclide(self):
|
||||
return self._right_nuclide
|
||||
|
||||
@property
|
||||
def binary_op(self):
|
||||
return self._binary_op
|
||||
|
||||
@left_nuclide.setter
|
||||
def left_nuclide(self, left_nuclide):
|
||||
self._left_nuclide = left_nuclide
|
||||
|
||||
@right_nuclide.setter
|
||||
def right_nuclide(self, right_nuclide):
|
||||
self._right_nuclide = right_nuclide
|
||||
|
||||
@binary_op.setter
|
||||
def binary_op(self, binary_op):
|
||||
self._binary_op = binary_op
|
||||
def __hash__(self):
|
||||
return hash(str(self))
|
||||
|
||||
def __eq__(self, other):
|
||||
return str(other) == str(self)
|
||||
|
||||
def __ne__(self, other):
|
||||
return not self == other
|
||||
|
||||
def __deepcopy__(self, memo):
|
||||
existing = memo.get(id(self))
|
||||
|
||||
# If this is the first time we have tried to copy this object, create a copy
|
||||
if existing is None:
|
||||
clone = type(self).__new__(type(self))
|
||||
clone._left_nuclide = self.left_nuclide
|
||||
clone._right_nuclide = self.right_nuclide
|
||||
clone._binary_op = self.binary_op
|
||||
|
||||
memo[id(self)] = clone
|
||||
|
||||
return clone
|
||||
|
||||
# If this object has been copied before, return the first copy made
|
||||
else:
|
||||
return existing
|
||||
|
||||
def __repr__(self):
|
||||
|
||||
string = ''
|
||||
|
|
@ -161,10 +200,38 @@ class CrossNuclide(object):
|
|||
|
||||
return string
|
||||
|
||||
@property
|
||||
def left_nuclide(self):
|
||||
return self._left_nuclide
|
||||
|
||||
@property
|
||||
def right_nuclide(self):
|
||||
return self._right_nuclide
|
||||
|
||||
@property
|
||||
def binary_op(self):
|
||||
return self._binary_op
|
||||
|
||||
@left_nuclide.setter
|
||||
def left_nuclide(self, left_nuclide):
|
||||
cv.check_type('left_nuclide', left_nuclide, (Nuclide, CrossNuclide))
|
||||
self._left_nuclide = left_nuclide
|
||||
|
||||
@right_nuclide.setter
|
||||
def right_nuclide(self, right_nuclide):
|
||||
cv.check_type('right_nuclide', right_nuclide, (Nuclide, CrossNuclide))
|
||||
self._right_nuclide = right_nuclide
|
||||
|
||||
@binary_op.setter
|
||||
def binary_op(self, binary_op):
|
||||
cv.check_type('binary_op', binary_op, basestring)
|
||||
cv.check_value('binary_op', binary_op, _TALLY_ARITHMETIC_OPS)
|
||||
self._binary_op = binary_op
|
||||
|
||||
|
||||
class CrossFilter(object):
|
||||
"""A special-purpose filter used to encapsulate all combinations of two
|
||||
tally's filter bins as a outer product for tally arithmetic.
|
||||
tally's filter bins as an outer product for tally arithmetic.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
|
|
@ -192,12 +259,10 @@ class CrossFilter(object):
|
|||
|
||||
left_type = left_filter.type
|
||||
right_type = right_filter.type
|
||||
self.type = '({0} {1} {2})'.format(left_type, binary_op, right_type)
|
||||
self._type = '({0} {1} {2})'.format(left_type, binary_op, right_type)
|
||||
|
||||
self._bins = {}
|
||||
self._bins['left'] = left_filter.bins
|
||||
self._bins['right'] = right_filter.bins
|
||||
self._num_bins = left_filter.num_bins * right_filter.num_bins
|
||||
self._stride = None
|
||||
|
||||
self._left_filter = None
|
||||
self._right_filter = None
|
||||
|
|
@ -205,13 +270,34 @@ class CrossFilter(object):
|
|||
|
||||
if left_filter is not None:
|
||||
self.left_filter = left_filter
|
||||
self._bins['left'] = left_filter.bins
|
||||
if right_filter is not None:
|
||||
self.right_filter = right_filter
|
||||
self._bins['right'] = right_filter.bins
|
||||
if binary_op is not None:
|
||||
self.binary_op = binary_op
|
||||
|
||||
def __hash__(self):
|
||||
return hash((self.type, self.bins))
|
||||
return hash((self.left_filter, self.right_filter))
|
||||
|
||||
def __eq__(self, other):
|
||||
return str(other) == str(self)
|
||||
|
||||
def __ne__(self, other):
|
||||
return not self == other
|
||||
|
||||
def __repr__(self):
|
||||
|
||||
string = 'CrossFilter\n'
|
||||
filter_type = '({0} {1} {2})'.format(self.left_filter.type,
|
||||
self.binary_op,
|
||||
self.right_filter.type)
|
||||
filter_bins = '({0} {1} {2})'.format(self.left_filter.bins,
|
||||
self.binary_op,
|
||||
self.right_filter.bins)
|
||||
string += '{0: <16}{1}{2}\n'.format('\tType', '=\t', filter_type)
|
||||
string += '{0: <16}{1}{2}\n'.format('\tBins', '=\t', filter_bins)
|
||||
return string
|
||||
|
||||
def __deepcopy__(self, memo):
|
||||
existing = memo.get(id(self))
|
||||
|
|
@ -221,9 +307,12 @@ class CrossFilter(object):
|
|||
clone = type(self).__new__(type(self))
|
||||
clone._left_filter = self.left_filter
|
||||
clone._right_filter = self.right_filter
|
||||
clone._binary_op = self.binary_op
|
||||
clone._type = self.type
|
||||
clone._bins = self.bins
|
||||
clone._num_bins = self.num_bins
|
||||
clone._stride = self.stride
|
||||
|
||||
memo[id(self)] = clone
|
||||
|
||||
return clone
|
||||
|
|
@ -250,54 +339,49 @@ class CrossFilter(object):
|
|||
|
||||
@property
|
||||
def bins(self):
|
||||
return (self._bins['left'], self._bins['right'])
|
||||
return self._bins['left'], self._bins['right']
|
||||
|
||||
@property
|
||||
def num_bins(self):
|
||||
return self._num_bins
|
||||
if self.left_filter is not None and self.right_filter is not None:
|
||||
return self.left_filter.num_bins * self.right_filter.num_bins
|
||||
else:
|
||||
return 0
|
||||
|
||||
@property
|
||||
def stride(self):
|
||||
return self.left_filter.stride * self.right_filter.stride
|
||||
return self._stride
|
||||
|
||||
@type.setter
|
||||
def type(self, filter_type):
|
||||
if filter_type not in _FILTER_TYPES.values():
|
||||
msg = 'Unable to set Filter type to "{0}" since it is not one ' \
|
||||
'of the supported types'.format(type)
|
||||
raise ValueError(msg)
|
||||
|
||||
self._type = filter_type
|
||||
|
||||
@left_filter.setter
|
||||
def left_filter(self, left_filter):
|
||||
cv.check_type('left_filter', left_filter, (Filter, CrossFilter))
|
||||
self._left_filter = left_filter
|
||||
self._bins['left'] = left_filter.bins
|
||||
|
||||
@right_filter.setter
|
||||
def right_filter(self, right_filter):
|
||||
cv.check_type('right_filter', right_filter, (Filter, CrossFilter))
|
||||
self._right_filter = right_filter
|
||||
self._bins['right'] = right_filter.bins
|
||||
|
||||
@binary_op.setter
|
||||
def binary_op(self, binary_op):
|
||||
cv.check_type('binary_op', binary_op, basestring)
|
||||
cv.check_value('binary_op', binary_op, _TALLY_ARITHMETIC_OPS)
|
||||
self._binary_op = binary_op
|
||||
|
||||
def __eq__(self, other):
|
||||
return str(other) == str(self)
|
||||
|
||||
def split_filters(self):
|
||||
|
||||
split_filters = []
|
||||
|
||||
# If left Filter is not a CrossFilter, simply append to list
|
||||
if isinstance(self.left_filter, Filter):
|
||||
split_filters.append(self.left_filter)
|
||||
# Recursively descend CrossFilter tree to collect all Filters
|
||||
else:
|
||||
split_filters.extend(self.left_filter.split_filters())
|
||||
|
||||
# If right Filter is not a CrossFilter, simply append to list
|
||||
if isinstance(self.right_filter, Filter):
|
||||
split_filters.append(self.right_filter)
|
||||
# Recursively descend CrossFilter tree to collect all Filters
|
||||
else:
|
||||
split_filters.extend(self.right_filter.split_filters())
|
||||
|
||||
return split_filters
|
||||
@stride.setter
|
||||
def stride(self, stride):
|
||||
self._stride = stride
|
||||
|
||||
def get_bin_index(self, filter_bin):
|
||||
"""Returns the index in the CrossFilter for some bin.
|
||||
|
|
@ -316,7 +400,7 @@ class CrossFilter(object):
|
|||
|
||||
Returns
|
||||
-------
|
||||
filter_index : int
|
||||
filter_index : Integral
|
||||
The index in the Tally data array for this filter bin.
|
||||
|
||||
"""
|
||||
|
|
@ -326,15 +410,56 @@ class CrossFilter(object):
|
|||
filter_index = left_index * self.right_filter.num_bins + right_index
|
||||
return filter_index
|
||||
|
||||
def __repr__(self):
|
||||
def get_pandas_dataframe(self, datasize, summary=None):
|
||||
"""Builds a Pandas DataFrame for the CrossFilter's bins.
|
||||
|
||||
string = 'CrossFilter\n'
|
||||
filter_type = '({0} {1} {2})'.format(self.left_filter.type,
|
||||
self.binary_op,
|
||||
self.right_filter.type)
|
||||
filter_bins = '({0} {1} {2})'.format(self.left_filter.bins,
|
||||
self.binary_op,
|
||||
self.right_filter.bins)
|
||||
string += '{0: <16}{1}{2}\n'.format('\tType', '=\t', filter_type)
|
||||
string += '{0: <16}{1}{2}\n'.format('\tBins', '=\t', filter_bins)
|
||||
return string
|
||||
This method constructs a Pandas DataFrame object for the CrossFilter
|
||||
with columns annotated by filter bin information. This is a helper
|
||||
method for the Tally.get_pandas_dataframe(...) method. This method
|
||||
recursively builds and concatenates Pandas DataFrames for the left
|
||||
and right filters and crossfilters.
|
||||
|
||||
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
|
||||
uses Pandas' Multi-index functionality.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
datasize : 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.
|
||||
|
||||
Returns
|
||||
-------
|
||||
pandas.DataFrame
|
||||
A Pandas DataFrame with columns of strings that characterize the
|
||||
crossfilter's bins. Each entry in the DataFrame will include one
|
||||
or more binary operations used to construct the crossfilter's bins.
|
||||
The number of rows in the DataFrame is the same as the total number
|
||||
of bins in the corresponding tally, with the filter bins
|
||||
appropriately tiled to map to the corresponding tally bins.
|
||||
|
||||
See also
|
||||
--------
|
||||
Tally.get_pandas_dataframe(), Filter.get_pandas_dataframe()
|
||||
|
||||
"""
|
||||
|
||||
# If left and right filters are identical, do not combine bins
|
||||
if self.left_filter == self.right_filter:
|
||||
df = self.left_filter.get_pandas_dataframe(datasize, summary)
|
||||
|
||||
# If left and right filters are different, combine their bins
|
||||
else:
|
||||
left_df = self.left_filter.get_pandas_dataframe(datasize, summary)
|
||||
right_df = self.right_filter.get_pandas_dataframe(datasize, summary)
|
||||
left_df = left_df.astype(str)
|
||||
right_df = right_df.astype(str)
|
||||
df = '(' + left_df + ' ' + self.binary_op + ' ' + right_df + ')'
|
||||
|
||||
return df
|
||||
|
|
|
|||
|
|
@ -38,22 +38,30 @@ class Element(object):
|
|||
if xs is not None:
|
||||
self.xs = xs
|
||||
|
||||
def __eq__(self, element2):
|
||||
# Check type
|
||||
if not isinstance(element2, Element):
|
||||
def __eq__(self, other):
|
||||
if isinstance(other, Element):
|
||||
if self._name != other._name:
|
||||
return False
|
||||
elif self._xs != other._xs:
|
||||
return False
|
||||
else:
|
||||
return True
|
||||
elif isinstance(other, basestring) and other == self.name:
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
||||
# Check name and xs
|
||||
if self._name != element2._name:
|
||||
return False
|
||||
elif self._xs != element2._xs:
|
||||
return False
|
||||
else:
|
||||
return True
|
||||
def __ne__(self, other):
|
||||
return not self == other
|
||||
|
||||
def __hash__(self):
|
||||
return hash((self._name, self._xs))
|
||||
|
||||
def __repr__(self):
|
||||
string = 'Element - {0}\n'.format(self._name)
|
||||
string += '{0: <16}{1}{2}\n'.format('\tXS', '=\t', self._xs)
|
||||
return string
|
||||
|
||||
@property
|
||||
def xs(self):
|
||||
return self._xs
|
||||
|
|
@ -70,9 +78,4 @@ class Element(object):
|
|||
@name.setter
|
||||
def name(self, name):
|
||||
check_type('name', name, basestring)
|
||||
self._name = name
|
||||
|
||||
def __repr__(self):
|
||||
string = 'Element - {0}\n'.format(self._name)
|
||||
string += '{0: <16}{1}{2}\n'.format('\tXS', '=\t', self._xs)
|
||||
return string
|
||||
self._name = name
|
||||
|
|
@ -30,14 +30,16 @@ class Executor(object):
|
|||
stdout=subprocess.PIPE)
|
||||
|
||||
# Capture and re-print OpenMC output in real-time
|
||||
while (True and output):
|
||||
line = p.stdout.readline()
|
||||
print(line, end='')
|
||||
|
||||
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
|
||||
|
||||
|
|
|
|||
518
openmc/filter.py
518
openmc/filter.py
|
|
@ -1,20 +1,26 @@
|
|||
from collections import Iterable
|
||||
import copy
|
||||
from numbers import Real, Integral
|
||||
import sys
|
||||
|
||||
import numpy as np
|
||||
|
||||
from openmc import Mesh
|
||||
from openmc.checkvalue import check_type, check_iterable_type, \
|
||||
check_greater_than, _isinstance
|
||||
from openmc.summary import Summary
|
||||
import openmc.checkvalue as cv
|
||||
|
||||
|
||||
if sys.version_info[0] >= 3:
|
||||
basestring = str
|
||||
|
||||
|
||||
_FILTER_TYPES = ['universe', 'material', 'cell', 'cellborn', 'surface',
|
||||
'mesh', 'energy', 'energyout', 'mu', 'polar', 'azimuthal',
|
||||
'distribcell', 'delayedgroup']
|
||||
|
||||
class Filter(object):
|
||||
"""A filter used to constrain a tally to a specific criterion, e.g. only tally
|
||||
events when the particle is in a certain cell and energy range.
|
||||
"""A filter used to constrain a tally to a specific criterion, e.g. only
|
||||
tally events when the particle is in a certain cell and energy range.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
|
|
@ -22,46 +28,60 @@ class Filter(object):
|
|||
The type of the tally filter. Acceptable values are "universe",
|
||||
"material", "cell", "cellborn", "surface", "mesh", "energy",
|
||||
"energyout", and "distribcell".
|
||||
bins : int or Iterable of int or Iterable of float
|
||||
bins : Integral or Iterable of Integral or Iterable of Real
|
||||
The bins for the filter. This takes on different meaning for different
|
||||
filters.
|
||||
filters. See the OpenMC online documentation for more details.
|
||||
|
||||
Attributes
|
||||
----------
|
||||
type : str
|
||||
The type of the tally filter.
|
||||
bins : int or Iterable of int or Iterable of float
|
||||
bins : Integral or Iterable of Integral or Iterable of Real
|
||||
The bins for the filter
|
||||
num_bins : Integral
|
||||
The number of filter bins
|
||||
mesh : Mesh or None
|
||||
A Mesh object for 'mesh' type filters.
|
||||
offset : Integral
|
||||
A value used to index tally bins for 'distribcell' tallies.
|
||||
stride : Integral
|
||||
The number of filter, nuclide and score bins within each of this
|
||||
filter's bins.
|
||||
|
||||
"""
|
||||
|
||||
# Initialize Filter class attributes
|
||||
def __init__(self, type=None, bins=None):
|
||||
self.type = type
|
||||
|
||||
self._type = None
|
||||
self._num_bins = 0
|
||||
self.bins = bins
|
||||
self._bins = None
|
||||
self._mesh = None
|
||||
self._offset = -1
|
||||
self._stride = None
|
||||
|
||||
def __eq__(self, filter2):
|
||||
# Check type
|
||||
if self.type != filter2.type:
|
||||
return False
|
||||
if type is not None:
|
||||
self.type = type
|
||||
if bins is not None:
|
||||
self.bins = bins
|
||||
|
||||
# Check number of bins
|
||||
elif len(self.bins) != len(filter2.bins):
|
||||
def __eq__(self, other):
|
||||
if not isinstance(other, Filter):
|
||||
return False
|
||||
|
||||
# Check bin edges
|
||||
elif not np.allclose(self.bins, filter2.bins):
|
||||
elif self.type != other.type:
|
||||
return False
|
||||
elif len(self.bins) != len(other.bins):
|
||||
return False
|
||||
elif not np.allclose(self.bins, other.bins):
|
||||
return False
|
||||
|
||||
else:
|
||||
return True
|
||||
|
||||
def __ne__(self, other):
|
||||
return not self == other
|
||||
|
||||
def __hash__(self):
|
||||
return hash((self._type, self._bins))
|
||||
return hash((self.type, tuple(self.bins)))
|
||||
|
||||
def __deepcopy__(self, memo):
|
||||
existing = memo.get(id(self))
|
||||
|
|
@ -84,6 +104,13 @@ class Filter(object):
|
|||
else:
|
||||
return existing
|
||||
|
||||
def __repr__(self):
|
||||
string = 'Filter\n'
|
||||
string += '{0: <16}{1}{2}\n'.format('\tType', '=\t', self.type)
|
||||
string += '{0: <16}{1}{2}\n'.format('\tBins', '=\t', self.bins)
|
||||
string += '{0: <16}{1}{2}\n'.format('\tOffset', '=\t', self.offset)
|
||||
return string
|
||||
|
||||
@property
|
||||
def type(self):
|
||||
return self._type
|
||||
|
|
@ -94,7 +121,14 @@ class Filter(object):
|
|||
|
||||
@property
|
||||
def num_bins(self):
|
||||
return self._num_bins
|
||||
if self.bins is None:
|
||||
return 0
|
||||
elif self.type in ['energy', 'energyout']:
|
||||
return len(self.bins) - 1
|
||||
elif self.type in ['cell', 'cellborn', 'surface', 'universe', 'material']:
|
||||
return len(self.bins)
|
||||
else:
|
||||
return self._num_bins
|
||||
|
||||
@property
|
||||
def mesh(self):
|
||||
|
|
@ -121,15 +155,13 @@ class Filter(object):
|
|||
|
||||
@bins.setter
|
||||
def bins(self, bins):
|
||||
if bins is None:
|
||||
self.num_bins = 0
|
||||
elif self._type is None:
|
||||
if self.type is None:
|
||||
msg = 'Unable to set bins for Filter to "{0}" since ' \
|
||||
'the Filter type has not yet been set'.format(bins)
|
||||
raise ValueError(msg)
|
||||
|
||||
# If the bin edge is a single value, it is a Cell, Material, etc. ID
|
||||
if not _isinstance(bins, Iterable):
|
||||
if not isinstance(bins, Iterable):
|
||||
bins = [bins]
|
||||
|
||||
# If the bins are in a collection, convert it to a list
|
||||
|
|
@ -137,14 +169,14 @@ class Filter(object):
|
|||
bins = list(bins)
|
||||
|
||||
if self.type in ['cell', 'cellborn', 'surface', 'material',
|
||||
'universe', 'distribcell', 'delayedgroup']:
|
||||
check_iterable_type('filter bins', bins, Integral)
|
||||
'universe', 'distribcell', 'delayedgroup']:
|
||||
cv.check_iterable_type('filter bins', bins, Integral)
|
||||
for edge in bins:
|
||||
check_greater_than('filter bin', edge, 0, equality=True)
|
||||
cv.check_greater_than('filter bin', edge, 0, equality=True)
|
||||
|
||||
elif self._type in ['energy', 'energyout']:
|
||||
elif self.type in ['energy', 'energyout']:
|
||||
for edge in bins:
|
||||
if not _isinstance(edge, Real):
|
||||
if not cv._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)
|
||||
|
|
@ -163,12 +195,12 @@ class Filter(object):
|
|||
raise ValueError(msg)
|
||||
|
||||
# mesh filters
|
||||
elif self._type == 'mesh':
|
||||
elif self.type == 'mesh':
|
||||
if not len(bins) == 1:
|
||||
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 _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)
|
||||
|
|
@ -180,16 +212,15 @@ class Filter(object):
|
|||
# If all error checks passed, add bin edges
|
||||
self._bins = np.array(bins)
|
||||
|
||||
# FIXME
|
||||
@num_bins.setter
|
||||
def num_bins(self, num_bins):
|
||||
check_type('filter num_bins', num_bins, Integral)
|
||||
check_greater_than('filter num_bins', num_bins, 0, equality=True)
|
||||
cv.check_type('filter num_bins', num_bins, Integral)
|
||||
cv.check_greater_than('filter num_bins', num_bins, 0, equality=True)
|
||||
self._num_bins = num_bins
|
||||
|
||||
@mesh.setter
|
||||
def mesh(self, mesh):
|
||||
check_type('filter mesh', mesh, Mesh)
|
||||
cv.check_type('filter mesh', mesh, Mesh)
|
||||
|
||||
self._mesh = mesh
|
||||
self.type = 'mesh'
|
||||
|
|
@ -197,12 +228,12 @@ class Filter(object):
|
|||
|
||||
@offset.setter
|
||||
def offset(self, offset):
|
||||
check_type('filter offset', offset, Integral)
|
||||
cv.check_type('filter offset', offset, Integral)
|
||||
self._offset = offset
|
||||
|
||||
@stride.setter
|
||||
def stride(self, stride):
|
||||
check_type('filter stride', stride, Integral)
|
||||
cv.check_type('filter stride', stride, Integral)
|
||||
if stride < 0:
|
||||
msg = 'Unable to set stride "{0}" for a "{1}" Filter since it ' \
|
||||
'is a negative value'.format(stride, self.type)
|
||||
|
|
@ -277,25 +308,63 @@ class Filter(object):
|
|||
|
||||
return merged_filter
|
||||
|
||||
def is_subset(self, other):
|
||||
"""Determine if another filter is a subset of this filter.
|
||||
|
||||
If all of the bins in the other filter are included as bins in this
|
||||
filter, then it is a subset of this filter.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
other : Filter
|
||||
The filter to query as a subset of this filter
|
||||
|
||||
Returns
|
||||
-------
|
||||
bool
|
||||
Whether or not the other filter is a subset of this filter
|
||||
|
||||
"""
|
||||
|
||||
if not isinstance(other, Filter):
|
||||
return False
|
||||
elif self.type != other.type:
|
||||
return False
|
||||
elif self.type in ['energy', 'energyout']:
|
||||
if len(self.bins) != len(other.bins):
|
||||
return False
|
||||
else:
|
||||
return np.allclose(self.bins, other.bins)
|
||||
|
||||
for bin in other.bins:
|
||||
if bin not in self.bins:
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
def get_bin_index(self, filter_bin):
|
||||
"""Returns the index in the Filter for some bin.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
filter_bin : int or tuple
|
||||
filter_bin : Integral or tuple
|
||||
The bin is the integer ID for 'material', 'surface', 'cell',
|
||||
'cellborn', and 'universe' Filters. The bin is an integer for the
|
||||
cell instance ID for 'distribcell' Filters. The bin is a 2-tuple of
|
||||
floats for 'energy' and 'energyout' filters corresponding to the
|
||||
energy boundaries of the bin of interest. The bin is a (x,y,z)
|
||||
3-tuple for 'mesh' filters corresponding to the mesh cell of
|
||||
energy boundaries of the bin of interest. The bin is an (x,y,z)
|
||||
3-tuple for 'mesh' filters corresponding to the mesh cell
|
||||
interest.
|
||||
|
||||
Returns
|
||||
-------
|
||||
filter_index : int
|
||||
filter_index : Integral
|
||||
The index in the Tally data array for this filter bin.
|
||||
|
||||
See also
|
||||
--------
|
||||
Filter.get_bin()
|
||||
|
||||
"""
|
||||
|
||||
try:
|
||||
|
|
@ -317,10 +386,14 @@ class Filter(object):
|
|||
|
||||
# Use lower energy bound to find index for energy Filters
|
||||
elif self.type in ['energy', 'energyout']:
|
||||
val = np.where(self.bins == filter_bin[0])[0][0]
|
||||
filter_index = val
|
||||
deltas = np.abs(self.bins - filter_bin[1]) / filter_bin[1]
|
||||
min_delta = np.min(deltas)
|
||||
if min_delta < 1E-3:
|
||||
filter_index = deltas.argmin() - 1
|
||||
else:
|
||||
raise ValueError
|
||||
|
||||
# Filter bins for distribcell are the "IDs" of each unique placement
|
||||
# Filter bins for distribcells are "IDs" of each unique placement
|
||||
# of the Cell in the Geometry (integers starting at 0)
|
||||
elif self.type == 'distribcell':
|
||||
filter_index = filter_bin
|
||||
|
|
@ -332,14 +405,355 @@ class Filter(object):
|
|||
|
||||
except ValueError:
|
||||
msg = 'Unable to get the bin index for Filter since "{0}" ' \
|
||||
'is not one of the bins'.format(filter_bin)
|
||||
'is not one of the bins'.format(filter_bin)
|
||||
raise ValueError(msg)
|
||||
|
||||
return filter_index
|
||||
|
||||
def __repr__(self):
|
||||
string = 'Filter\n'
|
||||
string += '{0: <16}{1}{2}\n'.format('\tType', '=\t', self.type)
|
||||
string += '{0: <16}{1}{2}\n'.format('\tBins', '=\t', self.bins)
|
||||
string += '{0: <16}{1}{2}\n'.format('\tOffset', '=\t', self.offset)
|
||||
return string
|
||||
def get_bin(self, bin_index):
|
||||
"""Returns the filter bin for some filter bin index.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
bin_index : Integral
|
||||
The zero-based index into the filter's array of bins. The bin
|
||||
index for 'material', 'surface', 'cell', 'cellborn', and 'universe'
|
||||
filters corresponds to the ID in the filter's list of bins. For
|
||||
'distribcell' tallies the bin index necessarily can only be zero
|
||||
since only one cell can be tracked per tally. The bin index for
|
||||
'energy' and 'energyout' filters corresponds to the energy range of
|
||||
interest in the filter bins of energies. The bin index for 'mesh'
|
||||
filters is the index into the flattened array of (x,y) or (x,y,z)
|
||||
mesh cell bins.
|
||||
|
||||
Returns
|
||||
-------
|
||||
bin : 1-, 2-, or 3-tuple of Real
|
||||
The bin in the Tally data array. The bin for 'material', surface',
|
||||
'cell', 'cellborn', 'universe' and 'distribcell' filters is a
|
||||
1-tuple of the ID corresponding to the appropriate filter bin.
|
||||
The bin for 'energy' and 'energyout' filters is a 2-tuple of the
|
||||
lower and upper energies bounding the energy interval for the filter
|
||||
bin. The bin for 'mesh' tallies is a 2-tuple or 3-tuple of the x,y
|
||||
or x,y,z mesh cell indices corresponding to the bin in a 2D/3D mesh.
|
||||
|
||||
See also
|
||||
--------
|
||||
Filter.get_bin_index()
|
||||
|
||||
"""
|
||||
|
||||
cv.check_type('bin_index', bin_index, Integral)
|
||||
cv.check_greater_than('bin_index', bin_index, 0, equality=True)
|
||||
cv.check_less_than('bin_index', bin_index, self.num_bins)
|
||||
|
||||
if self.type == 'mesh':
|
||||
|
||||
# Construct 3-tuple of x,y,z cell indices for a 3D mesh
|
||||
if len(self.mesh.dimension) == 3:
|
||||
nx, ny, nz = self.mesh.dimension
|
||||
x = bin_index / (ny * nz)
|
||||
y = (bin_index - (x * ny * nz)) / nz
|
||||
z = bin_index - (x * ny * nz) - (y * nz)
|
||||
filter_bin = (x, y, z)
|
||||
|
||||
# Construct 2-tuple of x,y cell indices for a 2D mesh
|
||||
else:
|
||||
nx, ny = self.mesh.dimension
|
||||
x = bin_index / ny
|
||||
y = bin_index - (x * ny)
|
||||
filter_bin = (x, y)
|
||||
|
||||
# Construct 2-tuple of lower, upper energies for energy(out) filters
|
||||
elif self.type in ['energy', 'energyout']:
|
||||
filter_bin = (self.bins[bin_index], self.bins[bin_index+1])
|
||||
# Construct 1-tuple of with the cell ID for distribcell filters
|
||||
elif self.type == 'distribcell':
|
||||
filter_bin = (self.bins[0],)
|
||||
# Construct 1-tuple with domain ID (e.g., material) for other filters
|
||||
else:
|
||||
filter_bin = (self.bins[bin_index],)
|
||||
|
||||
return filter_bin
|
||||
|
||||
def get_pandas_dataframe(self, data_size, summary=None):
|
||||
"""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.
|
||||
|
||||
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
|
||||
uses Pandas' Multi-index functionality.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
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.
|
||||
|
||||
Returns
|
||||
-------
|
||||
pandas.DataFrame
|
||||
A Pandas DataFrame with columns of strings that characterize the
|
||||
filter's bins. The number of rows in the DataFrame is the same as
|
||||
the total number of bins in the corresponding tally, with the filter
|
||||
bin appropriately tiled to map to the corresponding tally bins.
|
||||
|
||||
For 'cell', 'cellborn', 'surface', 'material', and 'universe'
|
||||
filters, the DataFrame includes a single column with the cell,
|
||||
surface, material or universe ID corresponding to each filter bin.
|
||||
|
||||
For 'distribcell' filters, the DataFrame either includes:
|
||||
|
||||
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).
|
||||
|
||||
For 'energy' and 'energyout' filters, the DataFrame include a single
|
||||
column with each element comprising a string with the lower, upper
|
||||
energy bounds for each filter bin.
|
||||
|
||||
For 'mesh' filters, the DataFrame includes three columns for the
|
||||
x,y,z mesh cell indices corresponding to each filter bin.
|
||||
|
||||
Raises
|
||||
------
|
||||
ImportError
|
||||
When Pandas is not installed, or summary info is requested but
|
||||
OpenCG is not installed.
|
||||
|
||||
See also
|
||||
--------
|
||||
Tally.get_pandas_dataframe(), CrossFilter.get_pandas_dataframe()
|
||||
|
||||
"""
|
||||
|
||||
# Attempt to import Pandas
|
||||
try:
|
||||
import pandas as pd
|
||||
except ImportError:
|
||||
msg = 'The Pandas Python package must be installed on your system'
|
||||
raise ImportError(msg)
|
||||
|
||||
# Initialize Pandas DataFrame
|
||||
df = pd.DataFrame()
|
||||
|
||||
# mesh filters
|
||||
if self.type == 'mesh':
|
||||
|
||||
# Initialize dictionary to build Pandas Multi-index column
|
||||
filter_dict = {}
|
||||
|
||||
# Append Mesh ID as outermost index of mult-index
|
||||
mesh_key = 'mesh {0}'.format(self.mesh.id)
|
||||
|
||||
# Find mesh dimensions - use 3D indices for simplicity
|
||||
if (len(self.mesh.dimension) == 3):
|
||||
nx, ny, nz = self.mesh.dimension
|
||||
else:
|
||||
nx, ny = self.mesh.dimension
|
||||
nz = 1
|
||||
|
||||
# Generate multi-index sub-column for x-axis
|
||||
filter_bins = np.arange(1, nx+1)
|
||||
repeat_factor = ny * nz * self.stride
|
||||
filter_bins = np.repeat(filter_bins, repeat_factor)
|
||||
tile_factor = data_size / len(filter_bins)
|
||||
filter_bins = np.tile(filter_bins, tile_factor)
|
||||
filter_dict[(mesh_key, 'x')] = filter_bins
|
||||
|
||||
# Generate multi-index sub-column for y-axis
|
||||
filter_bins = np.arange(1, ny+1)
|
||||
repeat_factor = nz * self.stride
|
||||
filter_bins = np.repeat(filter_bins, repeat_factor)
|
||||
tile_factor = data_size / len(filter_bins)
|
||||
filter_bins = np.tile(filter_bins, tile_factor)
|
||||
filter_dict[(mesh_key, 'y')] = filter_bins
|
||||
|
||||
# Generate multi-index sub-column for z-axis
|
||||
filter_bins = np.arange(1, nz+1)
|
||||
repeat_factor = self.stride
|
||||
filter_bins = np.repeat(filter_bins, repeat_factor)
|
||||
tile_factor = data_size / len(filter_bins)
|
||||
filter_bins = np.tile(filter_bins, tile_factor)
|
||||
filter_dict[(mesh_key, 'z')] = filter_bins
|
||||
|
||||
# Initialize a Pandas DataFrame from the mesh dictionary
|
||||
df = pd.concat([df, pd.DataFrame(filter_dict)])
|
||||
|
||||
# distribcell filters
|
||||
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 and extract the OpenCG geometry the Summary
|
||||
summary.make_opencg_geometry()
|
||||
opencg_geometry = summary.opencg_geometry
|
||||
openmc_geometry = summary.openmc_geometry
|
||||
|
||||
# Use OpenCG to compute the number of regions
|
||||
opencg_geometry.initialize_cell_offsets()
|
||||
num_regions = opencg_geometry.num_regions
|
||||
|
||||
# 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_offset(path, self.offset)
|
||||
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
|
||||
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 = {}
|
||||
|
||||
# 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')
|
||||
|
||||
# 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)
|
||||
|
||||
# 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
|
||||
|
||||
# Iterate over all regions (distribcell instances)
|
||||
for offset in range(num_offsets):
|
||||
coords = offsets_to_coords[offset]
|
||||
|
||||
# If entire LocalCoords has been unraveled into
|
||||
# Multi-index columns already, continue
|
||||
if coords is None:
|
||||
continue
|
||||
|
||||
# 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
|
||||
|
||||
# Assign entry to Lattice Multi-index column
|
||||
else:
|
||||
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._lat_y
|
||||
level_dict[lat_z_key][offset] = coords._lat_z
|
||||
|
||||
# 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
|
||||
|
||||
# Tile the Multi-index columns
|
||||
for level_key, level_bins in level_dict.items():
|
||||
level_bins = np.repeat(level_bins, self.stride)
|
||||
tile_factor = data_size / len(level_bins)
|
||||
level_bins = np.tile(level_bins, tile_factor)
|
||||
level_dict[level_key] = level_bins
|
||||
|
||||
# Initialize a Pandas DataFrame from the level dictionary
|
||||
if level_df is None:
|
||||
level_df = pd.DataFrame(level_dict)
|
||||
else:
|
||||
level_df = pd.concat([level_df, pd.DataFrame(level_dict)], axis=1)
|
||||
|
||||
# Create DataFrame column for distribcell instances IDs
|
||||
# NOTE: This is performed regardless of whether the user
|
||||
# requests Summary geometric information
|
||||
filter_bins = np.arange(self.num_bins)
|
||||
filter_bins = np.repeat(filter_bins, self.stride)
|
||||
tile_factor = data_size / len(filter_bins)
|
||||
filter_bins = np.tile(filter_bins, tile_factor)
|
||||
filter_bins = filter_bins
|
||||
df = pd.DataFrame({self.type : filter_bins})
|
||||
|
||||
# If OpenCG level info DataFrame was created, concatenate
|
||||
# with DataFrame of distribcell instance IDs
|
||||
if level_df is not None:
|
||||
level_df = level_df.dropna(axis=1, how='all')
|
||||
level_df = level_df.astype(np.int)
|
||||
df = pd.concat([level_df, df], axis=1)
|
||||
|
||||
# energy, energyout filters
|
||||
elif 'energy' in self.type:
|
||||
bins = self.bins
|
||||
num_bins = self.num_bins
|
||||
|
||||
# Create strings for
|
||||
template = '({0:.1e} - {1:.1e})'
|
||||
filter_bins = []
|
||||
for i in range(num_bins):
|
||||
filter_bins.append(template.format(bins[i], bins[i+1]))
|
||||
|
||||
# Tile the energy bins into a DataFrame column
|
||||
filter_bins = np.repeat(filter_bins, self.stride)
|
||||
tile_factor = data_size / len(filter_bins)
|
||||
filter_bins = np.tile(filter_bins, tile_factor)
|
||||
filter_bins = filter_bins
|
||||
df = pd.concat([df, pd.DataFrame({self.type + ' [MeV]' : filter_bins})])
|
||||
|
||||
# universe, material, surface, cell, and cellborn filters
|
||||
else:
|
||||
filter_bins = np.repeat(self.bins, self.stride)
|
||||
tile_factor = data_size / len(filter_bins)
|
||||
filter_bins = np.tile(filter_bins, tile_factor)
|
||||
filter_bins = filter_bins
|
||||
df = pd.concat([df, pd.DataFrame({self.type : filter_bins})])
|
||||
|
||||
return df
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
from collections import OrderedDict
|
||||
from xml.etree import ElementTree as ET
|
||||
|
||||
import openmc
|
||||
|
|
@ -110,7 +111,7 @@ class Geometry(object):
|
|||
|
||||
"""
|
||||
|
||||
nuclides = {}
|
||||
nuclides = OrderedDict()
|
||||
materials = self.get_all_materials()
|
||||
|
||||
for material in materials:
|
||||
|
|
@ -134,7 +135,9 @@ class Geometry(object):
|
|||
for cell in material_cells:
|
||||
materials.add(cell._fill)
|
||||
|
||||
return list(materials)
|
||||
materials = list(materials)
|
||||
materials.sort(key=lambda x: x.id)
|
||||
return materials
|
||||
|
||||
def get_all_material_cells(self):
|
||||
all_cells = self.get_all_cells()
|
||||
|
|
@ -144,7 +147,9 @@ class Geometry(object):
|
|||
if cell._type == 'normal':
|
||||
material_cells.add(cell)
|
||||
|
||||
return list(material_cells)
|
||||
material_cells = list(material_cells)
|
||||
material_cells.sort(key=lambda x: x.id)
|
||||
return material_cells
|
||||
|
||||
def get_all_material_universes(self):
|
||||
"""Return all universes composed of at least one non-fill cell
|
||||
|
|
@ -165,7 +170,9 @@ class Geometry(object):
|
|||
if cell._type == 'normal':
|
||||
material_universes.add(universe)
|
||||
|
||||
return list(material_universes)
|
||||
material_universes = list(material_universes)
|
||||
material_universes.sort(key=lambda x: x.id)
|
||||
return material_universes
|
||||
|
||||
|
||||
class GeometryFile(object):
|
||||
|
|
@ -198,7 +205,13 @@ class GeometryFile(object):
|
|||
|
||||
"""
|
||||
|
||||
root_universe = self._geometry._root_universe
|
||||
# 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
|
||||
|
|
|
|||
|
|
@ -83,6 +83,38 @@ class Material(object):
|
|||
# If specified, this file will be used instead of composition values
|
||||
self._distrib_otf_file = None
|
||||
|
||||
def __repr__(self):
|
||||
string = 'Material\n'
|
||||
string += '{0: <16}{1}{2}\n'.format('\tID', '=\t', self._id)
|
||||
string += '{0: <16}{1}{2}\n'.format('\tName', '=\t', self._name)
|
||||
|
||||
string += '{0: <16}{1}{2}'.format('\tDensity', '=\t', self._density)
|
||||
string += ' [{0}]\n'.format(self._density_units)
|
||||
|
||||
string += '{0: <16}\n'.format('\tS(a,b) Tables')
|
||||
|
||||
for sab in self._sab:
|
||||
string += '{0: <16}{1}[{2}{3}]\n'.format('\tS(a,b)', '=\t',
|
||||
sab[0], sab[1])
|
||||
|
||||
string += '{0: <16}\n'.format('\tNuclides')
|
||||
|
||||
for nuclide in self._nuclides:
|
||||
percent = self._nuclides[nuclide][1]
|
||||
percent_type = self._nuclides[nuclide][2]
|
||||
string += '{0: <16}'.format('\t{0}'.format(nuclide))
|
||||
string += '=\t{0: <12} [{1}]\n'.format(percent, percent_type)
|
||||
|
||||
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))
|
||||
string += '=\t{0: <12} [{1}]\n'.format(percent, percent_type)
|
||||
|
||||
return string
|
||||
|
||||
@property
|
||||
def id(self):
|
||||
return self._id
|
||||
|
|
@ -125,7 +157,7 @@ class Material(object):
|
|||
msg = 'Unable to set Material ID to "{0}" since a Material with ' \
|
||||
'this ID was already initialized'.format(material_id)
|
||||
raise ValueError(msg)
|
||||
check_greater_than('material ID', material_id, 0)
|
||||
check_greater_than('material ID', material_id, 0, equality=True)
|
||||
|
||||
self._id = material_id
|
||||
MATERIAL_IDS.append(material_id)
|
||||
|
|
@ -326,7 +358,7 @@ class Material(object):
|
|||
|
||||
"""
|
||||
|
||||
nuclides = {}
|
||||
nuclides = OrderedDict()
|
||||
|
||||
for nuclide_name, nuclide_tuple in self._nuclides.items():
|
||||
nuclide = nuclide_tuple[0]
|
||||
|
|
@ -335,38 +367,6 @@ class Material(object):
|
|||
|
||||
return nuclides
|
||||
|
||||
def __repr__(self):
|
||||
string = 'Material\n'
|
||||
string += '{0: <16}{1}{2}\n'.format('\tID', '=\t', self._id)
|
||||
string += '{0: <16}{1}{2}\n'.format('\tName', '=\t', self._name)
|
||||
|
||||
string += '{0: <16}{1}{2}'.format('\tDensity', '=\t', self._density)
|
||||
string += ' [{0}]\n'.format(self._density_units)
|
||||
|
||||
string += '{0: <16}\n'.format('\tS(a,b) Tables')
|
||||
|
||||
for sab in self._sab:
|
||||
string += '{0: <16}{1}[{2}{3}]\n'.format('\tS(a,b)', '=\t',
|
||||
sab[0], sab[1])
|
||||
|
||||
string += '{0: <16}\n'.format('\tNuclides')
|
||||
|
||||
for nuclide in self._nuclides:
|
||||
percent = self._nuclides[nuclide][1]
|
||||
percent_type = self._nuclides[nuclide][2]
|
||||
string += '{0: <16}'.format('\t{0}'.format(nuclide))
|
||||
string += '=\t{0: <12} [{1}]\n'.format(percent, percent_type)
|
||||
|
||||
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))
|
||||
string += '=\t{0: <12} [{1}]\n'.format(percent, percent_type)
|
||||
|
||||
return string
|
||||
|
||||
def _get_nuclide_xml(self, nuclide, distrib=False):
|
||||
xml_element = ET.Element("nuclide")
|
||||
xml_element.set("name", nuclide[0]._name)
|
||||
|
|
@ -581,6 +581,9 @@ class MaterialsFile(object):
|
|||
|
||||
"""
|
||||
|
||||
# Reset xml element tree
|
||||
self._materials_file.clear()
|
||||
|
||||
self._create_material_subelements()
|
||||
|
||||
# Clean the indentation in the file to be user-readable
|
||||
|
|
|
|||
|
|
@ -4,8 +4,10 @@ from numbers import Real, Integral
|
|||
from xml.etree import ElementTree as ET
|
||||
import sys
|
||||
|
||||
from openmc.checkvalue import (check_type, check_length, check_value,
|
||||
check_greater_than)
|
||||
import numpy as np
|
||||
|
||||
import openmc.checkvalue as cv
|
||||
|
||||
|
||||
if sys.version_info[0] >= 3:
|
||||
basestring = str
|
||||
|
|
@ -142,14 +144,14 @@ class Mesh(object):
|
|||
self._id = AUTO_MESH_ID
|
||||
AUTO_MESH_ID += 1
|
||||
else:
|
||||
check_type('mesh ID', mesh_id, Integral)
|
||||
check_greater_than('mesh ID', mesh_id, 0)
|
||||
cv.check_type('mesh ID', mesh_id, Integral)
|
||||
cv.check_greater_than('mesh ID', mesh_id, 0, equality=True)
|
||||
self._id = mesh_id
|
||||
|
||||
@name.setter
|
||||
def name(self, name):
|
||||
if name is not None:
|
||||
check_type('name for mesh ID="{0}"'.format(self._id),
|
||||
cv.check_type('name for mesh ID="{0}"'.format(self._id),
|
||||
name, basestring)
|
||||
self._name = name
|
||||
else:
|
||||
|
|
@ -157,34 +159,34 @@ class Mesh(object):
|
|||
|
||||
@type.setter
|
||||
def type(self, meshtype):
|
||||
check_type('type for mesh ID="{0}"'.format(self._id),
|
||||
cv.check_type('type for mesh ID="{0}"'.format(self._id),
|
||||
meshtype, basestring)
|
||||
check_value('type for mesh ID="{0}"'.format(self._id),
|
||||
cv.check_value('type for mesh ID="{0}"'.format(self._id),
|
||||
meshtype, ['regular'])
|
||||
self._type = meshtype
|
||||
|
||||
@dimension.setter
|
||||
def dimension(self, dimension):
|
||||
check_type('mesh dimension', dimension, Iterable, Integral)
|
||||
check_length('mesh dimension', dimension, 2, 3)
|
||||
cv.check_type('mesh dimension', dimension, Iterable, Integral)
|
||||
cv.check_length('mesh dimension', dimension, 2, 3)
|
||||
self._dimension = dimension
|
||||
|
||||
@lower_left.setter
|
||||
def lower_left(self, lower_left):
|
||||
check_type('mesh lower_left', lower_left, Iterable, Real)
|
||||
check_length('mesh lower_left', lower_left, 2, 3)
|
||||
cv.check_type('mesh lower_left', lower_left, Iterable, Real)
|
||||
cv.check_length('mesh lower_left', lower_left, 2, 3)
|
||||
self._lower_left = lower_left
|
||||
|
||||
@upper_right.setter
|
||||
def upper_right(self, upper_right):
|
||||
check_type('mesh upper_right', upper_right, Iterable, Real)
|
||||
check_length('mesh upper_right', upper_right, 2, 3)
|
||||
cv.check_type('mesh upper_right', upper_right, Iterable, Real)
|
||||
cv.check_length('mesh upper_right', upper_right, 2, 3)
|
||||
self._upper_right = upper_right
|
||||
|
||||
@width.setter
|
||||
def width(self, width):
|
||||
check_type('mesh width', width, Iterable, Real)
|
||||
check_length('mesh width', width, 2, 3)
|
||||
cv.check_type('mesh width', width, Iterable, Real)
|
||||
cv.check_length('mesh width', width, 2, 3)
|
||||
self._width = width
|
||||
|
||||
def __repr__(self):
|
||||
|
|
|
|||
3
openmc/mgxs/__init__.py
Normal file
3
openmc/mgxs/__init__.py
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
from openmc.mgxs.groups import EnergyGroups
|
||||
from openmc.mgxs.library import Library
|
||||
from openmc.mgxs.mgxs import *
|
||||
238
openmc/mgxs/groups.py
Normal file
238
openmc/mgxs/groups.py
Normal file
|
|
@ -0,0 +1,238 @@
|
|||
from collections import Iterable
|
||||
from numbers import Real
|
||||
import copy
|
||||
import sys
|
||||
|
||||
import numpy as np
|
||||
|
||||
import openmc.checkvalue as cv
|
||||
|
||||
|
||||
if sys.version_info[0] >= 3:
|
||||
basestring = str
|
||||
|
||||
|
||||
class EnergyGroups(object):
|
||||
"""An energy groups structure used for multi-group cross-sections.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
group_edges : Iterable of Real
|
||||
The energy group boundaries [MeV]
|
||||
|
||||
Attributes
|
||||
----------
|
||||
group_edges : Iterable of Real
|
||||
The energy group boundaries [MeV]
|
||||
num_group : Integral
|
||||
The number of energy groups
|
||||
|
||||
"""
|
||||
|
||||
def __init__(self, group_edges=None):
|
||||
self._group_edges = None
|
||||
|
||||
if group_edges is not None:
|
||||
self.group_edges = group_edges
|
||||
|
||||
def __deepcopy__(self, memo):
|
||||
existing = memo.get(id(self))
|
||||
|
||||
# If this is the first time we have tried to copy object, create copy
|
||||
if existing is None:
|
||||
clone = type(self).__new__(type(self))
|
||||
clone._group_edges = copy.deepcopy(self.group_edges, memo)
|
||||
|
||||
memo[id(self)] = clone
|
||||
|
||||
return clone
|
||||
|
||||
# If this object has been copied before, return the first copy made
|
||||
else:
|
||||
return existing
|
||||
|
||||
def __eq__(self, other):
|
||||
if not isinstance(other, EnergyGroups):
|
||||
return False
|
||||
elif self.group_edges != other.group_edges:
|
||||
return False
|
||||
else:
|
||||
return True
|
||||
|
||||
def __ne__(self, other):
|
||||
return not self == other
|
||||
|
||||
def __hash__(self):
|
||||
return hash(tuple(self.group_edges))
|
||||
|
||||
@property
|
||||
def group_edges(self):
|
||||
return self._group_edges
|
||||
|
||||
@property
|
||||
def num_groups(self):
|
||||
return len(self.group_edges) - 1
|
||||
|
||||
@group_edges.setter
|
||||
def group_edges(self, edges):
|
||||
cv.check_type('group edges', edges, Iterable, Real)
|
||||
cv.check_greater_than('number of group edges', len(edges), 1)
|
||||
self._group_edges = np.array(edges)
|
||||
|
||||
def get_group(self, energy):
|
||||
"""Returns the energy group in which the given energy resides.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
energy : Real
|
||||
The energy of interest in MeV
|
||||
|
||||
Returns
|
||||
-------
|
||||
Integral
|
||||
The energy group index, starting at 1 for the highest energies
|
||||
|
||||
Raises
|
||||
------
|
||||
ValueError
|
||||
If the group edges have not yet been set.
|
||||
|
||||
"""
|
||||
|
||||
if self.group_edges is None:
|
||||
msg = 'Unable to get energy group for energy "{0}" MeV since ' \
|
||||
'the group edges have not yet been set'.format(energy)
|
||||
raise ValueError(msg)
|
||||
|
||||
index = np.where(self.group_edges > energy)[0][0]
|
||||
group = self.num_groups - index + 1
|
||||
return group
|
||||
|
||||
def get_group_bounds(self, group):
|
||||
"""Returns the energy boundaries for the energy group of interest.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
group : Integral
|
||||
The energy group index, starting at 1 for the highest energies
|
||||
|
||||
Returns
|
||||
-------
|
||||
2-tuple
|
||||
The low and high energy bounds for the group in MeV
|
||||
|
||||
Raises
|
||||
------
|
||||
ValueError
|
||||
If the group edges have not yet been set.
|
||||
|
||||
"""
|
||||
|
||||
if self.group_edges is None:
|
||||
msg = 'Unable to get energy group bounds for group "{0}" since ' \
|
||||
'the group edges have not yet been set'.format(group)
|
||||
raise ValueError(msg)
|
||||
|
||||
cv.check_greater_than('group', group, 0)
|
||||
cv.check_less_than('group', group, self.num_groups, equality=True)
|
||||
|
||||
lower = self.group_edges[self.num_groups-group]
|
||||
upper = self.group_edges[self.num_groups-group+1]
|
||||
return lower, upper
|
||||
|
||||
def get_group_indices(self, groups='all'):
|
||||
"""Returns the array indices for one or more energy groups.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
groups : str, tuple
|
||||
The energy groups of interest - a tuple of the energy group indices,
|
||||
starting at 1 for the highest energies (default is 'all')
|
||||
|
||||
Returns
|
||||
-------
|
||||
ndarray
|
||||
The ndarray array indices for each energy group of interest
|
||||
|
||||
Raises
|
||||
------
|
||||
ValueError
|
||||
If the group edges have not yet been set, or if a group is requested
|
||||
that is outside the bounds of the number of energy groups.
|
||||
|
||||
"""
|
||||
|
||||
if self.group_edges is None:
|
||||
msg = 'Unable to get energy group indices for groups "{0}" since ' \
|
||||
'the group edges have not yet been set'.format(groups)
|
||||
raise ValueError(msg)
|
||||
|
||||
if groups == 'all':
|
||||
return np.arange(self.num_groups)
|
||||
else:
|
||||
indices = np.zeros(len(groups), dtype=np.int)
|
||||
|
||||
for i, group in enumerate(groups):
|
||||
cv.check_greater_than('group', group, 0)
|
||||
cv.check_less_than('group', group, self.num_groups, equality=True)
|
||||
indices[i] = group - 1
|
||||
|
||||
return indices
|
||||
|
||||
def get_condensed_groups(self, coarse_groups):
|
||||
"""Return a coarsened version of this EnergyGroups object.
|
||||
|
||||
This method merges together energy groups in this object into wider
|
||||
energy groups as defined by the list of groups specified by the user,
|
||||
and returns a new, coarse EnergyGroups object.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
coarse_groups : Iterable of 2-tuple
|
||||
The energy groups of interest - a list of 2-tuples, each directly
|
||||
corresponding to one of the new coarse groups. The values in the
|
||||
2-tuples are upper/lower energy groups used to construct a new
|
||||
coarse group. For example, if [(1,2), (3,4)] was used as the coarse
|
||||
groups, fine groups 1 and 2 would be merged into coarse group 1
|
||||
while fine groups 3 and 4 would be merged into coarse group 2.
|
||||
|
||||
Returns
|
||||
-------
|
||||
EnergyGroups
|
||||
A coarsened version of this EnergyGroups object.
|
||||
|
||||
Raises
|
||||
------
|
||||
ValueError
|
||||
If the group edges have not yet been set.
|
||||
"""
|
||||
|
||||
cv.check_type('group edges', coarse_groups, Iterable)
|
||||
for group in coarse_groups:
|
||||
cv.check_type('group edges', group, Iterable)
|
||||
cv.check_length('group edges', group, 2)
|
||||
cv.check_greater_than('lower group', group[0], 1, True)
|
||||
cv.check_less_than('lower group', group[0], self.num_groups, True)
|
||||
cv.check_greater_than('upper group', group[0], 1, True)
|
||||
cv.check_less_than('upper group', group[0], self.num_groups, True)
|
||||
cv.check_less_than('lower group', group[0], group[1], False)
|
||||
|
||||
# Compute the group indices into the coarse group
|
||||
group_bounds = [group[1] for group in coarse_groups]
|
||||
group_bounds.insert(0, coarse_groups[0][0])
|
||||
|
||||
# Determine the indices mapping the fine-to-coarse energy groups
|
||||
group_bounds = np.asarray(group_bounds)
|
||||
group_indices = np.flipud(self.num_groups - group_bounds)
|
||||
group_indices[-1] += 1
|
||||
|
||||
# Determine the edges between coarse energy groups and sort
|
||||
# in increasing order in case the user passed in unordered groups
|
||||
group_edges = self.group_edges[group_indices]
|
||||
group_edges = np.sort(group_edges)
|
||||
|
||||
# Create a new condensed EnergyGroups object
|
||||
condensed_groups = EnergyGroups()
|
||||
condensed_groups.group_edges = group_edges
|
||||
|
||||
return condensed_groups
|
||||
611
openmc/mgxs/library.py
Normal file
611
openmc/mgxs/library.py
Normal file
|
|
@ -0,0 +1,611 @@
|
|||
import sys
|
||||
import os
|
||||
import copy
|
||||
import pickle
|
||||
from numbers import Integral
|
||||
from collections import OrderedDict
|
||||
|
||||
import openmc
|
||||
import openmc.mgxs
|
||||
import openmc.checkvalue as cv
|
||||
|
||||
|
||||
if sys.version_info[0] >= 3:
|
||||
basestring = str
|
||||
|
||||
|
||||
class Library(object):
|
||||
"""A multi-group cross section library for some energy group structure.
|
||||
|
||||
This class can be used for both OpenMC input generation and tally data
|
||||
post-processing to compute spatially-homogenized and energy-integrated
|
||||
multi-group cross sections for deterministic neutronics calculations.
|
||||
|
||||
This class helps automate the generation of MGXS objects for some energy
|
||||
group structure and domain type. The Library serves as a collection for
|
||||
MGXS objects with routines to automate the initialization of tallies for
|
||||
input files, the loading of tally data from statepoint files, data storage,
|
||||
energy group condensation and more.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
openmc_geometry : openmc.Geometry
|
||||
An 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
|
||||
The types of cross sections in the library (e.g., ['total', 'scatter'])
|
||||
name : str, optional
|
||||
Name of the multi-group cross section. library Used as a label to
|
||||
identify tallies in OpenMC 'tallies.xml' file.
|
||||
|
||||
Attributes
|
||||
----------
|
||||
openmc_geometry : openmc.Geometry
|
||||
An 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
|
||||
The types of cross sections in the library (e.g., ['total', 'scatter'])
|
||||
domain_type : {'material', 'cell', 'distribcell', 'universe'}
|
||||
Domain type for spatial homogenization
|
||||
correction : 'P0' or None
|
||||
Apply the P0 correction to scattering matrices if set to 'P0'
|
||||
energy_groups : EnergyGroups
|
||||
Energy group structure for energy condensation
|
||||
tally_trigger : Trigger
|
||||
An (optional) tally precision trigger given to each tally used to
|
||||
compute the cross section
|
||||
all_mgxs : OrderedDict
|
||||
MGXS objects keyed by domain ID and cross section type
|
||||
statepoint : openmc.StatePoint
|
||||
The statepoint with tally data used to the compute cross sections
|
||||
name : str, optional
|
||||
Name of the multi-group cross section library. Used as a label to
|
||||
identify tallies in OpenMC 'tallies.xml' file.
|
||||
|
||||
"""
|
||||
|
||||
def __init__(self, openmc_geometry, by_nuclide=False,
|
||||
mgxs_types=None, name=''):
|
||||
|
||||
self._name = ''
|
||||
self._openmc_geometry = None
|
||||
self._by_nuclide = None
|
||||
self._mgxs_types = []
|
||||
self._domain_type = None
|
||||
self._correction = 'P0'
|
||||
self._energy_groups = None
|
||||
self._tally_trigger = None
|
||||
self._all_mgxs = OrderedDict()
|
||||
self._sp_filename = None
|
||||
|
||||
self.name = name
|
||||
self.openmc_geometry = openmc_geometry
|
||||
self.by_nuclide = by_nuclide
|
||||
|
||||
if mgxs_types is not None:
|
||||
self.mgxs_types = mgxs_types
|
||||
|
||||
def __deepcopy__(self, memo):
|
||||
existing = memo.get(id(self))
|
||||
|
||||
# If this is the first time we have tried to copy this object, copy it
|
||||
if existing is None:
|
||||
clone = type(self).__new__(type(self))
|
||||
clone._name = self.name
|
||||
clone._openmc_geometry = self.openmc_geometry
|
||||
clone._by_nuclide = self.by_nuclide
|
||||
clone._mgxs_types = self.mgxs_types
|
||||
clone._domain_type = self.domain_type
|
||||
clone._correction = self.correction
|
||||
clone._energy_groups = copy.deepcopy(self.energy_groups, memo)
|
||||
clone._tally_trigger = copy.deepcopy(self.tally_trigger, memo)
|
||||
clone._all_mgxs = self.all_mgxs
|
||||
clone._sp_filename = self._sp_filename
|
||||
|
||||
clone._all_mgxs = OrderedDict()
|
||||
for domain in self.domains:
|
||||
clone.all_mgxs[domain.id] = OrderedDict()
|
||||
for mgxs_type in self.mgxs_types:
|
||||
mgxs = copy.deepcopy(self.all_mgxs[domain.id][mgxs_type])
|
||||
clone.all_mgxs[domain.id][mgxs_type] = mgxs
|
||||
|
||||
memo[id(self)] = clone
|
||||
|
||||
return clone
|
||||
|
||||
# If this object has been copied before, return the first copy made
|
||||
else:
|
||||
return existing
|
||||
|
||||
@property
|
||||
def openmc_geometry(self):
|
||||
return self._openmc_geometry
|
||||
|
||||
@property
|
||||
def name(self):
|
||||
return self._name
|
||||
|
||||
@property
|
||||
def mgxs_types(self):
|
||||
return self._mgxs_types
|
||||
|
||||
@property
|
||||
def by_nuclide(self):
|
||||
return self._by_nuclide
|
||||
|
||||
@property
|
||||
def domains(self):
|
||||
if self.domain_type is None:
|
||||
raise ValueError('Unable to get all domains without a domain type')
|
||||
|
||||
if self.domain_type == 'material':
|
||||
return self.openmc_geometry.get_all_materials()
|
||||
elif self.domain_type == 'cell' or self.domain_type == 'distribcell':
|
||||
return self.openmc_geometry.get_all_material_cells()
|
||||
elif self.domain_type == 'universe':
|
||||
return self.openmc_geometry.get_all_universes()
|
||||
|
||||
@property
|
||||
def domain_type(self):
|
||||
return self._domain_type
|
||||
|
||||
@property
|
||||
def correction(self):
|
||||
return self._correction
|
||||
|
||||
@property
|
||||
def energy_groups(self):
|
||||
return self._energy_groups
|
||||
|
||||
@property
|
||||
def tally_trigger(self):
|
||||
return self._tally_trigger
|
||||
|
||||
@property
|
||||
def num_groups(self):
|
||||
return self.energy_groups.num_groups
|
||||
|
||||
@property
|
||||
def all_mgxs(self):
|
||||
return self._all_mgxs
|
||||
|
||||
@property
|
||||
def statepoint(self):
|
||||
return self._sp_filename
|
||||
|
||||
@openmc_geometry.setter
|
||||
def openmc_geometry(self, openmc_geometry):
|
||||
cv.check_type('openmc_geometry', openmc_geometry, openmc.Geometry)
|
||||
self._openmc_geometry = openmc_geometry
|
||||
|
||||
@name.setter
|
||||
def name(self, name):
|
||||
cv.check_type('name', name, basestring)
|
||||
self._name = name
|
||||
|
||||
@mgxs_types.setter
|
||||
def mgxs_types(self, mgxs_types):
|
||||
if mgxs_types == 'all':
|
||||
self._mgxs_types = openmc.mgxs.MGXS_TYPES
|
||||
else:
|
||||
cv.check_iterable_type('mgxs_types', mgxs_types, basestring)
|
||||
for mgxs_type in mgxs_types:
|
||||
cv.check_value('mgxs_type', mgxs_type, openmc.mgxs.MGXS_TYPES)
|
||||
self._mgxs_types = mgxs_types
|
||||
|
||||
@by_nuclide.setter
|
||||
def by_nuclide(self, by_nuclide):
|
||||
cv.check_type('by_nuclide', by_nuclide, bool)
|
||||
self._by_nuclide = by_nuclide
|
||||
|
||||
@domain_type.setter
|
||||
def domain_type(self, domain_type):
|
||||
cv.check_value('domain type', domain_type, tuple(openmc.mgxs.DOMAIN_TYPES))
|
||||
self._domain_type = domain_type
|
||||
|
||||
@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
|
||||
|
||||
@tally_trigger.setter
|
||||
def tally_trigger(self, tally_trigger):
|
||||
cv.check_type('tally trigger', tally_trigger, openmc.Trigger)
|
||||
self._tally_trigger = tally_trigger
|
||||
|
||||
def build_library(self):
|
||||
"""Initialize MGXS objects in each domain and for each reaction type
|
||||
in the library.
|
||||
|
||||
This routine will populate the all_mgxs instance attribute dictionary
|
||||
with MGXS subclass objects keyed by each domain ID (e.g., Material IDs)
|
||||
and cross section type (e.g., 'nu-fission', 'total', etc.).
|
||||
|
||||
"""
|
||||
|
||||
# Initialize MGXS for each domain and mgxs type and store in dictionary
|
||||
for domain in self.domains:
|
||||
self.all_mgxs[domain.id] = OrderedDict()
|
||||
for mgxs_type in self.mgxs_types:
|
||||
mgxs = openmc.mgxs.MGXS.get_mgxs(mgxs_type, name=self.name)
|
||||
mgxs.domain = domain
|
||||
mgxs.domain_type = self.domain_type
|
||||
mgxs.energy_groups = self.energy_groups
|
||||
mgxs.by_nuclide = self.by_nuclide
|
||||
|
||||
# If a tally trigger was specified, add it to the MGXS
|
||||
if self.tally_trigger:
|
||||
mgxs.tally_trigger = self.tally_trigger
|
||||
|
||||
# Specify whether to use a transport ('P0') correction
|
||||
if isinstance(mgxs, openmc.mgxs.ScatterMatrixXS):
|
||||
mgxs.correction = self.correction
|
||||
|
||||
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
|
||||
|
||||
Parameters
|
||||
----------
|
||||
tallies_file : openmc.TalliesFile
|
||||
A TalliesFile object 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)
|
||||
|
||||
# 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)
|
||||
|
||||
def load_from_statepoint(self, statepoint):
|
||||
"""Extracts tallies in an OpenMC StatePoint with the data needed to
|
||||
compute multi-group cross sections.
|
||||
|
||||
This method is needed to compute cross section data from tallies
|
||||
in an OpenMC StatePoint object.
|
||||
|
||||
NOTE: The statepoint must first be linked with an OpenMC Summary object.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
statepoint : openmc.StatePoint
|
||||
An OpenMC StatePoint object with tally data
|
||||
|
||||
Raises
|
||||
------
|
||||
ValueError
|
||||
When this method is called with a statepoint that has not been
|
||||
linked with a summary object.
|
||||
|
||||
"""
|
||||
|
||||
cv.check_type('statepoint', statepoint, openmc.StatePoint)
|
||||
|
||||
if not statepoint.with_summary:
|
||||
msg = 'Unable to load data from a statepoint which has not been ' \
|
||||
'linked with a summary file'
|
||||
raise ValueError(msg)
|
||||
|
||||
self._sp_filename = statepoint._f.filename
|
||||
|
||||
# Load tallies for 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)
|
||||
mgxs.load_from_statepoint(statepoint)
|
||||
|
||||
def get_mgxs(self, domain, mgxs_type):
|
||||
"""Return the MGXS object for some domain and reaction rate type.
|
||||
|
||||
This routine searches the library for an MGXS object for the spatial
|
||||
domain and reaction rate type requested by the user.
|
||||
|
||||
NOTE: This routine must be called after the build_library() routine.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
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'}
|
||||
The type of multi-group cross section object to return
|
||||
|
||||
Returns
|
||||
-------
|
||||
openmc.mgxs.MGXS
|
||||
The MGXS object for the requested domain and reaction rate type
|
||||
|
||||
Raises
|
||||
------
|
||||
ValueError
|
||||
If no MGXS object can be found for the requested domain or
|
||||
multi-group cross section type
|
||||
|
||||
"""
|
||||
|
||||
if self.domain_type == 'material':
|
||||
cv.check_type('domain', domain, (openmc.Material, Integral))
|
||||
elif self.domain_type == 'cell' or self.domain_type == 'distribcell':
|
||||
cv.check_type('domain', domain, (openmc.Cell, Integral))
|
||||
elif self.domain_type == 'universe':
|
||||
cv.check_type('domain', domain, (openmc.Universe, Integral))
|
||||
|
||||
# Check that requested domain is included in library
|
||||
if cv._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)
|
||||
raise ValueError(msg)
|
||||
else:
|
||||
domain_id = domain.id
|
||||
|
||||
# Check that requested domain is included in library
|
||||
if mgxs_type not in self.mgxs_types:
|
||||
msg = 'Unable to find MGXS type "{0}"'.format(mgxs_type)
|
||||
raise ValueError(msg)
|
||||
|
||||
return self.all_mgxs[domain_id][mgxs_type]
|
||||
|
||||
def get_condensed_library(self, coarse_groups):
|
||||
"""Construct an energy-condensed version of this library.
|
||||
|
||||
This routine condenses each of the multi-group cross sections in the
|
||||
library to a coarse energy group structure. NOTE: This routine must
|
||||
be called after the load_from_statepoint(...) routine loads the tallies
|
||||
from the statepoint into each of the cross sections.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
coarse_groups : openmc.mgxs.EnergyGroups
|
||||
The coarse energy group structure of interest
|
||||
|
||||
Returns
|
||||
-------
|
||||
Library
|
||||
A new multi-group cross section library condensed to the group
|
||||
structure of interest
|
||||
|
||||
Raises
|
||||
------
|
||||
ValueError
|
||||
When this method is called before a statepoint has been loaded
|
||||
|
||||
See also
|
||||
--------
|
||||
MGXS.get_condensed_xs(coarse_groups)
|
||||
|
||||
"""
|
||||
|
||||
if self.statepoint is None:
|
||||
msg = 'Unable to get a condensed coarse group cross section ' \
|
||||
'library since the statepoint has not yet been loaded'
|
||||
raise ValueError(msg)
|
||||
|
||||
cv.check_type('coarse_groups', coarse_groups, openmc.mgxs.EnergyGroups)
|
||||
cv.check_less_than('coarse groups', coarse_groups.num_groups,
|
||||
self.num_groups, equality=True)
|
||||
cv.check_value('upper coarse energy', coarse_groups.group_edges[-1],
|
||||
[self.energy_groups.group_edges[-1]])
|
||||
cv.check_value('lower coarse energy', coarse_groups.group_edges[0],
|
||||
[self.energy_groups.group_edges[0]])
|
||||
|
||||
# Clone this Library to initialize the condensed version
|
||||
condensed_library = copy.deepcopy(self)
|
||||
condensed_library.energy_groups = coarse_groups
|
||||
|
||||
# Condense the MGXS for each domain and mgxs type
|
||||
for domain in self.domains:
|
||||
for mgxs_type in self.mgxs_types:
|
||||
mgxs = condensed_library.get_mgxs(domain, mgxs_type)
|
||||
condensed_mgxs = mgxs.get_condensed_xs(coarse_groups)
|
||||
condensed_library.all_mgxs[domain.id][mgxs_type] = condensed_mgxs
|
||||
|
||||
return condensed_library
|
||||
|
||||
def get_subdomain_avg_library(self):
|
||||
"""Construct a subdomain-averaged version of this library.
|
||||
|
||||
This routine averages each multi-group cross section across distribcell
|
||||
instances. The method performs spatial homogenization to compute the
|
||||
scalar flux-weighted average cross section across the subdomains.
|
||||
|
||||
NOTE: This method is only relevant for distribcell domain types and
|
||||
simplys returns a deep copy of the library for all other domains types.
|
||||
|
||||
Returns
|
||||
-------
|
||||
Library
|
||||
A new multi-group cross section library averaged across subdomains
|
||||
|
||||
Raises
|
||||
------
|
||||
ValueError
|
||||
When this method is called before a statepoint has been loaded
|
||||
|
||||
See also
|
||||
--------
|
||||
MGXS.get_subdomain_avg_xs(subdomains)
|
||||
|
||||
"""
|
||||
|
||||
if self.statepoint is None:
|
||||
msg = 'Unable to get a subdomain-averaged cross section ' \
|
||||
'library since the statepoint has not yet been loaded'
|
||||
raise ValueError(msg)
|
||||
|
||||
# Clone this Library to initialize the subdomain-averaged version
|
||||
subdomain_avg_library = copy.deepcopy(self)
|
||||
|
||||
if subdomain_avg_library.domain_type == 'distribcell':
|
||||
subdomain_avg_library.domain_type = 'cell'
|
||||
else:
|
||||
return subdomain_avg_library
|
||||
|
||||
# Subdomain average the MGXS for each domain and mgxs type
|
||||
for domain in self.domains:
|
||||
for mgxs_type in self.mgxs_types:
|
||||
mgxs = subdomain_avg_library.get_mgxs(domain, mgxs_type)
|
||||
avg_mgxs = mgxs.get_subdomain_avg_xs()
|
||||
subdomain_avg_library.all_mgxs[domain.id][mgxs_type] = avg_mgxs
|
||||
|
||||
return subdomain_avg_library
|
||||
|
||||
def build_hdf5_store(self, filename='mgxs.h5', directory='mgxs',
|
||||
subdomains='all', nuclides='all', xs_type='macro'):
|
||||
"""Export the multi-group cross section library to an HDF5 binary file.
|
||||
|
||||
This method constructs an HDF5 file which stores the library's
|
||||
multi-group cross section data. The data is stored in a hierarchy of
|
||||
HDF5 groups from the domain type, domain id, subdomain id (for
|
||||
distribcell domains), nuclides and cross section types. Two datasets for
|
||||
the mean and standard deviation are stored for each subdomain entry in
|
||||
the HDF5 file. The number of groups is stored as a file attribute.
|
||||
|
||||
NOTE: This requires the h5py Python package.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
filename : str
|
||||
Filename for the HDF5 file. Defaults to 'mgxs.h5'.
|
||||
directory : str
|
||||
Directory for the HDF5 file. Defaults to 'mgxs'.
|
||||
subdomains : {'all', 'avg'}
|
||||
Report all subdomains or the average of all subdomain cross sections
|
||||
in the report. Defaults to 'all'.
|
||||
nuclides : {'all', 'sum'}
|
||||
The nuclides of the cross-sections to include in the report. This
|
||||
may be a list of nuclide name strings (e.g., ['U-235', 'U-238']).
|
||||
The special string 'all' will report the cross sections for all
|
||||
nuclides in the spatial domain. The special string 'sum' will report
|
||||
the cross sections summed over all nuclides. Defaults to 'all'.
|
||||
xs_type: {'macro', 'micro'}
|
||||
Store the macro or micro cross section in units of cm^-1 or barns.
|
||||
Defaults to 'macro'.
|
||||
|
||||
Raises
|
||||
------
|
||||
ValueError
|
||||
When this method is called before a statepoint has been loaded
|
||||
|
||||
See also
|
||||
--------
|
||||
MGXS.build_hdf5_store(filename, directory, xs_type)
|
||||
|
||||
"""
|
||||
|
||||
if self.statepoint is None:
|
||||
msg = 'Unable to get a condensed coarse group cross section ' \
|
||||
'library since a statepoint has not yet been loaded'
|
||||
raise ValueError(msg)
|
||||
|
||||
cv.check_type('filename', filename, basestring)
|
||||
cv.check_type('directory', directory, basestring)
|
||||
|
||||
import h5py
|
||||
|
||||
# Make directory if it does not exist
|
||||
if not os.path.exists(directory):
|
||||
os.makedirs(directory)
|
||||
|
||||
# Add an attribute for the number of energy groups to the HDF5 file
|
||||
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.close()
|
||||
|
||||
# Export MGXS for each domain and mgxs type to an HDF5 file
|
||||
for domain in self.domains:
|
||||
for mgxs_type in self.mgxs_types:
|
||||
mgxs = self.all_mgxs[domain.id][mgxs_type]
|
||||
|
||||
if subdomains == 'avg':
|
||||
mgxs = mgxs.get_subdomain_avg_xs()
|
||||
|
||||
mgxs.build_hdf5_store(filename, directory,
|
||||
xs_type=xs_type, nuclides=nuclides)
|
||||
|
||||
def dump_to_file(self, filename='mgxs', directory='mgxs'):
|
||||
"""Store this Library object in a pickle binary file.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
filename : str
|
||||
Filename for the pickle file. Defaults to 'mgxs'.
|
||||
directory : str
|
||||
Directory for the pickle file. Defaults to 'mgxs'.
|
||||
|
||||
See also
|
||||
--------
|
||||
Library.load_from_file(filename, directory)
|
||||
|
||||
"""
|
||||
|
||||
cv.check_type('filename', filename, basestring)
|
||||
cv.check_type('directory', directory, basestring)
|
||||
|
||||
# Make directory if it does not exist
|
||||
if not os.path.exists(directory):
|
||||
os.makedirs(directory)
|
||||
|
||||
full_filename = os.path.join(directory, filename + '.pkl')
|
||||
full_filename = full_filename.replace(' ', '-')
|
||||
|
||||
# Load and return pickled Library object
|
||||
pickle.dump(self, open(full_filename, 'wb'))
|
||||
|
||||
@staticmethod
|
||||
def load_from_file(filename='mgxs', directory='mgxs'):
|
||||
"""Load a Library object from a pickle binary file.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
filename : str
|
||||
Filename for the pickle file. Defaults to 'mgxs'.
|
||||
directory : str
|
||||
Directory for the pickle file. Defaults to 'mgxs'.
|
||||
|
||||
Returns
|
||||
-------
|
||||
Library
|
||||
A Library object loaded from the pickle binary file
|
||||
|
||||
See also
|
||||
--------
|
||||
Library.dump_to_file(mgxs_lib, filename, directory)
|
||||
|
||||
"""
|
||||
|
||||
cv.check_type('filename', filename, basestring)
|
||||
cv.check_type('directory', directory, basestring)
|
||||
|
||||
# Make directory if it does not exist
|
||||
if not os.path.exists(directory):
|
||||
os.makedirs(directory)
|
||||
|
||||
full_filename = os.path.join(directory, filename + '.pkl')
|
||||
full_filename = full_filename.replace(' ', '-')
|
||||
|
||||
# Load and return pickled Library object
|
||||
return pickle.load(open(full_filename, 'rb'))
|
||||
2277
openmc/mgxs/mgxs.py
Normal file
2277
openmc/mgxs/mgxs.py
Normal file
File diff suppressed because it is too large
Load diff
|
|
@ -41,25 +41,32 @@ class Nuclide(object):
|
|||
if xs is not None:
|
||||
self.xs = xs
|
||||
|
||||
def __eq__(self, nuclide2):
|
||||
# Check type
|
||||
if not isinstance(nuclide2, Nuclide):
|
||||
return False
|
||||
|
||||
# Check name
|
||||
elif self._name != nuclide2._name:
|
||||
return False
|
||||
|
||||
# Check xs
|
||||
elif self._xs != nuclide2._xs:
|
||||
return False
|
||||
|
||||
else:
|
||||
def __eq__(self, other):
|
||||
if isinstance(other, Nuclide):
|
||||
if self._name != other._name:
|
||||
return False
|
||||
elif self._xs != other._xs:
|
||||
return False
|
||||
else:
|
||||
return True
|
||||
elif isinstance(other, basestring) and other == self.name:
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
||||
def __ne__(self, other):
|
||||
return not self == other
|
||||
|
||||
def __hash__(self):
|
||||
return hash((self._name, self._xs))
|
||||
|
||||
def __repr__(self):
|
||||
string = 'Nuclide - {0}\n'.format(self._name)
|
||||
string += '{0: <16}{1}{2}\n'.format('\tXS', '=\t', self._xs)
|
||||
if self._zaid is not None:
|
||||
string += '{0: <16}{1}{2}\n'.format('\tZAID', '=\t', self._zaid)
|
||||
return string
|
||||
|
||||
@property
|
||||
def name(self):
|
||||
return self._name
|
||||
|
|
@ -85,11 +92,4 @@ class Nuclide(object):
|
|||
@zaid.setter
|
||||
def zaid(self, zaid):
|
||||
check_type('zaid', zaid, Integral)
|
||||
self._zaid = zaid
|
||||
|
||||
def __repr__(self):
|
||||
string = 'Nuclide - {0}\n'.format(self._name)
|
||||
string += '{0: <16}{1}{2}\n'.format('\tXS', '=\t', self._xs)
|
||||
if self._zaid is not None:
|
||||
string += '{0: <16}{1}{2}\n'.format('\tZAID', '=\t', self._zaid)
|
||||
return string
|
||||
self._zaid = zaid
|
||||
|
|
@ -144,7 +144,7 @@ class Plot(object):
|
|||
AUTO_PLOT_ID += 1
|
||||
else:
|
||||
check_type('plot ID', plot_id, Integral)
|
||||
check_greater_than('plot ID', plot_id, 0)
|
||||
check_greater_than('plot ID', plot_id, 0, equality=True)
|
||||
self._id = plot_id
|
||||
|
||||
@name.setter
|
||||
|
|
@ -363,6 +363,9 @@ class PlotsFile(object):
|
|||
|
||||
"""
|
||||
|
||||
# Reset xml element tree
|
||||
self._plots_file.clear()
|
||||
|
||||
self._create_plot_subelements()
|
||||
|
||||
# Clean the indentation in the file to be user-readable
|
||||
|
|
|
|||
|
|
@ -213,6 +213,9 @@ class Intersection(Region):
|
|||
def __init__(self, *nodes):
|
||||
self.nodes = list(nodes)
|
||||
|
||||
def __str__(self):
|
||||
return '(' + ' '.join(map(str, self.nodes)) + ')'
|
||||
|
||||
@property
|
||||
def nodes(self):
|
||||
return self._nodes
|
||||
|
|
@ -222,9 +225,6 @@ class Intersection(Region):
|
|||
check_type('nodes', nodes, Iterable, Region)
|
||||
self._nodes = nodes
|
||||
|
||||
def __str__(self):
|
||||
return '(' + ' '.join(map(str, self.nodes)) + ')'
|
||||
|
||||
|
||||
class Union(Region):
|
||||
"""Union of two or more regions.
|
||||
|
|
@ -252,6 +252,9 @@ class Union(Region):
|
|||
def __init__(self, *nodes):
|
||||
self.nodes = list(nodes)
|
||||
|
||||
def __str__(self):
|
||||
return '(' + ' | '.join(map(str, self.nodes)) + ')'
|
||||
|
||||
@property
|
||||
def nodes(self):
|
||||
return self._nodes
|
||||
|
|
@ -261,9 +264,6 @@ class Union(Region):
|
|||
check_type('nodes', nodes, Iterable, Region)
|
||||
self._nodes = nodes
|
||||
|
||||
def __str__(self):
|
||||
return '(' + ' | '.join(map(str, self.nodes)) + ')'
|
||||
|
||||
|
||||
class Complement(Region):
|
||||
"""Complement of a region.
|
||||
|
|
@ -295,6 +295,9 @@ class Complement(Region):
|
|||
def __init__(self, node):
|
||||
self.node = node
|
||||
|
||||
def __str__(self):
|
||||
return '~' + str(self.node)
|
||||
|
||||
@property
|
||||
def node(self):
|
||||
return self._node
|
||||
|
|
@ -303,6 +306,3 @@ class Complement(Region):
|
|||
def node(self, node):
|
||||
check_type('node', node, Region)
|
||||
self._node = node
|
||||
|
||||
def __str__(self):
|
||||
return '~' + str(self.node)
|
||||
|
|
|
|||
|
|
@ -1178,6 +1178,13 @@ class SettingsFile(object):
|
|||
|
||||
"""
|
||||
|
||||
# Reset xml element tree
|
||||
self._settings_file.clear()
|
||||
self._source_subelement = None
|
||||
self._trigger_subelement = None
|
||||
self._eigenvalue_subelement = None
|
||||
self._source_element = None
|
||||
|
||||
self._create_eigenvalue_subelement()
|
||||
self._create_source_subelement()
|
||||
self._create_output_subelement()
|
||||
|
|
|
|||
|
|
@ -1,4 +1,3 @@
|
|||
import copy
|
||||
import sys
|
||||
import re
|
||||
import numpy as np
|
||||
|
|
@ -33,42 +32,42 @@ class StatePoint(object):
|
|||
each batch
|
||||
cmfd_src : ndarray
|
||||
CMFD fission source distribution over all mesh cells and energy groups.
|
||||
current_batch : int
|
||||
current_batch : Integral
|
||||
Number of batches simulated
|
||||
date_and_time : str
|
||||
Date and time when simulation began
|
||||
entropy : ndarray
|
||||
Shannon entropy of fission source at each batch
|
||||
gen_per_batch : int
|
||||
gen_per_batch : Integral
|
||||
Number of fission generations per batch
|
||||
global_tallies : 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 : float
|
||||
k_col_abs : Real
|
||||
Cross-product of collision and absorption estimates of k-effective
|
||||
k_col_tra : float
|
||||
k_col_tra : Real
|
||||
Cross-product of collision and tracklength estimates of k-effective
|
||||
k_abs_tra : float
|
||||
k_abs_tra : Real
|
||||
Cross-product of absorption and tracklength estimates of k-effective
|
||||
k_generation : 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 : int
|
||||
n_batches : Integral
|
||||
Number of batches
|
||||
n_inactive : int
|
||||
n_inactive : Integral
|
||||
Number of inactive batches
|
||||
n_particles : int
|
||||
n_particles : Integral
|
||||
Number of particles per generation
|
||||
n_realizations : int
|
||||
n_realizations : Integral
|
||||
Number of tally realizations
|
||||
path : str
|
||||
Working directory for simulation
|
||||
run_mode : str
|
||||
Simulation run mode, e.g. 'k-eigenvalue'
|
||||
seed : int
|
||||
seed : Integral
|
||||
Pseudorandom number generator seed
|
||||
source : ndarray of compound datatype
|
||||
Array of source sites. The compound datatype has fields 'wgt', 'xyz',
|
||||
|
|
@ -80,10 +79,10 @@ class StatePoint(object):
|
|||
Dictionary whose keys are tally IDs and whose values are Tally objects
|
||||
tallies_present : bool
|
||||
Indicate whether user-defined tallies are present
|
||||
version: tuple of int
|
||||
version: tuple of Integral
|
||||
Version of OpenMC
|
||||
with_summary : bool
|
||||
Indicate whether statepoint data has been linked against a summary file
|
||||
summary : None or openmc.summary.Summary
|
||||
A summary object if the statepoint has been linked with a summary file
|
||||
|
||||
"""
|
||||
|
||||
|
|
@ -109,7 +108,7 @@ class StatePoint(object):
|
|||
# Set flags for what data has been read
|
||||
self._meshes_read = False
|
||||
self._tallies_read = False
|
||||
self._with_summary = False
|
||||
self._summary = False
|
||||
self._global_tallies = None
|
||||
|
||||
def close(self):
|
||||
|
|
@ -121,31 +120,19 @@ class StatePoint(object):
|
|||
|
||||
@property
|
||||
def cmfd_balance(self):
|
||||
if self.cmfd_on:
|
||||
return self._f['cmfd/cmfd_balance'].value
|
||||
else:
|
||||
return None
|
||||
return self._f['cmfd/cmfd_balance'].value if self.cmfd_on else None
|
||||
|
||||
@property
|
||||
def cmfd_dominance(self):
|
||||
if self.cmfd_on:
|
||||
return self._f['cmfd/cmfd_dominance'].value
|
||||
else:
|
||||
return None
|
||||
return self._f['cmfd/cmfd_dominance'].value if self.cmfd_on else None
|
||||
|
||||
@property
|
||||
def cmfd_entropy(self):
|
||||
if self.cmfd_on:
|
||||
return self._f['cmfd/cmfd_entropy'].value
|
||||
else:
|
||||
return None
|
||||
return self._f['cmfd/cmfd_entropy'].value if self.cmfd_on else None
|
||||
|
||||
@property
|
||||
def cmfd_indices(self):
|
||||
if self.cmfd_on:
|
||||
return self._f['cmfd/indices'].value
|
||||
else:
|
||||
return None
|
||||
return self._f['cmfd/indices'].value if self.cmfd_on else None
|
||||
|
||||
@property
|
||||
def cmfd_src(self):
|
||||
|
|
@ -157,10 +144,7 @@ class StatePoint(object):
|
|||
|
||||
@property
|
||||
def cmfd_srccmp(self):
|
||||
if self.cmfd_on:
|
||||
return self._f['cmfd/cmfd_srccmp'].value
|
||||
else:
|
||||
return None
|
||||
return self._f['cmfd/cmfd_srccmp'].value if self.cmfd_on else None
|
||||
|
||||
@property
|
||||
def current_batch(self):
|
||||
|
|
@ -328,10 +312,7 @@ class StatePoint(object):
|
|||
|
||||
@property
|
||||
def source(self):
|
||||
if self.source_present:
|
||||
return self._f['source_bank'].value
|
||||
else:
|
||||
return None
|
||||
return self._f['source_bank'].value if self.source_present else None
|
||||
|
||||
@property
|
||||
def source_present(self):
|
||||
|
|
@ -459,16 +440,20 @@ class StatePoint(object):
|
|||
self._f['version_minor'].value,
|
||||
self._f['version_release'].value)
|
||||
|
||||
@property
|
||||
def summary(self):
|
||||
return self._summary
|
||||
|
||||
@property
|
||||
def with_summary(self):
|
||||
return self._with_summary
|
||||
return False if self.summary is None else True
|
||||
|
||||
def get_tally(self, scores=[], filters=[], nuclides=[],
|
||||
name=None, id=None, estimator=None):
|
||||
"""Finds and returns a Tally object with certain properties.
|
||||
|
||||
This routine searches the list of Tallies and returns the first Tally
|
||||
found it finds which satisfies all of the input parameters.
|
||||
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.
|
||||
|
||||
|
|
@ -482,7 +467,7 @@ class StatePoint(object):
|
|||
A list of Nuclide objects (default is []).
|
||||
name : str, optional
|
||||
The name specified for the Tally (default is None).
|
||||
id : int, optional
|
||||
id : Integral, optional
|
||||
The id specified for the Tally (default is None).
|
||||
estimator: str, optional
|
||||
The type of estimator ('tracklength', 'analog'; default is None).
|
||||
|
|
@ -536,8 +521,16 @@ class StatePoint(object):
|
|||
|
||||
# Iterate over the Filters requested by the user
|
||||
for filter in filters:
|
||||
if filter not in test_tally.filters:
|
||||
contains_filters = False
|
||||
contains_filters = False
|
||||
|
||||
# Test if requested filter is a subset of any of the test
|
||||
# tally's filters and if so continue to next filter
|
||||
for test_filter in test_tally.filters:
|
||||
if test_filter.is_subset(filter):
|
||||
contains_filters = True
|
||||
break
|
||||
|
||||
if not contains_filters:
|
||||
break
|
||||
|
||||
if not contains_filters:
|
||||
|
|
@ -624,4 +617,4 @@ class StatePoint(object):
|
|||
material_ids.append(summary.materials[bin].id)
|
||||
filter.bins = material_ids
|
||||
|
||||
self._with_summary = True
|
||||
self._summary = summary
|
||||
|
|
|
|||
|
|
@ -83,9 +83,8 @@ class Summary(object):
|
|||
name, xs = sab_table.decode().split('.')
|
||||
material.add_s_alpha_beta(name, xs)
|
||||
|
||||
# Set the Material's density to g/cm3 - this is what is used in
|
||||
# OpenMC
|
||||
material.set_density(density=density, units='g/cm3')
|
||||
# Set the Material's density to atom/b-cm as used by OpenMC
|
||||
material.set_density(density=density, units='atom/b-cm')
|
||||
|
||||
# Add all nuclides to the Material
|
||||
for fullname, density in zip(nuclides, nuc_densities):
|
||||
|
|
|
|||
|
|
@ -75,6 +75,22 @@ class Surface(object):
|
|||
def __pos__(self):
|
||||
return Halfspace(self, '+')
|
||||
|
||||
def __repr__(self):
|
||||
string = 'Surface\n'
|
||||
string += '{0: <16}{1}{2}\n'.format('\tID', '=\t', self._id)
|
||||
string += '{0: <16}{1}{2}\n'.format('\tName', '=\t', self._name)
|
||||
string += '{0: <16}{1}{2}\n'.format('\tType', '=\t', self._type)
|
||||
string += '{0: <16}{1}{2}\n'.format('\tBoundary', '=\t', self._boundary_type)
|
||||
|
||||
coeffs = '{0: <16}'.format('\tCoefficients') + '\n'
|
||||
|
||||
for coeff in self._coeffs:
|
||||
coeffs += '{0: <16}{1}{2}\n'.format(coeff, '=\t', self._coeffs[coeff])
|
||||
|
||||
string += coeffs
|
||||
|
||||
return string
|
||||
|
||||
@property
|
||||
def id(self):
|
||||
return self._id
|
||||
|
|
@ -103,7 +119,7 @@ class Surface(object):
|
|||
AUTO_SURFACE_ID += 1
|
||||
else:
|
||||
check_type('surface ID', surface_id, Integral)
|
||||
check_greater_than('surface ID', surface_id, 0)
|
||||
check_greater_than('surface ID', surface_id, 0, equality=True)
|
||||
self._id = surface_id
|
||||
|
||||
@name.setter
|
||||
|
|
@ -120,22 +136,6 @@ class Surface(object):
|
|||
check_value('boundary type', boundary_type, _BC_TYPES)
|
||||
self._boundary_type = boundary_type
|
||||
|
||||
def __repr__(self):
|
||||
string = 'Surface\n'
|
||||
string += '{0: <16}{1}{2}\n'.format('\tID', '=\t', self._id)
|
||||
string += '{0: <16}{1}{2}\n'.format('\tName', '=\t', self._name)
|
||||
string += '{0: <16}{1}{2}\n'.format('\tType', '=\t', self._type)
|
||||
string += '{0: <16}{1}{2}\n'.format('\tBoundary', '=\t', self._boundary_type)
|
||||
|
||||
coeffs = '{0: <16}'.format('\tCoefficients') + '\n'
|
||||
|
||||
for coeff in self._coeffs:
|
||||
coeffs += '{0: <16}{1}{2}\n'.format(coeff, '=\t', self._coeffs[coeff])
|
||||
|
||||
string += coeffs
|
||||
|
||||
return string
|
||||
|
||||
def create_xml_subelement(self):
|
||||
element = ET.Element("surface")
|
||||
element.set("id", str(self._id))
|
||||
|
|
|
|||
1208
openmc/tallies.py
1208
openmc/tallies.py
File diff suppressed because it is too large
Load diff
|
|
@ -58,6 +58,22 @@ class Trigger(object):
|
|||
else:
|
||||
return existing
|
||||
|
||||
def __eq__(self, other):
|
||||
if str(self) == str(other):
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
||||
def __ne__(self, other):
|
||||
return not self == other
|
||||
|
||||
def __repr__(self):
|
||||
string = 'Trigger\n'
|
||||
string += '{0: <16}{1}{2}\n'.format('\tType', '=\t', self._trigger_type)
|
||||
string += '{0: <16}{1}{2}\n'.format('\tThreshold', '=\t', self._threshold)
|
||||
string += '{0: <16}{1}{2}\n'.format('\tScores', '=\t', self._scores)
|
||||
return string
|
||||
|
||||
@property
|
||||
def trigger_type(self):
|
||||
return self._trigger_type
|
||||
|
|
@ -102,13 +118,6 @@ class Trigger(object):
|
|||
else:
|
||||
self._scores.append(score)
|
||||
|
||||
def __repr__(self):
|
||||
string = 'Trigger\n'
|
||||
string += '{0: <16}{1}{2}\n'.format('\tType', '=\t', self._trigger_type)
|
||||
string += '{0: <16}{1}{2}\n'.format('\tThreshold', '=\t', self._threshold)
|
||||
string += '{0: <16}{1}{2}\n'.format('\tScores', '=\t', self._scores)
|
||||
return string
|
||||
|
||||
def get_trigger_xml(self, element):
|
||||
"""Return XML representation of the trigger
|
||||
|
||||
|
|
|
|||
|
|
@ -73,6 +73,30 @@ class Cell(object):
|
|||
self._translation = None
|
||||
self._offsets = None
|
||||
|
||||
def __repr__(self):
|
||||
string = 'Cell\n'
|
||||
string += '{0: <16}{1}{2}\n'.format('\tID', '=\t', self._id)
|
||||
string += '{0: <16}{1}{2}\n'.format('\tName', '=\t', self._name)
|
||||
|
||||
if isinstance(self._fill, openmc.Material):
|
||||
string += '{0: <16}{1}{2}\n'.format('\tMaterial', '=\t',
|
||||
self._fill._id)
|
||||
elif isinstance(self._fill, (Universe, Lattice)):
|
||||
string += '{0: <16}{1}{2}\n'.format('\tFill', '=\t',
|
||||
self._fill._id)
|
||||
else:
|
||||
string += '{0: <16}{1}{2}\n'.format('\tFill', '=\t', self._fill)
|
||||
|
||||
string += '{0: <16}{1}{2}\n'.format('\tRegion', '=\t', self._region)
|
||||
|
||||
string += '{0: <16}{1}{2}\n'.format('\tRotation', '=\t',
|
||||
self._rotation)
|
||||
string += '{0: <16}{1}{2}\n'.format('\tTranslation', '=\t',
|
||||
self._translation)
|
||||
string += '{0: <16}{1}{2}\n'.format('\tOffset', '=\t', self._offsets)
|
||||
|
||||
return string
|
||||
|
||||
@property
|
||||
def id(self):
|
||||
return self._id
|
||||
|
|
@ -120,7 +144,7 @@ class Cell(object):
|
|||
AUTO_CELL_ID += 1
|
||||
else:
|
||||
cv.check_type('cell ID', cell_id, Integral)
|
||||
cv.check_greater_than('cell ID', cell_id, 0)
|
||||
cv.check_greater_than('cell ID', cell_id, 0, equality=True)
|
||||
self._id = cell_id
|
||||
|
||||
@name.setter
|
||||
|
|
@ -251,7 +275,7 @@ class Cell(object):
|
|||
|
||||
"""
|
||||
|
||||
nuclides = {}
|
||||
nuclides = OrderedDict()
|
||||
|
||||
if self._type != 'void':
|
||||
nuclides.update(self._fill.get_all_nuclides())
|
||||
|
|
@ -269,13 +293,34 @@ class Cell(object):
|
|||
|
||||
"""
|
||||
|
||||
cells = {}
|
||||
cells = OrderedDict()
|
||||
|
||||
if self._type == 'fill' or self._type == '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 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.
|
||||
|
|
@ -288,7 +333,7 @@ class Cell(object):
|
|||
|
||||
"""
|
||||
|
||||
universes = {}
|
||||
universes = OrderedDict()
|
||||
|
||||
if self._type == 'fill':
|
||||
universes[self._fill._id] = self._fill
|
||||
|
|
@ -298,30 +343,6 @@ class Cell(object):
|
|||
|
||||
return universes
|
||||
|
||||
def __repr__(self):
|
||||
string = 'Cell\n'
|
||||
string += '{0: <16}{1}{2}\n'.format('\tID', '=\t', self._id)
|
||||
string += '{0: <16}{1}{2}\n'.format('\tName', '=\t', self._name)
|
||||
|
||||
if isinstance(self._fill, openmc.Material):
|
||||
string += '{0: <16}{1}{2}\n'.format('\tMaterial', '=\t',
|
||||
self._fill._id)
|
||||
elif isinstance(self._fill, (Universe, Lattice)):
|
||||
string += '{0: <16}{1}{2}\n'.format('\tFill', '=\t',
|
||||
self._fill._id)
|
||||
else:
|
||||
string += '{0: <16}{1}{2}\n'.format('\tFill', '=\t', self._fill)
|
||||
|
||||
string += '{0: <16}{1}{2}\n'.format('\tRegion', '=\t', self._region)
|
||||
|
||||
string += '{0: <16}{1}{2}\n'.format('\tRotation', '=\t',
|
||||
self._rotation)
|
||||
string += '{0: <16}{1}{2}\n'.format('\tTranslation', '=\t',
|
||||
self._translation)
|
||||
string += '{0: <16}{1}{2}\n'.format('\tOffset', '=\t', self._offsets)
|
||||
|
||||
return string
|
||||
|
||||
def create_xml_subelement(self, xml_element):
|
||||
element = ET.Element("cell")
|
||||
element.set("id", str(self._id))
|
||||
|
|
@ -415,7 +436,7 @@ class Universe(object):
|
|||
|
||||
# Keys - Cell IDs
|
||||
# Values - Cells
|
||||
self._cells = {}
|
||||
self._cells = OrderedDict()
|
||||
|
||||
# Keys - Cell IDs
|
||||
# Values - Offsets
|
||||
|
|
@ -442,7 +463,7 @@ class Universe(object):
|
|||
AUTO_UNIVERSE_ID += 1
|
||||
else:
|
||||
cv.check_type('universe ID', universe_id, Integral)
|
||||
cv.check_greater_than('universe ID', universe_id, 0, True)
|
||||
cv.check_greater_than('universe ID', universe_id, 0, equality=True)
|
||||
self._id = universe_id
|
||||
|
||||
@name.setter
|
||||
|
|
@ -541,7 +562,7 @@ class Universe(object):
|
|||
|
||||
"""
|
||||
|
||||
nuclides = {}
|
||||
nuclides = OrderedDict()
|
||||
|
||||
# Append all Nuclides in each Cell in the Universe to the dictionary
|
||||
for cell_id, cell in self._cells.items():
|
||||
|
|
@ -559,7 +580,7 @@ class Universe(object):
|
|||
|
||||
"""
|
||||
|
||||
cells = {}
|
||||
cells = OrderedDict()
|
||||
|
||||
# Add this Universe's cells to the dictionary
|
||||
cells.update(self._cells)
|
||||
|
|
@ -570,6 +591,25 @@ class Universe(object):
|
|||
|
||||
return cells
|
||||
|
||||
def get_all_materials(self):
|
||||
"""Return all materials that are contained within the universe
|
||||
|
||||
Returns
|
||||
-------
|
||||
materials : dict
|
||||
Dictionary whose keys are material IDs and values are Material instances
|
||||
|
||||
"""
|
||||
|
||||
materials = OrderedDict()
|
||||
|
||||
# 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.
|
||||
|
||||
|
|
@ -584,7 +624,7 @@ class Universe(object):
|
|||
# Get all Cells in this Universe
|
||||
cells = self.get_all_cells()
|
||||
|
||||
universes = {}
|
||||
universes = OrderedDict()
|
||||
|
||||
# Append all Universes containing each Cell to the dictionary
|
||||
for cell_id, cell in cells.items():
|
||||
|
|
@ -603,6 +643,7 @@ class Universe(object):
|
|||
return string
|
||||
|
||||
def create_xml_subelement(self, xml_element):
|
||||
|
||||
# Iterate over all Cells
|
||||
for cell_id, cell in self._cells.items():
|
||||
|
||||
|
|
@ -684,7 +725,7 @@ class Lattice(object):
|
|||
AUTO_UNIVERSE_ID += 1
|
||||
else:
|
||||
cv.check_type('lattice ID', lattice_id, Integral)
|
||||
cv.check_greater_than('lattice ID', lattice_id, 0)
|
||||
cv.check_greater_than('lattice ID', lattice_id, 0, equality=True)
|
||||
self._id = lattice_id
|
||||
|
||||
@name.setter
|
||||
|
|
@ -717,7 +758,7 @@ class Lattice(object):
|
|||
|
||||
"""
|
||||
|
||||
univs = dict()
|
||||
univs = OrderedDict()
|
||||
for k in range(len(self._universes)):
|
||||
for j in range(len(self._universes[k])):
|
||||
if isinstance(self._universes[k][j], Universe):
|
||||
|
|
@ -745,7 +786,7 @@ class Lattice(object):
|
|||
|
||||
"""
|
||||
|
||||
nuclides = {}
|
||||
nuclides = OrderedDict()
|
||||
|
||||
# Get all unique Universes contained in each of the lattice cells
|
||||
unique_universes = self.get_unique_universes()
|
||||
|
|
@ -766,7 +807,7 @@ class Lattice(object):
|
|||
|
||||
"""
|
||||
|
||||
cells = {}
|
||||
cells = OrderedDict()
|
||||
unique_universes = self.get_unique_universes()
|
||||
|
||||
for universe_id, universe in unique_universes.items():
|
||||
|
|
@ -774,6 +815,25 @@ class Lattice(object):
|
|||
|
||||
return cells
|
||||
|
||||
def get_all_materials(self):
|
||||
"""Return all materials that are contained within the lattice
|
||||
|
||||
Returns
|
||||
-------
|
||||
materials : dict
|
||||
Dictionary whose keys are material IDs and values are Material instances
|
||||
|
||||
"""
|
||||
|
||||
materials = OrderedDict()
|
||||
|
||||
# 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 the lattice
|
||||
|
||||
|
|
@ -787,7 +847,7 @@ class Lattice(object):
|
|||
|
||||
# Initialize a dictionary of all Universes contained by the Lattice
|
||||
# in each nested Universe level
|
||||
all_universes = {}
|
||||
all_universes = OrderedDict()
|
||||
|
||||
# Get all unique Universes contained in each of the lattice cells
|
||||
unique_universes = self.get_unique_universes()
|
||||
|
|
@ -836,6 +896,50 @@ class RectLattice(Lattice):
|
|||
self._lower_left = None
|
||||
self._offsets = None
|
||||
|
||||
def __repr__(self):
|
||||
string = 'RectLattice\n'
|
||||
string += '{0: <16}{1}{2}\n'.format('\tID', '=\t', self._id)
|
||||
string += '{0: <16}{1}{2}\n'.format('\tName', '=\t', self._name)
|
||||
string += '{0: <16}{1}{2}\n'.format('\tDimension', '=\t',
|
||||
self._dimension)
|
||||
string += '{0: <16}{1}{2}\n'.format('\tLower Left', '=\t',
|
||||
self._lower_left)
|
||||
string += '{0: <16}{1}{2}\n'.format('\tPitch', '=\t', self._pitch)
|
||||
|
||||
if self._outer is not None:
|
||||
string += '{0: <16}{1}{2}\n'.format('\tOuter', '=\t',
|
||||
self._outer._id)
|
||||
else:
|
||||
string += '{0: <16}{1}{2}\n'.format('\tOuter', '=\t',
|
||||
self._outer)
|
||||
|
||||
string += '{0: <16}\n'.format('\tUniverses')
|
||||
|
||||
# Lattice nested Universe IDs - column major for Fortran
|
||||
for i, universe in enumerate(np.ravel(self._universes)):
|
||||
string += '{0} '.format(universe._id)
|
||||
|
||||
# Add a newline character every time we reach end of row of cells
|
||||
if (i+1) % self._dimension[-1] == 0:
|
||||
string += '\n'
|
||||
|
||||
string = string.rstrip('\n')
|
||||
|
||||
if self._offsets is not None:
|
||||
string += '{0: <16}\n'.format('\tOffsets')
|
||||
|
||||
# Lattice cell offsets
|
||||
for i, offset in enumerate(np.ravel(self._offsets)):
|
||||
string += '{0} '.format(offset)
|
||||
|
||||
# Add a newline character when we reach end of row of cells
|
||||
if (i+1) % self._dimension[-1] == 0:
|
||||
string += '\n'
|
||||
|
||||
string = string.rstrip('\n')
|
||||
|
||||
return string
|
||||
|
||||
@property
|
||||
def dimension(self):
|
||||
return self._dimension
|
||||
|
|
@ -893,51 +997,8 @@ class RectLattice(Lattice):
|
|||
|
||||
return offset
|
||||
|
||||
def __repr__(self):
|
||||
string = 'RectLattice\n'
|
||||
string += '{0: <16}{1}{2}\n'.format('\tID', '=\t', self._id)
|
||||
string += '{0: <16}{1}{2}\n'.format('\tName', '=\t', self._name)
|
||||
string += '{0: <16}{1}{2}\n'.format('\tDimension', '=\t',
|
||||
self._dimension)
|
||||
string += '{0: <16}{1}{2}\n'.format('\tLower Left', '=\t',
|
||||
self._lower_left)
|
||||
string += '{0: <16}{1}{2}\n'.format('\tPitch', '=\t', self._pitch)
|
||||
|
||||
if self._outer is not None:
|
||||
string += '{0: <16}{1}{2}\n'.format('\tOuter', '=\t',
|
||||
self._outer._id)
|
||||
else:
|
||||
string += '{0: <16}{1}{2}\n'.format('\tOuter', '=\t',
|
||||
self._outer)
|
||||
|
||||
string += '{0: <16}\n'.format('\tUniverses')
|
||||
|
||||
# Lattice nested Universe IDs - column major for Fortran
|
||||
for i, universe in enumerate(np.ravel(self._universes)):
|
||||
string += '{0} '.format(universe._id)
|
||||
|
||||
# Add a newline character every time we reach end of row of cells
|
||||
if (i+1) % self._dimension[-1] == 0:
|
||||
string += '\n'
|
||||
|
||||
string = string.rstrip('\n')
|
||||
|
||||
if self._offsets is not None:
|
||||
string += '{0: <16}\n'.format('\tOffsets')
|
||||
|
||||
# Lattice cell offsets
|
||||
for i, offset in enumerate(np.ravel(self._offsets)):
|
||||
string += '{0} '.format(offset)
|
||||
|
||||
# Add a newline character when we reach end of row of cells
|
||||
if (i+1) % self._dimension[-1] == 0:
|
||||
string += '\n'
|
||||
|
||||
string = string.rstrip('\n')
|
||||
|
||||
return string
|
||||
|
||||
def create_xml_subelement(self, xml_element):
|
||||
|
||||
# Determine if XML element already contains subelement for this Lattice
|
||||
path = './lattice[@id=\'{0}\']'.format(self._id)
|
||||
test = xml_element.find(path)
|
||||
|
|
@ -1052,6 +1113,34 @@ class HexLattice(Lattice):
|
|||
self._num_axial = None
|
||||
self._center = None
|
||||
|
||||
def __repr__(self):
|
||||
string = 'HexLattice\n'
|
||||
string += '{0: <16}{1}{2}\n'.format('\tID', '=\t', self._id)
|
||||
string += '{0: <16}{1}{2}\n'.format('\tName', '=\t', self._name)
|
||||
string += '{0: <16}{1}{2}\n'.format('\t# Rings', '=\t', self._num_rings)
|
||||
string += '{0: <16}{1}{2}\n'.format('\t# Axial', '=\t', self._num_axial)
|
||||
string += '{0: <16}{1}{2}\n'.format('\tCenter', '=\t',
|
||||
self._center)
|
||||
string += '{0: <16}{1}{2}\n'.format('\tPitch', '=\t', self._pitch)
|
||||
|
||||
if self._outer is not None:
|
||||
string += '{0: <16}{1}{2}\n'.format('\tOuter', '=\t',
|
||||
self._outer._id)
|
||||
else:
|
||||
string += '{0: <16}{1}{2}\n'.format('\tOuter', '=\t',
|
||||
self._outer)
|
||||
|
||||
string += '{0: <16}\n'.format('\tUniverses')
|
||||
|
||||
if self._num_axial is not None:
|
||||
slices = [self._repr_axial_slice(x) for x in self._universes]
|
||||
string += '\n'.join(slices)
|
||||
|
||||
else:
|
||||
string += self._repr_axial_slice(self._universes)
|
||||
|
||||
return string
|
||||
|
||||
@property
|
||||
def num_rings(self):
|
||||
return self._num_rings
|
||||
|
|
@ -1172,34 +1261,6 @@ class HexLattice(Lattice):
|
|||
6*(self._num_rings - 1 - r))
|
||||
raise ValueError(msg)
|
||||
|
||||
def __repr__(self):
|
||||
string = 'HexLattice\n'
|
||||
string += '{0: <16}{1}{2}\n'.format('\tID', '=\t', self._id)
|
||||
string += '{0: <16}{1}{2}\n'.format('\tName', '=\t', self._name)
|
||||
string += '{0: <16}{1}{2}\n'.format('\t# Rings', '=\t', self._num_rings)
|
||||
string += '{0: <16}{1}{2}\n'.format('\t# Axial', '=\t', self._num_axial)
|
||||
string += '{0: <16}{1}{2}\n'.format('\tCenter', '=\t',
|
||||
self._center)
|
||||
string += '{0: <16}{1}{2}\n'.format('\tPitch', '=\t', self._pitch)
|
||||
|
||||
if self._outer is not None:
|
||||
string += '{0: <16}{1}{2}\n'.format('\tOuter', '=\t',
|
||||
self._outer._id)
|
||||
else:
|
||||
string += '{0: <16}{1}{2}\n'.format('\tOuter', '=\t',
|
||||
self._outer)
|
||||
|
||||
string += '{0: <16}\n'.format('\tUniverses')
|
||||
|
||||
if self._num_axial is not None:
|
||||
slices = [self._repr_axial_slice(x) for x in self._universes]
|
||||
string += '\n'.join(slices)
|
||||
|
||||
else:
|
||||
string += self._repr_axial_slice(self._universes)
|
||||
|
||||
return string
|
||||
|
||||
def create_xml_subelement(self, xml_element):
|
||||
# Determine if XML element already contains subelement for this Lattice
|
||||
path = './hex_lattice[@id=\'{0}\']'.format(self._id)
|
||||
|
|
|
|||
2
setup.py
2
setup.py
|
|
@ -11,7 +11,7 @@ except ImportError:
|
|||
|
||||
kwargs = {'name': 'openmc',
|
||||
'version': '0.7.0',
|
||||
'packages': ['openmc'],
|
||||
'packages': ['openmc', 'openmc.mgxs'],
|
||||
'scripts': glob.glob('scripts/openmc-*'),
|
||||
|
||||
# Metadata
|
||||
|
|
|
|||
1
tests/test_mgxs_library_condense/inputs_true.dat
Normal file
1
tests/test_mgxs_library_condense/inputs_true.dat
Normal file
|
|
@ -0,0 +1 @@
|
|||
7e5c0de6e50c494abeea443d74606db809d74ce8bb2571eb4e1c98b3c9a33885b0aef2a4a82b6f95a1725b078d4a5ff01f68e1cc72addbd2d6bd0fb8251ad2e7
|
||||
49
tests/test_mgxs_library_condense/results_true.dat
Normal file
49
tests/test_mgxs_library_condense/results_true.dat
Normal file
|
|
@ -0,0 +1,49 @@
|
|||
material group in nuclide mean std. dev.
|
||||
0 1 1 total 0.419289 0.01638 material group in nuclide mean std. dev.
|
||||
0 1 1 total 0.07774 0.003273 material group in group out nuclide mean std. dev.
|
||||
0 1 1 1 total 0.352665 0.015654 material group out nuclide mean std. dev.
|
||||
0 1 1 total 1 0.119622 material group in nuclide mean std. dev.
|
||||
0 2 1 total 0.247316 0.009562 material group in nuclide mean std. dev.
|
||||
0 2 1 total 0 0 material group in group out nuclide mean std. dev.
|
||||
0 2 1 1 total 0.244838 0.009996 material group out nuclide mean std. dev.
|
||||
0 2 1 total 0 0 material group in nuclide mean std. dev.
|
||||
0 3 1 total 0.409938 0.042262 material group in nuclide mean std. dev.
|
||||
0 3 1 total 0 0 material group in group out nuclide mean std. dev.
|
||||
0 3 1 1 total 0.403354 0.041386 material group out nuclide mean std. dev.
|
||||
0 3 1 total 0 0 material group in nuclide mean std. dev.
|
||||
0 4 1 total 0.344007 0.05352 material group in nuclide mean std. dev.
|
||||
0 4 1 total 0 0 material group in group out nuclide mean std. dev.
|
||||
0 4 1 1 total 0.340438 0.052067 material group out nuclide mean std. dev.
|
||||
0 4 1 total 0 0 material group in nuclide mean std. dev.
|
||||
0 5 1 total 0 0 material group in nuclide mean std. dev.
|
||||
0 5 1 total 0 0 material group in group out nuclide mean std. dev.
|
||||
0 5 1 1 total 0 0 material group out nuclide mean std. dev.
|
||||
0 5 1 total 0 0 material group in nuclide mean std. dev.
|
||||
0 6 1 total 0 0 material group in nuclide mean std. dev.
|
||||
0 6 1 total 0 0 material group in group out nuclide mean std. dev.
|
||||
0 6 1 1 total 0 0 material group out nuclide mean std. dev.
|
||||
0 6 1 total 0 0 material group in nuclide mean std. dev.
|
||||
0 7 1 total 0 0 material group in nuclide mean std. dev.
|
||||
0 7 1 total 0 0 material group in group out nuclide mean std. dev.
|
||||
0 7 1 1 total 0 0 material group out nuclide mean std. dev.
|
||||
0 7 1 total 0 0 material group in nuclide mean std. dev.
|
||||
0 8 1 total 0 0 material group in nuclide mean std. dev.
|
||||
0 8 1 total 0 0 material group in group out nuclide mean std. dev.
|
||||
0 8 1 1 total 0 0 material group out nuclide mean std. dev.
|
||||
0 8 1 total 0 0 material group in nuclide mean std. dev.
|
||||
0 9 1 total 0.751873 0.559701 material group in nuclide mean std. dev.
|
||||
0 9 1 total 0 0 material group in group out nuclide mean std. dev.
|
||||
0 9 1 1 total 0.695491 0.50757 material group out nuclide mean std. dev.
|
||||
0 9 1 total 0 0 material group in nuclide mean std. dev.
|
||||
0 10 1 total 0 0 material group in nuclide mean std. dev.
|
||||
0 10 1 total 0 0 material group in group out nuclide mean std. dev.
|
||||
0 10 1 1 total 0 0 material group out nuclide mean std. dev.
|
||||
0 10 1 total 0 0 material group in nuclide mean std. dev.
|
||||
0 11 1 total 0.457329 0.403578 material group in nuclide mean std. dev.
|
||||
0 11 1 total 0 0 material group in group out nuclide mean std. dev.
|
||||
0 11 1 1 total 0.446737 0.392775 material group out nuclide mean std. dev.
|
||||
0 11 1 total 0 0 material group in nuclide mean std. dev.
|
||||
0 12 1 total 0.574978 0.38864 material group in nuclide mean std. dev.
|
||||
0 12 1 total 0 0 material group in group out nuclide mean std. dev.
|
||||
0 12 1 1 total 0.559478 0.377512 material group out nuclide mean std. dev.
|
||||
0 12 1 total 0 0
|
||||
|
|
@ -0,0 +1,85 @@
|
|||
#!/usr/bin/env python
|
||||
|
||||
import os
|
||||
import sys
|
||||
import glob
|
||||
import hashlib
|
||||
sys.path.insert(0, os.pardir)
|
||||
from testing_harness import PyAPITestHarness
|
||||
import openmc
|
||||
import openmc.mgxs
|
||||
|
||||
|
||||
class MGXSTestHarness(PyAPITestHarness):
|
||||
def _build_inputs(self):
|
||||
|
||||
# The openmc.mgxs module needs a summary.h5 file
|
||||
self._input_set.settings.output = {'summary': True}
|
||||
|
||||
# Generate inputs using parent class routine
|
||||
super(MGXSTestHarness, self)._build_inputs()
|
||||
|
||||
# Initialize a two-group structure
|
||||
energy_groups = openmc.mgxs.EnergyGroups(group_edges=[0, 0.625e-6, 20.])
|
||||
|
||||
# Initialize MGXS Library for a few cross section types
|
||||
self.mgxs_lib = openmc.mgxs.Library(self._input_set.geometry.geometry)
|
||||
self.mgxs_lib.by_nuclide = False
|
||||
self.mgxs_lib.mgxs_types = ['transport', 'nu-fission',
|
||||
'nu-scatter matrix', 'chi']
|
||||
self.mgxs_lib.energy_groups = energy_groups
|
||||
self.mgxs_lib.domain_type = 'material'
|
||||
self.mgxs_lib.build_library()
|
||||
|
||||
# Initialize a tallies file
|
||||
self._input_set.tallies = openmc.TalliesFile()
|
||||
self.mgxs_lib.add_to_tallies_file(self._input_set.tallies, merge=False)
|
||||
self._input_set.tallies.export_to_xml()
|
||||
|
||||
def _get_results(self, hash_output=False):
|
||||
"""Digest info in the statepoint and return as a string."""
|
||||
|
||||
# Read the statepoint file.
|
||||
statepoint = glob.glob(os.path.join(os.getcwd(), self._sp_name))[0]
|
||||
sp = openmc.StatePoint(statepoint)
|
||||
|
||||
# Read the summary file.
|
||||
summary = glob.glob(os.path.join(os.getcwd(), 'summary.h5'))[0]
|
||||
su = openmc.Summary(summary)
|
||||
sp.link_with_summary(su)
|
||||
|
||||
# Load the MGXS library from the statepoint
|
||||
self.mgxs_lib.load_from_statepoint(sp)
|
||||
|
||||
# Build a condensed 1-group MGXS Library
|
||||
one_group = openmc.mgxs.EnergyGroups([0., 20.])
|
||||
condense_lib = self.mgxs_lib.get_condensed_library(one_group)
|
||||
|
||||
# Build a string from Pandas Dataframe for each 1-group MGXS
|
||||
outstr = ''
|
||||
for domain in condense_lib.domains:
|
||||
for mgxs_type in condense_lib.mgxs_types:
|
||||
mgxs = condense_lib.get_mgxs(domain, mgxs_type)
|
||||
df = mgxs.get_pandas_dataframe()
|
||||
outstr += df.to_string()
|
||||
|
||||
print(outstr)
|
||||
|
||||
# Hash the results if necessary
|
||||
if hash_output:
|
||||
sha512 = hashlib.sha512()
|
||||
sha512.update(outstr.encode('utf-8'))
|
||||
outstr = sha512.hexdigest()
|
||||
|
||||
return outstr
|
||||
|
||||
|
||||
def _cleanup(self):
|
||||
super(MGXSTestHarness, self)._cleanup()
|
||||
f = os.path.join(os.getcwd(), 'tallies.xml')
|
||||
if os.path.exists(f): os.remove(f)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
harness = MGXSTestHarness('statepoint.10.*', True)
|
||||
harness.main()
|
||||
1
tests/test_mgxs_library_hdf5/inputs_true.dat
Normal file
1
tests/test_mgxs_library_hdf5/inputs_true.dat
Normal file
|
|
@ -0,0 +1 @@
|
|||
7e5c0de6e50c494abeea443d74606db809d74ce8bb2571eb4e1c98b3c9a33885b0aef2a4a82b6f95a1725b078d4a5ff01f68e1cc72addbd2d6bd0fb8251ad2e7
|
||||
168
tests/test_mgxs_library_hdf5/results_true.dat
Normal file
168
tests/test_mgxs_library_hdf5/results_true.dat
Normal file
|
|
@ -0,0 +1,168 @@
|
|||
domain=1 type=transport
|
||||
[ 0.38437891 0.81208747]
|
||||
[ 0.01648997 0.07418959]
|
||||
domain=1 type=nu-fission
|
||||
[ 0.02127008 0.69604034]
|
||||
[ 0.0008939 0.05345764]
|
||||
domain=1 type=nu-scatter matrix
|
||||
[[ 3.49923892e-01 1.73140769e-04]
|
||||
[ 1.94810926e-03 3.79607212e-01]]
|
||||
[[ 0.01664928 0.0001732 ]
|
||||
[ 0.00195193 0.04007819]]
|
||||
domain=1 type=chi
|
||||
[ 1. 0.]
|
||||
[ 0.11962178 0. ]
|
||||
domain=2 type=transport
|
||||
[ 0.24504295 0.26645769]
|
||||
[ 0.00882749 0.05220872]
|
||||
domain=2 type=nu-fission
|
||||
[ 0. 0.]
|
||||
[ 0. 0.]
|
||||
domain=2 type=nu-scatter matrix
|
||||
[[ 0.24365718 0. ]
|
||||
[ 0. 0.25478661]]
|
||||
[[ 0.00908307 0. ]
|
||||
[ 0. 0.05556256]]
|
||||
domain=2 type=chi
|
||||
[ 0. 0.]
|
||||
[ 0. 0.]
|
||||
domain=3 type=transport
|
||||
[ 0.28227749 1.42731974]
|
||||
[ 0.03724175 0.24712746]
|
||||
domain=3 type=nu-fission
|
||||
[ 0. 0.]
|
||||
[ 0. 0.]
|
||||
domain=3 type=nu-scatter matrix
|
||||
[[ 0.25396726 0.02727268]
|
||||
[ 0. 1.37652669]]
|
||||
[[ 0.03617307 0.00180698]
|
||||
[ 0. 0.2402569 ]]
|
||||
domain=3 type=chi
|
||||
[ 0. 0.]
|
||||
[ 0. 0.]
|
||||
domain=4 type=transport
|
||||
[ 0.25572316 1.17976682]
|
||||
[ 0.05191655 0.22938034]
|
||||
domain=4 type=nu-fission
|
||||
[ 0. 0.]
|
||||
[ 0. 0.]
|
||||
domain=4 type=nu-scatter matrix
|
||||
[[ 0.23297756 0.02228141]
|
||||
[ 0. 1.14680862]]
|
||||
[[ 0.04977114 0.00262525]
|
||||
[ 0. 0.22219839]]
|
||||
domain=4 type=chi
|
||||
[ 0. 0.]
|
||||
[ 0. 0.]
|
||||
domain=5 type=transport
|
||||
[ 0. 0.]
|
||||
[ 0. 0.]
|
||||
domain=5 type=nu-fission
|
||||
[ 0. 0.]
|
||||
[ 0. 0.]
|
||||
domain=5 type=nu-scatter matrix
|
||||
[[ 0. 0.]
|
||||
[ 0. 0.]]
|
||||
[[ 0. 0.]
|
||||
[ 0. 0.]]
|
||||
domain=5 type=chi
|
||||
[ 0. 0.]
|
||||
[ 0. 0.]
|
||||
domain=6 type=transport
|
||||
[ 0. 0.]
|
||||
[ 0. 0.]
|
||||
domain=6 type=nu-fission
|
||||
[ 0. 0.]
|
||||
[ 0. 0.]
|
||||
domain=6 type=nu-scatter matrix
|
||||
[[ 0. 0.]
|
||||
[ 0. 0.]]
|
||||
[[ 0. 0.]
|
||||
[ 0. 0.]]
|
||||
domain=6 type=chi
|
||||
[ 0. 0.]
|
||||
[ 0. 0.]
|
||||
domain=7 type=transport
|
||||
[ 0. 0.]
|
||||
[ 0. 0.]
|
||||
domain=7 type=nu-fission
|
||||
[ 0. 0.]
|
||||
[ 0. 0.]
|
||||
domain=7 type=nu-scatter matrix
|
||||
[[ 0. 0.]
|
||||
[ 0. 0.]]
|
||||
[[ 0. 0.]
|
||||
[ 0. 0.]]
|
||||
domain=7 type=chi
|
||||
[ 0. 0.]
|
||||
[ 0. 0.]
|
||||
domain=8 type=transport
|
||||
[ 0. 0.]
|
||||
[ 0. 0.]
|
||||
domain=8 type=nu-fission
|
||||
[ 0. 0.]
|
||||
[ 0. 0.]
|
||||
domain=8 type=nu-scatter matrix
|
||||
[[ 0. 0.]
|
||||
[ 0. 0.]]
|
||||
[[ 0. 0.]
|
||||
[ 0. 0.]]
|
||||
domain=8 type=chi
|
||||
[ 0. 0.]
|
||||
[ 0. 0.]
|
||||
domain=9 type=transport
|
||||
[ 0.50403601 1.68709544]
|
||||
[ 0.37962374 2.53662237]
|
||||
domain=9 type=nu-fission
|
||||
[ 0. 0.]
|
||||
[ 0. 0.]
|
||||
domain=9 type=nu-scatter matrix
|
||||
[[ 0.50403601 0. ]
|
||||
[ 0. 1.41795483]]
|
||||
[[ 0.37962374 0. ]
|
||||
[ 0. 2.15802716]]
|
||||
domain=9 type=chi
|
||||
[ 0. 0.]
|
||||
[ 0. 0.]
|
||||
domain=10 type=transport
|
||||
[ 0. 0.]
|
||||
[ 0. 0.]
|
||||
domain=10 type=nu-fission
|
||||
[ 0. 0.]
|
||||
[ 0. 0.]
|
||||
domain=10 type=nu-scatter matrix
|
||||
[[ 0. 0.]
|
||||
[ 0. 0.]]
|
||||
[[ 0. 0.]
|
||||
[ 0. 0.]]
|
||||
domain=10 type=chi
|
||||
[ 0. 0.]
|
||||
[ 0. 0.]
|
||||
domain=11 type=transport
|
||||
[ 0.30282618 1.00614519]
|
||||
[ 0.40131081 1.09163785]
|
||||
domain=11 type=nu-fission
|
||||
[ 0. 0.]
|
||||
[ 0. 0.]
|
||||
domain=11 type=nu-scatter matrix
|
||||
[[ 0.27567871 0.02714747]
|
||||
[ 0. 0.95792921]]
|
||||
[[ 0.38567601 0.02000859]
|
||||
[ 0. 1.05195936]]
|
||||
domain=11 type=chi
|
||||
[ 0. 0.]
|
||||
[ 0. 0.]
|
||||
domain=12 type=transport
|
||||
[ 0.25593293 1.11334475]
|
||||
[ 0.26842571 0.98867569]
|
||||
domain=12 type=nu-fission
|
||||
[ 0. 0.]
|
||||
[ 0. 0.]
|
||||
domain=12 type=nu-scatter matrix
|
||||
[[ 0.22631045 0.02962248]
|
||||
[ 0. 1.07168976]]
|
||||
[[ 0.25487194 0.0177599 ]
|
||||
[ 0. 0.95829029]]
|
||||
domain=12 type=chi
|
||||
[ 0. 0.]
|
||||
[ 0. 0.]
|
||||
93
tests/test_mgxs_library_hdf5/test_mgxs_library_hdf5.py
Normal file
93
tests/test_mgxs_library_hdf5/test_mgxs_library_hdf5.py
Normal file
|
|
@ -0,0 +1,93 @@
|
|||
#!/usr/bin/env python
|
||||
|
||||
import os
|
||||
import sys
|
||||
import glob
|
||||
import hashlib
|
||||
import h5py
|
||||
sys.path.insert(0, os.pardir)
|
||||
from testing_harness import PyAPITestHarness
|
||||
import openmc
|
||||
import openmc.mgxs
|
||||
|
||||
|
||||
class MGXSTestHarness(PyAPITestHarness):
|
||||
def _build_inputs(self):
|
||||
|
||||
# The openmc.mgxs module needs a summary.h5 file
|
||||
self._input_set.settings.output = {'summary': True}
|
||||
|
||||
# Generate inputs using parent class routine
|
||||
super(MGXSTestHarness, self)._build_inputs()
|
||||
|
||||
# Initialize a two-group structure
|
||||
energy_groups = openmc.mgxs.EnergyGroups(group_edges=[0, 0.625e-6, 20.])
|
||||
|
||||
# Initialize MGXS Library for a few cross section types
|
||||
self.mgxs_lib = openmc.mgxs.Library(self._input_set.geometry.geometry)
|
||||
self.mgxs_lib.by_nuclide = False
|
||||
self.mgxs_lib.mgxs_types = ['transport', 'nu-fission',
|
||||
'nu-scatter matrix', 'chi']
|
||||
self.mgxs_lib.energy_groups = energy_groups
|
||||
self.mgxs_lib.domain_type = 'material'
|
||||
self.mgxs_lib.build_library()
|
||||
|
||||
# Initialize a tallies file
|
||||
self._input_set.tallies = openmc.TalliesFile()
|
||||
self.mgxs_lib.add_to_tallies_file(self._input_set.tallies, merge=False)
|
||||
self._input_set.tallies.export_to_xml()
|
||||
|
||||
def _get_results(self, hash_output=False):
|
||||
"""Digest info in the statepoint and return as a string."""
|
||||
|
||||
# Read the statepoint file.
|
||||
statepoint = glob.glob(os.path.join(os.getcwd(), self._sp_name))[0]
|
||||
sp = openmc.StatePoint(statepoint)
|
||||
|
||||
# Read the summary file.
|
||||
summary = glob.glob(os.path.join(os.getcwd(), 'summary.h5'))[0]
|
||||
su = openmc.Summary(summary)
|
||||
sp.link_with_summary(su)
|
||||
|
||||
# Load the MGXS library from the statepoint
|
||||
self.mgxs_lib.load_from_statepoint(sp)
|
||||
|
||||
# Export the MGXS Library to an HDF5 file
|
||||
self.mgxs_lib.build_hdf5_store(directory='.')
|
||||
|
||||
# Open the MGXS HDF5 file
|
||||
f = h5py.File('mgxs.h5', 'r')
|
||||
|
||||
# Build a string from the datasets in the HDF5 file
|
||||
outstr = ''
|
||||
for domain in self.mgxs_lib.domains:
|
||||
for mgxs_type in self.mgxs_lib.mgxs_types:
|
||||
outstr += 'domain={0} type={1}\n'.format(domain.id, mgxs_type)
|
||||
key = 'material/{0}/{1}/average'.format(domain.id, mgxs_type)
|
||||
outstr += str(f[key][...]) + '\n'
|
||||
key = 'material/{0}/{1}/std. dev.'.format(domain.id, mgxs_type)
|
||||
outstr += str(f[key][...]) + '\n'
|
||||
|
||||
# Close the MGXS HDF5 file
|
||||
f.close()
|
||||
|
||||
# Hash the results if necessary
|
||||
if hash_output:
|
||||
sha512 = hashlib.sha512()
|
||||
sha512.update(outstr.encode('utf-8'))
|
||||
outstr = sha512.hexdigest()
|
||||
|
||||
return outstr
|
||||
|
||||
|
||||
def _cleanup(self):
|
||||
super(MGXSTestHarness, self)._cleanup()
|
||||
f = os.path.join(os.getcwd(), 'tallies.xml')
|
||||
if os.path.exists(f): os.remove(f)
|
||||
f = os.path.join(os.getcwd(), 'mgxs.h5')
|
||||
if os.path.exists(f): os.remove(f)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
harness = MGXSTestHarness('statepoint.10.*', True)
|
||||
harness.main()
|
||||
1
tests/test_mgxs_library_no_nuclides/inputs_true.dat
Normal file
1
tests/test_mgxs_library_no_nuclides/inputs_true.dat
Normal file
|
|
@ -0,0 +1 @@
|
|||
7e5c0de6e50c494abeea443d74606db809d74ce8bb2571eb4e1c98b3c9a33885b0aef2a4a82b6f95a1725b078d4a5ff01f68e1cc72addbd2d6bd0fb8251ad2e7
|
||||
121
tests/test_mgxs_library_no_nuclides/results_true.dat
Normal file
121
tests/test_mgxs_library_no_nuclides/results_true.dat
Normal file
|
|
@ -0,0 +1,121 @@
|
|||
material group in nuclide mean std. dev.
|
||||
1 1 1 total 0.384379 0.01649
|
||||
0 1 2 total 0.812087 0.07419 material group in nuclide mean std. dev.
|
||||
1 1 1 total 0.02127 0.000894
|
||||
0 1 2 total 0.69604 0.053458 material group in group out nuclide mean std. dev.
|
||||
3 1 1 1 total 0.349924 0.016649
|
||||
2 1 1 2 total 0.000173 0.000173
|
||||
1 1 2 1 total 0.001948 0.001952
|
||||
0 1 2 2 total 0.379607 0.040078 material group out nuclide mean std. dev.
|
||||
1 1 1 total 1 0.119622
|
||||
0 1 2 total 0 0.000000 material group in nuclide mean std. dev.
|
||||
1 2 1 total 0.245043 0.008827
|
||||
0 2 2 total 0.266458 0.052209 material group in nuclide mean std. dev.
|
||||
1 2 1 total 0 0
|
||||
0 2 2 total 0 0 material group in group out nuclide mean std. dev.
|
||||
3 2 1 1 total 0.243657 0.009083
|
||||
2 2 1 2 total 0.000000 0.000000
|
||||
1 2 2 1 total 0.000000 0.000000
|
||||
0 2 2 2 total 0.254787 0.055563 material group out nuclide mean std. dev.
|
||||
1 2 1 total 0 0
|
||||
0 2 2 total 0 0 material group in nuclide mean std. dev.
|
||||
1 3 1 total 0.282277 0.037242
|
||||
0 3 2 total 1.427320 0.247127 material group in nuclide mean std. dev.
|
||||
1 3 1 total 0 0
|
||||
0 3 2 total 0 0 material group in group out nuclide mean std. dev.
|
||||
3 3 1 1 total 0.253967 0.036173
|
||||
2 3 1 2 total 0.027273 0.001807
|
||||
1 3 2 1 total 0.000000 0.000000
|
||||
0 3 2 2 total 1.376527 0.240257 material group out nuclide mean std. dev.
|
||||
1 3 1 total 0 0
|
||||
0 3 2 total 0 0 material group in nuclide mean std. dev.
|
||||
1 4 1 total 0.255723 0.051917
|
||||
0 4 2 total 1.179767 0.229380 material group in nuclide mean std. dev.
|
||||
1 4 1 total 0 0
|
||||
0 4 2 total 0 0 material group in group out nuclide mean std. dev.
|
||||
3 4 1 1 total 0.232978 0.049771
|
||||
2 4 1 2 total 0.022281 0.002625
|
||||
1 4 2 1 total 0.000000 0.000000
|
||||
0 4 2 2 total 1.146809 0.222198 material group out nuclide mean std. dev.
|
||||
1 4 1 total 0 0
|
||||
0 4 2 total 0 0 material group in nuclide mean std. dev.
|
||||
1 5 1 total 0 0
|
||||
0 5 2 total 0 0 material group in nuclide mean std. dev.
|
||||
1 5 1 total 0 0
|
||||
0 5 2 total 0 0 material group in group out nuclide mean std. dev.
|
||||
3 5 1 1 total 0 0
|
||||
2 5 1 2 total 0 0
|
||||
1 5 2 1 total 0 0
|
||||
0 5 2 2 total 0 0 material group out nuclide mean std. dev.
|
||||
1 5 1 total 0 0
|
||||
0 5 2 total 0 0 material group in nuclide mean std. dev.
|
||||
1 6 1 total 0 0
|
||||
0 6 2 total 0 0 material group in nuclide mean std. dev.
|
||||
1 6 1 total 0 0
|
||||
0 6 2 total 0 0 material group in group out nuclide mean std. dev.
|
||||
3 6 1 1 total 0 0
|
||||
2 6 1 2 total 0 0
|
||||
1 6 2 1 total 0 0
|
||||
0 6 2 2 total 0 0 material group out nuclide mean std. dev.
|
||||
1 6 1 total 0 0
|
||||
0 6 2 total 0 0 material group in nuclide mean std. dev.
|
||||
1 7 1 total 0 0
|
||||
0 7 2 total 0 0 material group in nuclide mean std. dev.
|
||||
1 7 1 total 0 0
|
||||
0 7 2 total 0 0 material group in group out nuclide mean std. dev.
|
||||
3 7 1 1 total 0 0
|
||||
2 7 1 2 total 0 0
|
||||
1 7 2 1 total 0 0
|
||||
0 7 2 2 total 0 0 material group out nuclide mean std. dev.
|
||||
1 7 1 total 0 0
|
||||
0 7 2 total 0 0 material group in nuclide mean std. dev.
|
||||
1 8 1 total 0 0
|
||||
0 8 2 total 0 0 material group in nuclide mean std. dev.
|
||||
1 8 1 total 0 0
|
||||
0 8 2 total 0 0 material group in group out nuclide mean std. dev.
|
||||
3 8 1 1 total 0 0
|
||||
2 8 1 2 total 0 0
|
||||
1 8 2 1 total 0 0
|
||||
0 8 2 2 total 0 0 material group out nuclide mean std. dev.
|
||||
1 8 1 total 0 0
|
||||
0 8 2 total 0 0 material group in nuclide mean std. dev.
|
||||
1 9 1 total 0.504036 0.379624
|
||||
0 9 2 total 1.687095 2.536622 material group in nuclide mean std. dev.
|
||||
1 9 1 total 0 0
|
||||
0 9 2 total 0 0 material group in group out nuclide mean std. dev.
|
||||
3 9 1 1 total 0.504036 0.379624
|
||||
2 9 1 2 total 0.000000 0.000000
|
||||
1 9 2 1 total 0.000000 0.000000
|
||||
0 9 2 2 total 1.417955 2.158027 material group out nuclide mean std. dev.
|
||||
1 9 1 total 0 0
|
||||
0 9 2 total 0 0 material group in nuclide mean std. dev.
|
||||
1 10 1 total 0 0
|
||||
0 10 2 total 0 0 material group in nuclide mean std. dev.
|
||||
1 10 1 total 0 0
|
||||
0 10 2 total 0 0 material group in group out nuclide mean std. dev.
|
||||
3 10 1 1 total 0 0
|
||||
2 10 1 2 total 0 0
|
||||
1 10 2 1 total 0 0
|
||||
0 10 2 2 total 0 0 material group out nuclide mean std. dev.
|
||||
1 10 1 total 0 0
|
||||
0 10 2 total 0 0 material group in nuclide mean std. dev.
|
||||
1 11 1 total 0.302826 0.401311
|
||||
0 11 2 total 1.006145 1.091638 material group in nuclide mean std. dev.
|
||||
1 11 1 total 0 0
|
||||
0 11 2 total 0 0 material group in group out nuclide mean std. dev.
|
||||
3 11 1 1 total 0.275679 0.385676
|
||||
2 11 1 2 total 0.027147 0.020009
|
||||
1 11 2 1 total 0.000000 0.000000
|
||||
0 11 2 2 total 0.957929 1.051959 material group out nuclide mean std. dev.
|
||||
1 11 1 total 0 0
|
||||
0 11 2 total 0 0 material group in nuclide mean std. dev.
|
||||
1 12 1 total 0.255933 0.268426
|
||||
0 12 2 total 1.113345 0.988676 material group in nuclide mean std. dev.
|
||||
1 12 1 total 0 0
|
||||
0 12 2 total 0 0 material group in group out nuclide mean std. dev.
|
||||
3 12 1 1 total 0.226310 0.254872
|
||||
2 12 1 2 total 0.029622 0.017760
|
||||
1 12 2 1 total 0.000000 0.000000
|
||||
0 12 2 2 total 1.071690 0.958290 material group out nuclide mean std. dev.
|
||||
1 12 1 total 0 0
|
||||
0 12 2 total 0 0
|
||||
|
|
@ -0,0 +1,79 @@
|
|||
#!/usr/bin/env python
|
||||
|
||||
import os
|
||||
import sys
|
||||
import glob
|
||||
import hashlib
|
||||
sys.path.insert(0, os.pardir)
|
||||
from testing_harness import PyAPITestHarness
|
||||
import openmc
|
||||
import openmc.mgxs
|
||||
|
||||
|
||||
class MGXSTestHarness(PyAPITestHarness):
|
||||
def _build_inputs(self):
|
||||
|
||||
# The openmc.mgxs module needs a summary.h5 file
|
||||
self._input_set.settings.output = {'summary': True}
|
||||
|
||||
# Generate inputs using parent class routine
|
||||
super(MGXSTestHarness, self)._build_inputs()
|
||||
|
||||
# Initialize a two-group structure
|
||||
energy_groups = openmc.mgxs.EnergyGroups(group_edges=[0, 0.625e-6, 20.])
|
||||
|
||||
# Initialize MGXS Library for a few cross section types
|
||||
self.mgxs_lib = openmc.mgxs.Library(self._input_set.geometry.geometry)
|
||||
self.mgxs_lib.by_nuclide = False
|
||||
self.mgxs_lib.mgxs_types = ['transport', 'nu-fission',
|
||||
'nu-scatter matrix', 'chi']
|
||||
self.mgxs_lib.energy_groups = energy_groups
|
||||
self.mgxs_lib.domain_type = 'material'
|
||||
self.mgxs_lib.build_library()
|
||||
|
||||
# Initialize a tallies file
|
||||
self._input_set.tallies = openmc.TalliesFile()
|
||||
self.mgxs_lib.add_to_tallies_file(self._input_set.tallies, merge=False)
|
||||
self._input_set.tallies.export_to_xml()
|
||||
|
||||
def _get_results(self, hash_output=False):
|
||||
"""Digest info in the statepoint and return as a string."""
|
||||
|
||||
# Read the statepoint file.
|
||||
statepoint = glob.glob(os.path.join(os.getcwd(), self._sp_name))[0]
|
||||
sp = openmc.StatePoint(statepoint)
|
||||
|
||||
# Read the summary file.
|
||||
summary = glob.glob(os.path.join(os.getcwd(), 'summary.h5'))[0]
|
||||
su = openmc.Summary(summary)
|
||||
sp.link_with_summary(su)
|
||||
|
||||
# Load the MGXS library from the statepoint
|
||||
self.mgxs_lib.load_from_statepoint(sp)
|
||||
|
||||
# Build a string from Pandas Dataframe for each MGXS
|
||||
outstr = ''
|
||||
for domain in self.mgxs_lib.domains:
|
||||
for mgxs_type in self.mgxs_lib.mgxs_types:
|
||||
mgxs = self.mgxs_lib.get_mgxs(domain, mgxs_type)
|
||||
df = mgxs.get_pandas_dataframe()
|
||||
outstr += df.to_string()
|
||||
|
||||
# Hash the results if necessary
|
||||
if hash_output:
|
||||
sha512 = hashlib.sha512()
|
||||
sha512.update(outstr.encode('utf-8'))
|
||||
outstr = sha512.hexdigest()
|
||||
|
||||
return outstr
|
||||
|
||||
|
||||
def _cleanup(self):
|
||||
super(MGXSTestHarness, self)._cleanup()
|
||||
f = os.path.join(os.getcwd(), 'tallies.xml')
|
||||
if os.path.exists(f): os.remove(f)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
harness = MGXSTestHarness('statepoint.10.*', True)
|
||||
harness.main()
|
||||
1
tests/test_mgxs_library_nuclides/inputs_true.dat
Normal file
1
tests/test_mgxs_library_nuclides/inputs_true.dat
Normal file
|
|
@ -0,0 +1 @@
|
|||
04dcfca7d68981d7ec19d428c541acd6345ec2d608c581d56ce21d23548f52977fe713b5cdd7434bebf62067444d6562ef322175736a6a63e3985e5e48718081
|
||||
1971
tests/test_mgxs_library_nuclides/results_true.dat
Normal file
1971
tests/test_mgxs_library_nuclides/results_true.dat
Normal file
File diff suppressed because it is too large
Load diff
|
|
@ -0,0 +1,79 @@
|
|||
#!/usr/bin/env python
|
||||
|
||||
import os
|
||||
import sys
|
||||
import glob
|
||||
import hashlib
|
||||
sys.path.insert(0, os.pardir)
|
||||
from testing_harness import PyAPITestHarness
|
||||
import openmc
|
||||
import openmc.mgxs
|
||||
|
||||
|
||||
class MGXSTestHarness(PyAPITestHarness):
|
||||
def _build_inputs(self):
|
||||
|
||||
# The openmc.mgxs module needs a summary.h5 file
|
||||
self._input_set.settings.output = {'summary': True}
|
||||
|
||||
# Generate inputs using parent class routine
|
||||
super(MGXSTestHarness, self)._build_inputs()
|
||||
|
||||
# Initialize a two-group structure
|
||||
energy_groups = openmc.mgxs.EnergyGroups(group_edges=[0, 0.625e-6, 20.])
|
||||
|
||||
# Initialize MGXS Library for a few cross section types
|
||||
self.mgxs_lib = openmc.mgxs.Library(self._input_set.geometry.geometry)
|
||||
self.mgxs_lib.by_nuclide = True
|
||||
self.mgxs_lib.mgxs_types = ['transport', 'nu-fission',
|
||||
'nu-scatter matrix', 'chi']
|
||||
self.mgxs_lib.energy_groups = energy_groups
|
||||
self.mgxs_lib.domain_type = 'material'
|
||||
self.mgxs_lib.build_library()
|
||||
|
||||
# Initialize a tallies file
|
||||
self._input_set.tallies = openmc.TalliesFile()
|
||||
self.mgxs_lib.add_to_tallies_file(self._input_set.tallies, merge=False)
|
||||
self._input_set.tallies.export_to_xml()
|
||||
|
||||
def _get_results(self, hash_output=False):
|
||||
"""Digest info in the statepoint and return as a string."""
|
||||
|
||||
# Read the statepoint file.
|
||||
statepoint = glob.glob(os.path.join(os.getcwd(), self._sp_name))[0]
|
||||
sp = openmc.StatePoint(statepoint)
|
||||
|
||||
# Read the summary file.
|
||||
summary = glob.glob(os.path.join(os.getcwd(), 'summary.h5'))[0]
|
||||
su = openmc.Summary(summary)
|
||||
sp.link_with_summary(su)
|
||||
|
||||
# Load the MGXS library from the statepoint
|
||||
self.mgxs_lib.load_from_statepoint(sp)
|
||||
|
||||
# Build a string from Pandas Dataframe for each MGXS
|
||||
outstr = ''
|
||||
for domain in self.mgxs_lib.domains:
|
||||
for mgxs_type in self.mgxs_lib.mgxs_types:
|
||||
mgxs = self.mgxs_lib.get_mgxs(domain, mgxs_type)
|
||||
df = mgxs.get_pandas_dataframe()
|
||||
outstr += df.to_string()
|
||||
|
||||
# Hash the results if necessary
|
||||
if hash_output:
|
||||
sha512 = hashlib.sha512()
|
||||
sha512.update(outstr.encode('utf-8'))
|
||||
outstr = sha512.hexdigest()
|
||||
|
||||
return outstr
|
||||
|
||||
|
||||
def _cleanup(self):
|
||||
super(MGXSTestHarness, self)._cleanup()
|
||||
f = os.path.join(os.getcwd(), 'tallies.xml')
|
||||
if os.path.exists(f): os.remove(f)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
harness = MGXSTestHarness('statepoint.10.*', True)
|
||||
harness.main()
|
||||
|
|
@ -339,6 +339,9 @@ class PyAPITestHarness(TestHarness):
|
|||
"""Make sure the current inputs agree with the _true standard."""
|
||||
compare = filecmp.cmp('inputs_test.dat', 'inputs_true.dat')
|
||||
if not compare:
|
||||
f = open('inputs_test.dat')
|
||||
for line in f.readlines(): print(line)
|
||||
f.close()
|
||||
os.rename('inputs_test.dat', 'inputs_error.dat')
|
||||
assert compare, 'Input files are broken.'
|
||||
|
||||
|
|
@ -349,6 +352,7 @@ class PyAPITestHarness(TestHarness):
|
|||
output.append(os.path.join(os.getcwd(), 'geometry.xml'))
|
||||
output.append(os.path.join(os.getcwd(), 'settings.xml'))
|
||||
output.append(os.path.join(os.getcwd(), 'inputs_test.dat'))
|
||||
output.append(os.path.join(os.getcwd(), 'summary.h5'))
|
||||
for f in output:
|
||||
if os.path.exists(f):
|
||||
os.remove(f)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue