├── ANStransaction.pdf ├── LICENSE ├── README.md ├── getfilename.py ├── groups.py ├── main.py ├── mgxs.py ├── optimize.py ├── testreactor_slab1_inp.py ├── testreactor_slab2_inp.py └── yakxs.py /ANStransaction.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lanl/TOGA/66350a068ac3788be4140ed9e70c502ba27c6cd0/ANStransaction.pdf -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | BSD 3-Clause License 2 | 3 | Copyright (c) 2021, Los Alamos National Laboratory 4 | All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions are met: 8 | 9 | 1. Redistributions of source code must retain the above copyright notice, this 10 | list of conditions and the following disclaimer. 11 | 12 | 2. Redistributions in binary form must reproduce the above copyright notice, 13 | this list of conditions and the following disclaimer in the documentation 14 | and/or other materials provided with the distribution. 15 | 16 | 3. Neither the name of the copyright holder nor the names of its 17 | contributors may be used to endorse or promote products derived from 18 | this software without specific prior written permission. 19 | 20 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 21 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 23 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 24 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 26 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 27 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 28 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # TOGA 2 | Tool for Optimization and Group-structure Analysis of nuclear multi-group cross sections 3 | 4 | 5 | The flexible cross-section generation tool is Python-based software that runs the open-source Monte Carlo code OpenMC (https://docs.openmc.org/en/stable/ ) to generate and optimize crosssections for any reactor geometry. Please follow directions on the OpenMC documentation page for installation instructions. In addition, please set the environment variable “OPENMC_MG_CROSS_SECTIONS” equal to mgxs.h5. The optimization aims to choose energy group structures as well as scattering representation that maximize accuracy with respect to continuous-energy results while avoiding significant computational expense. It then outputs these cross-sections in an ISOXML format readable by the Idaho National Lab code suite MOOSE (Olin William Calvin, Mark D DeHart, “Architecture for the Performance of Nuclear Fuel Depletion Calculations”, Idaho National Laboratory report, November 2019). 6 | 7 | The user should create geometry files and modify the main file to specify user preferences. To run code, simply run main.py in the same folder as the geometry file(s) and the rest of the source code. 8 | 9 | 10 | © 2021. Triad National Security, LLC. All rights reserved. 11 | This program was produced under U.S. Government contract 89233218CNA000001 for Los Alamos National Laboratory (LANL), which is operated by Triad National Security, LLC for the U.S. Department of Energy/National Nuclear Security Administration. All rights in the program are reserved by Triad National Security, LLC, and the U.S. Department of Energy/National Nuclear Security Administration. The Government is granted for itself and others acting on its behalf a nonexclusive, paid-up, irrevocable worldwide license in this material to reproduce, prepare derivative works, distribute copies to the public, perform publicly and display publicly, and to permit others to do so. 12 | 13 | 14 | This program is open source under the BSD-3 License. 15 | Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 16 | 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 17 | 18 | 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 19 | 20 | 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. 21 | 22 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 23 | -------------------------------------------------------------------------------- /getfilename.py: -------------------------------------------------------------------------------- 1 | class FileName: 2 | 3 | def __init__(self): 4 | self 5 | 6 | def get_filename(self, ending): 7 | 8 | import os, sys 9 | filenames = [] 10 | for i in os.listdir(os.getcwd()): 11 | if i.endswith(ending): 12 | filenames.append(i) 13 | else: 14 | continue 15 | 16 | filenames.sort() 17 | self.listfn=filenames 18 | -------------------------------------------------------------------------------- /groups.py: -------------------------------------------------------------------------------- 1 | # Class to define common group structures 2 | 3 | class Groups: 4 | 5 | def __init__(self): 6 | 7 | self.GroupStructures = {} 8 | 9 | def CASMO(self): 10 | 11 | print("Using the CASMO group structures") 12 | 13 | two_group = [0.0, 0.625, 2e7] 14 | 15 | three_group = [0.0, 0.625, 8.21e5, 2e7] 16 | 17 | four_group = [0.0, 0.625, 5.53e3, 8.21e5, 2e7] 18 | 19 | seven_group = [0.0, 5.8e-2, 0.14, 0.625, 4.0, 5.53e3, 8.21e5, 2e7] 20 | 21 | eight_group = [0.0, 5.8e-2, 0.14, 0.28, 0.625, 4.0, 5.53e3, 8.21e5, 2e7] 22 | 23 | nine_group = [0.0, 5.8e-2, 0.14, 0.625, 0.972, 1.15, 4.0, 5.53e3, 8.21e5, 2e7] 24 | 25 | twelve_group = [0.0, 3.e-2, 5.8e-2, 0.14, 0.28, 0.35, 0.625, 4.0, 4.8052e1, 26 | 5.53e3, 8.21e5, 2.231e6, 2e7] 27 | 28 | fourteen_group = [0.0, 3.e-2, 5.8e-2, 0.14, 0.28, 0.35, 0.625, 0.972, 1.15, 29 | 4.0, 4.8052e1, 5.53e3, 8.21e5, 2.231e6, 2e7] 30 | 31 | sixteen_group = [0.0, 3.e-2, 5.8e-2, 0.14, 0.28, 0.35, 0.625, 0.972, 1.02, 32 | 1.097, 1.15, 1.3, 4.0, 5.53e3, 8.21e5, 2.231e6, 2e7] 33 | 34 | eighteen_group = [0.0, 5.8e-2, 0.14, 0.28, 0.625, 0.972, 1.15, 1.855, 4.0, 35 | 9.877, 1.5968e1, 1.48728e2, 5.53e3, 9.118e3, 1.11e5, 5.e5, 8.21e5, 2.231e6, 36 | 2e7] 37 | 38 | twentythree_group = [0.0, 3.e-2, 5.8e-2, 0.14, 0.28, 0.35, 0.625, 1.02, 1.097, 39 | 1.855, 4.0, 9.877, 1.5968e1, 1.48728e2, 5.53e3, 9.118e3, 1.11e5, 5.e5, 8.21e5, 40 | 1.353e6, 2.231e6, 3.679e6, 6.0655e6, 2e7] 41 | 42 | twentyfive_group = [0.0, 3.e-2, 5.8e-2, 0.14, 0.28, 0.35, 0.625, 0.972, 1.02, 43 | 1.097, 1.15, 1.855, 4.0, 9.877, 1.5968e1, 1.48728e2, 5.53e3, 9.118e3, 1.11e5, 44 | 5.e5, 8.21e5, 1.353e6, 2.231e6, 3.679e6, 6.0655e6, 2e7] 45 | 46 | forty_group = [0.0, 1.5e-5, 3e-2, 4.2e-2, 5.8e-2, 8e-2, 1e-1, 1.4e-1, 1.8e-1, 47 | 2.2e-1, 2.8e-1, 3.5e-1, 0.625, 8.5e-1, 9.5e-1, 9.72e-1, 1.02, 1.097, 1.15, 48 | 1.3, 1.5, 1.855, 2.1, 2.6, 3.3, 4., 9.877, 1.5968e1, 2.77e1, 4.8052e1, 49 | 1.48728e2, 5.53e3, 9.118e3, 1.11e5, 5.e5, 8.21e5, 1.353e6, 2.231e6, 3.679e6, 50 | 6.0655e6, 2e7] 51 | 52 | seventy_group = [0.0, 1.5e-5, 5e-3, 1e-2, 1.5e-2, 2e-2, 2.5e-2, 3e-2, 3.5e-2, 53 | 4.2e-2, 5e-2, 5.8e-2, 6.7e-2, 8e-2, 1e-1, 1.4e-1, 1.8e-1, 2.2e-1, 2.5e-1, 54 | 2.8e-1, 3e-1, 3.2e-1, 3.5e-1, 4e-1, 5e-1, 0.625, 7.8e-1, 8.5e-1, 9.1e-1, 55 | 9.5e-1, 9.72e-1, 9.96e-1, 1.02, 1.045, 1.071, 1.097, 1.123, 1.15, 1.3, 1.5, 56 | 1.855, 2.1, 2.6, 3.3, 4, 9.877, 1.5968e1, 2.77e1, 4.8052e1, 7.55014e1, 57 | 1.48728e2, 3.67262e2, 9.06898e2, 2.23945e3, 3.5191e3, 5.53e3, 9.118e3, 58 | 1.503e4, 2.478e4, 4.085e4, 6.743e4, 1.11e5, 1.83e5, 3.025e5, 5e5, 8.21e5, 59 | 1.353e6, 2.231e6, 3.679e6, 6.0655e6, 2e7] 60 | 61 | self.GroupStructures = { 62 | 2: two_group, 63 | 3: three_group, 64 | 4: four_group, 65 | 7: seven_group, 66 | 8: eight_group, 67 | 9: nine_group, 68 | 12: twelve_group, 69 | 14: fourteen_group, 70 | 16: sixteen_group, 71 | 18: eighteen_group, 72 | 23: twentythree_group, 73 | 25: twentyfive_group, 74 | 40: forty_group, 75 | 70: seventy_group 76 | } 77 | 78 | def LANL(self): 79 | 80 | print("Using LANL group structures") 81 | 82 | LANL30 = [0.0, 1.52e-1, 4.14e-1, 1.13, 3.06, 8.32, 2.26e1, 6.14e1, 1.67e2, 83 | 4.54e2, 1.235e3, 3.35e3, 9.12e3, 2.48e4, 6.76e4, 1.84e5, 3.03e5, 5.e5, 8.23e5, 84 | 1.353e6, 1.738e6, 2.232e6, 2.865e6, 3.68e6, 6.07e6, 7.79e6, 1.e7, 1.2e7, 85 | 1.35e7, 1.5e7, 2.e7] 86 | 87 | LANL70 = [0.0, 1.0677e1, 6.14e1, 1.01301e2, 1.30073e2, 1.67e2, 2.14454e2, 88 | 2.75365e2, 3.53575e2, 4.54e2, 5.82947e2, 7.48518e2, 9.61117e2, 1.08909e3, 89 | 1.235e3, 1.58461e3, 1.7956e3, 2.03468e3, 2.3056e3, 2.61259e3, 2.96045e3, 90 | 3.35e3, 3.80129e3, 4.30743e3, 4.88095e3, 5.53084e3, 6.26727e3, 7.10174e3, 91 | 8.04733e3, 9.12e3, 1.03333e4, 1.17088e4, 1.32678e4, 1.50344e4, 1.70362e4, 92 | 1.93045e4, 2.18749e4, 2.48e4, 2.80879e4, 3.18278e4, 4.08677e4, 5.24752e4, 93 | 6.76e4, 8.6517e4, 1.1109e5, 1.42642e5, 1.84e5, 2.35178e5, 3.03e5, 3.87742e5, 94 | 4.39369e5, 4.8255e5, 5.64161e5, 6.39279e5, 7.24398e5, 8.23e5, 9.30145e5, 95 | 1.05399e6, 1.19433e6, 1.353e6, 1.738e6, 2.232e6, 2.865e6, 3.68e6, 4.72367e6, 96 | 6.07e6, 7.79e6, 1.e7, 1.2875e7, 1.65e7, 2.e7] 97 | 98 | LANL80 = [0.0, 1.52e-1, 4.14e-1, 1.13, 3.06, 8.32, 1.0677e1, 2.26e1, 6.14e1, 99 | 1.01301e2, 1.30073e2, 1.67e2, 2.14454e2, 2.75365e2, 3.53575e2, 4.54e2, 5.82947e2, 100 | 7.48518e2, 9.61117e2, 1.08909e3, 1.235e3, 1.58461e3, 1.7956e3, 2.03468e3, 101 | 2.3056e3, 2.61259e3, 2.96045e3, 3.35e3, 3.80129e3, 4.30743e3, 4.88095e3, 102 | 5.53084e3, 6.26727e3, 7.10174e3, 8.04733e3, 9.12e3, 1.03333e4, 1.17088e4, 103 | 1.32678e4, 1.50344e4, 1.70362e4, 1.93045e4, 2.18749e4, 2.48e4, 2.80879e4, 104 | 3.18278e4, 4.08677e4, 5.24752e4, 6.76e4, 8.6517e4, 1.1109e5, 1.42642e5, 105 | 1.84e5, 2.35178e5, 3.03e5, 3.87742e5, 4.39369e5, 4.8255e5, 5.e5, 5.64161e5, 106 | 6.39279e5, 7.24398e5, 8.23e5, 9.30145e5, 1.05399e6, 1.19433e6, 1.353e6, 107 | 1.738e6, 2.232e6, 2.865e6, 3.68e6, 4.72367e6, 6.07e6, 7.79e6, 1.e7, 1.2e7, 108 | 1.2875e7, 1.35e7, 1.5e7, 1.65e7, 2.e7] 109 | 110 | 111 | self.GroupStructures = { 112 | 30: LANL30, 113 | 70: LANL70, 114 | 80: LANL80 115 | } 116 | 117 | def XMAS(self): 118 | 119 | print("Using XMAS group structure and constituent WIMS-69 (for thermal systems) \ 120 | and APOLLO-99 (for fast systems)") 121 | 122 | WIMS_69 = [0.0, 5.e-3, 123 | 1.e-2, 1.5e-2, 2.e-2, 2.5e-2, 3.e-2, 3.5e-2, 4.2e-2, 5.e-2, 5.8e-2, 6.7e-2, 124 | 8.e-2, 1.00001e-1, 1.4e-1, 1.8e-1, 2.2e-1, 2.48e-1, 2.8e-1, 3.e-1, 3.2e-1, 125 | 3.5e-1, 4.e-1, 5.e-1, 6.25e-1, 7.8e-1, 8.5e-1, 9.1e-1, 9.5e-1, 9.72e-1, 126 | 9.96e-1, 1.02, 1.045, 1.071, 1.097, 1.12535, 1.15, 1.3, 1.5, 2.1, 2.6, 3.3, 127 | 4.0, 9.90555, 1.59283e1, 2.76077e1, 4.82516e1, 7.56736e1, 1.48625e2, 128 | 3.71703e2, 9.14242e2, 1.43382e3, 2.24867e3, 3.52662e3, 5.53084e3, 9.11882e3, 129 | 1.50344e4, 2.47875e4, 4.08677e4, 6.73795e4, 1.1109e5, 1.83156e5, 3.01974e5, 130 | 4.97871e5, 8.2085e5, 1.35335e6, 2.2313e6, 3.67879e6, 6.06531e6, 2.e7] 131 | 132 | APOLLO_104 = [0.0, 3.e-3, 6.9e-3, 133 | 7.7e-2, 9.5e-2, 134 | 1.15e-1, 1.34e-1, 1.6e-1, 1.89e-1, 3.145e-1, 135 | 3.91e-1, 4.33e-1, 4.85e-1, 5.4e-1, 7.05e-1, 7.9e-1, 136 | 8.6e-1, 9.3e-1, 9.86e-1, 137 | 1.035, 1.11, 1.17, 1.235, 1.3375, 1.37, 1.44498, 1.475, 138 | 1.59, 1.67, 1.755, 1.84, 1.93, 2.02, 2.13, 2.36, 2.55, 2.72, 2.76792, 3.38075, 139 | 4.12925, 5.04348, 5.34643, 6.16012, 7.52398, 8.315298, 9.18981, 1.12245e1, 140 | 1.37096e1, 1.94548e1, 2.26033e1, 2.49805e1, 3.05113e1, 3.37201e1, 3.72665e1, 141 | 4.0169e1, 4.55174e1, 5.1578e1, 5.55951e1, 6.79041e1, 9.16609e1, 1.36742e2, 142 | 2.03995e2, 3.04325e2, 4.53999e2, 6.77287e2, 7.48518e2, 1.01039e3, 1.2341e3, 143 | 1.50733e3, 2.03468e3, 3.35463e3, 5.00451e3, 7.46586e3, 1.11378e4, 1.66156e4, 144 | 2.73944e4, 2.9283e4, 3.69786e4, 5.51656e4, 8.22975e4, 1.22773e5, 2.47235e5, 145 | 2.73237e5, 4.07622e5, 4.50492e5, 5.50232e5, 6.08101e5, 9.0718e5, 1.00259e6, 146 | 1.10803e6, 1.22456e6, 1.65299e6, 2.01897e6, 2.46597e6, 3.01194e6, 4.49329e6, 147 | 5.48812e6, 6.7032e6, 8.18731e6, 1.e7, 1.16183e7, 1.38403e7, 1.49182e7, 1.73325e7, 148 | 2.e7] 149 | 150 | XMAS_172 = [0.0, 3.e-3, 5.e-3, 6.9e-3, 1.e-2, 1.5e-2, 2.e-2, 2.5e-2, 3.e-2, 151 | 3.5e-2, 4.2e-2, 5.e-2, 5.8e-2, 6.7e-2, 7.7e-2, 8.e-2, 9.5e-2, 1.00001e-1, 152 | 1.15e-1, 1.34e-1, 1.4e-1, 1.6e-1, 1.8e-1, 1.89e-1, 2.2e-1, 2.48e-1, 2.8e-1, 153 | 3.e-1, 3.145e-1, 3.2e-1, 3.5e-1, 3.91e-1, 4.e-1, 4.33e-1, 4.85e-1, 5.e-1, 154 | 5.4e-1, 6.25e-1, 7.05e-1, 7.8e-1, 7.9e-1, 8.5e-1, 8.6e-1, 9.1e-1, 9.3e-1, 155 | 9.5e-1, 9.72e-1, 9.86e-1, 9.96e-1, 1.02, 1.035, 1.045, 1.071, 1.097, 1.11, 156 | 1.12535, 1.15, 1.17, 1.235, 1.3, 1.3375, 1.37, 1.44498, 1.475, 1.5, 1.59, 1.67, 157 | 1.755, 1.84, 1.93, 2.02, 2.1, 2.13, 2.36, 2.55, 2.6, 2.72, 2.76792, 3.3, 3.38075, 158 | 4.0, 4.12925, 5.04348, 5.34643, 6.16012, 7.52398, 8.315298, 9.18981, 9.90555, 159 | 1.12245e1, 1.37096e1, 1.59283e1, 1.94548e1, 2.26033e1, 2.49805e1, 2.76077e1, 160 | 3.05113e1, 3.37201e1, 3.72665e1, 4.0169e1, 4.55174e1, 4.82516e1, 5.1578e1, 161 | 5.55951e1, 6.79041e1, 7.56736e1, 9.16609e1, 1.36742e2, 1.48625e2, 2.03995e2, 162 | 3.04325e2, 3.71703e2, 4.53999e2, 6.77287e2, 7.48518e2, 9.14242e2, 1.01039e3, 163 | 1.2341e3, 1.43382e3, 1.50733e3, 2.03468e3, 2.24867e3, 3.35463e3, 3.52662e3, 164 | 5.00451e3, 5.53084e3, 7.46586e3, 9.11882e3, 1.11378e4, 1.50344e4, 1.66156e4, 165 | 2.47875e4, 2.73944e4, 2.9283e4, 3.69786e4, 4.08677e4, 5.51656e4, 6.73795e4, 166 | 8.22975e4, 1.1109e5, 1.22773e5, 1.83156e5, 2.47235e5, 2.73237e5, 3.01974e5, 167 | 4.07622e5, 4.50492e5, 4.97871e5, 5.50232e5, 6.08101e5, 8.2085e5, 9.0718e5, 168 | 1.00259e6, 1.10803e6, 1.22456e6, 1.35335e6, 1.65299e6, 2.01897e6, 2.2313e6, 169 | 2.46597e6, 3.01194e6, 3.67879e6, 4.49329e6, 5.48812e6, 6.06531e6, 6.7032e6, 170 | 8.18731e6, 1.e7, 1.16183e7, 1.38403e7, 1.49182e7, 1.73325e7, 2.e7] 171 | 172 | self.GroupStructures = { 173 | 69: WIMS_69, 174 | 104: APOLLO_104, 175 | 172: XMAS_172 176 | } 177 | 178 | def ANL(self): 179 | 180 | print("Using ANL group structures") 181 | 182 | # NOTE: The energy group structures must all share group edges with the largest group 183 | # i.e. the smaller group structures must be sub-sets of the largest structure 184 | 185 | four_group = [0.0, 2.2603e1, 1.5846e3, 1.1109e5, 1.4191e7] #Modifed to be subset of 70 groups 186 | 187 | nine_group = [0.0, 5.0435, 4.54e2, 2.0347e3, 9.1188e3, 4.0868e4, 1.8316e5, 188 | 8.2085e5, 2.2313e6, 1.4191e7] 189 | 190 | thirtythree_group = [0.0, 4.1746e-1, 5.3158e-1, 3.9279, 8.3153, 1.371e1, 191 | 2.2603e1, 3.7267e1, 6.1442e1, 1.013e2, 1.6702e2, 2.7536e2, 4.54e2, 192 | 7.4852e2, 1.2341e3, 2.0347e3, 3.3546e3, 5.5308e3, 9.1188e3, 1.5034e4, 193 | 2.4787e4, 4.0868e4, 6.7379e4, 1.1109e5, 1.8316e5, 3.0197e5, 4.9787e5, 194 | 8.2085e5, 1.3534e6, 2.2313e6, 3.6788e6, 6.0653e6, 1.e7, 1.4191e7] 195 | 196 | seventy_group = [0.0, 4.1746e-1, 5.3158e-1, 6.8256e-1, 8.7642e-1, 197 | 1.1254, 1.445, 1.8554, 2.3824, 3.059, 3.9279, 5.0435, 6.4759, 8.3153, 198 | 1.0677e1, 1.371e1, 1.7603e1, 2.2603e1, 2.9023e1, 3.7267e1, 4.7851e1, 199 | 6.1442e1, 7.8893e1, 1.013e2, 1.3007e2, 1.6702e2, 2.1445e2, 2.7536e2, 200 | 3.5357e2, 4.54e2, 5.8295e2, 7.4852e2, 9.6112e2, 1.2341e3, 1.5846e3, 201 | 2.0347e3, 2.6126e3, 3.3546e3, 4.3074e3, 5.5308e3, 7.1017e3, 9.1188e3, 202 | 1.1709e4, 1.5034e4, 1.9305e4, 2.4787e4, 3.1828e4, 4.0868e4, 5.2475e4, 203 | 6.7379e4, 8.6517e4, 1.1109e5, 1.4264e5, 1.8316e5, 2.3518e5, 3.0197e5, 204 | 3.8774e5, 4.9787e5, 6.3928e5, 8.2085e5, 1.054e6, 1.3534e6, 1.7377e6, 205 | 2.2313e6, 2.865e6, 3.6788e6, 4.7237e6, 6.0653e6, 7.788e6, 1.e7, 1.4191e7] 206 | 207 | self.GroupStructures = { 208 | 4: four_group, 209 | 9: nine_group, 210 | 33: thirtythree_group, 211 | 70: seventy_group 212 | } 213 | 214 | def CUSTOM(self): 215 | 216 | print("Using custom group structures") 217 | 218 | # NOTE: The energy group structures must all share group edges with the largest group 219 | # i.e. the smaller group structures must be sub-sets of the largest structure 220 | 221 | two_group = [0.0, 0.625, 2e7] 222 | 223 | three_group = [0.0, 0.625, 8.21e5, 2e7] 224 | 225 | four_group = [0.0, 0.625, 5.53e3, 8.21e5, 2e7] 226 | 227 | self.GroupStructures = { 228 | 2: two_group, 229 | 3: three_group, 230 | 4: four_group 231 | } 232 | 233 | def Stauff(self): 234 | 235 | print("Using Stauff's group structure") 236 | 237 | nine_group = [0.0, 8.e-2, 1.8e-1, 6.25e-1, 1.3, 4., 1.4873e2, 9.118e3, 238 | 5.e5, 2.e7] 239 | 240 | self.GroupStructures = { 241 | 9: nine_group 242 | } 243 | -------------------------------------------------------------------------------- /main.py: -------------------------------------------------------------------------------- 1 | import matplotlib.pyplot as plt 2 | import pyrankvote 3 | from pyrankvote import Candidate, Ballot 4 | 5 | import openmc 6 | from groups import * 7 | from getfilename import * 8 | from mgxs import * 9 | 10 | ########## Optimization Mode ####################### 11 | 12 | # If equivalence = True fluxes are included in the ISOXML 13 | # output. This allows MOOSE to calculate basic equivalence factors. 14 | # Please note this feature is NOT compatible with optimization 15 | # at this time since the equivalence fluxes cannot be automatically 16 | # condensed with the rest of the library. 17 | 18 | # If optimize = True, define GroupStructures below 19 | # and set iso_histrogram and/or angle_histogram, or neither 20 | # and set opt_stratgy as 'successive' or 'combinations', defaults to 'combinations'. 21 | # Additionally, opt_tolerance will only choose parameters whose 22 | # final answers are within tolerance of the most accurate run. 23 | # opt_tolerance defaults to 1% of the pcm difference (k_mg - k_ce). 24 | 25 | # If optimize = False, the user must set 26 | # quantify_error (True/False): where True makes the resultant mgxs run and 27 | # computes the k-eff bias, plots cross sections and a fission rate error plot. 28 | 29 | # The variable 'legendre' corresponds to the legendre order used in 30 | # the scattering representation. 31 | # If optimize = True, 'legendre' corresponds to the max order 32 | # which will be considered in the optimization. 33 | 34 | equivalence = False 35 | legendre = 5 36 | optimize = False 37 | # If optimize = True, set the following variables: 38 | opt_strategy = 'successive' # choose from: 'successive', 'combinations' 39 | opt_tolerance = 5 #[percent pcm] 40 | iso_histogram = False 41 | angle_histogram = False 42 | # If optimize = False, you may use the 'quantify_error' variable: 43 | quantify_error = False 44 | 45 | ################# Energy Groups ################# 46 | 47 | # Some common group structures are specified in the clsas Groups (groups.py) 48 | # Set G. where is CASMO, LANL, XMAS, or CUSTOM (no others yet available) 49 | # If CUSTOM please edit the CUSTOM function in groups.py to enter your own groups. 50 | 51 | # If optimize = True, all group structures will be used. 52 | # If optimize = False, only the group structure specified in num_groups will be used. 53 | # Select a number of delayed precursor groups, between 1 and 8. Default is 6. 54 | 55 | G = Groups() 56 | G.CASMO() 57 | num_groups = 70 58 | num_delayed_groups = 6 # options: 1-8 59 | 60 | ################# Cross Sections ################# 61 | 62 | # Of the options listed, include desired reaction types. 63 | # Note: some types will necessitate other types to be included. 64 | # Read the OpenMC errors & warnings during runtime 65 | # to determine which types you may need to add. 66 | # 'absorption' 67 | # 'beta' 68 | # 'chi' 69 | # 'chi-delayed' 70 | # 'chi-prompt' 71 | # 'decay-rate' 72 | # 'delayed-nu-fission' 73 | # 'fission' 74 | # 'inverse-velocity' 75 | # 'kappa-fission' 76 | # 'multiplicity matrix' 77 | # 'nu-fission' 78 | # 'nu-scatter matrix' 79 | # 'prompt-nu-fission' 80 | # 'scatter matrix' 81 | # 'total' 82 | # 'transport' 83 | 84 | mgxs_types = ['transport', 'total', 'absorption', 'nu-fission', 'fission', 85 | 'scatter matrix', 'nu-scatter matrix', 'multiplicity matrix', 'chi', 'inverse-velocity', 86 | 'chi-prompt', 'chi-delayed', 'prompt-nu-fission', 'delayed-nu-fission', 'beta', 'decay-rate'] 87 | 88 | # Note: Generating cross sections "by_nuclide" is not yet offered by this wrapper. 89 | 90 | ################# Problem Documentation ################# 91 | 92 | # Any string (including an empty string) is accepted in the following variables: 93 | LibraryName = "Example" 94 | Description = "" 95 | Generator = "Self" 96 | TimeCreated = "2021" 97 | 98 | ################# MPI options ################# 99 | 100 | # If running in MPI, choose MPI = True 101 | # Note these mpi args are specially generated for a specific machine. 102 | # If running on a different parallel system, please adapt them to your needs. 103 | # You may need to make modifications to the openmc.run() function in 104 | # mgxs.py and optimize.py. 105 | 106 | MPI = False 107 | machinefile = 'mach' 108 | numprocs = '16' 109 | numthreads = '7' 110 | mpicommand = 'mpirun' 111 | 112 | ################# Run MGXS ################# 113 | 114 | XS = MGXS() 115 | fn = FileName() 116 | 117 | # tabulation is defined as the list of reactor states ran. 118 | # Please include as many input files as there are reactor states. 119 | # Under these settings, any file ending in "inp.py" is considered an input file, 120 | # however, the user may change this setting in the following line: 121 | 122 | fn.get_filename(ending="inp.py") 123 | tabulation = OrderedDict() 124 | tabulation['states'] = list(range(0, len(fn.listfn))) 125 | mgxs_libs = [] 126 | n = 0 127 | 128 | for f in fn.listfn: 129 | f = f.replace('.py', '') 130 | print(f) 131 | module = __import__(f) 132 | 133 | materials = module.materials 134 | u_root = module.u_root 135 | geom = module.geom 136 | settings = module.settings 137 | mesh = module.mesh 138 | domain_type = module.domain_type 139 | domain = module.domain 140 | subdomain_to_plot = module.subdomain_to_plot 141 | 142 | if domain_type == 'material': 143 | description = "cross sections for material: " 144 | elif domain_type == 'cell': 145 | description = "cross sections for cell: " 146 | elif domain_type == 'mesh': 147 | description = "cross sections for mesh cell number: " 148 | 149 | #Launching the mgxs module to compute & optimize multi-group cross sections 150 | if optimize == True and MPI == True: 151 | mgxs_libs.append(XS.compute_mgxs(n, LibraryName, u_root, 152 | settings, geom, mesh, domain_type, domain, subdomain_to_plot, mgxs_types, 153 | G.GroupStructures, num_delayed_groups=num_delayed_groups, optimize=optimize, 154 | opt_strategy=opt_strategy, opt_tolerance=opt_tolerance, legendre=legendre, 155 | iso_hist=iso_histogram, angle_hist=angle_histogram, tabulation=tabulation, 156 | MPI=MPI, machinefile=machinefile, numprocs=numprocs, numthreads=numthreads, 157 | mpicommand=mpicommand, Description=Description, Generator=Generator, 158 | TimeCreated=TimeCreated)) 159 | elif optimize == True and MPI == False: 160 | mgxs_libs.append(XS.compute_mgxs(n, LibraryName, u_root, 161 | settings, geom, mesh, domain_type, domain, subdomain_to_plot, mgxs_types, 162 | G.GroupStructures, num_delayed_groups=num_delayed_groups, optimize=optimize, 163 | opt_strategy=opt_strategy, opt_tolerance=opt_tolerance, legendre=legendre, 164 | iso_hist=iso_histogram, angle_hist=angle_histogram, tabulation=tabulation, 165 | Description=Description, Generator=Generator, TimeCreated=TimeCreated)) 166 | elif optimize == False and MPI == True: 167 | mgxs_libs.append(XS.compute_mgxs(n, LibraryName, u_root, 168 | settings, geom, mesh, domain_type, domain, subdomain_to_plot, mgxs_types, 169 | G.GroupStructures, num_groups=num_groups, num_delayed_groups=num_delayed_groups, 170 | legendre=legendre, quantify_error=quantify_error, tabulation=tabulation, 171 | MPI=MPI, machinefile=machinefile, numprocs=numprocs, numthreads=numthreads, 172 | mpicommand=mpicommand, Description=Description, Generator=Generator, 173 | TimeCreated=TimeCreated)) 174 | elif optimize == False and MPI == False: 175 | mgxs_libs.append(XS.compute_mgxs(n, LibraryName, u_root, 176 | settings, geom, mesh, domain_type, domain, subdomain_to_plot, mgxs_types, 177 | G.GroupStructures, num_groups=num_groups, num_delayed_groups=num_delayed_groups, 178 | legendre=legendre, quantify_error=quantify_error, tabulation=tabulation, 179 | Description=Description, Generator=Generator, TimeCreated=TimeCreated)) 180 | n += 1 181 | 182 | ################# Select XS options ################# 183 | # Now that the optimization has occured for each input file separately, 184 | # we optimize over all the best options globally. 185 | print("Selecting best options over all the reactor states...") 186 | 187 | if optimize == True and len(XS.choices) > 1: 188 | options = OrderedDict() 189 | candidates = [] 190 | ballots = [] 191 | 192 | i = 0 193 | for state in XS.choices: 194 | for vote in state: 195 | if vote not in options.values(): 196 | options[str(i)] = vote 197 | i += 1 198 | 199 | for key in options.keys(): 200 | candidates.append(Candidate(key)) 201 | for state in XS.choices: 202 | state_ballot = [] 203 | for vote in state: 204 | for key, value in options.items(): 205 | if vote == value and Candidate(key) not in state_ballot: 206 | state_ballot.append(Candidate(key)) 207 | ballots.append(Ballot(ranked_candidates=state_ballot)) 208 | 209 | election_results = pyrankvote.instant_runoff_voting(candidates,ballots) 210 | winners = election_results.get_winners() 211 | selection = options[str(winners[0])] 212 | print("The best Group/Legendre combination is: ", selection) 213 | 214 | elif optimize == True and len(XS.choices) == 1: 215 | selection = (XS.choices[0][0][0], XS.choices[0][0][1]) 216 | print("The best Group/Legendre combination is: ", selection) 217 | elif optimize == False: 218 | selection = (num_groups, legendre) 219 | print("The best Group/Legendre combination is: ", selection) 220 | 221 | ################# Print to ISOXML ################# 222 | # Now that the library has be optimally condensed, 223 | # the cross sections will be re-formatted to an ISOXML 224 | # file readable by MOOSE 225 | print("Condensing libraries and reformatting to ISOXML...") 226 | 227 | output = YAKXS(LibraryName, str(selection[0]), equivalence) 228 | new_structure = openmc.mgxs.EnergyGroups(G.GroupStructures[selection[0]]) 229 | 230 | for i in range(n): 231 | xsdata_names = [] 232 | for d in mgxs_libs[i].domains: 233 | xsdata_names.append(d.name) 234 | mgxs_libs[i] = mgxs_libs[i].get_condensed_library(new_structure) 235 | if domain_type == 'mesh': 236 | mgxs_file, new_materials, new_geometry = mgxs_libs[i].create_mg_mode() 237 | else: 238 | mgxs_file, new_materials, new_geometry = mgxs_libs[i].create_mg_mode( 239 | xsdata_names=xsdata_names) 240 | mgxs_file.name = str(i)+'_mgxs.h5' 241 | mgxs_file.export_to_hdf5(filename=mgxs_file.name) 242 | 243 | output.export_to_xml(selection[0], num_delayed_groups, mgxs_types, selection[1], equivalence, 244 | mgxs_libs, tabulation, Description=Description, Generator=Generator, 245 | TimeCreated=TimeCreated) 246 | 247 | print("Done reformatting... See mgxs.xml for output.") 248 | -------------------------------------------------------------------------------- /mgxs.py: -------------------------------------------------------------------------------- 1 | import copy 2 | import os 3 | 4 | import matplotlib as mpl 5 | import matplotlib.pyplot as plt 6 | import numpy as np 7 | 8 | import openmc 9 | from optimize import * 10 | from yakxs import * 11 | 12 | class MGXS: 13 | 14 | def __init__(self): 15 | 16 | self.choices = [] 17 | self.biases = [] 18 | 19 | def compute_mgxs(self, n, libname, universe, settings, geometry, mesh, 20 | domain_type, domain, subdomain_to_plot, mgxs_types, GroupStructures, 21 | num_groups=None, num_delayed_groups=6, optimize=False, 22 | opt_strategy='successive', opt_tolerance=1.0, 23 | legendre=0, iso_hist=False, angle_hist=False, quantify_error=False, 24 | tabulation=None, MPI=False, machinefile='', numprocs='', numthreads='', 25 | mpicommand='', Description="", Generator='INL', TimeCreated='', 26 | mgxs_bynuclide=[], mgxs_tablewise =[], mgxs_librarywise =[]): 27 | 28 | print("computing mgxs...") 29 | os.environ['OPENMC_MG_CROSS_SECTIONS'] = 'mgxs.h5' 30 | if GroupStructures == {}: 31 | print("ERROR: GroupStructures requires at least one entry. \ 32 | Define GroupStructures in main.py") 33 | 34 | if optimize == True: 35 | num_groups = max(GroupStructures.keys()) 36 | group_edges = GroupStructures[num_groups] 37 | else: 38 | group_edges = GroupStructures[num_groups] 39 | energy_groups = openmc.mgxs.EnergyGroups(group_edges) 40 | 41 | tallies_file = openmc.Tallies() 42 | if quantify_error == True: 43 | t1 = openmc.Tally(tally_id=100) 44 | t1.filters.append(openmc.EnergyFilter(group_edges)) 45 | if domain_type == 'cell': 46 | t1.filters.append(openmc.CellFilter(subdomain_to_plot)) 47 | elif domain_type == 'material': 48 | t1.filters.append(openmc.MaterialFilter(subdomain_to_plot)) 49 | t1.scores = ['flux'] 50 | tallies_file.append(t1, False) 51 | t2 = openmc.Tally(tally_id=200) 52 | t2.filters.append(openmc.MeshFilter(mesh)) 53 | t2.scores = ['fission'] 54 | tallies_file.append(t2, True) 55 | t3 = openmc.Tally(tally_id=300) 56 | 57 | for i, d in enumerate(domain): 58 | t = openmc.Tally(tally_id=301+i, name=d.name) 59 | t.filters.append(openmc.EnergyFilter(group_edges)) 60 | if domain_type == 'cell': 61 | t.filters.append(openmc.CellFilter(d)) 62 | elif domain_type == 'material': 63 | t.filters.append(openmc.MaterialFilter(d)) 64 | elif domain_type == 'mesh': 65 | t.filters.append(openmc.MeshFilter(d)) 66 | t.scores = ['flux'] 67 | tallies_file.append(t, False) 68 | 69 | # Base library 70 | mgxs_lib = openmc.mgxs.Library(geometry) 71 | mgxs_lib.energy_groups = energy_groups 72 | mgxs_lib.mgxs_types = mgxs_types 73 | mgxs_lib.num_delayed_groups = num_delayed_groups 74 | mgxs_lib.domain_type = domain_type 75 | mgxs_lib.domains = domain 76 | mgxs_lib.legendre_order = legendre 77 | mgxs_lib.by_nuclide = False 78 | mgxs_lib.check_library_for_openmc_mgxs() 79 | mgxs_lib.build_library() 80 | mgxs_lib.add_to_tallies_file(tallies_file, merge=True) 81 | 82 | # Isotropic histogram library 83 | if iso_hist == True: 84 | iso_mgxs_lib = openmc.mgxs.Library(geometry) 85 | iso_mgxs_lib.energy_groups = energy_groups 86 | iso_mgxs_lib.mgxs_types = mgxs_types 87 | iso_mgxs_lib.num_delayed_groups = num_delayed_groups 88 | iso_mgxs_lib.domain_type = domain_type 89 | iso_mgxs_lib.domains = domain 90 | iso_mgxs_lib.correction = None 91 | iso_mgxs_lib.scatter_format = 'histogram' 92 | iso_mgxs_lib.histogram_bins = 10 93 | iso_mgxs_lib.by_nuclide = False 94 | iso_mgxs_lib.check_library_for_openmc_mgxs() 95 | iso_mgxs_lib.build_library() 96 | iso_mgxs_lib.add_to_tallies_file(tallies_file, merge=True) 97 | else: 98 | iso_mgxs_lib = None 99 | 100 | # Angle-dependent histogram library 101 | if angle_hist == True: 102 | angle_mgxs_lib = openmc.mgxs.Library(geometry) 103 | angle_mgxs_lib.energy_groups = energy_groups 104 | angle_mgxs_lib.mgxs_types = mgxs_types 105 | angle_mgxs_lib.num_delayed_groups = num_delayed_groups 106 | angle_mgxs_lib.domain_type = domain_type 107 | angle_mgxs_lib.domains = domain 108 | angle_mgxs_lib.correction = None 109 | angle_mgxs_lib.scatter_format = 'histogram' 110 | angle_mgxs_lib.histogram_bins = 10 111 | angle_mgxs_lib.num_azimuthal = 10 112 | angle_mgxs_lib.by_nuclide = False 113 | angle_mgxs_lib.check_library_for_openmc_mgxs() 114 | angle_mgxs_lib.build_library() 115 | angle_mgxs_lib.add_to_tallies_file(tallies_file, merge=True) 116 | else: 117 | angle_mgxs_lib = None 118 | 119 | tallies_file.export_to_xml() 120 | if MPI == True: 121 | openmc.run(mpi_args=[mpicommand,'--bind-to','socket','-np',numprocs, 122 | '-machinefile',machinefile],threads=numthreads,cwd='.') 123 | else: 124 | openmc.run() 125 | 126 | ce_spfile = './'+str(n)+'statepoint_ce.h5' 127 | os.rename('statepoint.'+str(settings.batches)+'.h5',ce_spfile) 128 | ce_sumfile = './'+str(n)+'summary_ce.h5' 129 | os.rename('summary.h5',ce_sumfile) 130 | SPCE = openmc.StatePoint(ce_spfile, autolink=False) 131 | su = openmc.Summary(ce_sumfile) 132 | SPCE.link_with_summary(su) 133 | print("loading data...") 134 | mgxs_lib.load_from_statepoint(SPCE) 135 | 136 | # Optimization step 137 | OPT = Optimize(num_groups, legendre) 138 | if optimize == True: 139 | tolerance = 1.0+opt_tolerance/100.0 140 | if opt_strategy == 'successive': 141 | self.choices.append(OPT.successive(n, MPI, mpicommand, numprocs, 142 | numthreads, machinefile, settings, SPCE, GroupStructures, mgxs_lib, 143 | legendre, iso_mgxs_lib, angle_mgxs_lib, tolerance)) 144 | elif opt_strategy == 'combinations': 145 | self.choices.append(OPT.combinations(n, MPI, mpicommand, numprocs, 146 | numthreads, machinefile, settings, SPCE, GroupStructures, mgxs_lib, 147 | legendre, iso_mgxs_lib, angle_mgxs_lib, tolerance)) 148 | else: 149 | print("Please set opt_strategy to either 'successive' or 'combinations'.") 150 | 151 | # Error Quantification step 152 | if quantify_error == True: 153 | k_ce = SPCE.k_combined 154 | mgxs_file, new_materials, new_geometry = mgxs_lib.create_mg_mode() 155 | mgxs_file.export_to_hdf5() 156 | mgxs_file.name = 'mgxs.h5' 157 | new_materials.export_to_xml() 158 | new_geometry.export_to_xml() 159 | settings.energy_mode = 'multi-group' 160 | settings.temperature = {'method': 'nearest', 'tolerance': 3000} 161 | settings.export_to_xml() 162 | tallies_file = openmc.Tallies() 163 | tallies_file.append(t2, True) 164 | tallies_file.export_to_xml() 165 | print("running in multi-group mode") 166 | if MPI == True: 167 | openmc.run(mpi_args=[mpicommand,'--bind-to','socket','-np',numprocs, 168 | '-machinefile',machinefile],threads=numthreads,cwd='.') 169 | else: 170 | openmc.run() 171 | 172 | mg_spfile = './statepoint_mg.h5' 173 | os.rename('statepoint.'+str(settings.batches)+'.h5',mg_spfile) 174 | mg_sumfile = './summary_mg.h5' 175 | os.rename('summary.h5',mg_sumfile) 176 | SPMG = openmc.StatePoint(mg_spfile, autolink=False) 177 | su = openmc.Summary(mg_sumfile) 178 | SPMG.link_with_summary(su) 179 | 180 | k_mg = SPMG.k_combined 181 | bias = 1.0E5 * (k_mg - k_ce) 182 | print('Continuous-Energy keff = {0:1.6f}'.format(k_ce)) 183 | print('Multi-Group keff = {0:1.6f}'.format(k_mg)) 184 | print('bias [pcm]: {0:1.1f}'.format(bias.nominal_value)) 185 | 186 | # Plotting cross sections 187 | print("plotting mgxs...") 188 | 189 | flux_ce = SPCE.get_tally(id=100) 190 | mg_groups_plt = [] 191 | ce_flux_plt = [] 192 | for i in range(num_groups+1): 193 | mg_groups_plt.append(group_edges[i]) 194 | if i != num_groups: 195 | ce_flux_plt.append(flux_ce.mean[i][0][0]) 196 | ce_flux_plt.append(flux_ce.mean[i][0][0]) 197 | if i != 0 and i != num_groups: 198 | mg_groups_plt.append(group_edges[i]) 199 | 200 | if domain_type == 'mesh': 201 | print("Cannot plot CE/MG cross sections for a material when \ 202 | Mesh domain is used, since a mesh does not know what material is in \ 203 | each cell") 204 | else: 205 | for i, domains in enumerate(mgxs_lib.domains): 206 | if mgxs_lib.domains[i].name == subdomain_to_plot.name: 207 | dom = mgxs_lib.domains[i] 208 | position = i 209 | if domain_type == 'material': 210 | if subdomain_to_plot.temperature == None: 211 | fig = openmc.plot_xs(dom, ['total']) 212 | else: 213 | fig = openmc.plot_xs(dom, ['total'], 214 | temperature=subdomain_to_plot.temperature) 215 | elif domain_type == 'cell': 216 | if subdomain_to_plot.temperature == None: 217 | fig = openmc.plot_xs(dom.fill, ['total']) 218 | else: 219 | fig = openmc.plot_xs(dom.fill, ['total'], 220 | temperature=subdomain_to_plot.temperature) 221 | openmc.plot_xs(new_materials[position], ['total'], plot_CE=False, 222 | mg_cross_sections='mgxs.h5', axis=fig.axes[0]) 223 | fig.axes[0].legend(loc=2, prop={'size': 6}).set_visible(True) 224 | fig.axes[0].set_title("Cross Sections for "+mgxs_lib.domains[position].name 225 | +' bias [pcm]: {0:1.1f}'.format(bias.nominal_value)) 226 | ax2 = fig.axes[0].twinx() 227 | ax2.plot(mg_groups_plt, ce_flux_plt, color='red', label='ce flux') 228 | ax2.set_ylabel('Flux spectrum [particle-cm per source particle]') 229 | ax2.set_yscale('log') 230 | ax2.legend(loc=1, prop={'size': 6}) 231 | plt.savefig('xsplot'+str(n)) 232 | plt.tight_layout() 233 | plt.close() 234 | 235 | # Plotting 2D reaction rates 236 | if len(mesh.dimension) != 2: 237 | print("2D error plot can only be produced if 2D mesh is used") 238 | else: 239 | print("plotting 2D error plot...") 240 | 241 | mg_fission_tally = SPMG.get_tally(id=200) 242 | mg_fission_rates = mg_fission_tally.get_values(scores=['fission']) 243 | mg_fission_rates.shape = mesh.dimension 244 | mg_fission_rates /= np.mean(mg_fission_rates[mg_fission_rates > 0.]) 245 | mg_fission_rates[mg_fission_rates == 0.] = np.nan 246 | ce_fission_tally = SPCE.get_tally(id=200) 247 | ce_fission_rates = ce_fission_tally.get_values(scores=['fission']) 248 | ce_fission_rates.shape = mesh.dimension 249 | ce_fission_rates /= np.mean(ce_fission_rates[ce_fission_rates > 0.]) 250 | ce_fission_rates[ce_fission_rates == 0.] = np.nan 251 | ratios = [] 252 | for i in range(len(ce_fission_rates)): 253 | ratios.append(np.divide(mg_fission_rates[i]-ce_fission_rates[i], 254 | ce_fission_rates[i])[:]*100) 255 | 256 | norm = mpl.colors.Normalize(vmin=0, vmax=20.0) 257 | plt.imshow(ratios, interpolation='none', cmap='jet', norm=norm, origin='lower') 258 | plt.title('Relative Fission Rate Error (%)') 259 | plt.colorbar() 260 | plt.savefig('FissionRates'+str(n)) 261 | 262 | # Printing mgxs, flux, std_dev to text 263 | if domain_type != 'mesh': 264 | print("outputing error data to text...") 265 | 266 | total_mgxs = mgxs_lib.get_mgxs(subdomain_to_plot, 'total').get_xs(value='mean') 267 | std_dev_mgxs = mgxs_lib.get_mgxs(subdomain_to_plot, 'total').get_xs(value='std_dev') 268 | np.savetxt("mgxs_error"+str(n)+".txt", np.c_[total_mgxs, std_dev_mgxs], 269 | header='Total MGXS for subdomain std_dev') 270 | 271 | flux = [] 272 | flux_std_dev = [] 273 | for i in range(num_groups): 274 | flux.append(flux_ce.mean[i][0][0]) 275 | flux_std_dev.append(flux_ce.std_dev[i][0][0]) 276 | np.savetxt("flux_error"+str(n)+".txt", np.c_[flux, flux_std_dev], 277 | header='Flux for subdomain std_dev') 278 | 279 | return mgxs_lib 280 | -------------------------------------------------------------------------------- /optimize.py: -------------------------------------------------------------------------------- 1 | import copy 2 | import matplotlib as mpl 3 | import matplotlib.pyplot as plt 4 | import openmc 5 | import os 6 | 7 | class Optimize: 8 | 9 | #################################################################### 10 | 11 | def __init__(self, num_groups, legendre): 12 | 13 | self.G = num_groups 14 | self.L = legendre 15 | 16 | #################################################################### 17 | 18 | def successive(self, n, MPI, mpicommand, numprocs, numthreads, machinefile, 19 | settings, SPCE, GroupStructures, mgxs_lib, legendre, iso_mgxs_lib, 20 | angle_mgxs_lib, tolerance): 21 | 22 | print("This is the successive optimization option. An energy", \ 23 | "optimization takes place using L=0 to select the best group structure G.", \ 24 | "Then, a scattering optimization takes place using G to select the best Legendre expansion L.", \ 25 | "Finally, another energy optimization takes place using L to select the best group structure.") 26 | ranked_choices = [] 27 | 28 | BestGroups, BestBias = self.optimize_energy(n, MPI, mpicommand, numprocs, 29 | numthreads, machinefile, settings, SPCE, GroupStructures, mgxs_lib, 30 | tolerance, legendre=0) 31 | 32 | ranked_choices.append([BestGroups, 0]) 33 | 34 | if legendre > 0: 35 | BestLegendre = self.optimize_scatter(n, MPI, mpicommand, numprocs, 36 | numthreads, machinefile, settings, SPCE, legendre, mgxs_lib, 37 | iso_mgxs_lib, angle_mgxs_lib, tolerance, GroupStructures, 38 | num_groups=BestGroups) 39 | 40 | ranked_choices.append([BestGroups, BestLegendre]) 41 | 42 | BestGroups, BestBias = self.optimize_energy(n, MPI, mpicommand, 43 | numprocs, numthreads, machinefile, settings, SPCE, GroupStructures, 44 | mgxs_lib, tolerance, legendre=BestLegendre) 45 | 46 | ranked_choices.append([BestGroups, BestLegendre]) 47 | 48 | else: 49 | BestLegendre = 0 50 | 51 | ranked_choices = ranked_choices[::-1] 52 | self.G = BestGroups 53 | self.L = BestLegendre 54 | self.B = BestBias 55 | return ranked_choices 56 | 57 | #################################################################### 58 | 59 | def combinations(self, n, MPI, mpicommand, numprocs, numthreads, machinefile, 60 | settings, SPCE, GroupStructures, mgxs_lib, legendre, iso_mgxs_lib, 61 | angle_mgxs_lib, tolerance): 62 | 63 | print("This is the combinations optimization option.", \ 64 | "An energy optimization will take place for every Legendre expansion", \ 65 | "specified in main.py.") 66 | 67 | def sort_by_bias(element): 68 | return element[0] 69 | 70 | Groups = [] 71 | Bias = [] 72 | Costs = [] 73 | temp_choices = [] 74 | ranked_choices = [] 75 | 76 | for L in range(legendre+1): 77 | TempGroups, TempBias = self.optimize_energy(n, MPI, mpicommand, 78 | numprocs, numthreads, machinefile, settings, SPCE, GroupStructures, 79 | mgxs_lib, tolerance, legendre=L) 80 | Groups.append(TempGroups) 81 | Bias.append(TempBias) 82 | Costs.append(self.TempCost*(L+1)) 83 | temp_choices.append([TempBias,TempGroups,L]) 84 | 85 | BestLegendre = Costs.index(min(Costs)) 86 | BestGroups = Groups[BestLegendre] 87 | BestBias = Bias[BestLegendre] 88 | 89 | temp_choices.sort(key=sort_by_bias) 90 | for element in temp_choices: 91 | ranked_choices.append(element[1::]) 92 | self.G = BestGroups 93 | self.L = BestLegendre 94 | self.B = BestBias 95 | return ranked_choices 96 | 97 | #################################################################### 98 | 99 | def optimize_energy(self, n, MPI, mpicommand, numprocs, numthreads, machinefile, 100 | settings, SPCE, GroupStructures, mgxs_lib, tolerance, legendre=0): 101 | 102 | print("optimizing energy...") 103 | 104 | settings.energy_mode = 'multi-group' 105 | settings.max_order = legendre 106 | settings.temperature = {'method': 'nearest', 'tolerance': 3000} 107 | settings.export_to_xml() 108 | if os.path.isfile('tallies.xml'): 109 | os.remove('tallies.xml') 110 | k_ce = SPCE.k_combined 111 | 112 | groups = [] 113 | biases = [] 114 | stdev = [] 115 | costs = [] 116 | for Ncoarse_grps in GroupStructures: 117 | print("Running with", Ncoarse_grps, "energy groups and Legendre expansion of", 118 | legendre) 119 | new_structure = openmc.mgxs.EnergyGroups(GroupStructures[Ncoarse_grps]) 120 | new_mgxs_file, new_materials, new_geometry = mgxs_lib.get_condensed_library( 121 | new_structure).create_mg_mode() 122 | new_mgxs_file.export_to_hdf5(filename='mgxs.h5') 123 | new_materials.export_to_xml() 124 | new_geometry.export_to_xml() 125 | if MPI == True: 126 | openmc.run(mpi_args=[mpicommand,'--bind-to','socket','-np',numprocs, 127 | '-machinefile',machinefile],threads=numthreads,cwd='.') 128 | else: 129 | openmc.run() 130 | 131 | mg_spfile = './statepoint_mg.h5' 132 | os.rename('statepoint.'+str(settings.batches)+'.h5',mg_spfile) 133 | mg_sumfile = './summary_mg.h5' 134 | os.rename('summary.h5',mg_sumfile) 135 | SPMG = openmc.StatePoint(mg_spfile, autolink=False) 136 | su = openmc.Summary(mg_sumfile) 137 | SPMG.link_with_summary(su) 138 | 139 | k_mg = SPMG.k_combined 140 | bias = 1.0E5 * (k_mg - k_ce) 141 | cost = Ncoarse_grps * bias 142 | groups.append(Ncoarse_grps) 143 | biases.append(abs(bias.nominal_value)) 144 | stdev.append(abs(bias.std_dev)) 145 | costs.append(abs(cost.nominal_value)) 146 | print('Continuous-Energy keff = {0:1.6f}'.format(k_ce)) 147 | print('Multi-Group keff = {0:1.6f}'.format(k_mg)) 148 | print('bias [pcm]: {0:1.1f}'.format(bias.nominal_value)) 149 | 150 | # Select optimal group structure 151 | costs_sorted = sorted(costs) 152 | i = 0 153 | choice = costs.index(costs_sorted[i]) 154 | while biases[choice] > biases[-1]*tolerance: 155 | i = i + 1 156 | choice = costs.index(costs_sorted[i]) 157 | BestGroupStructure = GroupStructures[groups[choice]] 158 | print("The least-cost was acheived with ", groups[choice], " groups.") 159 | self.TempCost = costs_sorted[i] 160 | 161 | 162 | plt.errorbar(groups, biases, stdev, ecolor='k', elinewidth=0.5, capsize=2) 163 | plt.title("Multi-group bias in k-eff wrt CE mode (L=%i)" %(legendre)) 164 | plt.xlabel("Number of groups") 165 | plt.ylabel("k-eff difference [pcm]") 166 | plt.savefig("Group_bias"+str(legendre)+"_state"+str(n)) 167 | plt.clf() 168 | 169 | return groups[choice], biases[choice] 170 | 171 | #################################################################### 172 | 173 | def optimize_scatter(self, n, MPI, mpicommand, numprocs, numthreads, machinefile, 174 | settings, SPCE, legendre, mgxs_lib, iso_mgxs_lib, angle_mgxs_lib, tolerance, 175 | GroupStructures, num_groups=0): 176 | 177 | print("optimizing scatter representation...") 178 | 179 | settings.energy_mode = 'multi-group' 180 | settings.temperature = {'method': 'nearest', 'tolerance': 3000} 181 | if os.path.isfile('tallies.xml'): 182 | os.remove('tallies.xml') 183 | k_ce = SPCE.k_combined 184 | 185 | if num_groups == 0: 186 | num_groups = max(GroupStructures.keys()) 187 | 188 | new_structure = openmc.mgxs.EnergyGroups(GroupStructures[num_groups]) 189 | new_mgxs_file, new_materials, new_geometry = mgxs_lib.get_condensed_library( 190 | new_structure).create_mg_mode() 191 | new_mgxs_file.export_to_hdf5(filename='mgxs.h5') 192 | new_materials.export_to_xml() 193 | new_geometry.export_to_xml() 194 | 195 | scattering = [] 196 | biases = [] 197 | stdev = [] 198 | costs = [] 199 | for i in range(legendre+1): 200 | print("Running with scattering order", i, "and", num_groups, "energy groups.") 201 | settings.max_order = i 202 | settings.export_to_xml() 203 | if MPI == True: 204 | openmc.run(mpi_args=[mpicommand,'--bind-to','socket','-np',numprocs, 205 | '-machinefile',machinefile],threads=numthreads,cwd='.') 206 | else: 207 | openmc.run() 208 | 209 | mg_spfile = './statepoint_mg.h5' 210 | os.rename('statepoint.'+str(settings.batches)+'.h5',mg_spfile) 211 | mg_sumfile = './summary_mg.h5' 212 | os.rename('summary.h5',mg_sumfile) 213 | SPMG = openmc.StatePoint(mg_spfile, autolink=False) 214 | su = openmc.Summary(mg_sumfile) 215 | SPMG.link_with_summary(su) 216 | 217 | k_mg = SPMG.k_combined 218 | bias = 1.0E5 * (k_mg - k_ce) 219 | cost = (i+1) * bias 220 | scattering.append(i) 221 | biases.append(abs(bias.nominal_value)) 222 | stdev.append(abs(bias.std_dev)) 223 | costs.append(abs(cost.nominal_value)) 224 | print('Continuous-Energy keff = {0:1.6f}'.format(k_ce)) 225 | print('Legendre order',i,'keff = {0:1.6f}'.format(k_mg)) 226 | print('bias [pcm]: {0:1.1f}'.format(bias.nominal_value)) 227 | 228 | plt.errorbar(scattering, biases, stdev, ecolor='k', elinewidth=0.5, capsize=2, 229 | color='b', label="Legendre representation") 230 | 231 | if iso_mgxs_lib is not None: 232 | iso_mgxs_lib.load_from_statepoint(SPCE) 233 | iso_mgxs_file, iso_materials_file, iso_geometry_file = iso_mgxs_lib.create_mg_mode() 234 | iso_materials_file.cross_sections = 'mgxs.h5' 235 | iso_mgxs_file.export_to_hdf5(filename='mgxs.h5') 236 | iso_materials_file.export_to_xml() 237 | iso_geometry_file.export_to_xml() 238 | if MPI == True: 239 | openmc.run(mpi_args=[mpicommand,'--bind-to','socket','-np',numprocs, 240 | '-machinefile',machinefile],threads=numthreads,cwd='.') 241 | else: 242 | openmc.run() 243 | 244 | iso_mg_spfile = './statepoint_mg_iso.h5' 245 | os.rename('statepoint.' + str(settings.batches) + '.h5', iso_mg_spfile) 246 | iso_mg_sumfile = './summary_mg_iso.h5' 247 | os.rename('summary.h5', iso_mg_sumfile) 248 | iso_mgsp = openmc.StatePoint(iso_mg_spfile, autolink=False) 249 | iso_mgsum = openmc.Summary(iso_mg_sumfile) 250 | iso_mgsp.link_with_summary(iso_mgsum) 251 | 252 | iso_mg_keff = iso_mgsp.k_combined 253 | iso_bias = 1.0e5 * (iso_mg_keff - k_ce) 254 | x = range(legendre+1) 255 | iso = [abs(iso_bias.nominal_value)] * (legendre+1) 256 | print('Continuous-Energy keff = {0:1.6f}'.format(k_ce)) 257 | print('Isotropic histogram keff = {0:1.6f}'.format(iso_mg_keff)) 258 | print('bias for iso [pcm]: {0:1.1f}'.format(iso_bias.nominal_value)) 259 | plt.plot(x, iso, color='r', label="Histogram: isotropic (10 bins)") 260 | 261 | if angle_mgxs_lib is not None: 262 | angle_mgxs_lib.load_from_statepoint(SPCE) 263 | angle_mgxs_file, angle_materials_file, angle_geometry_file = angle_mgxs_lib.create_mg_mode() 264 | angle_materials_file.cross_sections = 'mgxs.h5' 265 | angle_mgxs_file.export_to_hdf5(filename='mgxs.h5') 266 | angle_materials_file.export_to_xml() 267 | angle_geometry_file.export_to_xml() 268 | if MPI == True: 269 | openmc.run(mpi_args=[mpicommand,'--bind-to','socket','-np',numprocs, 270 | '-machinefile',machinefile],threads=numthreads,cwd='.') 271 | else: 272 | openmc.run() 273 | 274 | angle_mg_spfile = './statepoint_mg_angle.h5' 275 | os.rename('statepoint.' + str(settings.batches) + '.h5', angle_mg_spfile) 276 | angle_mg_sumfile = './summary_mg_angle.h5' 277 | os.rename('summary.h5', angle_mg_sumfile) 278 | angle_mgsp = openmc.StatePoint(angle_mg_spfile, autolink=False) 279 | angle_mgsum = openmc.Summary(angle_mg_sumfile) 280 | angle_mgsp.link_with_summary(angle_mgsum) 281 | 282 | angle_mg_keff = angle_mgsp.k_combined 283 | angle_bias = 1.0e5 * (angle_mg_keff - k_ce) 284 | x = range(legendre+1) 285 | angle = [abs(angle_bias.nominal_value)] * (legendre+1) 286 | print('Continuous-Energy keff = {0:1.6f}'.format(k_ce)) 287 | print('Angle histogram keff = {0:1.6f}'.format(angle_mg_keff)) 288 | print('bias for angle [pcm]: {0:1.1f}'.format(angle_bias.nominal_value)) 289 | plt.plot(x, angle, color='g', label="Histogram: angle-dependent (10 bins, 10 azimuthal") 290 | 291 | # Select optimal legendre order 292 | costs_sorted = sorted(costs) 293 | i = 0 294 | choice = costs.index(costs_sorted[i]) 295 | while biases[choice] > biases[-1]*tolerance: 296 | i = i + 1 297 | choice = costs.index(costs_sorted[i]) 298 | print("The least-cost was acheived with a Legendre expansion order of ", choice, ".") 299 | 300 | plt.legend() 301 | plt.title("Multi-group bias in k-eff wrt CE mode (G=%i)" %(num_groups)) 302 | plt.xlabel("Legendre scattering order") 303 | plt.ylabel("k-eff difference [pcm]") 304 | plt.savefig("Scatter_bias"+str(num_groups)+"_state"+str(n)) 305 | plt.clf() 306 | 307 | return choice 308 | -------------------------------------------------------------------------------- /testreactor_slab1_inp.py: -------------------------------------------------------------------------------- 1 | # OpenMC input deck for testbed reactor model 2 | 3 | ################################################ 4 | # Imports 5 | ################################################ 6 | 7 | import openmc 8 | import matplotlib.pyplot as plt 9 | import openmc.checkvalue as cv 10 | from mgxs import * 11 | 12 | ################################################ 13 | # Define Materials 14 | ################################################ 15 | 16 | fuel_mat = openmc.Material(material_id=1, name='fuel_mat') 17 | fuel_mat.temperature = 295. 18 | fuel_mat.add_nuclide('U235',0.2) 19 | fuel_mat.add_nuclide('U238',0.8) 20 | fuel_mat.add_nuclide('H1',1.0) 21 | fuel_mat.add_element('Zr',1.0) 22 | fuel_mat.set_density('g/cm3',9.8) 23 | # fuel_mat.add_s_alpha_beta('c_Zr_in_ZrH') 24 | # fuel_mat.add_s_alpha_beta('c_H_in_ZrH') 25 | 26 | mod_mat = openmc.Material(material_id=2, name='mod_mat') 27 | mod_mat.add_element('Zr',1.0) 28 | mod_mat.add_nuclide('H1',2.0) 29 | mod_mat.set_density('g/cm3',5.6) 30 | # mod_mat.add_s_alpha_beta('c_Zr_in_ZrH') 31 | # mod_mat.add_s_alpha_beta('c_H_in_ZrH') 32 | 33 | vapor_mat = openmc.Material(material_id=3, name='vapor_mat') 34 | vapor_mat.add_nuclide('Na23',1.0) 35 | vapor_mat.set_density('g/cm3',0.1) 36 | 37 | pipe_mat = openmc.Material(material_id=4, name='pipe_mat') 38 | pipe_mat.add_element('Mo',1.0) 39 | pipe_mat.set_density('g/cm3',8.0) 40 | 41 | monolith_mat = openmc.Material(material_id=5, name='monolith_mat') 42 | monolith_mat.add_nuclide('C0',1.0) 43 | monolith_mat.set_density('g/cm3',1.75) 44 | # monolith_mat.add_s_alpha_beta('c_Graphite') 45 | 46 | reflector_mat = openmc.Material(material_id=6, name='reflector_mat') 47 | reflector_mat.add_nuclide('Be9',1.0) 48 | reflector_mat.add_nuclide('O16',1.0) 49 | reflector_mat.set_density('g/cm3',2.9) 50 | # reflector_mat.add_s_alpha_beta('c_Be_in_BeO') 51 | # reflector_mat.add_s_alpha_beta('c_O_in_BeO') 52 | 53 | materials = openmc.Materials([fuel_mat,mod_mat,vapor_mat,pipe_mat,monolith_mat,reflector_mat]) 54 | materials.export_to_xml() 55 | 56 | ################################################ 57 | # Define Geometry 58 | ################################################ 59 | 60 | ################# Surfaces ################# 61 | 62 | # ZCylinders to model pins 63 | pipe_inner = openmc.ZCylinder(surface_id=100, x0=0, y0=0, r=0.6) 64 | pipe_outer = openmc.ZCylinder(surface_id=101, x0=0, y0=0, r=0.7) 65 | mod_r = openmc.ZCylinder(surface_id=102, x0=0, y0=0, r=0.75) 66 | fuel_r = openmc.ZCylinder(surface_id=103, x0=0, y0=0, r=0.8) 67 | 68 | # top & bottom of the assembly 69 | assembly_z0 = openmc.ZPlane(surface_id=300, z0=-1, boundary_type='reflective') 70 | assembly_z1 = openmc.ZPlane(surface_id=301, z0=1, boundary_type='reflective') 71 | 72 | # assembly hexagon 73 | assembly = openmc.model.hexagonal_prism(edge_length=16.166, orientation='y') 74 | 75 | # reflector hexagon 76 | reflector = openmc.model.hexagonal_prism(edge_length=27.713, orientation='y', 77 | boundary_type='vacuum') 78 | 79 | ################# Cells ################# 80 | 81 | pipe_cell_inner = openmc.Cell(name= 'pipe_cell_inner', cell_id=100) 82 | pipe_cell_wall = openmc.Cell(name= 'pipe_cell_wall', cell_id=101) 83 | pipe_cell_outer = openmc.Cell(name= 'pipe_cell_outer', cell_id=102) 84 | mod_cell_inner = openmc.Cell(name= 'mod_cell_inner', cell_id=103) 85 | mod_cell_outer = openmc.Cell(name= 'mod_cell_outer', cell_id=104) 86 | fuel_cell_inner = openmc.Cell(name= 'fuel_cell_inner', cell_id=105) 87 | fuel_cell_outer = openmc.Cell(name= 'fuel_cell_outer', cell_id=106) 88 | 89 | monolith_cell = openmc.Cell(name= '', cell_id=201) 90 | assembly_cell = openmc.Cell(name= '', cell_id=301) 91 | 92 | reflect_cell = openmc.Cell(name= '', cell_id=401) 93 | 94 | ################# Regions ################# 95 | 96 | pipe_cell_inner.region = -pipe_inner & -assembly_z1 & +assembly_z0 97 | pipe_cell_wall.region = -pipe_outer & + pipe_inner & -assembly_z1 & +assembly_z0 98 | pipe_cell_outer.region = +pipe_outer & -assembly_z1 & +assembly_z0 99 | mod_cell_inner.region = -mod_r & -assembly_z1 & +assembly_z0 100 | mod_cell_outer.region = +mod_r & -assembly_z1 & +assembly_z0 101 | fuel_cell_inner.region = -fuel_r & -assembly_z1 & +assembly_z0 102 | fuel_cell_outer.region = +fuel_r & -assembly_z1 & +assembly_z0 103 | 104 | assembly_cell.region = assembly & -assembly_z1 & +assembly_z0 105 | 106 | reflect_cell.region = ~assembly & reflector & -assembly_z1 & +assembly_z0 107 | 108 | # fill cells with material 109 | pipe_cell_inner.fill = vapor_mat 110 | pipe_cell_wall.fill = pipe_mat 111 | pipe_cell_outer.fill = monolith_mat 112 | mod_cell_inner.fill = mod_mat 113 | mod_cell_outer.fill = monolith_mat 114 | fuel_cell_inner.fill = fuel_mat 115 | fuel_cell_outer.fill = monolith_mat 116 | monolith_cell.fill = monolith_mat 117 | 118 | reflect_cell.fill = reflector_mat 119 | 120 | ################# Universes ################# 121 | 122 | u_pipe = openmc.Universe(universe_id=100) 123 | u_pipe.add_cells( 124 | [pipe_cell_inner, pipe_cell_wall, pipe_cell_outer]) 125 | 126 | u_mod = openmc.Universe(universe_id=101) 127 | u_mod.add_cells( 128 | [mod_cell_inner, mod_cell_outer]) 129 | 130 | u_fuel = openmc.Universe(universe_id=102) 131 | u_fuel.add_cells( 132 | [fuel_cell_inner, fuel_cell_outer]) 133 | 134 | u_monolith = openmc.Universe(universe_id=200, 135 | cells=(monolith_cell,)) 136 | 137 | u_reflect = openmc.Universe(universe_id=300, 138 | cells=(reflect_cell,)) 139 | 140 | u_root = openmc.Universe(universe_id=400) 141 | 142 | ################# Lattice ################# 143 | 144 | lattice = openmc.HexLattice() 145 | lattice.center = (0.0,0.0) 146 | lattice.pitch = (1.88,) 147 | lattice.outer = u_monolith 148 | 149 | ring1 = [u_pipe] 150 | ring2 = [u_fuel,u_mod,u_fuel, 151 | u_mod,u_fuel,u_mod] 152 | ring3 = [u_mod,u_pipe,u_fuel, 153 | u_pipe,u_mod,u_pipe, 154 | u_fuel,u_pipe,u_mod, 155 | u_pipe,u_fuel,u_pipe] 156 | ring4 = [u_pipe,u_fuel,u_mod, 157 | u_pipe,u_mod,u_fuel, 158 | u_pipe,u_fuel,u_mod, 159 | u_pipe,u_mod,u_fuel, 160 | u_pipe,u_fuel,u_mod, 161 | u_pipe,u_mod,u_fuel] 162 | ring5 = [u_fuel,u_mod,u_pipe, 163 | u_fuel,u_mod,u_fuel, 164 | u_pipe,u_mod,u_fuel, 165 | u_mod,u_pipe,u_fuel, 166 | u_mod,u_fuel,u_pipe, 167 | u_mod,u_fuel,u_mod, 168 | u_pipe,u_fuel,u_mod, 169 | u_fuel,u_pipe,u_mod] 170 | ring6 = [u_mod,u_pipe,u_fuel, 171 | u_mod,u_pipe,u_fuel, 172 | u_pipe,u_mod,u_fuel, 173 | u_pipe,u_mod,u_pipe, 174 | u_fuel,u_mod,u_pipe, 175 | u_fuel,u_pipe,u_mod, 176 | u_fuel,u_pipe,u_mod, 177 | u_pipe,u_fuel,u_mod, 178 | u_pipe,u_fuel,u_pipe, 179 | u_mod,u_fuel,u_pipe] 180 | ring7 = [u_pipe,u_fuel,u_mod, 181 | u_pipe,u_fuel,u_mod, 182 | u_pipe,u_mod,u_fuel, 183 | u_pipe,u_mod,u_fuel, 184 | u_pipe,u_fuel,u_mod, 185 | u_pipe,u_fuel,u_mod, 186 | u_pipe,u_mod,u_fuel, 187 | u_pipe,u_mod,u_fuel, 188 | u_pipe,u_fuel,u_mod, 189 | u_pipe,u_fuel,u_mod, 190 | u_pipe,u_mod,u_fuel, 191 | u_pipe,u_mod,u_fuel] 192 | ring8 = [u_fuel,u_mod,u_pipe, 193 | u_fuel,u_mod,u_pipe, 194 | u_fuel,u_mod,u_fuel, 195 | u_pipe,u_mod,u_fuel, 196 | u_pipe,u_mod,u_fuel, 197 | u_mod,u_pipe,u_fuel, 198 | u_mod,u_pipe,u_fuel, 199 | u_mod,u_fuel,u_pipe, 200 | u_mod,u_fuel,u_pipe, 201 | u_mod,u_fuel,u_mod, 202 | u_pipe,u_fuel,u_mod, 203 | u_pipe,u_fuel,u_mod, 204 | u_fuel,u_pipe,u_mod, 205 | u_fuel,u_pipe,u_mod] 206 | ring9=[u_mod]*48 207 | 208 | lattice.universes = \ 209 | [ring9,ring8,ring7,ring6,ring5,ring4,ring3,ring2,ring1] 210 | assembly_cell.fill = lattice 211 | u_root.add_cells( 212 | [assembly_cell, reflect_cell]) 213 | 214 | print(lattice) 215 | geom = openmc.Geometry(u_root) 216 | geom.export_to_xml() 217 | 218 | ######################## 219 | # Plot 220 | ######################## 221 | 222 | # xy plot 223 | plt.figure(figsize=(12,12)) 224 | u_root.plot(origin=(0,0,0),width=(50,60),color_by='material',pixels=[400,400]) 225 | plt.savefig('Plot') 226 | plt.clf() 227 | 228 | ####################### 229 | # Run Settings 230 | ####################### 231 | 232 | uniform_dist = openmc.stats.Box([-24,-24,-1],[24,24,1],only_fissionable=True) 233 | 234 | settings = openmc.Settings() 235 | settings.output = {'tallies':False} 236 | settings.seed = 1 237 | settings.batches = 200 238 | settings.inactive = 100 239 | settings.particles = 1000 240 | settings.source = openmc.source.Source(space=uniform_dist) 241 | settings.trigger_active = True 242 | settings.trigger_max_batches = settings.batches * 4 243 | settings.temperature = {'multipole': True, 'method': 'interpolation', 'range': [290,2501]} 244 | settings.export_to_xml() 245 | 246 | ####################### 247 | # MGXS Settings 248 | ###################### 249 | 250 | ############ Set the domain ########### 251 | # If domain_type = 'material', 252 | # assign the list of desired materials to domain (eg [fuel_mat, water_mat]); 253 | # if all materials are desired, use geom.get_all_materials().values 254 | 255 | # If domain_type = 'cell' 256 | # assign the list of desired materials to domain (eg [fuel_cell, water_cell]); 257 | # if all cells are desired, use geom.get_all_material_cells().values() 258 | 259 | # If domain_type = 'mesh' 260 | # assign the list of desired meshes to domain (eg [mesh]); 261 | 262 | # subdomain_to_plot will be the subdomain whose mgxs are plotted. 263 | # To define subdomain_to_plot 264 | # use the name of a material or cell 265 | # this requires setting a name when defining this material or cell, 266 | # and if domain_type = 'mesh', enter a blank string '' since that cannot be plotted. 267 | 268 | domain_type = 'material' 269 | domain = geom.get_all_materials().values() 270 | subdomain_to_plot = fuel_mat 271 | 272 | # ################# Mesh ################# 273 | # Create a mesh over the geometry. 274 | # If domain = 'mesh' 275 | # the mgxs will be generated on this mesh. 276 | # If quantify_error = True, 277 | # a 2D fission RR error plot will be generated on this mesh. 278 | mesh = openmc.RegularMesh() 279 | mesh.dimension = [170,170] 280 | mesh.lower_left = [-14,-16.165] 281 | mesh.upper_right = [14,16.165] 282 | 283 | ###################### 284 | #end example -------------------------------------------------------------------------------- /testreactor_slab2_inp.py: -------------------------------------------------------------------------------- 1 | # OpenMC input deck for testbed reactor model 2 | 3 | ################################################ 4 | # Imports 5 | ################################################ 6 | 7 | import openmc 8 | import matplotlib.pyplot as plt 9 | import openmc.checkvalue as cv 10 | from mgxs import * 11 | 12 | ################################################ 13 | # Define Materials 14 | ################################################ 15 | 16 | fuel_mat = openmc.Material(material_id=1, name='fuel_mat') 17 | fuel_mat.temperature = 900. 18 | fuel_mat.add_nuclide('U235',0.2) 19 | fuel_mat.add_nuclide('U238',0.8) 20 | fuel_mat.add_nuclide('H1',1.0) 21 | fuel_mat.add_element('Zr',1.0) 22 | fuel_mat.set_density('g/cm3',9.8) 23 | # fuel_mat.add_s_alpha_beta('c_Zr_in_ZrH') 24 | # fuel_mat.add_s_alpha_beta('c_H_in_ZrH') 25 | 26 | mod_mat = openmc.Material(material_id=2, name='mod_mat') 27 | mod_mat.add_element('Zr',1.0) 28 | mod_mat.add_nuclide('H1',2.0) 29 | mod_mat.set_density('g/cm3',5.6) 30 | # mod_mat.add_s_alpha_beta('c_Zr_in_ZrH') 31 | # mod_mat.add_s_alpha_beta('c_H_in_ZrH') 32 | 33 | vapor_mat = openmc.Material(material_id=3, name='vapor_mat') 34 | vapor_mat.add_nuclide('Na23',1.0) 35 | vapor_mat.set_density('g/cm3',0.1) 36 | 37 | pipe_mat = openmc.Material(material_id=4, name='pipe_mat') 38 | pipe_mat.add_element('Mo',1.0) 39 | pipe_mat.set_density('g/cm3',8.0) 40 | 41 | monolith_mat = openmc.Material(material_id=5, name='monolith_mat') 42 | monolith_mat.add_nuclide('C0',1.0) 43 | monolith_mat.set_density('g/cm3',1.75) 44 | # monolith_mat.add_s_alpha_beta('c_Graphite') 45 | 46 | reflector_mat = openmc.Material(material_id=6, name='reflector_mat') 47 | reflector_mat.add_nuclide('Be9',1.0) 48 | reflector_mat.add_nuclide('O16',1.0) 49 | reflector_mat.set_density('g/cm3',2.9) 50 | # reflector_mat.add_s_alpha_beta('c_Be_in_BeO') 51 | # reflector_mat.add_s_alpha_beta('c_O_in_BeO') 52 | 53 | materials = openmc.Materials([fuel_mat,mod_mat,vapor_mat,pipe_mat,monolith_mat,reflector_mat]) 54 | materials.export_to_xml() 55 | 56 | ################################################ 57 | # Define Geometry 58 | ################################################ 59 | 60 | ################# Surfaces ################# 61 | 62 | # ZCylinders to model pins 63 | pipe_inner = openmc.ZCylinder(surface_id=100, x0=0, y0=0, r=0.6) 64 | pipe_outer = openmc.ZCylinder(surface_id=101, x0=0, y0=0, r=0.7) 65 | mod_r = openmc.ZCylinder(surface_id=102, x0=0, y0=0, r=0.75) 66 | fuel_r = openmc.ZCylinder(surface_id=103, x0=0, y0=0, r=0.8) 67 | 68 | # top & bottom of the assembly 69 | assembly_z0 = openmc.ZPlane(surface_id=300, z0=-1, boundary_type='reflective') 70 | assembly_z1 = openmc.ZPlane(surface_id=301, z0=1, boundary_type='reflective') 71 | 72 | # assembly hexagon 73 | assembly = openmc.model.hexagonal_prism(edge_length=16.166, orientation='y') 74 | 75 | # reflector hexagon 76 | reflector = openmc.model.hexagonal_prism(edge_length=27.713, orientation='y', 77 | boundary_type='vacuum') 78 | 79 | ################# Cells ################# 80 | 81 | pipe_cell_inner = openmc.Cell(name= 'pipe_cell_inner', cell_id=100) 82 | pipe_cell_wall = openmc.Cell(name= 'pipe_cell_wall', cell_id=101) 83 | pipe_cell_outer = openmc.Cell(name= 'pipe_cell_outer', cell_id=102) 84 | mod_cell_inner = openmc.Cell(name= 'mod_cell_inner', cell_id=103) 85 | mod_cell_outer = openmc.Cell(name= 'mod_cell_outer', cell_id=104) 86 | fuel_cell_inner = openmc.Cell(name= 'fuel_cell_inner', cell_id=105) 87 | fuel_cell_outer = openmc.Cell(name= 'fuel_cell_outer', cell_id=106) 88 | 89 | monolith_cell = openmc.Cell(name= '', cell_id=201) 90 | assembly_cell = openmc.Cell(name= '', cell_id=301) 91 | 92 | reflect_cell = openmc.Cell(name= '', cell_id=401) 93 | 94 | ################# Regions ################# 95 | 96 | pipe_cell_inner.region = -pipe_inner & -assembly_z1 & +assembly_z0 97 | pipe_cell_wall.region = -pipe_outer & + pipe_inner & -assembly_z1 & +assembly_z0 98 | pipe_cell_outer.region = +pipe_outer & -assembly_z1 & +assembly_z0 99 | mod_cell_inner.region = -mod_r & -assembly_z1 & +assembly_z0 100 | mod_cell_outer.region = +mod_r & -assembly_z1 & +assembly_z0 101 | fuel_cell_inner.region = -fuel_r & -assembly_z1 & +assembly_z0 102 | fuel_cell_outer.region = +fuel_r & -assembly_z1 & +assembly_z0 103 | 104 | assembly_cell.region = assembly & -assembly_z1 & +assembly_z0 105 | 106 | reflect_cell.region = ~assembly & reflector & -assembly_z1 & +assembly_z0 107 | 108 | # fill cells with material 109 | pipe_cell_inner.fill = vapor_mat 110 | pipe_cell_wall.fill = pipe_mat 111 | pipe_cell_outer.fill = monolith_mat 112 | mod_cell_inner.fill = mod_mat 113 | mod_cell_outer.fill = monolith_mat 114 | fuel_cell_inner.fill = fuel_mat 115 | fuel_cell_outer.fill = monolith_mat 116 | monolith_cell.fill = monolith_mat 117 | 118 | reflect_cell.fill = reflector_mat 119 | 120 | ################# Universes ################# 121 | 122 | u_pipe = openmc.Universe(universe_id=100) 123 | u_pipe.add_cells( 124 | [pipe_cell_inner, pipe_cell_wall, pipe_cell_outer]) 125 | 126 | u_mod = openmc.Universe(universe_id=101) 127 | u_mod.add_cells( 128 | [mod_cell_inner, mod_cell_outer]) 129 | 130 | u_fuel = openmc.Universe(universe_id=102) 131 | u_fuel.add_cells( 132 | [fuel_cell_inner, fuel_cell_outer]) 133 | 134 | u_monolith = openmc.Universe(universe_id=200, 135 | cells=(monolith_cell,)) 136 | 137 | u_reflect = openmc.Universe(universe_id=300, 138 | cells=(reflect_cell,)) 139 | 140 | u_root = openmc.Universe(universe_id=400) 141 | 142 | ################# Lattice ################# 143 | 144 | lattice = openmc.HexLattice() 145 | lattice.center = (0.0,0.0) 146 | lattice.pitch = (1.88,) 147 | lattice.outer = u_monolith 148 | 149 | ring1 = [u_pipe] 150 | ring2 = [u_fuel,u_mod,u_fuel, 151 | u_mod,u_fuel,u_mod] 152 | ring3 = [u_mod,u_pipe,u_fuel, 153 | u_pipe,u_mod,u_pipe, 154 | u_fuel,u_pipe,u_mod, 155 | u_pipe,u_fuel,u_pipe] 156 | ring4 = [u_pipe,u_fuel,u_mod, 157 | u_pipe,u_mod,u_fuel, 158 | u_pipe,u_fuel,u_mod, 159 | u_pipe,u_mod,u_fuel, 160 | u_pipe,u_fuel,u_mod, 161 | u_pipe,u_mod,u_fuel] 162 | ring5 = [u_fuel,u_mod,u_pipe, 163 | u_fuel,u_mod,u_fuel, 164 | u_pipe,u_mod,u_fuel, 165 | u_mod,u_pipe,u_fuel, 166 | u_mod,u_fuel,u_pipe, 167 | u_mod,u_fuel,u_mod, 168 | u_pipe,u_fuel,u_mod, 169 | u_fuel,u_pipe,u_mod] 170 | ring6 = [u_mod,u_pipe,u_fuel, 171 | u_mod,u_pipe,u_fuel, 172 | u_pipe,u_mod,u_fuel, 173 | u_pipe,u_mod,u_pipe, 174 | u_fuel,u_mod,u_pipe, 175 | u_fuel,u_pipe,u_mod, 176 | u_fuel,u_pipe,u_mod, 177 | u_pipe,u_fuel,u_mod, 178 | u_pipe,u_fuel,u_pipe, 179 | u_mod,u_fuel,u_pipe] 180 | ring7 = [u_pipe,u_fuel,u_mod, 181 | u_pipe,u_fuel,u_mod, 182 | u_pipe,u_mod,u_fuel, 183 | u_pipe,u_mod,u_fuel, 184 | u_pipe,u_fuel,u_mod, 185 | u_pipe,u_fuel,u_mod, 186 | u_pipe,u_mod,u_fuel, 187 | u_pipe,u_mod,u_fuel, 188 | u_pipe,u_fuel,u_mod, 189 | u_pipe,u_fuel,u_mod, 190 | u_pipe,u_mod,u_fuel, 191 | u_pipe,u_mod,u_fuel] 192 | ring8 = [u_fuel,u_mod,u_pipe, 193 | u_fuel,u_mod,u_pipe, 194 | u_fuel,u_mod,u_fuel, 195 | u_pipe,u_mod,u_fuel, 196 | u_pipe,u_mod,u_fuel, 197 | u_mod,u_pipe,u_fuel, 198 | u_mod,u_pipe,u_fuel, 199 | u_mod,u_fuel,u_pipe, 200 | u_mod,u_fuel,u_pipe, 201 | u_mod,u_fuel,u_mod, 202 | u_pipe,u_fuel,u_mod, 203 | u_pipe,u_fuel,u_mod, 204 | u_fuel,u_pipe,u_mod, 205 | u_fuel,u_pipe,u_mod] 206 | ring9=[u_mod]*48 207 | 208 | lattice.universes = \ 209 | [ring9,ring8,ring7,ring6,ring5,ring4,ring3,ring2,ring1] 210 | assembly_cell.fill = lattice 211 | u_root.add_cells( 212 | [assembly_cell, reflect_cell]) 213 | 214 | print(lattice) 215 | geom = openmc.Geometry(u_root) 216 | geom.export_to_xml() 217 | 218 | ######################## 219 | # Plot 220 | ######################## 221 | 222 | # xy plot 223 | plt.figure(figsize=(12,12)) 224 | u_root.plot(origin=(0,0,0),width=(50,60),color_by='material',pixels=[400,400]) 225 | plt.savefig('Plot') 226 | plt.clf() 227 | 228 | ####################### 229 | # Run Settings 230 | ####################### 231 | 232 | uniform_dist = openmc.stats.Box([-24,-24,-1],[24,24,1],only_fissionable=True) 233 | 234 | settings = openmc.Settings() 235 | settings.output = {'tallies':False} 236 | settings.seed = 1 237 | settings.batches = 200 238 | settings.inactive = 100 239 | settings.particles = 1000 240 | settings.source = openmc.source.Source(space=uniform_dist) 241 | settings.trigger_active = True 242 | settings.trigger_max_batches = settings.batches * 4 243 | settings.temperature = {'multipole': True, 'method': 'interpolation', 'range': [290,2501]} 244 | settings.export_to_xml() 245 | 246 | ####################### 247 | # MGXS Settings 248 | ###################### 249 | 250 | ############ Set the domain ########### 251 | # If domain_type = 'material', 252 | # assign the list of desired materials to domain (eg [fuel_mat, water_mat]); 253 | # if all materials are desired, use geom.get_all_materials().values 254 | 255 | # If domain_type = 'cell' 256 | # assign the list of desired materials to domain (eg [fuel_cell, water_cell]); 257 | # if all cells are desired, use geom.get_all_material_cells().values() 258 | 259 | # If domain_type = 'mesh' 260 | # assign the list of desired meshes to domain (eg [mesh]); 261 | 262 | # subdomain_to_plot will be the subdomain whose mgxs are plotted. 263 | # To define subdomain_to_plot 264 | # use the name of a material or cell 265 | # this requires setting a name when defining this material or cell, 266 | # and if domain_type = 'mesh', enter a blank string '' since that cannot be plotted. 267 | 268 | domain_type = 'material' 269 | domain = geom.get_all_materials().values() 270 | subdomain_to_plot = fuel_mat 271 | 272 | # ################# Mesh ################# 273 | # Create a mesh over the geometry. 274 | # If domain = 'mesh' 275 | # the mgxs will be generated on this mesh. 276 | # If quantify_error = True, 277 | # a 2D fission RR error plot will be generated on this mesh. 278 | mesh = openmc.RegularMesh() 279 | mesh.dimension = [170,170] 280 | mesh.lower_left = [-14,-16.165] 281 | mesh.upper_right = [14,16.165] 282 | 283 | ###################### 284 | #end example -------------------------------------------------------------------------------- /yakxs.py: -------------------------------------------------------------------------------- 1 | from collections import OrderedDict 2 | import h5py 3 | from itertools import product 4 | import numpy as np 5 | from xml.etree import ElementTree as ET 6 | 7 | import openmc 8 | from openmc._xml import clean_indentation 9 | from getfilename import * 10 | 11 | class YAKXS: 12 | 13 | def __init__(self, LibraryName, NGroup, equivalence): 14 | 15 | self.yakxs = ET.Element("YakXs") 16 | self.root = ET.SubElement(self.yakxs, "Multigroup_Cross_Section_Libraries") 17 | self.root.set("Name", LibraryName) 18 | self.root.set("NGroup", NGroup) 19 | if equivalence: 20 | self.equivalence = ET.SubElement(self.yakxs, "Equivalence_Data_Library") 21 | self.equivalence.set("Name", LibraryName) 22 | self.equivalence.set("NGroup", NGroup) 23 | 24 | def export_to_xml(self, NGroups, num_delayed_groups, mgxs_types, legendre_order, 25 | equivalence, mgxs_libs, tabulation, Description="", Generator="", 26 | TimeCreated="", mgxs_bynuclide=[], mgxs_tablewise =[], mgxs_librarywise =[]): 27 | 28 | hf = h5py.File('0_mgxs.h5', 'r') 29 | ID = 0 30 | 31 | fn = FileName() 32 | fn.get_filename(ending="_mgxs.h5") 33 | 34 | if equivalence: 35 | fn2 = FileName() 36 | fn3 = FileName() 37 | fn2.get_filename(ending="statepoint_ce.h5") 38 | fn3.get_filename(ending="summary_ce.h5") 39 | 40 | for name in list(hf): 41 | ID += 1 42 | 43 | groups = list(hf[name]) 44 | reactions = list(hf[name][groups[0]]) 45 | mgxs_tablewise = reactions 46 | if 'transport' in mgxs_types: 47 | reactions.append('transport') 48 | 49 | ################# Header elements ################ 50 | library = ET.SubElement(self.root, "Multigroup_Cross_Section_Library") 51 | library.set("ID", str(ID)) 52 | library.set("Description", Description+name) 53 | library.set("Ver", str(1.0)) 54 | library.set("Generator", Generator) 55 | library.set("TimeCreated", TimeCreated) 56 | 57 | if equivalence: 58 | equivalence_data = ET.SubElement(self.equivalence, "EquivalenceData") 59 | equivalence_data.set("ID", str(ID)) 60 | 61 | ################# Tabulation elements ################ 62 | GridCoordNames = ET.SubElement(library, "Tabulation") 63 | ReferenceGridIndex = ET.SubElement(library, "ReferenceGridIndex") 64 | GridCoordNames.text = "" 65 | ReferenceGridIndex.text = "" 66 | IndexDict = OrderedDict() 67 | 68 | if equivalence: 69 | GridCoordNames2 = ET.SubElement(equivalence_data, "Tabulation") 70 | ReferenceGridIndex2 = ET.SubElement(equivalence_data, "ReferenceGridIndex") 71 | 72 | for key in tabulation: 73 | IndexDict[key] = {} 74 | ReferenceGridIndex.text = \ 75 | ReferenceGridIndex.text+str(len(tabulation[key]))+" " 76 | GridCoordNames.text = GridCoordNames.text+key+" " 77 | variable = ET.SubElement(library, key) 78 | if equivalence: 79 | variable2 = ET.SubElement(equivalence_data, key) 80 | values = "" 81 | countvalue = 0 82 | for value in tabulation[key]: 83 | countvalue = countvalue+1 84 | IndexDict[key].update({value: countvalue}) 85 | values = values+str(value)+" " 86 | variable.text = values[:-1] 87 | if equivalence: 88 | variable2.text = values[:-1] 89 | ReferenceGridIndex.text = ReferenceGridIndex.text[:-1] 90 | GridCoordNames.text = GridCoordNames.text[:-1] 91 | if equivalence: 92 | GridCoordNames2.text = GridCoordNames.text 93 | ReferenceGridIndex2.text = ReferenceGridIndex.text 94 | 95 | AllReactions = ET.SubElement(library, "AllReactions") 96 | AllReactions.text = self.ReactionTypes(reactions) 97 | 98 | TablewiseReactions = ET.SubElement(library, "TablewiseReactions") 99 | TablewiseReactions.text = self.ReactionTypes(mgxs_tablewise) 100 | 101 | ################# Tables: permutations of tabulation ################ 102 | for i, f in enumerate(fn.listfn): 103 | 104 | Table = ET.SubElement(library, "Table") 105 | Table.set("gridIndex", str(i+1)) 106 | if equivalence: 107 | Table2 = ET.SubElement(equivalence_data, "Table") 108 | Table2.set("gridIndex", str(i+1)) 109 | Flux = ET.SubElement(Table2, "Flux") 110 | Flux.text = "" 111 | 112 | SPCE = openmc.StatePoint(fn2.listfn[i]) 113 | if mgxs_libs[i].domain_type == 'mesh': 114 | t = SPCE.get_tally(id=301) 115 | for E in range(NGroups): 116 | result = t.mean[ID-1 + E*len(list(hf))] 117 | Flux.text = Flux.text+str(result[0][0])+" " 118 | else: 119 | t = SPCE.get_tally(name=name) 120 | for result in t.mean: 121 | Flux.text = Flux.text+str(result[0][0])+" " 122 | Flux.text = Flux.text[:-1] 123 | 124 | Isotope = ET.SubElement(Table, "Isotope") 125 | Isotope.set("Name", "pseudo") 126 | Isotope.set("L", str(legendre_order)) 127 | Isotope.set("I", str(num_delayed_groups)) 128 | 129 | Tablewise = ET.SubElement(Table, "Tablewise") 130 | Tablewise.set("L", str(legendre_order)) 131 | Tablewise.set("I", str(num_delayed_groups)) 132 | 133 | datafile = h5py.File(f,'r') 134 | for rxn in reactions: 135 | 136 | if rxn == 'total' or rxn == 'transport': 137 | if rxn == 'total': 138 | Reaction = ET.SubElement(Tablewise, 'Total') 139 | elif rxn == 'transport': 140 | Reaction = ET.SubElement(Tablewise, 'Transport') 141 | Reaction.set("index", 'g') 142 | Reaction.text = "" 143 | if mgxs_libs[i].domain_type == 'mesh': 144 | data = mgxs_libs[i].get_mgxs(mgxs_libs[i].domains[0], rxn 145 | ).get_xs()[ID-1] 146 | else: 147 | for j, domain in enumerate(mgxs_libs[i].domains): 148 | if j == ID-1: 149 | data = mgxs_libs[i].get_mgxs(domain, rxn).get_xs() 150 | for d in data: 151 | Reaction.text = Reaction.text+str(d)+" " 152 | Reaction.text = Reaction.text[:-1] 153 | 154 | if rxn in self.Conversion: 155 | Reaction = ET.SubElement(Tablewise, self.Conversion[rxn]) 156 | Reaction.set("index", self.DefaultIndex[rxn]) 157 | Reaction.text = "" 158 | 159 | # For scattering data 160 | if rxn == 'scatter_data': 161 | Reaction.set("profile", str(1)) 162 | Profile = ET.SubElement(Reaction, "Profile") 163 | Value = ET.SubElement(Reaction, "Value") 164 | 165 | g_min = list(datafile[name][groups[0]][rxn]['g_min']) 166 | g_max = list(datafile[name][groups[0]][rxn]['g_max']) 167 | data = list(datafile[name][groups[0]][rxn]['scatter_matrix']) 168 | 169 | Profile.text = "\n" 170 | Value.text = "\n" 171 | 172 | for j in range(legendre_order+1): 173 | for k in range(len(g_min)): 174 | Profile.text = Profile.text+str( 175 | g_min[i])+" "+str(g_max[k])+"\n" 176 | for j in range(legendre_order+1): 177 | count = 0 178 | for g_in in range(NGroups): 179 | for g_out in range(g_min[g_in]-1,g_max[g_in]): 180 | Value.text = Value.text+str(data[j+( 181 | legendre_order+1)*count])+" " 182 | count = count+1 183 | Value.text = Value.text+"\n" 184 | 185 | #For non-scattering data 186 | else: 187 | data = list(datafile[name][groups[0]][rxn]) 188 | for d in data: 189 | if rxn == 'inverse-velocity': 190 | Reaction.text = Reaction.text+str(1/d)+" " 191 | elif rxn == 'chi-delayed' or rxn == 'beta': 192 | for g in d: 193 | Reaction.text = Reaction.text+str(g)+" " 194 | else: 195 | Reaction.text = Reaction.text+str(d)+" " 196 | Reaction.text = Reaction.text[:-1] 197 | 198 | Librarywise = ET.SubElement(library, "Librarywise") 199 | Librarywise.set("L", str(legendre_order)) 200 | Librarywise.set("I", str(num_delayed_groups)) 201 | 202 | clean_indentation(self.yakxs) 203 | tree = ET.ElementTree(self.yakxs) 204 | tree.write('./mgxs.xml', xml_declaration=True, encoding='utf-8') 205 | 206 | def ReactionTypes(self, mgxs_types): 207 | 208 | self.Conversion = { 209 | "absorption": 'Absorption', 210 | "fission": 'Fission', 211 | "scatter matrix": 'Scattering', 212 | "scatter_data": 'Scattering', 213 | "nu-fission": 'nuFission', 214 | "kappa-fission": 'kappaFission', 215 | "chi": 'FissionSpectrum', 216 | "chi-delayed": 'DNSpectrum', 217 | "inverse-velocity": 'NeutronVelocity', 218 | "decay-rate": 'DNPlambda', 219 | "beta": 'DNFraction' 220 | } 221 | 222 | self.DefaultIndex = { 223 | "absorption": 'g', 224 | "fission": 'g', 225 | "scatter matrix": 'pgl', 226 | "scatter_data": 'pgl', 227 | "nu-fission": 'p', 228 | "kappa-fission": 'g', 229 | "chi": 'g', 230 | "chi-delayed": 'gi', 231 | "inverse-velocity": 'g', 232 | "decay-rate": 'i', 233 | "beta": "pi" 234 | } 235 | 236 | text = "" 237 | for mgxs in mgxs_types: 238 | if mgxs in self.Conversion: 239 | text = text+self.Conversion[mgxs]+" " 240 | if mgxs == 'total': 241 | text = text+"Total"+" " 242 | if mgxs == 'transport': 243 | text = text+"Transport"+" " 244 | text = text[:-1] 245 | 246 | return text 247 | --------------------------------------------------------------------------------