diff --git a/src/utils/openmc/filter.py b/src/utils/openmc/filter.py index 089f9f18ac..742c91d370 100644 --- a/src/utils/openmc/filter.py +++ b/src/utils/openmc/filter.py @@ -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 diff --git a/src/utils/openmc/tallies.py b/src/utils/openmc/tallies.py index ba9185668e..dc05650815 100644 --- a/src/utils/openmc/tallies.py +++ b/src/utils/openmc/tallies.py @@ -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)