mirror of
https://github.com/openmc-dev/openmc.git
synced 2026-07-28 06:05:58 -04:00
Fixed some bugs in tally arithmetic tiling / repeats of NumPy data arrays
This commit is contained in:
parent
6c23391309
commit
e5b1cae874
2 changed files with 67 additions and 57 deletions
|
|
@ -21,15 +21,15 @@ class Filter(object):
|
|||
def __eq__(self, filter2):
|
||||
|
||||
# Check type
|
||||
if self._type != filter2._type:
|
||||
if self.type != filter2.type:
|
||||
return False
|
||||
|
||||
# Check number of bins
|
||||
elif len(self._bins) != len(filter2._bins):
|
||||
elif len(self.bins) != len(filter2.bins):
|
||||
return False
|
||||
|
||||
# Check bin edges
|
||||
elif not np.allclose(self._bins, filter2._bins):
|
||||
elif not np.allclose(self.bins, filter2.bins):
|
||||
return False
|
||||
|
||||
else:
|
||||
|
|
@ -38,8 +38,8 @@ class Filter(object):
|
|||
|
||||
def __hash__(self):
|
||||
hashable = []
|
||||
hashable.append(self._type)
|
||||
hashable.append(self._bins)
|
||||
hashable.append(self.type)
|
||||
hashable.append(self.bins)
|
||||
return hash(tuple(hashable))
|
||||
|
||||
|
||||
|
|
@ -51,12 +51,12 @@ class Filter(object):
|
|||
if existing is None:
|
||||
|
||||
clone = type(self).__new__(type(self))
|
||||
clone._type = self._type
|
||||
clone._bins = copy.deepcopy(self._bins, memo)
|
||||
clone._num_bins = self._num_bins
|
||||
clone._mesh = copy.deepcopy(self._mesh, memo)
|
||||
clone._offset = self._offset
|
||||
clone._stride = self._stride
|
||||
clone._type = self.type
|
||||
clone._bins = copy.deepcopy(self.bins, memo)
|
||||
clone._num_bins = self.num_bins
|
||||
clone._mesh = copy.deepcopy(self.mesh, memo)
|
||||
clone._offset = self.offset
|
||||
clone._stride = self.stride
|
||||
|
||||
memo[id(self)] = clone
|
||||
|
||||
|
|
@ -117,7 +117,7 @@ class Filter(object):
|
|||
if bins is None:
|
||||
self.num_bins = 0
|
||||
|
||||
elif self._type is None:
|
||||
elif self.type is None:
|
||||
msg = 'Unable to set bins for Filter to "{0}" since ' \
|
||||
'the Filter type has not yet been set'.format(bins)
|
||||
raise ValueError(msg)
|
||||
|
|
@ -130,35 +130,35 @@ class Filter(object):
|
|||
else:
|
||||
bins = list(bins)
|
||||
|
||||
if self._type in ['cell', 'cellborn', 'surface', 'material',
|
||||
if self.type in ['cell', 'cellborn', 'surface', 'material',
|
||||
'universe', 'distribcell']:
|
||||
|
||||
for edge in bins:
|
||||
|
||||
if not is_integer(edge):
|
||||
msg = 'Unable to add bin "{0}" to a {1} Filter since ' \
|
||||
'it is a non-integer'.format(edge, self._type)
|
||||
'it is a non-integer'.format(edge, self.type)
|
||||
raise ValueError(msg)
|
||||
|
||||
elif edge < 0:
|
||||
msg = 'Unable to add bin "{0}" to a {1} Filter since ' \
|
||||
'it is a negative integer'.format(edge, self._type)
|
||||
'it is a negative integer'.format(edge, self.type)
|
||||
raise ValueError(msg)
|
||||
|
||||
|
||||
elif self._type in ['energy', 'energyout']:
|
||||
elif self.type in ['energy', 'energyout']:
|
||||
|
||||
for edge in bins:
|
||||
|
||||
if not is_integer(edge) and not is_float(edge):
|
||||
msg = 'Unable to add bin edge "{0}" to a {1} Filter ' \
|
||||
'since it is a non-integer or floating point ' \
|
||||
'value'.format(edge, self._type)
|
||||
'value'.format(edge, self.type)
|
||||
raise ValueError(msg)
|
||||
|
||||
elif edge < 0.:
|
||||
msg = 'Unable to add bin edge "{0}" to a {1} Filter ' \
|
||||
'since it is a negative value'.format(edge, self._type)
|
||||
'since it is a negative value'.format(edge, self.type)
|
||||
raise ValueError(msg)
|
||||
|
||||
# Check that bin edges are monotonically increasing
|
||||
|
|
@ -167,12 +167,12 @@ class Filter(object):
|
|||
if index > 0 and bins[index] < bins[index-1]:
|
||||
msg = 'Unable to add bin edges "{0}" to a {1} Filter ' \
|
||||
'since they are not monotonically ' \
|
||||
'increasing'.format(bins, self._type)
|
||||
'increasing'.format(bins, self.type)
|
||||
raise ValueError(msg)
|
||||
|
||||
|
||||
# mesh filters
|
||||
elif self._type == 'mesh':
|
||||
elif self.type == 'mesh':
|
||||
|
||||
if not len(bins) == 1:
|
||||
msg = 'Unable to add bins "{0}" to a mesh Filter since ' \
|
||||
|
|
@ -193,14 +193,13 @@ class Filter(object):
|
|||
self._bins = bins
|
||||
|
||||
|
||||
# FIXME
|
||||
@num_bins.setter
|
||||
def num_bins(self, num_bins):
|
||||
|
||||
if not is_integer(num_bins) or num_bins < 0:
|
||||
msg = 'Unable to set the number of bins "{0}" for a {1} Filter ' \
|
||||
'since it is not a positive ' \
|
||||
'integer'.format(num_bins, self._type)
|
||||
'integer'.format(num_bins, self.type)
|
||||
raise ValueError(msg)
|
||||
|
||||
self._num_bins = num_bins
|
||||
|
|
@ -216,7 +215,7 @@ class Filter(object):
|
|||
|
||||
self._mesh = mesh
|
||||
self.type = 'mesh'
|
||||
self.bins = self._mesh._id
|
||||
self.bins = self.mesh.id
|
||||
|
||||
|
||||
@offset.setter
|
||||
|
|
@ -224,7 +223,7 @@ class Filter(object):
|
|||
|
||||
if not is_integer(offset):
|
||||
msg = 'Unable to set offset "{0}" for a {1} Filter since it is a ' \
|
||||
'non-integer value'.format(offset, self._type)
|
||||
'non-integer value'.format(offset, self.type)
|
||||
raise ValueError(msg)
|
||||
|
||||
self._offset = offset
|
||||
|
|
@ -235,12 +234,12 @@ class Filter(object):
|
|||
|
||||
if not is_integer(stride):
|
||||
msg = 'Unable to set stride "{0}" for a {1} Filter since it is a ' \
|
||||
'non-integer value'.format(stride, self._type)
|
||||
'non-integer value'.format(stride, self.type)
|
||||
raise ValueError(msg)
|
||||
|
||||
if stride < 0:
|
||||
msg = 'Unable to set stride "{0}" for a {1} Filter since it is a ' \
|
||||
'negative value'.format(stride, self._type)
|
||||
'negative value'.format(stride, self.type)
|
||||
raise ValueError(msg)
|
||||
|
||||
self._stride = stride
|
||||
|
|
@ -274,14 +273,14 @@ class Filter(object):
|
|||
def merge(self, filter):
|
||||
|
||||
if not self.can_merge(filter):
|
||||
msg = 'Unable to merge {0} with {1} filters'.format(self._type, filter._type)
|
||||
msg = 'Unable to merge {0} with {1} filters'.format(self.type, filter.type)
|
||||
raise ValueError(msg)
|
||||
|
||||
# Create deep copy of filter to return as merged filter
|
||||
merged_filter = copy.deepcopy(self)
|
||||
|
||||
# Merge unique filter bins
|
||||
merged_bins = list(set(self._bins + filter._bins))
|
||||
merged_bins = list(set(self.bins + filter.bins))
|
||||
merged_filter.bins = merged_bins
|
||||
merged_filter.num_bins = len(merged_bins)
|
||||
|
||||
|
|
@ -335,7 +334,7 @@ class Filter(object):
|
|||
|
||||
# Filter bins for distribcell are the "IDs" of each unique placement
|
||||
# of the Cell in the Geometry (integers starting at 0)
|
||||
elif self._type == 'distribcell':
|
||||
elif self.type == 'distribcell':
|
||||
filter_index = filter_bin
|
||||
|
||||
# Use ID for all other Filters (e.g., material, cell, etc.)
|
||||
|
|
@ -354,7 +353,7 @@ class Filter(object):
|
|||
def __repr__(self):
|
||||
|
||||
string = 'Filter\n'
|
||||
string += '{0: <16}{1}{2}\n'.format('\tType', '=\t', self._type)
|
||||
string += '{0: <16}{1}{2}\n'.format('\tBins', '=\t', self._bins)
|
||||
string += '{0: <16}{1}{2}\n'.format('\tOffset', '=\t', self._offset)
|
||||
string += '{0: <16}{1}{2}\n'.format('\tType', '=\t', self.type)
|
||||
string += '{0: <16}{1}{2}\n'.format('\tBins', '=\t', self.bins)
|
||||
string += '{0: <16}{1}{2}\n'.format('\tOffset', '=\t', self.offset)
|
||||
return string
|
||||
|
|
|
|||
|
|
@ -58,14 +58,14 @@ class Tally(object):
|
|||
self_num_filter_bins = self.mean.shape[0]
|
||||
other_num_filter_bins = other.mean.shape[0]
|
||||
num_filter_bins = self_num_filter_bins * other_num_filter_bins
|
||||
self_new_bins = max(num_filter_bins - self_num_filter_bins, 1)
|
||||
other_new_bins = max(num_filter_bins - other_num_filter_bins, 1)
|
||||
self_repeat_factor = num_filter_bins / self_num_filter_bins
|
||||
other_tile_factor = num_filter_bins / other_num_filter_bins
|
||||
|
||||
# Replicate the data
|
||||
self_mean = np.repeat(self_mean, self_new_bins, axis=0)
|
||||
other_mean = np.tile(other_mean, (other_new_bins, 1, 1))
|
||||
self_std_dev = np.repeat(self_std_dev, self_new_bins, axis=0)
|
||||
other_std_dev = np.tile(other_std_dev, (other_new_bins, 1, 1))
|
||||
self_mean = np.repeat(self_mean, self_repeat_factor, axis=0)
|
||||
other_mean = np.tile(other_mean, (other_tile_factor, 1, 1))
|
||||
self_std_dev = np.repeat(self_std_dev, self_repeat_factor, axis=0)
|
||||
other_std_dev = np.tile(other_std_dev, (other_tile_factor, 1, 1))
|
||||
|
||||
if self.nuclides != other.nuclides:
|
||||
|
||||
|
|
@ -74,14 +74,14 @@ class Tally(object):
|
|||
self_num_nuclide_bins = self.mean.shape[1]
|
||||
other_num_nuclide_bins = other.mean.shape[1]
|
||||
num_nuclide_bins = self_num_nuclide_bins * other_num_nuclide_bins
|
||||
self_new_bins = max(num_nuclide_bins - self_num_nuclide_bins, 1)
|
||||
other_new_bins = max(num_nuclide_bins - other_num_nuclide_bins, 1)
|
||||
self_repeat_factor = num_nuclide_bins / self_num_nuclide_bins
|
||||
other_tile_factor = num_nuclide_bins / other_num_nuclide_bins
|
||||
|
||||
# Replicate the data
|
||||
self_mean = np.repeat(self_mean, self_new_bins, axis=1)
|
||||
other_mean = np.tile(other_mean, (1, other_new_bins, 1))
|
||||
self_std_dev = np.repeat(self_std_dev, self_new_bins, axis=1)
|
||||
other_std_dev = np.tile(other_std_dev, (1, other_new_bins, 1))
|
||||
self_mean = np.repeat(self_mean, self_repeat_factor, axis=1)
|
||||
other_mean = np.tile(other_mean, (1, other_tile_factor, 1))
|
||||
self_std_dev = np.repeat(self_std_dev, self_repeat_factor, axis=1)
|
||||
other_std_dev = np.tile(other_std_dev, (1, other_tile_factor, 1))
|
||||
|
||||
if self.scores != other.scores:
|
||||
|
||||
|
|
@ -90,14 +90,14 @@ class Tally(object):
|
|||
self_num_score_bins = self.mean.shape[2]
|
||||
other_num_score_bins = other.mean.shape[2]
|
||||
num_score_bins = self_num_score_bins * other_num_score_bins
|
||||
self_new_bins = max(num_score_bins - self_num_score_bins, 1)
|
||||
other_new_bins = max(num_score_bins - other_num_score_bins, 1)
|
||||
self_repeat_factor = num_score_bins / self_num_score_bins
|
||||
other_tile_factor = num_score_bins / other_num_score_bins
|
||||
|
||||
# Replicate the data
|
||||
self_mean = np.repeat(self_mean, self_new_bins, axis=2)
|
||||
other_mean = np.tile(other_mean, (1, 1, other_new_bins))
|
||||
self_std_dev = np.repeat(self_std_dev, self_new_bins, axis=2)
|
||||
other_std_dev = np.tile(other_std_dev, (1, 1, other_new_bins))
|
||||
self_mean = np.repeat(self_mean, self_repeat_factor, axis=2)
|
||||
other_mean = np.tile(other_mean, (1, 1, other_tile_factor))
|
||||
self_std_dev = np.repeat(self_std_dev, self_repeat_factor, axis=2)
|
||||
other_std_dev = np.tile(other_std_dev, (1, 1, other_tile_factor))
|
||||
|
||||
data = {}
|
||||
data['self'] = {}
|
||||
|
|
@ -1571,10 +1571,21 @@ class Tally(object):
|
|||
# Find the total length of the tally data array
|
||||
data_size = self.mean.size
|
||||
|
||||
# Split CrossFilters into separate filters
|
||||
split_filters = []
|
||||
|
||||
for filter in self.filters:
|
||||
|
||||
if isinstance(filter, _CrossFilter):
|
||||
split_filters.append(filter.left_filter)
|
||||
split_filters.append(filter.right_filter)
|
||||
else:
|
||||
split_filters.append(filter)
|
||||
|
||||
# Build DataFrame columns for filters if user requested them
|
||||
if filters:
|
||||
|
||||
for filter in self.filters:
|
||||
for filter in split_filters:
|
||||
|
||||
# mesh filters
|
||||
if filter.type == 'mesh':
|
||||
|
|
@ -2114,7 +2125,7 @@ class _CrossScore(object):
|
|||
@left_score.setter
|
||||
def left_score(self, left_score):
|
||||
|
||||
if not is_string(left_score):
|
||||
if not isinstance(left_score, (_CrossScore, str)):
|
||||
msg = 'Unable to set CrossScore left score to {0} which ' \
|
||||
'is not a string'.format(left_score)
|
||||
raise ValueError(msg)
|
||||
|
|
@ -2125,7 +2136,7 @@ class _CrossScore(object):
|
|||
@right_score.setter
|
||||
def right_score(self, right_score):
|
||||
|
||||
if not is_string(right_score):
|
||||
if not isinstance(right_score, (_CrossScore, str)):
|
||||
msg = 'Unable to set CrossScore right score to {0} which ' \
|
||||
'is not a string'.format(right_score)
|
||||
raise ValueError(msg)
|
||||
|
|
@ -2186,7 +2197,7 @@ class _CrossNuclide(object):
|
|||
@left_nuclide.setter
|
||||
def left_nuclide(self, left_nuclide):
|
||||
|
||||
if not isinstance(left_nuclide, Nuclide) or is_integer(left_nuclide):
|
||||
if not isinstance(left_nuclide, (Nuclide, _CrossNuclide, int)):
|
||||
msg = 'Unable to set CrossNuclide left nuclide to {0} which ' \
|
||||
'is not an integer or Nuclide'.format(left_nuclide)
|
||||
raise ValueError(msg)
|
||||
|
|
@ -2197,7 +2208,7 @@ class _CrossNuclide(object):
|
|||
@right_nuclide.setter
|
||||
def right_nuclide(self, right_nuclide):
|
||||
|
||||
if not isinstance(right_nuclide, Nuclide) or is_integer(right_nuclide):
|
||||
if not isinstance(right_nuclide, (Nuclide, _CrossNuclide, int)):
|
||||
msg = 'Unable to set CrossNuclide right nuclide to {0} which ' \
|
||||
'is not an integer or Nuclide'.format(right_nuclide)
|
||||
raise ValueError(msg)
|
||||
|
|
@ -2290,7 +2301,7 @@ class _CrossFilter(object):
|
|||
@left_filter.setter
|
||||
def left_filter(self, left_filter):
|
||||
|
||||
if not isinstance(left_filter, Filter):
|
||||
if not isinstance(left_filter, (Filter, _CrossFilter)):
|
||||
msg = 'Unable to set CrossFilter left filter to {0} which ' \
|
||||
'is not a Filter'.format(left_filter)
|
||||
raise ValueError(msg)
|
||||
|
|
@ -2301,7 +2312,7 @@ class _CrossFilter(object):
|
|||
@right_filter.setter
|
||||
def right_filter(self, right_filter):
|
||||
|
||||
if not isinstance(right_filter, Filter):
|
||||
if not isinstance(right_filter, (Filter, _CrossFilter)):
|
||||
msg = 'Unable to set CrossFilter right filter to {0} which ' \
|
||||
'is not a Filter'.format(right_filter)
|
||||
raise ValueError(msg)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue