mirror of
https://github.com/openmc-dev/openmc.git
synced 2026-07-29 06:35:48 -04:00
Fixed some bugs in tally merging with introduction of comparison operators for filers and nuclides
This commit is contained in:
parent
a2ac93a843
commit
077eff7f19
4 changed files with 106 additions and 23 deletions
|
|
@ -57,6 +57,12 @@ class Element(object):
|
|||
def __ne__(self, other):
|
||||
return not self == other
|
||||
|
||||
def __lt__(self, other):
|
||||
return not self > other
|
||||
|
||||
def __hash__(self):
|
||||
return hash(repr(self))
|
||||
|
||||
def __hash__(self):
|
||||
return hash(repr(self))
|
||||
|
||||
|
|
|
|||
|
|
@ -77,6 +77,23 @@ class Filter(object):
|
|||
def __ne__(self, other):
|
||||
return not self == other
|
||||
|
||||
def __gt__(self, other):
|
||||
if self.type != other.type:
|
||||
if self.type in _FILTER_TYPES and other.type in _FILTER_TYPES:
|
||||
delta = _FILTER_TYPES.index(self.type) - \
|
||||
_FILTER_TYPES.index(other.type)
|
||||
return True if delta > 0 else False
|
||||
else:
|
||||
return False
|
||||
else:
|
||||
if 'energy' in self.type and 'energy' in other.type:
|
||||
return self.bins[0] >= other.bins[-1]
|
||||
else:
|
||||
return max(self.bins) > max(other.bins)
|
||||
|
||||
def __lt__(self, other):
|
||||
return not self > other
|
||||
|
||||
def __hash__(self):
|
||||
return hash(repr(self))
|
||||
|
||||
|
|
@ -297,7 +314,13 @@ class Filter(object):
|
|||
|
||||
# Merge unique filter bins
|
||||
merged_bins = set(np.concatenate((self.bins, other.bins)))
|
||||
merged_filter.bins = list(sorted(merged_bins))
|
||||
|
||||
# Sort energy bin edges
|
||||
if 'energy' in self.type:
|
||||
merged_bins = sorted(merged_bins)
|
||||
|
||||
# Assign merged bins to merged filter
|
||||
merged_filter.bins = list(merged_bins)
|
||||
|
||||
# Count bins in the merged filter
|
||||
if 'energy' in merged_filter.type:
|
||||
|
|
|
|||
|
|
@ -60,6 +60,12 @@ class Nuclide(object):
|
|||
def __ne__(self, other):
|
||||
return not self == other
|
||||
|
||||
def __gt__(self, other):
|
||||
return repr(self) > repr(other)
|
||||
|
||||
def __lt__(self, other):
|
||||
return not self > other
|
||||
|
||||
def __hash__(self):
|
||||
return hash(repr(self))
|
||||
|
||||
|
|
|
|||
|
|
@ -826,18 +826,30 @@ class Tally(object):
|
|||
if self.estimator != other.estimator:
|
||||
return False
|
||||
|
||||
equal_filters = sorted(self.filters) == sorted(other.filters)
|
||||
equal_nuclides = sorted(self.nuclides) == sorted(other.nuclides)
|
||||
equal_scores = sorted(self.scores) == sorted(other.scores)
|
||||
equality = [equal_filters, equal_nuclides, equal_scores]
|
||||
|
||||
# If all filters, nuclides and scores match then tallies are mergeable
|
||||
if equal_filters and equal_nuclides and equal_scores:
|
||||
return True
|
||||
|
||||
# Variables to indicate matching filter bins, nuclides and scores
|
||||
merge_filters = self._can_merge_filters(other)
|
||||
merge_nuclides = self._can_merge_nuclides(other)
|
||||
merge_scores = self._can_merge_scores(other)
|
||||
mergeability = [merge_filters, merge_nuclides, merge_scores]
|
||||
|
||||
if not all(mergeability):
|
||||
return False
|
||||
|
||||
# If the tally results have been read from the statepoint, we can only
|
||||
# merge along one of filter bins, scores or nuclides
|
||||
if self._results_read and sum(mergeability) > 1:
|
||||
# at least two of filters, nuclides and scores must match
|
||||
elif self._results_read and sum(equality) < 2:
|
||||
return False
|
||||
else:
|
||||
return all([merge_filters, merge_nuclides, merge_scores])
|
||||
return True
|
||||
|
||||
def merge(self, other):
|
||||
"""Merge another tally with this one
|
||||
|
|
@ -871,8 +883,16 @@ class Tally(object):
|
|||
# Create deep copy of other tally to use for array concatenation
|
||||
other_copy = copy.deepcopy(other)
|
||||
|
||||
# FIXME: document and create vars for merge_filters, etc.
|
||||
merge_filters = self._can_merge_filters(other)
|
||||
merge_nuclides = self._can_merge_nuclides(other)
|
||||
merge_scores = self._can_merge_scores(other)
|
||||
equal_filters = sorted(self.filters) == sorted(other.filters)
|
||||
equal_nuclides = sorted(self.nuclides) == sorted(other.nuclides)
|
||||
equal_scores = sorted(self.scores) == sorted(other.scores)
|
||||
|
||||
# If two tallies can be merged along a filter's bins
|
||||
if self._can_merge_filters(other):
|
||||
if merge_filters and not equal_filters:
|
||||
|
||||
# Search for mergeable filters
|
||||
for i, filter1 in enumerate(self.filters):
|
||||
|
|
@ -880,12 +900,14 @@ class Tally(object):
|
|||
if filter1 != filter2 and filter1.can_merge(filter2):
|
||||
other_copy._swap_filters(other_copy.filters[i], filter2)
|
||||
merged_tally.filters[i] = filter1.merge(filter2)
|
||||
join_right = filter1 < filter2
|
||||
merge_axis = i
|
||||
break
|
||||
|
||||
# If two tallies can be merged along nuclide bins
|
||||
if self._can_merge_nuclides(other):
|
||||
if merge_nuclides and not equal_nuclides:
|
||||
merge_axis = self.num_filters
|
||||
join_right = True
|
||||
|
||||
# Add unique nuclides from other tally to merged tally
|
||||
for nuclide in other.nuclides:
|
||||
|
|
@ -893,8 +915,9 @@ class Tally(object):
|
|||
merged_tally.add_nuclide(nuclide)
|
||||
|
||||
# If two tallies can be merged along score bins
|
||||
if self._can_merge_scores(other):
|
||||
if merge_scores and not equal_scores:
|
||||
merge_axis = self.num_filters + 1
|
||||
join_right = True
|
||||
|
||||
# Add unique scores from other tally to merged tally
|
||||
for score in other.scores:
|
||||
|
|
@ -908,37 +931,57 @@ class Tally(object):
|
|||
if self.sum is not None and other_copy.sum is not None:
|
||||
self_sum = self.get_reshaped_data(value='sum')
|
||||
other_sum = other_copy.get_reshaped_data(value='sum')
|
||||
merged_tally._sum = \
|
||||
np.concatenate((self_sum, other_sum), axis=merge_axis)
|
||||
merged_tally._sum = \
|
||||
np.reshape(merged_tally._sum, merged_tally.shape)
|
||||
|
||||
if join_right:
|
||||
merged_sum = \
|
||||
np.concatenate((self_sum, other_sum), axis=merge_axis)
|
||||
else:
|
||||
merged_sum = \
|
||||
np.concatenate((other_sum, self_sum), axis=merge_axis)
|
||||
|
||||
merged_tally._sum = np.reshape(merged_sum, merged_tally.shape)
|
||||
|
||||
# Concatenate sum_sq arrays if present in both tallies
|
||||
if self.sum_sq is not None and other.sum_sq is not None:
|
||||
self_sum_sq = self.get_reshaped_data(value='sum_sq')
|
||||
other_sum_sq = other_copy.get_reshaped_data(value='sum_sq')
|
||||
merged_tally._sum_sq = \
|
||||
np.concatenate((self_sum_sq, other_sum_sq), axis=merge_axis)
|
||||
merged_tally._sum_sq = \
|
||||
np.reshape(merged_tally._sum_sq, merged_tally.shape)
|
||||
|
||||
if join_right:
|
||||
merged_sum_sq = \
|
||||
np.concatenate((self_sum_sq, other_sum_sq), axis=merge_axis)
|
||||
else:
|
||||
merged_sum_sq = \
|
||||
np.concatenate((other_sum_sq, self_sum_sq), axis=merge_axis)
|
||||
|
||||
merged_tally._sum_sq = np.reshape(merged_sum_sq, merged_tally.shape)
|
||||
|
||||
# Concatenate mean arrays if present in both tallies
|
||||
if self.mean is not None and other.mean is not None:
|
||||
self_mean = self.get_reshaped_data(value='mean')
|
||||
other_mean = other_copy.get_reshaped_data(value='mean')
|
||||
merged_tally._mean = \
|
||||
np.concatenate((self_mean, other_mean), axis=merge_axis)
|
||||
merged_tally._mean = \
|
||||
np.reshape(merged_tally._mean, merged_tally.shape)
|
||||
|
||||
if join_right:
|
||||
merged_mean = \
|
||||
np.concatenate((self_mean, other_mean), axis=merge_axis)
|
||||
else:
|
||||
merged_mean = \
|
||||
np.concatenate((other_mean, self_mean), axis=merge_axis)
|
||||
|
||||
merged_tally._mean = np.reshape(merged_mean, merged_tally.shape)
|
||||
|
||||
# Concatenate std. dev. arrays if present in both tallies
|
||||
if self.std_dev is not None and other.std_dev is not None:
|
||||
self_std_dev = self.get_reshaped_data(value='std_dev')
|
||||
other_std_dev = other_copy.get_reshaped_data(value='std_dev')
|
||||
merged_tally._std_dev = \
|
||||
np.concatenate((self_std_dev, other_std_dev), axis=merge_axis)
|
||||
merged_tally._std_dev = \
|
||||
np.reshape(merged_tally._std_dev, merged_tally.shape)
|
||||
|
||||
if join_right:
|
||||
merged_std_dev = \
|
||||
np.concatenate((self_std_dev, other_std_dev), axis=merge_axis)
|
||||
else:
|
||||
merged_std_dev = \
|
||||
np.concatenate((other_std_dev, self_std_dev), axis=merge_axis)
|
||||
|
||||
merged_tally._std_dev = np.reshape(merged_std_dev, merged_tally.shape)
|
||||
|
||||
# Sparsify merged tally if both tallies are sparse
|
||||
merged_tally.sparse = self.sparse and other.sparse
|
||||
|
|
@ -2878,7 +2921,12 @@ class Tally(object):
|
|||
'since it does not contain any results.'.format(self.id)
|
||||
raise ValueError(msg)
|
||||
|
||||
# Create deep copy of tally to return as sliced tally
|
||||
new_tally = copy.deepcopy(self)
|
||||
|
||||
# Differentiate Tally with a new auto-generated Tally ID
|
||||
new_tally.id = None
|
||||
|
||||
new_tally.sparse = False
|
||||
|
||||
if not self.derived and self.sum is not None:
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue