OpenMC/scripts/openmc-update-mgxs
2020-01-27 13:59:04 -06:00

212 lines
7.2 KiB
Python
Executable file

#!/usr/bin/env python3
"""Update OpenMC's deprecated multi-group cross section XML files to the latest
HDF5-based format.
"""
import os
import warnings
import xml.etree.ElementTree as ET
import argparse
import numpy as np
import openmc.mgxs_library
def parse_args():
"""Read the input files from the commandline."""
# Create argument parser
parser = argparse.ArgumentParser(description=__doc__,
formatter_class=argparse.RawTextHelpFormatter)
parser.add_argument('-i', '--input', type=argparse.FileType('r'),
help='input XML file')
parser.add_argument('-o', '--output', nargs='?', default='',
help='output file, in HDF5 format')
args = vars(parser.parse_args())
if args['output'] == '':
filename = args['input'].name
extension = os.path.splitext(filename)
if extension == '.xml':
filename = filename[:filename.rfind('.')] + '.h5'
args['output'] = filename
# Parse and return commandline arguments.
return args
def get_data(element, entry):
value = element.find(entry)
if value is not None:
value = value.text.strip()
elif entry in element.attrib:
value = element.attrib[entry].strip()
else:
value = None
return value
def main():
args = parse_args()
# Parse the XML data.
tree = ET.parse(args['input'])
root = tree.getroot()
# Get old metadata
group_structure = tree.find('group_structure').text.strip()
group_structure = np.array(group_structure.split(), dtype=float)
# Convert from MeV to eV
group_structure *= 1.e6
energy_groups = openmc.mgxs.EnergyGroups(group_structure)
inverse_velocity = tree.find('inverse-velocity')
if inverse_velocity is not None:
inverse_velocity = inverse_velocity.text.split()
inverse_velocity = np.array(inverse_velocity, dtype=float)
else:
inverse_velocity = None
xsd = []
names = []
# Now move on to the cross section data itself
for xsdata_elem in root.iter('xsdata'):
name = get_data(xsdata_elem, 'name')
temperature = get_data(xsdata_elem, 'kT')
if temperature is not None:
temperature = float(temperature) / openmc.data.K_BOLTZMANN * 1.E6
else:
temperature = 294.
temperatures = [temperature]
awr = get_data(xsdata_elem, 'awr')
if awr is not None:
awr = float(awr)
representation = get_data(xsdata_elem, 'representation')
if representation is None:
representation = 'isotropic'
if representation == 'angle':
n_azi = int(get_data(xsdata_elem, 'num_azimuthal'))
n_pol = int(get_data(xsdata_elem, 'num_polar'))
scatter_format = get_data(xsdata_elem, 'scatt_type')
if scatter_format is None:
scatter_format = 'legendre'
order = int(get_data(xsdata_elem, 'order'))
tab_leg = get_data(xsdata_elem, 'tabular_legendre')
if tab_leg is not None:
warnings.warn('The tabular_legendre option has moved to the '
'settings.xml file and must be added manually')
# Either add the data to a previously existing xsdata (if it is
# for the same 'name' but a different temperature), or create a
# new one.
try:
# It is in our list, so store that entry
i = names.index(name)
except ValueError:
# It is not in our list, so add it
i = -1
xsd.append(openmc.XSdata(name, energy_groups,
temperatures=temperatures,
representation=representation))
if awr is not None:
xsd[-1].atomic_weight_ratio = awr
if representation == 'angle':
xsd[-1].num_azimuthal = n_azi
xsd[-1].num_polar = n_pol
xsd[-1].scatter_format = scatter_format
xsd[-1].order = order
names.append(name)
if scatter_format == 'legendre':
order_dim = order + 1
else:
order_dim = order
if i != -1:
xsd[i].add_temperature(temperature)
total = get_data(xsdata_elem, 'total')
if total is not None:
total = np.array(total.split(), dtype=float)
total.shape = xsd[i].xs_shapes['[G]']
xsd[i].set_total(total, temperature)
if inverse_velocity is not None:
xsd[i].set_inverse_velocity(inverse_velocity, temperature)
absorption = get_data(xsdata_elem, 'absorption')
absorption = np.array(absorption.split(), dtype=float)
absorption.shape = xsd[i].xs_shapes['[G]']
xsd[i].set_absorption(absorption, temperature)
scatter = get_data(xsdata_elem, 'scatter')
scatter = np.array(scatter.split(), dtype=float)
# This is now a flattened-array of something that started with a
# shape of [Order][G][G']; we need to unflatten and then switch the
# ordering
in_shape = (order_dim, energy_groups.num_groups,
energy_groups.num_groups)
if representation == 'angle':
in_shape = (n_pol, n_azi) + in_shape
scatter.shape = in_shape
scatter = np.swapaxes(scatter, 2, 3)
scatter = np.swapaxes(scatter, 3, 4)
else:
scatter.shape = in_shape
scatter = np.swapaxes(scatter, 0, 1)
scatter = np.swapaxes(scatter, 1, 2)
xsd[i].set_scatter_matrix(scatter, temperature)
multiplicity = get_data(xsdata_elem, 'multiplicity')
if multiplicity is not None:
multiplicity = np.array(multiplicity.split(), dtype=float)
multiplicity.shape = xsd[i].xs_shapes["[G][G']"]
xsd[i].set_multiplicity_matrix(multiplicity, temperature)
fission = get_data(xsdata_elem, 'fission')
if fission is not None:
fission = np.array(fission.split(), dtype=float)
fission.shape = xsd[i].xs_shapes['[G]']
xsd[i].set_fission(fission, temperature)
kappa_fission = get_data(xsdata_elem, 'kappa_fission')
if kappa_fission is not None:
kappa_fission = np.array(kappa_fission.split(), dtype=float)
kappa_fission.shape = xsd[i].xs_shapes['[G]']
xsd[i].set_kappa_fission(kappa_fission, temperature)
chi = get_data(xsdata_elem, 'chi')
if chi is not None:
chi = np.array(chi.split(), dtype=float)
chi.shape = xsd[i].xs_shapes['[G]']
xsd[i].set_chi(chi, temperature)
else:
chi = None
nu_fission = get_data(xsdata_elem, 'nu_fission')
if nu_fission is not None:
nu_fission = np.array(nu_fission.split(), dtype=float)
if chi is not None:
nu_fission.shape = xsd[i].xs_shapes['[G]']
else:
nu_fission.shape = xsd[i].xs_shapes["[G][G']"]
xsd[i].set_nu_fission(nu_fission, temperature)
# Build library as we go, but first we have enough to initialize it
lib = openmc.MGXSLibrary(energy_groups)
lib.add_xsdatas(xsd)
lib.export_to_hdf5(args['output'])
if __name__ == '__main__':
main()