mirror of
https://github.com/openmc-dev/openmc.git
synced 2026-07-28 14:15:42 -04:00
Removed Tally.summation(...) routine in place of explicit tally summations in openmc.mgxs module for subdomain averaging
This commit is contained in:
parent
d0a85cd082
commit
02c30fd5de
3 changed files with 47 additions and 101 deletions
|
|
@ -318,6 +318,7 @@ class Filter(object):
|
|||
boolean
|
||||
Whether or not the other filter is a subset of this filter
|
||||
"""
|
||||
|
||||
if not isinstance(other, Filter):
|
||||
return False
|
||||
elif self.type != other.type:
|
||||
|
|
@ -325,8 +326,8 @@ class Filter(object):
|
|||
elif self.type in ['energy', 'energyout']:
|
||||
return np.all(self.bins == other.bins)
|
||||
|
||||
for bin in other.bins:
|
||||
if bin not in self.bins:
|
||||
for bin in self.bins:
|
||||
if bin not in other.bins:
|
||||
return False
|
||||
|
||||
return True
|
||||
|
|
|
|||
|
|
@ -403,7 +403,9 @@ class MultiGroupXS(object):
|
|||
def get_subdomain_avg_xs(self, subdomains='all'):
|
||||
"""Construct a subdomain-averaged version of this cross-section.
|
||||
|
||||
This is primarily useful for averaging across distribcell instances.
|
||||
This is primarily useful for averaging across distribcell instances or
|
||||
mesh cells. This routine performs spatial homogenization to compute the
|
||||
scalar flux-weighted average cross-section across the subdomains.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
|
|
@ -440,17 +442,49 @@ class MultiGroupXS(object):
|
|||
# Clone this MultiGroupXS to initialize the subdomain-averaged version
|
||||
avg_xs = copy.deepcopy(self)
|
||||
|
||||
# Reset subdomain indices and offsets for distribcell domains
|
||||
# If domain is distribcell, make subdomain-averaged a 'cell' domain
|
||||
if self.domain_type == 'distribcell':
|
||||
avg_xs.domain_type = 'cell'
|
||||
avg_xs._offset = 0
|
||||
# TODO: Implement this for mesh tallies
|
||||
elif self.domain_type == 'mesh':
|
||||
raise NotImplementedError('Average mesh xs are not yet implemented')
|
||||
|
||||
# Overwrite tallies with new subdomain-averaged versions
|
||||
avg_xs._tallies = {}
|
||||
for tally_type, tally in self.tallies.items():
|
||||
tally_sum = tally.summation(filter_type=self.domain_type,
|
||||
filter_bins=subdomains)
|
||||
tally_sum /= len(subdomains)
|
||||
avg_xs.tallies[tally_type] = tally_sum
|
||||
# Average each of the tallies across subdomains
|
||||
for tally_type, tally in avg_xs.tallies.items():
|
||||
|
||||
# Make condensed tally derived and null out sum, sum_sq
|
||||
tally._derived = True
|
||||
tally._sum = None
|
||||
tally._sum_sq = None
|
||||
|
||||
# Get tally data arrays reshaped with one dimension per filter
|
||||
mean = tally.get_reshaped_data(value='mean')
|
||||
std_dev = tally.get_reshaped_data(value='std_dev')
|
||||
|
||||
# Get the mean of the mean, std. dev. across requested subdomains
|
||||
mean = np.mean(mean[subdomains, ...], axis=0)
|
||||
std_dev = np.mean(std_dev[subdomains, ...]**2, axis=0)
|
||||
std_dev = np.sqrt(std_dev)
|
||||
|
||||
# If domain is distribcell, make subdomain-averaged a 'cell' domain
|
||||
domain_filter = tally.find_filter(self._domain_type)
|
||||
if domain_filter.type == 'distribcell':
|
||||
domain_filter.type = 'cell'
|
||||
domain_filter.num_bins = 1
|
||||
# TODO: Implement this for mesh tallies
|
||||
elif domain_filter.type == 'mesh':
|
||||
raise NotImplementedError('Average mesh xs are not yet implemented')
|
||||
|
||||
# Reshape averaged data arrays with one dimension for all filters
|
||||
new_shape = \
|
||||
(tally.num_filter_bins, tally.num_nuclides, tally.num_score_bins,)
|
||||
mean = np.reshape(mean, new_shape)
|
||||
std_dev = np.reshape(std_dev, new_shape)
|
||||
|
||||
# Override tally's data with the new condensed data
|
||||
tally._mean = mean
|
||||
tally._std_dev = std_dev
|
||||
|
||||
# Compute the subdomain-averaged multi-group cross-section
|
||||
avg_xs.compute_xs()
|
||||
|
|
@ -733,6 +767,7 @@ class MultiGroupXS(object):
|
|||
df = self.get_pandas_dataframe()
|
||||
|
||||
# Capitalize column label strings
|
||||
df.columns = df.columns.astype(str)
|
||||
df.columns = map(str.title, df.columns)
|
||||
|
||||
# Export the data using Pandas IO API
|
||||
|
|
|
|||
|
|
@ -2316,96 +2316,6 @@ class Tally(object):
|
|||
|
||||
return new_tally
|
||||
|
||||
def summation(self, scores=[], filter_type=None,
|
||||
filter_bins=[], nuclides=[]):
|
||||
"""Build a sliced tally for the specified filter bins, nuclides, scores.
|
||||
|
||||
This method constructs a new tally to encapsulate a subset of the data
|
||||
represented by this tally. The subset of data to include in the tally
|
||||
slice is determined by the scores, filter bins and nuclides specified
|
||||
in the input parameters.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
scores : list
|
||||
A list of one or more score strings to sum across
|
||||
(e.g., ['absorption', 'nu-fission']; default is [])
|
||||
|
||||
filter_type : str
|
||||
A filter type string (e.g., 'cell', 'energy') corresponding to the
|
||||
filter bins to sum across
|
||||
|
||||
filter_bins : Iterable of Integral or tuple
|
||||
A list of the filter bins corresponding to the filters parameter
|
||||
Each bin in the list is the integer ID for 'material', 'surface',
|
||||
'cell', 'cellborn', and 'universe' Filters. Each bin is an integer
|
||||
for the cell instance ID for 'distribcell Filters. Each bin is a
|
||||
2-tuple of floats for 'energy' and 'energyout' filters corresponding
|
||||
to the energy boundaries of the bin of interest. Each bin is an
|
||||
(x,y,z) 3-tuple for 'mesh' filters corresponding to the mesh cell of
|
||||
interest.
|
||||
|
||||
nuclides : list
|
||||
A list of nuclide name strings to sum across
|
||||
(e.g., ['U-235', 'U-238']; default is [])
|
||||
|
||||
Returns
|
||||
-------
|
||||
Tally
|
||||
A new tally which encapsulates the sum of data requested.
|
||||
|
||||
"""
|
||||
|
||||
# If user did not specify any scores, do not sum across scores
|
||||
if len(scores) == 0:
|
||||
scores = [[]]
|
||||
# Sum across any scores specified by the user
|
||||
else:
|
||||
scores = [[score] for score in scores]
|
||||
|
||||
# If user did not specify any nuclides, do not sum across nuclides
|
||||
if len(nuclides) == 0:
|
||||
nuclides = [[]]
|
||||
# Sum across any nuclides specified by the user
|
||||
else:
|
||||
nuclides = [[nuclide] for nuclide in nuclides]
|
||||
|
||||
# Sum across any filter bins specified by the user
|
||||
if filter_type in FILTER_TYPES.values():
|
||||
filter_bins = [[(filter_bin,)] for filter_bin in filter_bins]
|
||||
filters = [[filter_type]]
|
||||
# If user did not specify a filter type, do not sum across filter bins
|
||||
else:
|
||||
filter_bins = [[]]
|
||||
filters = [[]]
|
||||
|
||||
# Initialize Tally sum
|
||||
tally_sum = 0
|
||||
|
||||
# Iterate over all Tally slice operands in summation
|
||||
prod = [scores, filters, filter_bins, nuclides]
|
||||
summed_filters = defaultdict(list)
|
||||
for scores, filters, filter_bins, nuclides in itertools.product(*prod):
|
||||
tally_slice = self.get_slice(scores, filters, filter_bins, nuclides)
|
||||
|
||||
# Remove filters summed across to avoid bulky CrossFilters
|
||||
if filter_type:
|
||||
filter = tally_slice.find_filter(filter_type)
|
||||
tally_slice.remove_filter(filter)
|
||||
summed_filters[filter_type].append(filter)
|
||||
|
||||
# Accumulate this Tally slice into the Tally sum
|
||||
tally_sum += tally_slice
|
||||
|
||||
# FIXME: test if this works for filter
|
||||
for filter_type in summed_filters:
|
||||
filters = summed_filters[filter_type]
|
||||
for i in range(1, len(filters)):
|
||||
filters[i] = CrossFilter(filters[i-1], filters[i], '+')
|
||||
tally_sum.add_filter(filters[-1])
|
||||
|
||||
return tally_sum
|
||||
|
||||
def tile_filter(self, new_filter):
|
||||
"""Combines filters, scores and nuclides with another tally.
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue