mirror of
https://github.com/openmc-dev/openmc.git
synced 2026-07-28 14:15:42 -04:00
Removed MultiGroupXS.pickle/unpickle routines, added initial implementatoin for micro multi-group cross-sectoins
This commit is contained in:
parent
4f86e8819a
commit
ddb249049c
1 changed files with 260 additions and 173 deletions
|
|
@ -4,7 +4,6 @@ import os
|
|||
import sys
|
||||
import copy
|
||||
import abc
|
||||
import pickle
|
||||
|
||||
import numpy as np
|
||||
|
||||
|
|
@ -75,10 +74,11 @@ class MultiGroupXS(object):
|
|||
__metaclass__ = abc.ABCMeta
|
||||
|
||||
def __init__(self, domain=None, domain_type=None,
|
||||
energy_groups=None, name=''):
|
||||
xs_type=None, energy_groups=None, name=''):
|
||||
|
||||
self._name = ''
|
||||
self._rxn_type = None
|
||||
self._xs_type = None
|
||||
self._domain = None
|
||||
self._domain_type = None
|
||||
self._energy_groups = None
|
||||
|
|
@ -87,6 +87,8 @@ class MultiGroupXS(object):
|
|||
self._xs_tally = None
|
||||
|
||||
self.name = name
|
||||
if xs_type is not None:
|
||||
self.xs_type = xs_type
|
||||
if domain_type is not None:
|
||||
self.domain_type = domain_type
|
||||
if domain is not None:
|
||||
|
|
@ -102,6 +104,7 @@ class MultiGroupXS(object):
|
|||
clone = type(self).__new__(type(self))
|
||||
clone._name = self.name
|
||||
clone._rxn_type = self.rxn_type
|
||||
clone._xs_type = self.xs_type
|
||||
clone._domain = self.domain
|
||||
clone._domain_type = self.domain_type
|
||||
clone._energy_groups = copy.deepcopy(self.energy_groups, memo)
|
||||
|
|
@ -128,6 +131,10 @@ class MultiGroupXS(object):
|
|||
def rxn_type(self):
|
||||
return self._rxn_type
|
||||
|
||||
@property
|
||||
def xs_type(self):
|
||||
return self._xs_type
|
||||
|
||||
@property
|
||||
def domain(self):
|
||||
return self._domain
|
||||
|
|
@ -163,6 +170,11 @@ class MultiGroupXS(object):
|
|||
cv.check_type('name', name, basestring)
|
||||
self._name = name
|
||||
|
||||
@xs_type.setter
|
||||
def xs_type(self, xs_type):
|
||||
cv.check_value('xs_type', xs_type, ('macro', 'micro'))
|
||||
self._xs_type = xs_type
|
||||
|
||||
@domain.setter
|
||||
def domain(self, domain):
|
||||
cv.check_type('domain', domain, tuple(DOMAINS))
|
||||
|
|
@ -218,10 +230,16 @@ class MultiGroupXS(object):
|
|||
self.tallies[key].estimator = estimator
|
||||
self.tallies[key].add_filter(domain_filter)
|
||||
|
||||
# Add all non-domain specific Filters (i.e., 'energy') to the Tally
|
||||
# Add all non-domain specific Filters (e.g., 'energy') to the Tally
|
||||
for filter in filters:
|
||||
self.tallies[key].add_filter(filter)
|
||||
|
||||
# If this is a microscopic cross-section, add all nuclides to tally
|
||||
if self.xs_type == 'micro' and score != 'flux':
|
||||
all_nuclides = self.domain.get_all_nuclides()
|
||||
for nuclide in all_nuclides:
|
||||
self.tallies[key].add_nuclide(nuclide)
|
||||
|
||||
@abc.abstractmethod
|
||||
def compute_xs(self):
|
||||
"""Computes multi-group cross sections using OpenMC tally arithmetic."""
|
||||
|
|
@ -264,7 +282,8 @@ class MultiGroupXS(object):
|
|||
filter_bins, tally.nuclides)
|
||||
self.tallies[tally_type] = sp_tally
|
||||
|
||||
def get_xs(self, groups='all', subdomains='all', value='mean'):
|
||||
def get_xs(self, groups='all', subdomains='all',
|
||||
nuclides='all', xs_type='macro', value='mean'):
|
||||
"""Returns an array of multi-group cross sections.
|
||||
|
||||
This method constructs a 2D NumPy array for the requested multi-group
|
||||
|
|
@ -278,6 +297,13 @@ class MultiGroupXS(object):
|
|||
subdomains : Iterable of Integral or 'all'
|
||||
Subdomain IDs of interest
|
||||
|
||||
nuclides : Iterable of str or 'all'
|
||||
A list of nuclide name strings
|
||||
(e.g., ['U-235', 'U-238']; default is 'all')
|
||||
|
||||
xs_type: {'macro' or 'micro'}
|
||||
Return the macro or micro cross section in units of cm^-1 or barns
|
||||
|
||||
value : str
|
||||
A string for the type of value to return - 'mean' (default),
|
||||
'std_dev' or 'rel_err' are accepted
|
||||
|
|
@ -286,7 +312,7 @@ class MultiGroupXS(object):
|
|||
-------
|
||||
xs : ndarray
|
||||
A NumPy array of the multi-group cross section indexed in the order
|
||||
each group and subdomain is listed in the parameters.
|
||||
each group, subdomain and nuclide is listed in the parameters.
|
||||
|
||||
Raises
|
||||
------
|
||||
|
|
@ -319,9 +345,15 @@ class MultiGroupXS(object):
|
|||
filters.append('energy')
|
||||
filter_bins.append((self.energy_groups.get_group_bounds(group),))
|
||||
|
||||
# Construct list of nuclides for all requested nuclides
|
||||
if nuclides != 'all' and nuclides != ['total']:
|
||||
cv.check_iterable_type('nuclides', nuclides, basestring)
|
||||
else:
|
||||
nuclides = []
|
||||
|
||||
# Query the multi-group cross section tally for the data
|
||||
xs = self.xs_tally.get_values(filters=filters,
|
||||
filter_bins=filter_bins, value=value)
|
||||
xs = self.xs_tally.get_values(filters=filters, filter_bins=filter_bins,
|
||||
nuclides=nuclides, value=value)
|
||||
return xs
|
||||
|
||||
def get_condensed_xs(self, coarse_groups):
|
||||
|
|
@ -439,11 +471,7 @@ class MultiGroupXS(object):
|
|||
|
||||
# Clone this MultiGroupXS to initialize the subdomain-averaged version
|
||||
avg_xs = copy.deepcopy(self)
|
||||
|
||||
# If domain is distribcell, make subdomain-averaged a 'cell' domain
|
||||
if self.domain_type == 'distribcell':
|
||||
avg_xs.domain_type = 'cell'
|
||||
avg_xs._offset = 0
|
||||
avg_xs.domain_type = 'cell'
|
||||
|
||||
# Average each of the tallies across subdomains
|
||||
for tally_type, tally in avg_xs.tallies.items():
|
||||
|
|
@ -483,7 +511,7 @@ class MultiGroupXS(object):
|
|||
|
||||
return avg_xs
|
||||
|
||||
def print_xs(self, subdomains='all'):
|
||||
def print_xs(self, subdomains='all', nuclides='all'):
|
||||
"""Prints a string representation for the multi-group cross section.
|
||||
|
||||
Parameters
|
||||
|
|
@ -491,129 +519,73 @@ class MultiGroupXS(object):
|
|||
subdomains : Iterable of Integral or 'all'
|
||||
The subdomain IDs of the cross sections to include in the report
|
||||
|
||||
nuclides : Iterable of str or 'all'
|
||||
The nuclides of the cross-sections to include in the report
|
||||
|
||||
"""
|
||||
|
||||
if subdomains != 'all':
|
||||
cv.check_iterable_type('subdomains', subdomains, Integral)
|
||||
if nuclides != 'all':
|
||||
cv.check_iterable_type('nuclides', nuclides, basestring)
|
||||
else:
|
||||
if self.xs_type == 'micro':
|
||||
nuclides = self.domain.get_all_nuclides()
|
||||
else:
|
||||
nuclides = ['total']
|
||||
|
||||
# Build header for string with type and domain info
|
||||
string = 'Multi-Group XS\n'
|
||||
string += '{0: <16}=\t{1}\n'.format('\tType', self.rxn_type)
|
||||
string += '{0: <16}=\t{1}\n'.format('\tReaction Type', self.rxn_type)
|
||||
string += '{0: <16}=\t{1}\n'.format('\tDomain Type', self.domain_type)
|
||||
string += '{0: <16}=\t{1}\n'.format('\tDomain ID', self.domain.id)
|
||||
|
||||
# Append cross section data if it has been computed
|
||||
if self.xs_tally is not None:
|
||||
if subdomains == 'all':
|
||||
if self.domain_type == 'distribcell':
|
||||
subdomains = np.arange(self.num_subdomains, dtype=np.int)
|
||||
# If cross section data has not been computed, only print string header
|
||||
if self.xs_tally is None:
|
||||
print(string)
|
||||
return
|
||||
|
||||
if subdomains == 'all':
|
||||
if self.domain_type == 'distribcell':
|
||||
subdomains = np.arange(self.num_subdomains, dtype=np.int)
|
||||
else:
|
||||
subdomains = [self.domain.id]
|
||||
|
||||
# Loop over all subdomains
|
||||
for subdomain in subdomains:
|
||||
|
||||
if self.domain_type == 'distribcell':
|
||||
string += '{0: <16}=\t{1}\n'.format('\tSubdomain', subdomain)
|
||||
|
||||
# Loop over all Nuclides
|
||||
for nuclide in nuclides:
|
||||
|
||||
# Build header for cross section type based on the nuclide
|
||||
if nuclide == 'total':
|
||||
string += '{0: <16}\n'.format('\tCross Sections [cm^-1]:')
|
||||
else:
|
||||
subdomains = [self.domain.id]
|
||||
string += '{0: <16}=\t{1}\n'.format('\tNuclide', nuclide)
|
||||
string += '{0: <16}\n'.format('\tCross Sections [barns]:')
|
||||
|
||||
# Loop over all subdomains
|
||||
for subdomain in subdomains:
|
||||
|
||||
if self.domain_type == 'distribcell':
|
||||
string += '{0: <16}=\t{1}\n'.format('\tSubdomain', subdomain)
|
||||
|
||||
string += '{0: <16}\n'.format('\tCross Sections [cm^-1]:')
|
||||
template = '{0: <12}Group {1} [{2: <10} - {3: <10}MeV]:\t'
|
||||
|
||||
# Loop over energy groups ranges
|
||||
for group in range(1, self.num_groups+1):
|
||||
bounds = self.energy_groups.get_group_bounds(group)
|
||||
string += template.format('', group, bounds[0], bounds[1])
|
||||
average = self.get_xs([group], [subdomain], 'mean')
|
||||
rel_err = self.get_xs([group], [subdomain], 'rel_err')*100.
|
||||
average = self.get_xs([group], [subdomain],
|
||||
[nuclide], 'mean')
|
||||
rel_err = self.get_xs([group], [subdomain],
|
||||
[nuclide], 'rel_err') * 100.
|
||||
average = np.nan_to_num(average.flatten())[0]
|
||||
rel_err = np.nan_to_num(rel_err.flatten())[0]
|
||||
string += '{:.2e} +/- {:1.2e}%'.format(average, rel_err)
|
||||
string += '\n'
|
||||
string += '\n'
|
||||
string += '\n'
|
||||
|
||||
print(string)
|
||||
|
||||
def pickle(self, filename='mgxs', directory='mgxs'):
|
||||
"""Store the MultiGroupXS as a pickled binary file.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
filename : str
|
||||
Filename for the pickled binary file (default is 'mgxs')
|
||||
|
||||
directory : str
|
||||
Directory for the pickled binary file (default is 'mgxs')
|
||||
|
||||
"""
|
||||
|
||||
cv.check_type('filename', filename, basestring)
|
||||
cv.check_type('directory', directory, basestring)
|
||||
|
||||
# Make directory if it does not exist
|
||||
if not os.path.exists(directory):
|
||||
os.makedirs(directory)
|
||||
|
||||
# Create an empty dictionary to store the data
|
||||
xs_results = dict()
|
||||
|
||||
# Store all of this MultiGroupXS' class attributes in the dictionary
|
||||
xs_results['name'] = self.name
|
||||
xs_results['rxn_type'] = self.rxn_type
|
||||
xs_results['domain_type'] = self.domain_type
|
||||
xs_results['domain'] = self.domain
|
||||
xs_results['energy_groups'] = self.energy_groups
|
||||
xs_results['tallies'] = self.tallies
|
||||
xs_results['xs_tally'] = self.xs_tally
|
||||
xs_results['offset'] = self.offset
|
||||
xs_results['subdomain_indices'] = self.subdomain_indices
|
||||
|
||||
# Pickle the MultiGroupXS results to a binary file
|
||||
filename = directory + '/' + filename + '.pkl'
|
||||
filename = filename.replace(' ', '-')
|
||||
pickle.dump(xs_results, open(filename, 'wb'))
|
||||
|
||||
def unpickle(self, filename='mgxs', directory='mgxs'):
|
||||
"""Restore the MultiGroupXS from a pickled binary file.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
filename : str
|
||||
Filename for the pickled binary file (default is 'mgxs')
|
||||
|
||||
directory : str
|
||||
Directory for the pickled binary file (default is 'mgxs')
|
||||
|
||||
Raises
|
||||
------
|
||||
ValueError
|
||||
When the requested filename does not exist.
|
||||
|
||||
"""
|
||||
|
||||
cv.check_type('filename', filename, basestring)
|
||||
cv.check_type('directory', directory, basestring)
|
||||
|
||||
filename = directory + '/' + filename + '.pkl'
|
||||
filename = filename.replace(' ', '-')
|
||||
|
||||
# Check that the file exists
|
||||
if not os.path.exists(filename):
|
||||
msg = 'Unable to import from filename="{0}"'.format(filename)
|
||||
raise ValueError(msg)
|
||||
|
||||
# Load the pickle file into a dictionary
|
||||
xs_results = pickle.load(open(filename, 'rb'))
|
||||
|
||||
# Store the MultiGroupXS class attributes
|
||||
self.name = xs_results['name']
|
||||
self._rxn_type = xs_results['rxn_type']
|
||||
self.domain_type = xs_results['domain_type']
|
||||
self.domain = xs_results['domain']
|
||||
self.energy_groups = xs_results['energy_groups']
|
||||
self._tallies = xs_results['tallies']
|
||||
self._xs_tally = xs_results['xs_tally']
|
||||
self._offset = xs_results['offset']
|
||||
|
||||
def build_hdf5_store(self, filename='mgxs', directory='mgxs', append=True):
|
||||
"""Export the multi-group cross section data into an HDF5 binary file.
|
||||
|
||||
|
|
@ -671,6 +643,14 @@ class MultiGroupXS(object):
|
|||
else:
|
||||
xs_results = h5py.File(filename, 'w')
|
||||
|
||||
if self.xs_type == 'micro':
|
||||
nuclides = self.domain.get_all_nuclides()
|
||||
densities = []
|
||||
for nuclide in nuclides:
|
||||
densities.append(nuclides[nuclide][1])
|
||||
else:
|
||||
nuclides = ['total']
|
||||
|
||||
# Create an HDF5 group within the file for the domain
|
||||
domain_type_group = xs_results.require_group(self.domain_type)
|
||||
group_name = '{0} {1}'.format(self.domain_type, self.domain.id)
|
||||
|
|
@ -684,7 +664,7 @@ class MultiGroupXS(object):
|
|||
# Determine number of digits to pad subdomain group keys
|
||||
num_digits = len(str(self.num_subdomains))
|
||||
|
||||
# Create a separate HDF5 dataset for each subdomain
|
||||
# Create a separate HDF5 group for each subdomain
|
||||
for i, subdomain in enumerate(subdomains):
|
||||
|
||||
# Create an HDF5 group for the subdomain
|
||||
|
|
@ -695,19 +675,31 @@ class MultiGroupXS(object):
|
|||
subdomain_group = domain_group
|
||||
|
||||
# Create a separate HDF5 group for the rxn type
|
||||
xs_group = subdomain_group.require_group(self.rxn_type)
|
||||
rxn_group = subdomain_group.require_group(self.rxn_type)
|
||||
|
||||
# Extract the cross section for this
|
||||
average = self.get_xs(subdomains=[subdomain], value='mean')
|
||||
std_dev = self.get_xs(subdomains=[subdomain], value='std_dev')
|
||||
average = average.squeeze()
|
||||
std_dev = std_dev.squeeze()
|
||||
# Create a separate HDF5 group for each nuclide
|
||||
for j, nuclide in enumerate(nuclides):
|
||||
|
||||
# Add MultiGroupXS results data to the HDF5 group
|
||||
xs_group.require_dataset('average', dtype=np.float64,
|
||||
shape=average.shape, data=average)
|
||||
xs_group.require_dataset('std. dev.', dtype=np.float64,
|
||||
shape=std_dev.shape, data=std_dev)
|
||||
if nuclide != 'total':
|
||||
nuclide_group = rxn_group.require_group(nuclide)
|
||||
nuclide_group.require_dataset('density', dtype=np.float64,
|
||||
data=[densities[j]], shape=(1,))
|
||||
else:
|
||||
nuclide_group = rxn_group
|
||||
|
||||
# Extract the cross section for this subdomain and nuclide
|
||||
average = self.get_xs(subdomains=[subdomain],
|
||||
nuclides=[nuclide], value='mean')
|
||||
std_dev = self.get_xs(subdomains=[subdomain],
|
||||
nuclides=[nuclide], value='std_dev')
|
||||
average = average.squeeze()
|
||||
std_dev = std_dev.squeeze()
|
||||
|
||||
# Add MultiGroupXS results data to the HDF5 group
|
||||
nuclide_group.require_dataset('average', dtype=np.float64,
|
||||
shape=average.shape, data=average)
|
||||
nuclide_group.require_dataset('std. dev.', dtype=np.float64,
|
||||
shape=std_dev.shape, data=std_dev)
|
||||
|
||||
# Close the MultiGroup results HDF5 file
|
||||
xs_results.close()
|
||||
|
|
@ -791,7 +783,6 @@ class MultiGroupXS(object):
|
|||
modified.write(data)
|
||||
modified.write('\n\\end{document}')
|
||||
|
||||
|
||||
def get_pandas_dataframe(self, groups='indices', summary=None):
|
||||
"""Build a Pandas DataFrame for the MultiGroupXS data.
|
||||
|
||||
|
|
@ -869,8 +860,9 @@ class MultiGroupXS(object):
|
|||
|
||||
class TotalXS(MultiGroupXS):
|
||||
|
||||
def __init__(self, domain=None, domain_type=None, groups=None, name=''):
|
||||
super(TotalXS, self).__init__(domain, domain_type, groups, name)
|
||||
def __init__(self, domain=None, domain_type=None,
|
||||
xs_type=None, groups=None, name=''):
|
||||
super(TotalXS, self).__init__(domain, domain_type, xs_type, groups, name)
|
||||
self._rxn_type = 'total'
|
||||
|
||||
def create_tallies(self):
|
||||
|
|
@ -900,8 +892,9 @@ class TotalXS(MultiGroupXS):
|
|||
|
||||
class TransportXS(MultiGroupXS):
|
||||
|
||||
def __init__(self, domain=None, domain_type=None, groups=None, name=''):
|
||||
super(TransportXS, self).__init__(domain, domain_type, groups, name)
|
||||
def __init__(self, domain=None, domain_type=None,
|
||||
xs_type=None, groups=None, name=''):
|
||||
super(TransportXS, self).__init__(domain, domain_type, xs_type, groups, name)
|
||||
self._rxn_type = 'transport'
|
||||
|
||||
def create_tallies(self):
|
||||
|
|
@ -939,8 +932,9 @@ class TransportXS(MultiGroupXS):
|
|||
|
||||
class AbsorptionXS(MultiGroupXS):
|
||||
|
||||
def __init__(self, domain=None, domain_type=None, groups=None, name=''):
|
||||
super(AbsorptionXS, self).__init__(domain, domain_type, groups, name)
|
||||
def __init__(self, domain=None, domain_type=None,
|
||||
xs_type=None, groups=None, name=''):
|
||||
super(AbsorptionXS, self).__init__(domain, domain_type, xs_type, groups, name)
|
||||
self._rxn_type = 'absorption'
|
||||
|
||||
def create_tallies(self):
|
||||
|
|
@ -970,8 +964,9 @@ class AbsorptionXS(MultiGroupXS):
|
|||
|
||||
class CaptureXS(MultiGroupXS):
|
||||
|
||||
def __init__(self, domain=None, domain_type=None, groups=None, name=''):
|
||||
super(CaptureXS, self).__init__(domain, domain_type, groups, name)
|
||||
def __init__(self, domain=None, domain_type=None,
|
||||
xs_type=None, groups=None, name=''):
|
||||
super(CaptureXS, self).__init__(domain, domain_type, xs_type, groups, name)
|
||||
self._rxn_type = 'capture'
|
||||
|
||||
def create_tallies(self):
|
||||
|
|
@ -1002,8 +997,9 @@ class CaptureXS(MultiGroupXS):
|
|||
|
||||
class FissionXS(MultiGroupXS):
|
||||
|
||||
def __init__(self, domain=None, domain_type=None, groups=None, name=''):
|
||||
super(FissionXS, self).__init__(domain, domain_type, groups, name)
|
||||
def __init__(self, domain=None, domain_type=None,
|
||||
xs_type=None, groups=None, name=''):
|
||||
super(FissionXS, self).__init__(domain, domain_type, xs_type, groups, name)
|
||||
self._rxn_type = 'fission'
|
||||
|
||||
def create_tallies(self):
|
||||
|
|
@ -1033,8 +1029,9 @@ class FissionXS(MultiGroupXS):
|
|||
|
||||
class NuFissionXS(MultiGroupXS):
|
||||
|
||||
def __init__(self, domain=None, domain_type=None, groups=None, name=''):
|
||||
super(NuFissionXS, self).__init__(domain, domain_type, groups, name)
|
||||
def __init__(self, domain=None, domain_type=None,
|
||||
xs_type=None, groups=None, name=''):
|
||||
super(NuFissionXS, self).__init__(domain, domain_type, xs_type, groups, name)
|
||||
self._rxn_type = 'nu-fission'
|
||||
|
||||
def create_tallies(self):
|
||||
|
|
@ -1064,8 +1061,9 @@ class NuFissionXS(MultiGroupXS):
|
|||
|
||||
class ScatterXS(MultiGroupXS):
|
||||
|
||||
def __init__(self, domain=None, domain_type=None, groups=None, name=''):
|
||||
super(ScatterXS, self).__init__(domain, domain_type, groups, name)
|
||||
def __init__(self, domain=None, domain_type=None,
|
||||
xs_type=None, groups=None, name=''):
|
||||
super(ScatterXS, self).__init__(domain, domain_type, xs_type, groups, name)
|
||||
self._rxn_type = 'scatter'
|
||||
|
||||
def create_tallies(self):
|
||||
|
|
@ -1095,8 +1093,9 @@ class ScatterXS(MultiGroupXS):
|
|||
|
||||
class NuScatterXS(MultiGroupXS):
|
||||
|
||||
def __init__(self, domain=None, domain_type=None, groups=None, name=''):
|
||||
super(NuScatterXS, self).__init__(domain, domain_type, groups, name)
|
||||
def __init__(self, domain=None, domain_type=None,
|
||||
xs_type=None, groups=None, name=''):
|
||||
super(NuScatterXS, self).__init__(domain, domain_type, xs_type, groups, name)
|
||||
self._rxn_type = 'nu-scatter'
|
||||
|
||||
def create_tallies(self):
|
||||
|
|
@ -1126,8 +1125,9 @@ class NuScatterXS(MultiGroupXS):
|
|||
|
||||
class ScatterMatrixXS(MultiGroupXS):
|
||||
|
||||
def __init__(self, domain=None, domain_type=None, groups=None, name=''):
|
||||
super(ScatterMatrixXS, self).__init__(domain, domain_type, groups, name)
|
||||
def __init__(self, domain=None, domain_type=None,
|
||||
xs_type=None, groups=None, name=''):
|
||||
super(ScatterMatrixXS, self).__init__(domain, domain_type, xs_type, groups, name)
|
||||
self._rxn_type = 'scatter matrix'
|
||||
|
||||
def create_tallies(self):
|
||||
|
|
@ -1175,7 +1175,7 @@ class ScatterMatrixXS(MultiGroupXS):
|
|||
self._xs_tally._std_dev = np.nan_to_num(self.xs_tally.std_dev)
|
||||
|
||||
def get_xs(self, in_groups='all', out_groups='all',
|
||||
subdomains='all', value='mean'):
|
||||
subdomains='all', nuclides='all', value='mean'):
|
||||
"""Returns an array of multi-group cross sections.
|
||||
|
||||
This method constructs a 2D NumPy array for the requested scattering
|
||||
|
|
@ -1192,6 +1192,10 @@ class ScatterMatrixXS(MultiGroupXS):
|
|||
subdomains : Iterable of Integral or 'all'
|
||||
Subdomain IDs of interest
|
||||
|
||||
nuclides : Iterable of str or 'all'
|
||||
A list of nuclide name strings
|
||||
(e.g., ['U-235', 'U-238']; default is 'all')
|
||||
|
||||
value : str
|
||||
A string for the type of value to return - 'mean' (default),
|
||||
'std_dev' or 'rel_err' are accepted
|
||||
|
|
@ -1240,13 +1244,19 @@ class ScatterMatrixXS(MultiGroupXS):
|
|||
filters.append('energyout')
|
||||
filter_bins.append((self.energy_groups.get_group_bounds(group),))
|
||||
|
||||
# Construct list of nuclides for all requested nuclides
|
||||
if nuclides != 'all' and nuclides != ['total']:
|
||||
cv.check_iterable_type('nuclides', nuclides, basestring)
|
||||
else:
|
||||
nuclides = []
|
||||
|
||||
# Query the multi-group cross section tally for the data
|
||||
xs = self.xs_tally.get_values(filters=filters,
|
||||
filter_bins=filter_bins, value=value)
|
||||
xs = self.xs_tally.get_values(filters=filters, filter_bins=filter_bins,
|
||||
nuclides=nuclides, value=value)
|
||||
xs = np.nan_to_num(xs)
|
||||
return xs
|
||||
|
||||
def print_xs(self, subdomains='all'):
|
||||
def print_xs(self, subdomains='all', nuclides='all'):
|
||||
"""Prints a string representation for the multi-group cross section.
|
||||
|
||||
Parameters
|
||||
|
|
@ -1254,10 +1264,20 @@ class ScatterMatrixXS(MultiGroupXS):
|
|||
subdomains : Iterable of Integral or 'all'
|
||||
The subdomain IDs of the cross sections to include in the report
|
||||
|
||||
nuclides : Iterable of str or 'all'
|
||||
The nuclides of the cross-sections to include in the report
|
||||
|
||||
"""
|
||||
|
||||
if subdomains != 'all':
|
||||
cv.check_iterable_type('subdomains', subdomains, Integral)
|
||||
if nuclides != 'all':
|
||||
cv.check_iterable_type('nuclides', nuclides, basestring)
|
||||
else:
|
||||
if self.xs_type == 'micro':
|
||||
nuclides = self.domain.get_all_nuclides()
|
||||
else:
|
||||
nuclides = ['total']
|
||||
|
||||
# Build header for string with type and domain info
|
||||
string = 'Multi-Group XS\n'
|
||||
|
|
@ -1265,53 +1285,70 @@ class ScatterMatrixXS(MultiGroupXS):
|
|||
string += '{0: <16}=\t{1}\n'.format('\tDomain Type', self.domain_type)
|
||||
string += '{0: <16}=\t{1}\n'.format('\tDomain ID', self.domain.id)
|
||||
|
||||
# Append cross section data if it has been computed
|
||||
if self.xs_tally is not None:
|
||||
string += '{0: <16}\n'.format('\tEnergy Groups:')
|
||||
template = '{0: <12}Group {1} [{2: <10} - {3: <10}MeV]\n'
|
||||
# If cross section data has not been computed, only print string header
|
||||
if self.xs_tally is None:
|
||||
print(string)
|
||||
return
|
||||
|
||||
# Loop over energy groups ranges
|
||||
for group in range(1, self.num_groups+1):
|
||||
bounds = self.energy_groups.get_group_bounds(group)
|
||||
string += template.format('', group, bounds[0], bounds[1])
|
||||
string += '{0: <16}\n'.format('\tEnergy Groups:')
|
||||
template = '{0: <12}Group {1} [{2: <10} - {3: <10}MeV]\n'
|
||||
|
||||
if subdomains == 'all':
|
||||
if self.domain_type == 'distribcell':
|
||||
subdomains = np.arange(self.num_subdomains, dtype=np.int)
|
||||
# Loop over energy groups ranges
|
||||
for group in range(1, self.num_groups+1):
|
||||
bounds = self.energy_groups.get_group_bounds(group)
|
||||
string += template.format('', group, bounds[0], bounds[1])
|
||||
|
||||
if subdomains == 'all':
|
||||
if self.domain_type == 'distribcell':
|
||||
subdomains = np.arange(self.num_subdomains, dtype=np.int)
|
||||
else:
|
||||
subdomains = [self.domain.id]
|
||||
|
||||
# Loop over all subdomains
|
||||
for subdomain in subdomains:
|
||||
|
||||
if self.domain_type == 'distribcell':
|
||||
string += \
|
||||
'{0: <16}=\t{1}\n'.format('\tSubdomain', subdomain)
|
||||
|
||||
# Loop over all Nuclides
|
||||
for nuclide in nuclides:
|
||||
|
||||
# Build header for cross section type based on the nuclide
|
||||
if nuclide == 'total':
|
||||
string += '{0: <16}\n'.format('\tCross Sections [cm^-1]:')
|
||||
else:
|
||||
subdomains = [self.domain.id]
|
||||
string += '{0: <16}=\t{1}\n'.format('\tNuclide', nuclide)
|
||||
string += '{0: <16}\n'.format('\tCross Sections [barns]:')
|
||||
|
||||
# Loop over all subdomains
|
||||
for subdomain in subdomains:
|
||||
|
||||
if self.domain_type == 'distribcell':
|
||||
string += \
|
||||
'{0: <16}=\t{1}\n'.format('\tSubdomain', subdomain)
|
||||
|
||||
string += '{0: <16}\n'.format('\tCross Sections [cm^-1]:')
|
||||
template = '{0: <12}Group {1} -> Group {2}:\t\t'
|
||||
|
||||
# Loop over incoming/outgoing energy groups ranges
|
||||
for in_group in range(1, self.num_groups+1):
|
||||
for out_group in range(1, self.num_groups+1):
|
||||
string += template.format('', in_group, out_group)
|
||||
average = self.get_xs([in_group], [out_group],
|
||||
[subdomain], 'mean')
|
||||
rel_err = self.get_xs([in_group], [out_group],
|
||||
[subdomain], 'rel_err') * 100.
|
||||
average = \
|
||||
self.get_xs([in_group], [out_group],
|
||||
[subdomain], [nuclide], 'mean')
|
||||
rel_err = \
|
||||
self.get_xs([in_group], [out_group],
|
||||
[subdomain], [nuclide], 'rel_err') * 100
|
||||
average = np.nan_to_num(average.flatten())[0]
|
||||
rel_err = np.nan_to_num(rel_err.flatten())[0]
|
||||
string += '{:1.2e} +/- {:1.2e}%'.format(average, rel_err)
|
||||
string += '\n'
|
||||
string += '\n'
|
||||
string += '\n'
|
||||
string += '\n'
|
||||
|
||||
print(string)
|
||||
|
||||
|
||||
class NuScatterMatrixXS(ScatterMatrixXS):
|
||||
|
||||
def __init__(self, domain=None, domain_type=None, groups=None, name=''):
|
||||
super(NuScatterMatrixXS, self).__init__(domain, domain_type, groups, name)
|
||||
def __init__(self, domain=None, domain_type=None,
|
||||
xs_type=None, groups=None, name=''):
|
||||
super(NuScatterMatrixXS, self).__init__(domain, domain_type, xs_type, groups, name)
|
||||
self._rxn_type = 'nu-scatter matrix'
|
||||
|
||||
def create_tallies(self):
|
||||
|
|
@ -1360,10 +1397,13 @@ class NuScatterMatrixXS(ScatterMatrixXS):
|
|||
|
||||
class Chi(MultiGroupXS):
|
||||
|
||||
def __init__(self, domain=None, domain_type=None, groups=None, name=''):
|
||||
super(Chi, self).__init__(domain, domain_type, groups, name)
|
||||
def __init__(self, domain=None, domain_type=None,
|
||||
xs_type=None, groups=None, name=''):
|
||||
super(Chi, self).__init__(domain, domain_type, xs_type, groups, name)
|
||||
self._rxn_type = 'chi'
|
||||
|
||||
# FIXME: Make this work for micros!!!
|
||||
|
||||
def create_tallies(self):
|
||||
"""Construct the OpenMC tallies needed to compute this cross section."""
|
||||
|
||||
|
|
@ -1390,3 +1430,50 @@ class Chi(MultiGroupXS):
|
|||
self._xs_tally = nu_fission_out / nu_fission_in
|
||||
self._xs_tally._mean = np.nan_to_num(self.xs_tally.mean)
|
||||
self._xs_tally._std_dev = np.nan_to_num(self.xs_tally.std_dev)
|
||||
|
||||
def get_xs(self, groups='all', subdomains='all',
|
||||
nuclides='all', xs_type='macro', value='mean'):
|
||||
"""Returns an array of multi-group cross sections.
|
||||
|
||||
This method constructs a 2D NumPy array for the requested multi-group
|
||||
cross section data data for one or more energy groups and subdomains.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
groups : Iterable of Integral or 'all'
|
||||
Energy groups of interest
|
||||
|
||||
subdomains : Iterable of Integral or 'all'
|
||||
Subdomain IDs of interest
|
||||
|
||||
nuclides : Iterable of str or 'all'
|
||||
A list of nuclide name strings
|
||||
(e.g., ['U-235', 'U-238']; default is 'all')
|
||||
|
||||
xs_type: {'macro' or 'micro'}
|
||||
Return the macro or micro cross section in units of cm^-1 or barns
|
||||
|
||||
value : str
|
||||
A string for the type of value to return - 'mean' (default),
|
||||
'std_dev' or 'rel_err' are accepted
|
||||
|
||||
Returns
|
||||
-------
|
||||
xs : ndarray
|
||||
A NumPy array of the multi-group cross section indexed in the order
|
||||
each group, subdomain and nuclide is listed in the parameters.
|
||||
|
||||
Raises
|
||||
------
|
||||
ValueError
|
||||
When this method is called before the multi-group cross section is
|
||||
computed from tally data.
|
||||
|
||||
"""
|
||||
|
||||
if self.xs_type == 'micro' and xs_type == 'macro':
|
||||
raise NotImplementedError('Unable to compute macro Chi from micros')
|
||||
|
||||
xs = super(Chi, self).get_xs(groups, subdomains,
|
||||
nuclides, xs_type, value)
|
||||
return xs
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue