Merge branch 'mgxs' into iso-lab

This commit is contained in:
Will Boyd 2015-10-06 13:11:57 -04:00
commit c4b14a5ef8
29 changed files with 6812 additions and 1396 deletions

9
.gitignore vendored
View file

@ -62,4 +62,11 @@ data/nndc
.idea/*
# IPython notebook checkpoints
.ipynb_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

File diff suppressed because one or more lines are too long

View file

@ -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

View file

@ -342,7 +342,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",
@ -358,7 +369,7 @@
"outputs": [
{
"data": {
"image/png": "iVBORw0KGgoAAAANSUhEUgAAAPoAAAD6AgMAAAD1grKuAAAABGdBTUEAALGPC/xhBQAAACBjSFJN\nAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAADFBMVEX///9yEhLpgJFNv8Tq\nQYT7AAAAAWJLR0QAiAUdSAAAAAd0SU1FB98JFQMZGiFPL70AAALKSURBVGje7dpLcqQwDAbgHHE2\nYeEj+D4cwQucBUfo+3CEXoSp8OhuhF70T4qpKXmdr21LogK2Pj7A8QmNP+HDhw8fPnz48Kf6VH9G\n+66vy+je8k19jnf8C5dXIPv86ms56lPdjvaYbyodx3ze+XLE76cXFiD4zPji99z0/AJ4n1lfvJ6f\nnl0A6x+578efMSg1wPr172/jPO5yFXM+Ef78gdblM+WPHyguP//t1/g6pA0wfln+ho/fwgYYn19C\n/xwDvwHGc9OvC+hs37DTrwuwfWanXxdQTC9Mvyygs3wjTL8uwPJpn/tNDbSGz7T0SBEWw4vLXzbQ\n6b6RoveIoO6TvPxlA63qs7z8ZQPF9F+SH22vbX8OQKf5Rtv+EgDNJ3X58wZaxWd1+fMGiuFvir8b\nvjp8J/tGy/6jAmRvhW8fwL3vVT+o3grfPoB7r/IpALI3tz8FoJN84/NV873hB8UnM3xzANtf8nb4\ndwmg3grfFEDJO8JPE0i9Ff4pAYL3pI8mkHor/HMCeO9JH00g9SafEsh7T/ppARBvp48UwJnelT5S\nACd7O31TAlnvKx9SQCd7B58KgPO+8iMFuPWe9E8F8BveWX7bAjzX9y4//Jve+fhsH6Ctv7n8PTzj\nvY/v9gEOHz58+PBX+6v/f/wPvnd54f3j6venE/yl769Xv7+j3x/o98/V32/o9+fl389Xnx+g5x/o\n+Qt6/oOeP6HnX+j5G3z+h54/ouefV5/foufP6Pk3ev4On/+j9w/o/Qd6/4Le/6D3T/D9V67Y/ZsV\nQBq+s+8f0ftP+P41axXguP9NWgDuu/Cdfv+N3r/D9/9TAID+A7T/Ae2/gPs/0P4TtP8F7r9J3AIO\n9P+g/Udw/9Oygbf7r9D+L7j/DO1/Q/vv4P4/tP8Q7n9E+y/h/k+0/xTuf4X7b+H+X7T/+BPuf3aM\n8OHDhw8fPnz4w/4vzcvgeY10sY0AAAAldEVYdGRhdGU6Y3JlYXRlADIwMTUtMDktMjFUMTA6MDg6\nNTcrMDc6MDALr51VAAAAJXRFWHRkYXRlOm1vZGlmeQAyMDE1LTA5LTIxVDEwOjA4OjU3KzA3OjAw\nevIl6QAAAABJRU5ErkJggg==\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\nMTUtMTAtMDNUMTM6MDI6MDItMDQ6MDCXyx9dAAAAJXRFWHRkYXRlOm1vZGlmeQAyMDE1LTEwLTAz\nVDEzOjAyOjAyLTA0OjAw5pan4QAAAABJRU5ErkJggg==\n",
"text/plain": [
"<IPython.core.display.Image object>"
]
@ -387,13 +398,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()"
]
},
{
@ -569,8 +579,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: b167d70c877c516deca785801b9fa6f53fb0985b\n",
" Date/Time: 2015-09-21 10:25:26\n",
" Git SHA1: e0c2aace2e73367536fa03e153b67a2d038cd2b3\n",
" Date/Time: 2015-10-03 13:02:02\n",
" MPI Processes: 1\n",
"\n",
" ===========================================================================\n",
" ========================> INITIALIZATION <=========================\n",
@ -625,20 +636,20 @@
"\n",
" =======================> TIMING STATISTICS <=======================\n",
"\n",
" Total time for initialization = 9.1800E-01 seconds\n",
" Reading cross sections = 6.5800E-01 seconds\n",
" Total time in simulation = 1.7037E+01 seconds\n",
" Time in transport only = 1.7024E+01 seconds\n",
" Time in inactive batches = 2.8600E+00 seconds\n",
" Time in active batches = 1.4177E+01 seconds\n",
" Time synchronizing fission bank = 4.0000E-03 seconds\n",
" Sampling source sites = 4.0000E-03 seconds\n",
" Total time for initialization = 4.1600E-01 seconds\n",
" Reading cross sections = 9.1000E-02 seconds\n",
" Total time in simulation = 1.4793E+01 seconds\n",
" Time in transport only = 1.4785E+01 seconds\n",
" Time in inactive batches = 2.1450E+00 seconds\n",
" Time in active batches = 1.2648E+01 seconds\n",
" Time synchronizing fission bank = 2.0000E-03 seconds\n",
" Sampling source sites = 2.0000E-03 seconds\n",
" SEND/RECV source sites = 0.0000E+00 seconds\n",
" Time accumulating tallies = 0.0000E+00 seconds\n",
" Total time for finalization = 1.0000E-03 seconds\n",
" Total time elapsed = 1.7971E+01 seconds\n",
" Calculation Rate (inactive) = 4370.63 neutrons/second\n",
" Calculation Rate (active) = 2645.13 neutrons/second\n",
" Total time elapsed = 1.5219E+01 seconds\n",
" Calculation Rate (inactive) = 5827.51 neutrons/second\n",
" Calculation Rate (active) = 2964.90 neutrons/second\n",
"\n",
" ============================> RESULTS <============================\n",
"\n",
@ -746,13 +757,6 @@
" <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",
@ -767,9 +771,8 @@
"</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.046353 0.00935"
]
},
"execution_count": 26,
@ -809,22 +812,17 @@
" <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",
@ -835,9 +833,8 @@
"</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.95873 0.00774"
]
},
"execution_count": 27,
@ -880,13 +877,6 @@
" <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",
@ -901,9 +891,8 @@
"</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.091622 0.011163"
]
},
"execution_count": 28,
@ -949,20 +938,11 @@
" <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",
@ -975,8 +955,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.802012 0.006609"
]
},
"execution_count": 29,
@ -1014,27 +993,16 @@
" <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",
@ -1045,13 +1013,8 @@
"</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.246604 0.011825"
]
},
"execution_count": 30,
@ -1087,22 +1050,17 @@
" <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",
@ -1113,13 +1071,11 @@
"</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.046353 0.01894 "
]
},
"execution_count": 31,
@ -1179,87 +1135,78 @@
" <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.641746e-07</td>\n",
" <td>6.859257e-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>2.099861e-01</td>\n",
" <td>1.966887e-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.556665e-01</td>\n",
" <td>3.717881e-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.554650e-03</td>\n",
" <td>5.218094e-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>7.165057e-03</td>\n",
" <td>5.625590e-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>2.276535e-01</td>\n",
" <td>8.544314e-04</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>8.089493e-03</td>\n",
" <td>5.080374e-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>3.370111e-03</td>\n",
" <td>1.361116e-05</td>\n",
" </tr>\n",
" </tbody>\n",
@ -1267,27 +1214,25 @@
"</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.641746e-07 6.859257e-09 \n",
"1 2.099861e-01 1.966887e-03 \n",
"2 3.556665e-01 3.717881e-03 \n",
"3 5.554650e-03 5.218094e-05 \n",
"4 7.165057e-03 5.625590e-05 \n",
"5 2.276535e-01 8.544314e-04 \n",
"6 8.089493e-03 5.080374e-05 \n",
"7 3.370111e-03 1.361116e-05 "
]
},
"execution_count": 33,
@ -1416,21 +1361,12 @@
" <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",
@ -1439,7 +1375,7 @@
" <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",
@ -1448,7 +1384,7 @@
" <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",
@ -1457,7 +1393,7 @@
" <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",
@ -1468,12 +1404,11 @@
"</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.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"
]
},
"execution_count": 37,
@ -1509,21 +1444,12 @@
" <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",
@ -1532,7 +1458,7 @@
" <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",
@ -1541,7 +1467,7 @@
" <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",
@ -1550,7 +1476,7 @@
" <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",
@ -1559,7 +1485,7 @@
" <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",
@ -1568,7 +1494,7 @@
" <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",
@ -1577,7 +1503,7 @@
" <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",
@ -1586,7 +1512,7 @@
" <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",
@ -1595,7 +1521,7 @@
" <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",
@ -1606,17 +1532,16 @@
"</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.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"
]
},
"execution_count": 38,
@ -1649,7 +1574,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython2",
"version": "2.7.9"
"version": "2.7.6"
}
},
"nbformat": 4,

View file

@ -65,6 +65,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/

View file

@ -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 *

View file

@ -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,33 @@ 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
@property
def left_score(self):
return self._left_score
@ -54,19 +92,20 @@ 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)
@ -75,7 +114,7 @@ class CrossScore(object):
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,6 +151,33 @@ class CrossNuclide(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_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
@property
def left_nuclide(self):
return self._left_nuclide
@ -126,14 +192,18 @@ class CrossNuclide(object):
@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
def __eq__(self, other):
@ -164,7 +234,7 @@ class CrossNuclide(object):
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 +262,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 +273,21 @@ 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 __deepcopy__(self, memo):
existing = memo.get(id(self))
@ -221,9 +297,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 +329,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 +390,7 @@ class CrossFilter(object):
Returns
-------
filter_index : int
filter_index : Integral
The index in the Tally data array for this filter bin.
"""
@ -326,6 +400,60 @@ class CrossFilter(object):
filter_index = left_index * self.right_filter.num_bins + right_index
return filter_index
def get_pandas_dataframe(self, datasize, summary=None):
"""Builds a Pandas DataFrame for the CrossFilter's bins.
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
----------
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
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
def __repr__(self):
string = 'CrossFilter\n'
@ -337,4 +465,4 @@ class CrossFilter(object):
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
return string

View file

@ -38,18 +38,18 @@ class Element(object):
if xs is not None:
self.xs = xs
def __eq__(self, element2):
# Check type
if not isinstance(element2, Element):
return False
# Check name and xs
if self._name != element2._name:
return False
elif self._xs != element2._xs:
return False
else:
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
def __hash__(self):
return hash((self._name, self._xs))

View file

@ -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

View file

@ -1,19 +1,25 @@
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', 'distribcell']
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
----------
@ -21,46 +27,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))
@ -93,7 +113,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):
@ -120,15 +147,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 cv._isinstance(bins, Iterable):
bins = [bins]
# If the bins are in a collection, convert it to a list
@ -137,13 +162,13 @@ class Filter(object):
if self.type in ['cell', 'cellborn', 'surface', 'material',
'universe', 'distribcell']:
check_iterable_type('filter bins', bins, Integral)
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)
@ -162,12 +187,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 cv._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)
@ -179,16 +204,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'
@ -196,12 +220,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)
@ -270,31 +294,66 @@ class Filter(object):
merged_filter = copy.deepcopy(self)
# Merge unique filter bins
merged_bins = list(set(self.bins + filter.bins))
merged_bins = list(set(list(self.bins) + list(filter.bins)))
merged_filter.bins = merged_bins
merged_filter.num_bins = len(merged_bins)
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']:
return np.all(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:
@ -319,7 +378,7 @@ class Filter(object):
val = np.where(self.bins == filter_bin[0])[0][0]
filter_index = val
# 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
@ -331,11 +390,358 @@ 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 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
def __repr__(self):
string = 'Filter\n'
string += '{0: <16}{1}{2}\n'.format('\tType', '=\t', self.type)

View file

@ -132,9 +132,12 @@ class Material(object):
@name.setter
def name(self, name):
check_type('name for Material ID="{0}"'.format(self._id),
name, basestring)
self._name = name
if name is not None:
check_type('name for Material ID="{0}"'.format(self._id),
name, basestring)
self._name = name
else:
self._name = None
def set_density(self, units, density=NO_DENSITY):
"""Set the density of the material

View file

@ -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,45 +144,49 @@ 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)
self._id = mesh_id
@name.setter
def name(self, name):
check_type('name for mesh ID="{0}"'.format(self._id), name, basestring)
self._name = name
if name is not None:
cv.check_type('name for mesh ID="{0}"'.format(self._id),
name, basestring)
self._name = name
else:
self._name = None
@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):

2
openmc/mgxs/__init__.py Normal file
View file

@ -0,0 +1,2 @@
from groups import EnergyGroups
from mgxs import *

275
openmc/mgxs/groups.py Normal file
View file

@ -0,0 +1,275 @@
from collections import Iterable
from numbers import Real, Integral
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 : ndarray
The energy group boundaries [MeV]
num_groups : Integral
The number of energy groups
Attributes
----------
group_edges : ndarray
The energy group boundaries [MeV]
num_groups : Integral
The number of energy groups
"""
def __init__(self, group_edges=None, num_groups=None):
self._group_edges = None
self._num_groups = None
if group_edges is not None:
self.group_edges = group_edges
if num_groups is not None:
self.num_groups = num_groups
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)
clone._num_groups = self.num_groups
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 self._num_groups
@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)
self._num_groups = len(edges)-1
def generate_bin_edges(self, start, stop, num_groups, spacing='linear'):
"""Generate equally or logarithmically-spaced energy group boundaries.
Parameters
----------
start : Real
The lowest energy in MeV
stop : Real
The highest energy in MeV
num_groups : Integral
The number of energy groups
spacing : {'linear', 'logarithmic'}
The spacing between groups
"""
cv.check_type('first edge', start, Real)
cv.check_type('last edge', stop, Real)
cv.check_type('number of groups', num_groups, Integral)
cv.check_type('spacing', spacing, basestring)
cv.check_greater_than('first edge', start, 0, True)
cv.check_greater_than('last edge', stop, start, False)
cv.check_greater_than('number of groups', num_groups, 0)
cv.check_value('spacing', spacing, ('linear', 'logarithmic'))
if spacing == 'linear':
self.group_edges = np.linspace(start, stop, num_groups + 1)
elif spacing == 'logarithmic':
self.group_edges = \
np.logspace(np.log10(start), np.log10(stop), num_groups + 1)
self._num_groups = num_groups
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]
group = self.num_groups - index
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)
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':
indices = 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), (2,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[0] for group in coarse_groups]
group_bounds.append(coarse_groups[-1][1])
# 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

2050
openmc/mgxs/mgxs.py Normal file

File diff suppressed because it is too large Load diff

View file

@ -42,21 +42,18 @@ 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 __hash__(self):
return hash((self._name, self._xs))

View file

@ -83,14 +83,14 @@ def get_opencg_material(openmc_material):
raise ValueError(msg)
global OPENCG_MATERIALS
material_id = openmc_material._id
material_id = openmc_material.id
# If this Material was already created, use it
if material_id in OPENCG_MATERIALS:
return OPENCG_MATERIALS[material_id]
# Create an OpenCG Material to represent this OpenMC Material
name = openmc_material._name
name = openmc_material.name
opencg_material = opencg.Material(material_id=material_id, name=name)
# Add the OpenMC Material to the global collection of all OpenMC Materials
@ -123,14 +123,14 @@ def get_openmc_material(opencg_material):
raise ValueError(msg)
global OPENMC_MATERIALS
material_id = opencg_material._id
material_id = opencg_material.id
# If this Material was already created, use it
if material_id in OPENMC_MATERIALS:
return OPENMC_MATERIALS[material_id]
# Create an OpenMC Material to represent this OpenCG Material
name = opencg_material._name
name = opencg_material.name
openmc_material = openmc.Material(material_id=material_id, name=name)
# Add the OpenMC Material to the global collection of all OpenMC Materials
@ -168,8 +168,8 @@ def is_opencg_surface_compatible(opencg_surface):
'since "{0}" is not a Surface'.format(opencg_surface)
raise ValueError(msg)
if opencg_surface._type in ['x-squareprism',
'y-squareprism', 'z-squareprism']:
if opencg_surface.type in ['x-squareprism',
'y-squareprism', 'z-squareprism']:
return False
else:
return True
@ -196,59 +196,59 @@ def get_opencg_surface(openmc_surface):
raise ValueError(msg)
global OPENCG_SURFACES
surface_id = openmc_surface._id
surface_id = openmc_surface.id
# If this Material was already created, use it
if surface_id in OPENCG_SURFACES:
return OPENCG_SURFACES[surface_id]
# Create an OpenCG Surface to represent this OpenMC Surface
name = openmc_surface._name
name = openmc_surface.name
# Correct for OpenMC's syntax for Surfaces dividing Cells
boundary = openmc_surface._boundary_type
boundary = openmc_surface.boundary_type
if boundary == 'transmission':
boundary = 'interface'
opencg_surface = None
if openmc_surface._type == 'plane':
A = openmc_surface._coeffs['A']
B = openmc_surface._coeffs['B']
C = openmc_surface._coeffs['C']
D = openmc_surface._coeffs['D']
if openmc_surface.type == 'plane':
A = openmc_surface.a
B = openmc_surface.b
C = openmc_surface.c
D = openmc_surface.d
opencg_surface = opencg.Plane(surface_id, name, boundary, A, B, C, D)
elif openmc_surface._type == 'x-plane':
x0 = openmc_surface._coeffs['x0']
elif openmc_surface.type == 'x-plane':
x0 = openmc_surface.x0
opencg_surface = opencg.XPlane(surface_id, name, boundary, x0)
elif openmc_surface._type == 'y-plane':
y0 = openmc_surface._coeffs['y0']
elif openmc_surface.type == 'y-plane':
y0 = openmc_surface.y0
opencg_surface = opencg.YPlane(surface_id, name, boundary, y0)
elif openmc_surface._type == 'z-plane':
z0 = openmc_surface._coeffs['z0']
elif openmc_surface.type == 'z-plane':
z0 = openmc_surface.z0
opencg_surface = opencg.ZPlane(surface_id, name, boundary, z0)
elif openmc_surface._type == 'x-cylinder':
y0 = openmc_surface._coeffs['y0']
z0 = openmc_surface._coeffs['z0']
R = openmc_surface._coeffs['R']
elif openmc_surface.type == 'x-cylinder':
y0 = openmc_surface.y0
z0 = openmc_surface.z0
R = openmc_surface.r
opencg_surface = opencg.XCylinder(surface_id, name,
boundary, y0, z0, R)
elif openmc_surface._type == 'y-cylinder':
x0 = openmc_surface._coeffs['x0']
z0 = openmc_surface._coeffs['z0']
R = openmc_surface._coeffs['R']
elif openmc_surface.type == 'y-cylinder':
x0 = openmc_surface.x0
z0 = openmc_surface.z0
R = openmc_surface.r
opencg_surface = opencg.YCylinder(surface_id, name,
boundary, x0, z0, R)
elif openmc_surface._type == 'z-cylinder':
x0 = openmc_surface._coeffs['x0']
y0 = openmc_surface._coeffs['y0']
R = openmc_surface._coeffs['R']
elif openmc_surface.type == 'z-cylinder':
x0 = openmc_surface.x0
y0 = openmc_surface.y0
R = openmc_surface.r
opencg_surface = opencg.ZCylinder(surface_id, name,
boundary, x0, y0, R)
@ -282,61 +282,61 @@ def get_openmc_surface(opencg_surface):
raise ValueError(msg)
global openmc_surface
surface_id = opencg_surface._id
surface_id = opencg_surface.id
# If this Surface was already created, use it
if surface_id in OPENMC_SURFACES:
return OPENMC_SURFACES[surface_id]
# Create an OpenMC Surface to represent this OpenCG Surface
name = opencg_surface._name
name = opencg_surface.name
# Correct for OpenMC's syntax for Surfaces dividing Cells
boundary = opencg_surface._boundary_type
boundary = opencg_surface.boundary_type
if boundary == 'interface':
boundary = 'transmission'
if opencg_surface._type == 'plane':
A = opencg_surface._coeffs['A']
B = opencg_surface._coeffs['B']
C = opencg_surface._coeffs['C']
D = opencg_surface._coeffs['D']
if opencg_surface.type == 'plane':
A = opencg_surface.a
B = opencg_surface.b
C = opencg_surface.c
D = opencg_surface.d
openmc_surface = openmc.Plane(surface_id, boundary, A, B, C, D, name)
elif opencg_surface._type == 'x-plane':
x0 = opencg_surface._coeffs['x0']
elif opencg_surface.type == 'x-plane':
x0 = opencg_surface.x0
openmc_surface = openmc.XPlane(surface_id, boundary, x0, name)
elif opencg_surface._type == 'y-plane':
y0 = opencg_surface._coeffs['y0']
elif opencg_surface.type == 'y-plane':
y0 = opencg_surface.y0
openmc_surface = openmc.YPlane(surface_id, boundary, y0, name)
elif opencg_surface._type == 'z-plane':
z0 = opencg_surface._coeffs['z0']
elif opencg_surface.type == 'z-plane':
z0 = opencg_surface.z0
openmc_surface = openmc.ZPlane(surface_id, boundary, z0, name)
elif opencg_surface._type == 'x-cylinder':
y0 = opencg_surface._coeffs['y0']
z0 = opencg_surface._coeffs['z0']
R = opencg_surface._coeffs['R']
elif opencg_surface.type == 'x-cylinder':
y0 = opencg_surface.y0
z0 = opencg_surface.z0
R = opencg_surface.r
openmc_surface = openmc.XCylinder(surface_id, boundary, y0, z0, R, name)
elif opencg_surface._type == 'y-cylinder':
x0 = opencg_surface._coeffs['x0']
z0 = opencg_surface._coeffs['z0']
R = opencg_surface._coeffs['R']
elif opencg_surface.type == 'y-cylinder':
x0 = opencg_surface.x0
z0 = opencg_surface.z0
R = opencg_surface.r
openmc_surface = openmc.YCylinder(surface_id, boundary, x0, z0, R, name)
elif opencg_surface._type == 'z-cylinder':
x0 = opencg_surface._coeffs['x0']
y0 = opencg_surface._coeffs['y0']
R = opencg_surface._coeffs['R']
elif opencg_surface.type == 'z-cylinder':
x0 = opencg_surface.x0
y0 = opencg_surface.y0
R = opencg_surface.r
openmc_surface = openmc.ZCylinder(surface_id, boundary, x0, y0, R, name)
else:
msg = 'Unable to create an OpenMC Surface from an OpenCG ' \
'Surface of type "{0}" since it is not a compatible ' \
'Surface type in OpenMC'.format(opencg_surface._type)
'Surface type in OpenMC'.format(opencg_surface.type)
raise ValueError(msg)
# Add the OpenMC Surface to the global collection of all OpenMC Surfaces
@ -373,20 +373,20 @@ def get_compatible_opencg_surfaces(opencg_surface):
raise ValueError(msg)
global OPENMC_SURFACES
surface_id = opencg_surface._id
surface_id = opencg_surface.id
# If this Surface was already created, use it
if surface_id in OPENMC_SURFACES:
return OPENMC_SURFACES[surface_id]
# Create an OpenMC Surface to represent this OpenCG Surface
name = opencg_surface._name
boundary = opencg_surface._boundary_type
name = opencg_surface.name
boundary = opencg_surface.boundary_type
if opencg_surface._type == 'x-squareprism':
y0 = opencg_surface._coeffs['y0']
z0 = opencg_surface._coeffs['z0']
R = opencg_surface._coeffs['R']
if opencg_surface.type == 'x-squareprism':
y0 = opencg_surface.y0
z0 = opencg_surface.z0
R = opencg_surface.r
# Create a list of the four planes we need
left = opencg.YPlane(name=name, boundary=boundary, y0=y0-R)
@ -395,10 +395,10 @@ def get_compatible_opencg_surfaces(opencg_surface):
top = opencg.ZPlane(name=name, boundary=boundary, z0=z0+R)
surfaces = [left, right, bottom, top]
elif opencg_surface._type == 'y-squareprism':
x0 = opencg_surface._coeffs['x0']
z0 = opencg_surface._coeffs['z0']
R = opencg_surface._coeffs['R']
elif opencg_surface.type == 'y-squareprism':
x0 = opencg_surface.x0
z0 = opencg_surface.z0
R = opencg_surface.r
# Create a list of the four planes we need
left = opencg.XPlane(name=name, boundary=boundary, x0=x0-R)
@ -407,10 +407,10 @@ def get_compatible_opencg_surfaces(opencg_surface):
top = opencg.ZPlane(name=name, boundary=boundary, z0=z0+R)
surfaces = [left, right, bottom, top]
elif opencg_surface._type == 'z-squareprism':
x0 = opencg_surface._coeffs['x0']
y0 = opencg_surface._coeffs['y0']
R = opencg_surface._coeffs['R']
elif opencg_surface.type == 'z-squareprism':
x0 = opencg_surface.x0['x0']
y0 = opencg_surface.y0['y0']
R = opencg_surface.r['R']
# Create a list of the four planes we need
left = opencg.XPlane(name=name, boundary=boundary, x0=x0-R)
@ -422,7 +422,7 @@ def get_compatible_opencg_surfaces(opencg_surface):
else:
msg = 'Unable to create a compatible OpenMC Surface an OpenCG ' \
'Surface of type "{0}" since it already a compatible ' \
'Surface type in OpenMC'.format(opencg_surface._type)
'Surface type in OpenMC'.format(opencg_surface.type)
raise ValueError(msg)
# Add the OpenMC Surface(s) to the global collection of all OpenMC Surfaces
@ -455,37 +455,37 @@ def get_opencg_cell(openmc_cell):
raise ValueError(msg)
global OPENCG_CELLS
cell_id = openmc_cell._id
cell_id = openmc_cell.id
# If this Cell was already created, use it
if cell_id in OPENCG_CELLS:
return OPENCG_CELLS[cell_id]
# Create an OpenCG Cell to represent this OpenMC Cell
name = openmc_cell._name
name = openmc_cell.name
opencg_cell = opencg.Cell(cell_id, name)
fill = openmc_cell._fill
fill = openmc_cell.fill
if (openmc_cell._type == 'normal'):
opencg_cell.setFill(get_opencg_material(fill))
elif (openmc_cell._type == 'fill'):
opencg_cell.setFill(get_opencg_universe(fill))
if (openmc_cell.fill_type == 'material'):
opencg_cell.fill = get_opencg_material(fill)
elif (openmc_cell.fill_type == 'universe'):
opencg_cell.fill = get_opencg_universe(fill)
else:
opencg_cell.setFill(get_opencg_lattice(fill))
opencg_cell.fill = get_opencg_lattice(fill)
if openmc_cell._rotation is not None:
opencg_cell.setRotation(openmc_cell._rotation)
if openmc_cell.rotation is not None:
opencg_cell.rotation = openmc_cell.rotation
if openmc_cell._translation is not None:
opencg_cell.setTranslation(openmc_cell._translation)
if openmc_cell.translation is not None:
opencg_cell.translation = openmc_cell.translation
surfaces = openmc_cell._surfaces
surfaces = openmc_cell.surfaces
for surface_id in surfaces:
surface = surfaces[surface_id][0]
halfspace = surfaces[surface_id][1]
opencg_cell.addSurface(get_opencg_surface(surface), halfspace)
opencg_cell.add_surface(get_opencg_surface(surface), halfspace)
# Add the OpenMC Cell to the global collection of all OpenMC Cells
OPENMC_CELLS[cell_id] = openmc_cell
@ -536,8 +536,8 @@ def get_compatible_opencg_cells(opencg_cell, opencg_surface, halfspace):
compatible_cells = []
# SquarePrism Surfaces
if opencg_surface._type in ['x-squareprism', 'y-squareprism',
'z-squareprism']:
if opencg_surface.type in ['x-squareprism', 'y-squareprism',
'z-squareprism']:
# Get the compatible Surfaces (XPlanes and YPlanes)
compatible_surfaces = get_compatible_opencg_surfaces(opencg_surface)
@ -546,10 +546,10 @@ def get_compatible_opencg_cells(opencg_cell, opencg_surface, halfspace):
# If Cell is inside SquarePrism, add "inside" of Surface halfspaces
if halfspace == -1:
opencg_cell.addSurface(compatible_surfaces[0], +1)
opencg_cell.addSurface(compatible_surfaces[1], -1)
opencg_cell.addSurface(compatible_surfaces[2], +1)
opencg_cell.addSurface(compatible_surfaces[3], -1)
opencg_cell.add_surface(compatible_surfaces[0], +1)
opencg_cell.add_surface(compatible_surfaces[1], -1)
opencg_cell.add_surface(compatible_surfaces[2], +1)
opencg_cell.add_surface(compatible_surfaces[3], -1)
compatible_cells.append(opencg_cell)
# If Cell is outside SquarePrism, add "outside" of Surface halfspaces
@ -631,12 +631,12 @@ def make_opencg_cells_compatible(opencg_universe):
raise ValueError(msg)
# Check all OpenCG Cells in this Universe for compatibility with OpenMC
opencg_cells = opencg_universe._cells
opencg_cells = opencg_universe.cells
for cell_id, opencg_cell in opencg_cells.items():
# Check each of the OpenCG Surfaces for OpenMC compatibility
surfaces = opencg_cell._surfaces
surfaces = opencg_cell.surfaces
for surface_id in surfaces:
surface = surfaces[surface_id][0]
@ -659,7 +659,7 @@ def make_opencg_cells_compatible(opencg_universe):
opencg_universe.removeCell(opencg_cell)
# Add the compatible OpenCG Cells to the Universe
opencg_universe.addCells(cells)
opencg_universe.add_cells(cells)
# Make recursive call to look at the updated state of the
# OpenCG Universe and return
@ -690,34 +690,34 @@ def get_openmc_cell(opencg_cell):
raise ValueError(msg)
global OPENMC_CELLS
cell_id = opencg_cell._id
cell_id = opencg_cell.id
# If this Cell was already created, use it
if cell_id in OPENMC_CELLS:
return OPENMC_CELLS[cell_id]
# Create an OpenCG Cell to represent this OpenMC Cell
name = opencg_cell._name
name = opencg_cell.name
openmc_cell = openmc.Cell(cell_id, name)
fill = opencg_cell._fill
fill = opencg_cell.fill
if (opencg_cell._type == 'universe'):
if (opencg_cell.type == 'universe'):
openmc_cell.fill = get_openmc_universe(fill)
elif (opencg_cell._type == 'lattice'):
elif (opencg_cell.type == 'lattice'):
openmc_cell.fill = get_openmc_lattice(fill)
else:
openmc_cell.fill = get_openmc_material(fill)
if opencg_cell._rotation:
rotation = np.asarray(opencg_cell._rotation, dtype=np.int)
if opencg_cell.rotation:
rotation = np.asarray(opencg_cell.rotation, dtype=np.int)
openmc_cell.rotation = rotation
if opencg_cell._translation:
translation = np.asarray(opencg_cell._translation, dtype=np.float64)
openmc_cell.setTranslation(translation)
if opencg_cell.translation:
translation = np.asarray(opencg_cell.translation, dtype=np.float64)
openmc_cell.translation = translation
surfaces = opencg_cell._surfaces
surfaces = opencg_cell.surfaces
for surface_id in surfaces:
surface = surfaces[surface_id][0]
@ -754,22 +754,22 @@ def get_opencg_universe(openmc_universe):
raise ValueError(msg)
global OPENCG_UNIVERSES
universe_id = openmc_universe._id
universe_id = openmc_universe.id
# If this Universe was already created, use it
if universe_id in OPENCG_UNIVERSES:
return OPENCG_UNIVERSES[universe_id]
# Create an OpenCG Universe to represent this OpenMC Universe
name = openmc_universe._name
name = openmc_universe.name
opencg_universe = opencg.Universe(universe_id, name)
# Convert all OpenMC Cells in this Universe to OpenCG Cells
openmc_cells = openmc_universe._cells
openmc_cells = openmc_universe.cells
for cell_id, openmc_cell in openmc_cells.items():
opencg_cell = get_opencg_cell(openmc_cell)
opencg_universe.addCell(opencg_cell)
opencg_universe.add_cell(opencg_cell)
# Add the OpenMC Universe to the global collection of all OpenMC Universes
OPENMC_UNIVERSES[universe_id] = openmc_universe
@ -801,7 +801,7 @@ def get_openmc_universe(opencg_universe):
raise ValueError(msg)
global OPENMC_UNIVERSES
universe_id = opencg_universe._id
universe_id = opencg_universe.id
# If this Universe was already created, use it
if universe_id in OPENMC_UNIVERSES:
@ -811,11 +811,11 @@ def get_openmc_universe(opencg_universe):
make_opencg_cells_compatible(opencg_universe)
# Create an OpenMC Universe to represent this OpenCSg Universe
name = opencg_universe._name
name = opencg_universe.name
openmc_universe = openmc.Universe(universe_id, name)
# Convert all OpenCG Cells in this Universe to OpenMC Cells
opencg_cells = opencg_universe._cells
opencg_cells = opencg_universe.cells
for cell_id, opencg_cell in opencg_cells.items():
openmc_cell = get_openmc_cell(opencg_cell)
@ -851,7 +851,7 @@ def get_opencg_lattice(openmc_lattice):
raise ValueError(msg)
global OPENCG_LATTICES
lattice_id = openmc_lattice._id
lattice_id = openmc_lattice.id
# If this Lattice was already created, use it
if lattice_id in OPENCG_LATTICES:
@ -888,18 +888,18 @@ def get_opencg_lattice(openmc_lattice):
for z in range(dimension[2]):
for y in range(dimension[1]):
for x in range(dimension[0]):
universe_id = universes[x][dimension[1]-y-1][z]._id
universe_id = universes[x][dimension[1]-y-1][z].id
universe_array[z][y][x] = unique_universes[universe_id]
opencg_lattice = opencg.Lattice(lattice_id, name)
opencg_lattice.setDimension(dimension)
opencg_lattice.setWidth(pitch)
opencg_lattice.setUniverses(universe_array)
opencg_lattice.dimension = dimension
opencg_lattice.width = pitch
opencg_lattice.universes = universe_array
offset = np.array(lower_left, dtype=np.float64) - \
((np.array(pitch, dtype=np.float64) *
np.array(dimension, dtype=np.float64))) / -2.0
opencg_lattice.setOffset(offset)
opencg_lattice.offset = offset
# Add the OpenMC Lattice to the global collection of all OpenMC Lattices
OPENMC_LATTICES[lattice_id] = openmc_lattice
@ -931,23 +931,23 @@ def get_openmc_lattice(opencg_lattice):
raise ValueError(msg)
global OPENMC_LATTICES
lattice_id = opencg_lattice._id
lattice_id = opencg_lattice.id
# If this Lattice was already created, use it
if lattice_id in OPENMC_LATTICES:
return OPENMC_LATTICES[lattice_id]
dimension = opencg_lattice._dimension
width = opencg_lattice._width
offset = opencg_lattice._offset
universes = opencg_lattice._universes
dimension = opencg_lattice.dimension
width = opencg_lattice.width
offset = opencg_lattice.offset
universes = opencg_lattice.universes
# Initialize an empty array for the OpenMC nested Universes in this Lattice
universe_array = np.ndarray(tuple(np.array(dimension)),
dtype=openmc.Universe)
# Create OpenMC Universes for each unique nested Universe in this Lattice
unique_universes = opencg_lattice.getUniqueUniverses()
unique_universes = opencg_lattice.get_unique_universes()
for universe_id, universe in unique_universes.items():
unique_universes[universe_id] = get_openmc_universe(universe)
@ -956,7 +956,7 @@ def get_openmc_lattice(opencg_lattice):
for z in range(dimension[2]):
for y in range(dimension[1]):
for x in range(dimension[0]):
universe_id = universes[z][y][x]._id
universe_id = universes[z][y][x].id
universe_array[x][y][z] = unique_universes[universe_id]
# Reverse y-dimension in array to match ordering in OpenCG
@ -1011,12 +1011,12 @@ def get_opencg_geometry(openmc_geometry):
OPENMC_LATTICES.clear()
OPENCG_LATTICES.clear()
openmc_root_universe = openmc_geometry._root_universe
openmc_root_universe = openmc_geometry.root_universe
opencg_root_universe = get_opencg_universe(openmc_root_universe)
opencg_geometry = opencg.Geometry()
opencg_geometry.setRootUniverse(opencg_root_universe)
opencg_geometry.initializeCellOffsets()
opencg_geometry.root_universe = opencg_root_universe
opencg_geometry.initialize_cell_offsets()
return opencg_geometry
@ -1043,11 +1043,11 @@ def get_openmc_geometry(opencg_geometry):
# Deep copy the goemetry since it may be modified to make all Surfaces
# compatible with OpenMC's specifications
opencg_geometry.assignAutoIds()
opencg_geometry.assign_auto_ids()
opencg_geometry = copy.deepcopy(opencg_geometry)
# Update Cell bounding boxes in Geometry
opencg_geometry.updateBoundingBoxes()
opencg_geometry.update_bounding_boxes()
# Clear dictionaries and auto-generated ID
OPENMC_SURFACES.clear()
@ -1060,14 +1060,14 @@ def get_openmc_geometry(opencg_geometry):
OPENCG_LATTICES.clear()
# Make the entire geometry "compatible" before assigning auto IDs
universes = opencg_geometry.getAllUniverses()
universes = opencg_geometry.get_all_universes()
for universe_id, universe in universes.items():
if not isinstance(universe, opencg.Lattice):
make_opencg_cells_compatible(universe)
opencg_geometry.assignAutoIds()
opencg_geometry.assign_auto_ids()
opencg_root_universe = opencg_geometry._root_universe
opencg_root_universe = opencg_geometry.root_universe
openmc_root_universe = get_openmc_universe(opencg_root_universe)
openmc_geometry = openmc.Geometry()

View file

@ -33,42 +33,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 +80,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
"""
@ -104,7 +104,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):
@ -457,16 +457,23 @@ 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
if self.summary is None:
return False
else:
return 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.
@ -480,7 +487,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).
@ -534,8 +541,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:
@ -622,4 +637,4 @@ class StatePoint(object):
material_ids.append(summary.materials[bin].id)
filter.bins = material_ids
self._with_summary = True
self._summary = summary

View file

@ -72,6 +72,9 @@ class Summary(object):
nuc_densities = self._f['materials'][key]['nuclide_densities'][...]
nuclides = self._f['materials'][key]['nuclides'].value
# Create the Material
material = openmc.Material(material_id=material_id, name=name)
# Read the names of the S(a,b) tables for this Material and add them
if 'sab_names' in self._f['materials'][key]:
sab_tables = self._f['materials'][key]['sab_names'].value
@ -79,11 +82,8 @@ class Summary(object):
name, xs = sab_table.decode().split('.')
material.add_s_alpha_beta(name, xs)
# Create the Material
material = openmc.Material(material_id=material_id, name=name)
# 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):

View file

@ -101,8 +101,11 @@ class Surface(object):
@name.setter
def name(self, name):
check_type('surface name', name, basestring)
self._name = name
if name is not None:
check_type('surface name', name, basestring)
self._name = name
else:
self._name = None
@boundary_type.setter
def boundary_type(self, boundary_type):
@ -272,7 +275,7 @@ class XPlane(Plane):
@property
def x0(self):
return self.coeff['x0']
return self.coeffs['x0']
@x0.setter
def x0(self, x0):

File diff suppressed because it is too large Load diff

View file

@ -1,12 +0,0 @@
from checkvalue import *
from checkvalue import _isinstance
import numpy as np
zs = np.zeros((2,))
print _isinstance(zs[0], Integral)
print _isinstance(zs[0], Real)
print _isinstance(zs[0], (Integral, Real))
print check_iterable_type('thing', zs, (Real, Integral))

View file

@ -85,8 +85,15 @@ class Cell(object):
return self._fill
@property
def type(self):
return self._fill
def fill_type(self):
if isinstance(self.fill, openmc.Material):
return 'material'
elif isinstance(self.fill, openmc.Universe):
return 'universe'
elif isinstance(self.fill, openmc.Lattice):
return 'lattice'
else:
return None
@property
def surfaces(self):
@ -117,8 +124,11 @@ class Cell(object):
@name.setter
def name(self, name):
cv.check_type('cell name', name, basestring)
self._name = name
if name is not None:
cv.check_type('cell name', name, basestring)
self._name = name
else:
self._name = None
@fill.setter
def fill(self, fill):
@ -438,8 +448,11 @@ class Universe(object):
@name.setter
def name(self, name):
cv.check_type('universe name', name, basestring)
self._name = name
if name is not None:
cv.check_type('universe name', name, basestring)
self._name = name
else:
self._name = None
def add_cell(self, cell):
"""Add a cell to the universe.
@ -677,8 +690,11 @@ class Lattice(object):
@name.setter
def name(self, name):
cv.check_type('lattice name', name, basestring)
self._name = name
if name is not None:
cv.check_type('lattice name', name, basestring)
self._name = name
else:
self._name = None
@outer.setter
def outer(self, outer):

View file

@ -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

View file

@ -33,6 +33,7 @@ contains
integer :: i_nuclide ! index into nuclides array
integer :: i_sab ! index into sab_tables array
integer :: j ! index in mat % i_sab_nuclides
integer :: u ! index into logarithmic mapping array
real(8) :: atom_density ! atom density of a nuclide
logical :: check_sab ! should we check for S(a,b) table?
type(Material), pointer :: mat ! current material
@ -50,9 +51,13 @@ contains
mat => materials(p % material)
! Find energy index on global or material unionized grid
if (grid_method == GRID_MAT_UNION) &
call find_energy_index(p % E, p % material)
! Find energy index on energy grid
u = 0
if (grid_method == GRID_MAT_UNION) then
call find_energy_index(p % E, p % material)
else if (grid_method == GRID_LOGARITHM) then
u = int(log(p % E/1.0e-11_8)/log_spacing)
end if
! Determine if this material has S(a,b) tables
check_sab = (mat % n_sab > 0)
@ -94,9 +99,9 @@ contains
! Calculate microscopic cross section for this nuclide
if (p % E /= micro_xs(i_nuclide) % last_E) then
call calculate_nuclide_xs(i_nuclide, i_sab, p % E, p % material, i)
call calculate_nuclide_xs(i_nuclide, i_sab, p % E, p % material, i, u)
else if (i_sab /= micro_xs(i_nuclide) % last_index_sab) then
call calculate_nuclide_xs(i_nuclide, i_sab, p % E, p % material, i)
call calculate_nuclide_xs(i_nuclide, i_sab, p % E, p % material, i, u)
end if
! ========================================================================
@ -137,16 +142,16 @@ contains
! given index in the nuclides array at the energy of the given particle
!===============================================================================
subroutine calculate_nuclide_xs(i_nuclide, i_sab, E, i_mat, i_nuc_mat)
subroutine calculate_nuclide_xs(i_nuclide, i_sab, E, i_mat, i_nuc_mat, u)
integer, intent(in) :: i_nuclide ! index into nuclides array
integer, intent(in) :: i_sab ! index into sab_tables array
integer, intent(in) :: i_mat ! index into materials array
integer, intent(in) :: i_nuc_mat ! index into nuclides array for a material
integer, intent(in) :: u ! index into logarithmic mapping array
integer :: i_grid ! index on nuclide energy grid
integer :: i_low ! lower logarithmic mapping index
integer :: i_high ! upper logarithmic mapping index
integer :: u ! index into logarithmic mapping array
real(8), intent(in) :: E ! energy
real(8) :: f ! interp factor on nuclide energy grid
type(Nuclide), pointer :: nuc
@ -173,7 +178,6 @@ contains
else
! Determine bounding indices based on which equal log-spaced interval
! the energy is in
u = int(log(E/1.0e-11_8)/log_spacing)
i_low = nuc % grid_index(u)
i_high = nuc % grid_index(u + 1) + 1

View file

@ -28,7 +28,6 @@ contains
integer :: L
integer :: R
integer :: n_iteration
real(8) :: testval
L = 1
R = n
@ -39,22 +38,11 @@ contains
n_iteration = 0
do while (R - L > 1)
! Check boundaries
if (val > array(L) .and. val < array(L+1)) then
array_index = L
return
elseif (val > array(R-1) .and. val < array(R)) then
array_index = R - 1
return
end if
! Find values at midpoint
array_index = L + (R - L)/2
testval = array(array_index)
if (val >= testval) then
if (val >= array(array_index)) then
L = array_index
elseif (val < testval) then
else
R = array_index
end if
@ -80,7 +68,6 @@ contains
integer :: L
integer :: R
integer :: n_iteration
real(8) :: testval
L = 1
R = n
@ -91,22 +78,11 @@ contains
n_iteration = 0
do while (R - L > 1)
! Check boundaries
if (val > array(L) .and. val < array(L+1)) then
array_index = L
return
elseif (val > array(R-1) .and. val < array(R)) then
array_index = R - 1
return
end if
! Find values at midpoint
array_index = L + (R - L)/2
testval = array(array_index)
if (val >= testval) then
if (val >= array(array_index)) then
L = array_index
elseif (val < testval) then
else
R = array_index
end if
@ -132,7 +108,6 @@ contains
integer :: L
integer :: R
integer :: n_iteration
real(8) :: testval
L = 1
R = n
@ -143,22 +118,11 @@ contains
n_iteration = 0
do while (R - L > 1)
! Check boundaries
if (val > array(L) .and. val < array(L+1)) then
array_index = L
return
elseif (val > array(R-1) .and. val < array(R)) then
array_index = R - 1
return
end if
! Find values at midpoint
array_index = L + (R - L)/2
testval = array(array_index)
if (val >= testval) then
if (val >= array(array_index)) then
L = array_index
elseif (val < testval) then
else
R = array_index
end if

View file

@ -126,7 +126,10 @@ class Test(object):
# Check for MPI
if self.mpi:
self.fc = os.path.join(MPI_DIR, 'bin', 'mpifort')
if os.path.exists(os.path.join(MPI_DIR, 'bin', 'mpifort')):
self.fc = os.path.join(MPI_DIR, 'bin', 'mpifort')
else:
self.fc = os.path.join(MPI_DIR, 'bin', 'mpif90')
else:
self.fc = FC