mirror of
https://github.com/openmc-dev/openmc.git
synced 2026-07-26 05:05:30 -04:00
Merge branch 'mgxs' into iso-lab
This commit is contained in:
commit
c4b14a5ef8
29 changed files with 6812 additions and 1396 deletions
9
.gitignore
vendored
9
.gitignore
vendored
|
|
@ -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
|
||||
2323
docs/source/pythonapi/examples/multi-group-cross-sections.ipynb
Normal file
2323
docs/source/pythonapi/examples/multi-group-cross-sections.ipynb
Normal file
File diff suppressed because one or more lines are too long
|
|
@ -0,0 +1,11 @@
|
|||
====================================
|
||||
Multi-Group Cross Section Generation
|
||||
====================================
|
||||
|
||||
.. only:: html
|
||||
|
||||
.. notebook:: multi-group-cross-sections.ipynb
|
||||
|
||||
.. only:: latex
|
||||
|
||||
IPython notebooks must be viewed in the online HTML documentation.
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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/
|
||||
|
|
|
|||
|
|
@ -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 *
|
||||
|
|
|
|||
204
openmc/cross.py
204
openmc/cross.py
|
|
@ -1,9 +1,20 @@
|
|||
import sys
|
||||
|
||||
from openmc import Filter, Nuclide
|
||||
from openmc.filter import _FILTER_TYPES
|
||||
import openmc.checkvalue as cv
|
||||
|
||||
|
||||
if sys.version_info[0] >= 3:
|
||||
basestring = str
|
||||
|
||||
# Acceptable tally arithmetic binary operations
|
||||
TALLY_ARITHMETIC_OPS = ['+', '-', '*', '/', '^']
|
||||
|
||||
|
||||
class CrossScore(object):
|
||||
"""A special-purpose tally score used to encapsulate all combinations of two
|
||||
tally's scores as a outer product for tally arithmetic.
|
||||
tally's scores as an outer product for tally arithmetic.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
|
|
@ -40,6 +51,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
|
||||
|
|
@ -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))
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
494
openmc/filter.py
494
openmc/filter.py
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
2
openmc/mgxs/__init__.py
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
from groups import EnergyGroups
|
||||
from mgxs import *
|
||||
275
openmc/mgxs/groups.py
Normal file
275
openmc/mgxs/groups.py
Normal 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
2050
openmc/mgxs/mgxs.py
Normal file
File diff suppressed because it is too large
Load diff
|
|
@ -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))
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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):
|
||||
|
|
|
|||
|
|
@ -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):
|
||||
|
|
|
|||
1134
openmc/tallies.py
1134
openmc/tallies.py
File diff suppressed because it is too large
Load diff
|
|
@ -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))
|
||||
|
|
@ -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):
|
||||
|
|
|
|||
2
setup.py
2
setup.py
|
|
@ -11,7 +11,7 @@ except ImportError:
|
|||
|
||||
kwargs = {'name': 'openmc',
|
||||
'version': '0.7.0',
|
||||
'packages': ['openmc'],
|
||||
'packages': ['openmc', 'openmc.mgxs'],
|
||||
'scripts': glob.glob('scripts/openmc-*'),
|
||||
|
||||
# Metadata
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue