mirror of
https://github.com/openmc-dev/openmc.git
synced 2026-07-28 14:15:42 -04:00
Fixed some bugs in tally sparsification - tally arithmetic ipython notebook now working
This commit is contained in:
parent
e613658930
commit
963238194b
1 changed files with 127 additions and 70 deletions
|
|
@ -83,6 +83,11 @@ class Tally(object):
|
|||
An array containing the sample mean for each bin
|
||||
std_dev : ndarray
|
||||
An array containing the sample standard deviation for each bin
|
||||
derived : bool
|
||||
Whether or not the tally is derived from one or more other tallies
|
||||
sparse : bool
|
||||
Whether or not the tally uses SciPy's LIL sparse matrix format for
|
||||
compressed data storage
|
||||
|
||||
"""
|
||||
|
||||
|
|
@ -246,6 +251,10 @@ class Tally(object):
|
|||
def scores(self):
|
||||
return self._scores
|
||||
|
||||
@property
|
||||
def shape(self):
|
||||
return (self.num_filter_bins, self.num_nuclides, self.num_score_bins)
|
||||
|
||||
@property
|
||||
def num_scores(self):
|
||||
return len(self._scores)
|
||||
|
|
@ -308,21 +317,18 @@ class Tally(object):
|
|||
return 1 if not val else val
|
||||
|
||||
# Reshape the results arrays
|
||||
new_shape = (nonzero(self.num_filter_bins),
|
||||
nonzero(self.num_nuclides),
|
||||
nonzero(self.num_score_bins))
|
||||
|
||||
sum = np.reshape(sum, new_shape)
|
||||
sum_sq = np.reshape(sum_sq, new_shape)
|
||||
sum = np.reshape(sum, self.shape)
|
||||
sum_sq = np.reshape(sum_sq, self.shape)
|
||||
|
||||
# Set the data for this Tally
|
||||
self._sum = sum
|
||||
self._sum_sq = sum_sq
|
||||
|
||||
# Convert NumPy arrays to SciPy sparse matrices
|
||||
# Convert NumPy arrays to SciPy sparse LIL matrices
|
||||
if self.sparse:
|
||||
self._sum = sps.lil_matrix(self._sum)
|
||||
self._sum_sq = sps.lil_matrix(self._sum_sq)
|
||||
self._sum = sps.lil_matrix(self._sum.flatten(), self._sum.shape)
|
||||
self._sum_sq = \
|
||||
sps.lil_matrix(self._sum_sq.flatten(), self._sum_sq.shape)
|
||||
|
||||
# Indicate that Tally results have been read
|
||||
self._results_read = True
|
||||
|
|
@ -331,7 +337,7 @@ class Tally(object):
|
|||
f.close()
|
||||
|
||||
if self.sparse:
|
||||
return self._sum.toarray()
|
||||
return np.reshape(self._sum.toarray(), self.shape)
|
||||
else:
|
||||
return self._sum
|
||||
|
||||
|
|
@ -345,7 +351,7 @@ class Tally(object):
|
|||
self.sum
|
||||
|
||||
if self.sparse:
|
||||
return self._sum_sq.toarray()
|
||||
return np.reshape(self._sum_sq.toarray(), self.shape)
|
||||
else:
|
||||
return self._sum_sq
|
||||
|
||||
|
|
@ -357,12 +363,13 @@ class Tally(object):
|
|||
|
||||
self._mean = self.sum / self.num_realizations
|
||||
|
||||
# Convert NumPy arrays to SciPy sparse matrices
|
||||
# Convert NumPy array to SciPy sparse LIL matrix
|
||||
if self.sparse:
|
||||
self._mean = sps.lil_matrix(self._mean)
|
||||
self._mean = \
|
||||
sps.lil_matrix(self._mean.flatten(), self._mean.shape)
|
||||
|
||||
if self.sparse:
|
||||
return self._mean.toarray()
|
||||
return np.reshape(self._mean.toarray(), self.shape)
|
||||
else:
|
||||
return self._mean
|
||||
|
||||
|
|
@ -378,14 +385,15 @@ class Tally(object):
|
|||
self._std_dev[nonzero] = np.sqrt((self.sum_sq[nonzero]/n -
|
||||
self.mean[nonzero]**2)/(n - 1))
|
||||
|
||||
# Convert NumPy arrays to SciPy sparse matrices
|
||||
# Convert NumPy array to SciPy sparse LIL matrix
|
||||
if self.sparse:
|
||||
self._std_dev = sps.lil_matrix(self._std_dev)
|
||||
self._std_dev = \
|
||||
sps.lil_matrix(self._std_dev.flatten(), self._std_dev.shape)
|
||||
|
||||
self.with_batch_statistics = True
|
||||
|
||||
if self.sparse:
|
||||
return self._std_dev.toarray()
|
||||
return np.reshape(self._std_dev.toarray(), self.shape)
|
||||
else:
|
||||
return self._std_dev
|
||||
|
||||
|
|
@ -1099,22 +1107,19 @@ class Tally(object):
|
|||
Raises
|
||||
------
|
||||
ValueError
|
||||
When this method is called before the Tally is populated with data
|
||||
by the StatePoint.read_results() method. ValueError is also thrown
|
||||
if the input parameters do not correspond to the Tally's attributes,
|
||||
When this method is called before the Tally is populated with data,
|
||||
or the input parameters do not correspond to the Tally's attributes,
|
||||
e.g., if the score(s) do not match those in the Tally.
|
||||
|
||||
"""
|
||||
|
||||
# Ensure that StatePoint.read_results() was called first
|
||||
# Ensure that the tally has data
|
||||
if (value == 'mean' and self.mean is None) or \
|
||||
(value == 'std_dev' and self.std_dev is None) or \
|
||||
(value == 'rel_err' and self.mean is None) or \
|
||||
(value == 'sum' and self.sum is None) or \
|
||||
(value == 'sum_sq' and self.sum_sq is None):
|
||||
msg = 'The Tally ID="{0}" has no data to return. Call the ' \
|
||||
'StatePoint.read_results() method before using ' \
|
||||
'Tally.get_values(...)'.format(self.id)
|
||||
msg = 'The Tally ID="{0}" has no data to return'.format(self.id)
|
||||
raise ValueError(msg)
|
||||
|
||||
# Get filter, nuclide and score indices
|
||||
|
|
@ -1148,20 +1153,41 @@ class Tally(object):
|
|||
"""
|
||||
"""
|
||||
|
||||
# FIXME: pandas dataframes, summation
|
||||
if self._sum is not None:
|
||||
self._sum = \
|
||||
sps.lil_matrix(self._sum.flatten(), self._sum.shape)
|
||||
if self._sum_sq is not None:
|
||||
self._sum_sq = \
|
||||
sps.lil_matrix(self._sum_sq.flatten(), self._sum_sq.shape)
|
||||
if self._mean is not None:
|
||||
self._mean = \
|
||||
sps.lil_matrix(self._mean.flatten(), self._mean.shape)
|
||||
if self._std_dev is not None:
|
||||
self._std_dev = \
|
||||
sps.lil_matrix(self._std_dev.flatten(), self._std_dev.shape)
|
||||
|
||||
self._sparse = True
|
||||
|
||||
# FIXME: get_values
|
||||
# FIXME: each of the properties which load in the data
|
||||
# FIXME: pandas dataframes
|
||||
# summation, slicing
|
||||
if self._sum:
|
||||
self._sum = sps.lil_matrix(self._sum)
|
||||
if self._sum_sq:
|
||||
self._sum_sq = sps.lil_matrix(self._sum_sq)
|
||||
if self._mean:
|
||||
self._mean = sps.lil_matrix(self._mean)
|
||||
if self._std_dev:
|
||||
self._std_dev = sps.lil_matrix(self._std_dev)
|
||||
def densify(self):
|
||||
"""
|
||||
"""
|
||||
|
||||
# If the tally is already dense, simply return
|
||||
if not self._sparse:
|
||||
return
|
||||
|
||||
# FIXME: pandas dataframes, summation
|
||||
if self._sum is not None:
|
||||
self._sum = np.reshape(self._sum.toarray(), self.shape)
|
||||
if self._sum_sq is not None:
|
||||
self._sum_sq = np.reshape(self._sum_sq.toarray(), self.shape)
|
||||
if self._mean is not None:
|
||||
self._mean = np.reshape(self._mean.toarray(), self.shape)
|
||||
if self._std_dev is not None:
|
||||
self._std_dev = np.reshape(self._std_dev.toarray(), self.shape)
|
||||
|
||||
self._sparse = False
|
||||
|
||||
def get_pandas_dataframe(self, filters=True, nuclides=True,
|
||||
scores=True, summary=None):
|
||||
|
|
@ -1200,17 +1226,14 @@ class Tally(object):
|
|||
------
|
||||
KeyError
|
||||
When this method is called before the Tally is populated with data
|
||||
by the StatePoint.read_results() method.
|
||||
ImportError
|
||||
When Pandas can not be found on the caller's system
|
||||
|
||||
"""
|
||||
|
||||
# Ensure that StatePoint.read_results() was called first
|
||||
# Ensure that the tally has data
|
||||
if self.mean is None or self.std_dev is None:
|
||||
msg = 'The Tally ID="{0}" has no data to return. Call the ' \
|
||||
'StatePoint.read_results() method before using ' \
|
||||
'Tally.get_pandas_dataframe(...)'.format(self.id)
|
||||
msg = 'The Tally ID="{0}" has no data to return'.format(self.id)
|
||||
raise KeyError(msg)
|
||||
|
||||
# If using Summary, ensure StatePoint.link_with_summary(...) was called
|
||||
|
|
@ -1356,16 +1379,13 @@ class Tally(object):
|
|||
Raises
|
||||
------
|
||||
KeyError
|
||||
When this method is called before the Tally is populated with data
|
||||
by the StatePoint.read_results() method.
|
||||
When this method is called before the Tally is populated with data.
|
||||
|
||||
"""
|
||||
|
||||
# Ensure that StatePoint.read_results() was called first
|
||||
# Ensure that the tally has data
|
||||
if self._sum is None or self._sum_sq is None and not self.derived:
|
||||
msg = 'The Tally ID="{0}" has no data to export. Call the ' \
|
||||
'StatePoint.read_results() method before using ' \
|
||||
'Tally.export_results(...)'.format(self.id)
|
||||
msg = 'The Tally ID="{0}" has no data to export'.format(self.id)
|
||||
raise KeyError(msg)
|
||||
|
||||
if not isinstance(filename, basestring):
|
||||
|
|
@ -1527,7 +1547,7 @@ class Tally(object):
|
|||
------
|
||||
ValueError
|
||||
When this method is called before the other tally is populated
|
||||
with data by the StatePoint.read_results() method.
|
||||
with data.
|
||||
|
||||
"""
|
||||
|
||||
|
|
@ -1708,6 +1728,12 @@ class Tally(object):
|
|||
|
||||
"""
|
||||
|
||||
# Use dense NumPy arrays for data alignment operations
|
||||
self_sparse = self.sparse
|
||||
other_sparse = other.sparse
|
||||
self.densify()
|
||||
other.densify()
|
||||
|
||||
# Get the set of filters that each tally is missing
|
||||
other_missing_filters = set(self.filters).difference(set(other.filters))
|
||||
self_missing_filters = set(other.filters).difference(set(self.filters))
|
||||
|
|
@ -1769,7 +1795,7 @@ class Tally(object):
|
|||
|
||||
# If necessary, swap other nuclide
|
||||
if other_index != i:
|
||||
other.swap_nuclides(nuclide, other.nuclides[i])
|
||||
other.swap_nuclides(nuclide, other.nuclides[i])
|
||||
|
||||
# Repeat and tile the data by score in preparation for performing
|
||||
# the tensor product across scores.
|
||||
|
|
@ -1820,6 +1846,12 @@ class Tally(object):
|
|||
filter.stride = stride
|
||||
stride *= filter.num_bins
|
||||
|
||||
# Restore tally operands to sparse storage
|
||||
if self.sparse:
|
||||
self.sparsify()
|
||||
if other.sparse:
|
||||
other.sparsify()
|
||||
|
||||
# Deep copy the mean and std dev data
|
||||
self_mean = copy.deepcopy(self.mean)
|
||||
self_std_dev = copy.deepcopy(self.std_dev)
|
||||
|
|
@ -1864,7 +1896,7 @@ class Tally(object):
|
|||
------
|
||||
ValueError
|
||||
If this is a derived tally or this method is called before the tally
|
||||
is populated with data by the StatePoint.read_results() method.
|
||||
is populated with data.
|
||||
|
||||
"""
|
||||
|
||||
|
|
@ -1981,7 +2013,7 @@ class Tally(object):
|
|||
------
|
||||
ValueError
|
||||
If this is a derived tally or this method is called before the tally
|
||||
is populated with data by the StatePoint.read_results() method.
|
||||
is populated with data.
|
||||
|
||||
"""
|
||||
|
||||
|
|
@ -2036,7 +2068,7 @@ class Tally(object):
|
|||
------
|
||||
ValueError
|
||||
If this is a derived tally or this method is called before the tally
|
||||
is populated with data by the StatePoint.read_results() method.
|
||||
is populated with data.
|
||||
|
||||
"""
|
||||
|
||||
|
|
@ -2103,8 +2135,7 @@ class Tally(object):
|
|||
Raises
|
||||
------
|
||||
ValueError
|
||||
When this method is called before the Tally is populated with data
|
||||
by the StatePoint.read_results() method.
|
||||
When this method is called before the Tally is populated with data.
|
||||
|
||||
"""
|
||||
|
||||
|
|
@ -2136,6 +2167,10 @@ class Tally(object):
|
|||
for score in self.scores:
|
||||
new_tally.add_score(score)
|
||||
|
||||
# If original tally operands were sparse, sparsify the sliced tally
|
||||
if self.sparse and other.sparse:
|
||||
new_tally.sparsify()
|
||||
|
||||
else:
|
||||
msg = 'Unable to add "{0}" to Tally ID="{1}"'.format(other, self.id)
|
||||
raise ValueError(msg)
|
||||
|
|
@ -2173,8 +2208,7 @@ class Tally(object):
|
|||
Raises
|
||||
------
|
||||
ValueError
|
||||
When this method is called before the Tally is populated with data
|
||||
by the StatePoint.read_results() method.
|
||||
When this method is called before the Tally is populated with data.
|
||||
|
||||
"""
|
||||
|
||||
|
|
@ -2205,6 +2239,10 @@ class Tally(object):
|
|||
for score in self.scores:
|
||||
new_tally.add_score(score)
|
||||
|
||||
# If original tally operands were sparse, sparsify the sliced tally
|
||||
if self.sparse and other.sparse:
|
||||
new_tally.sparsify()
|
||||
|
||||
else:
|
||||
msg = 'Unable to subtract "{0}" from Tally ' \
|
||||
'ID="{1}"'.format(other, self.id)
|
||||
|
|
@ -2243,8 +2281,7 @@ class Tally(object):
|
|||
Raises
|
||||
------
|
||||
ValueError
|
||||
When this method is called before the Tally is populated with data
|
||||
by the StatePoint.read_results() method.
|
||||
When this method is called before the Tally is populated with data.
|
||||
|
||||
"""
|
||||
|
||||
|
|
@ -2275,6 +2312,10 @@ class Tally(object):
|
|||
for score in self.scores:
|
||||
new_tally.add_score(score)
|
||||
|
||||
# If original tally operands were sparse, sparsify the sliced tally
|
||||
if self.sparse and other.sparse:
|
||||
new_tally.sparsify()
|
||||
|
||||
else:
|
||||
msg = 'Unable to multiply Tally ID="{0}" ' \
|
||||
'by "{1}"'.format(self.id, other)
|
||||
|
|
@ -2313,8 +2354,7 @@ class Tally(object):
|
|||
Raises
|
||||
------
|
||||
ValueError
|
||||
When this method is called before the Tally is populated with data
|
||||
by the StatePoint.read_results() method.
|
||||
When this method is called before the Tally is populated with data.
|
||||
|
||||
"""
|
||||
|
||||
|
|
@ -2345,6 +2385,10 @@ class Tally(object):
|
|||
for score in self.scores:
|
||||
new_tally.add_score(score)
|
||||
|
||||
# If original tally operands were sparse, sparsify the sliced tally
|
||||
if self.sparse and other.sparse:
|
||||
new_tally.sparsify()
|
||||
|
||||
else:
|
||||
msg = 'Unable to divide Tally ID="{0}" ' \
|
||||
'by "{1}"'.format(self.id, other)
|
||||
|
|
@ -2386,8 +2430,7 @@ class Tally(object):
|
|||
Raises
|
||||
------
|
||||
ValueError
|
||||
When this method is called before the Tally is populated with data
|
||||
by the StatePoint.read_results() method.
|
||||
When this method is called before the Tally is populated with data.
|
||||
|
||||
"""
|
||||
|
||||
|
|
@ -2419,6 +2462,10 @@ class Tally(object):
|
|||
for score in self.scores:
|
||||
new_tally.add_score(score)
|
||||
|
||||
# If original tally was sparse, sparsify the exponentiated tally
|
||||
if self.sparse:
|
||||
new_tally.sparsify()
|
||||
|
||||
else:
|
||||
msg = 'Unable to raise Tally ID="{0}" to ' \
|
||||
'power "{1}"'.format(self.id, power)
|
||||
|
|
@ -2569,12 +2616,11 @@ class Tally(object):
|
|||
Raises
|
||||
------
|
||||
ValueError
|
||||
When this method is called before the Tally is populated with data
|
||||
by the StatePoint.read_results() method.
|
||||
When this method is called before the Tally is populated with data.
|
||||
|
||||
"""
|
||||
|
||||
# Ensure that StatePoint.read_results() was called first
|
||||
# Ensure that the tally has data
|
||||
if not self.derived and self.sum is None:
|
||||
msg = 'Unable to use tally arithmetic with Tally ID="{0}" ' \
|
||||
'since it does not contain any results.'.format(self.id)
|
||||
|
|
@ -2657,6 +2703,10 @@ class Tally(object):
|
|||
filter.stride = stride
|
||||
stride *= filter.num_bins
|
||||
|
||||
# If original tally was sparse, sparsify the sliced tally
|
||||
if self.sparse:
|
||||
new_tally.sparsify()
|
||||
|
||||
return new_tally
|
||||
|
||||
def summation(self, scores=[], filter_type=None,
|
||||
|
|
@ -2759,6 +2809,10 @@ class Tally(object):
|
|||
filters[i] = CrossFilter(filters[i-1], filters[i], '+')
|
||||
tally_sum.add_filter(filters[-1])
|
||||
|
||||
# If original tally was sparse, sparsify the tally summation
|
||||
if self.sparse:
|
||||
tally_sum.sparsify()
|
||||
|
||||
return tally_sum
|
||||
|
||||
def diagonalize_filter(self, new_filter):
|
||||
|
|
@ -2799,7 +2853,6 @@ class Tally(object):
|
|||
num_filter_bins = new_tally.num_filter_bins
|
||||
num_nuclides = new_tally.num_nuclides
|
||||
num_score_bins = new_tally.num_score_bins
|
||||
new_shape = (num_filter_bins, num_nuclides, num_score_bins)
|
||||
|
||||
# Determine "base" indices along the new "diagonal", and the factor
|
||||
# by which the "base" indices should be repeated to account for all
|
||||
|
|
@ -2816,16 +2869,16 @@ class Tally(object):
|
|||
|
||||
# Inject this Tally's data along the diagonal of the diagonalized Tally
|
||||
if self.sum is not None:
|
||||
new_tally._sum = np.zeros(new_shape, dtype=np.float64)
|
||||
new_tally._sum = np.zeros(self.shape, dtype=np.float64)
|
||||
new_tally._sum[diag_indices, :, :] = self.sum
|
||||
if self.sum_sq is not None:
|
||||
new_tally._sum_sq = np.zeros(new_shape, dtype=np.float64)
|
||||
new_tally._sum_sq = np.zeros(self.shape, dtype=np.float64)
|
||||
new_tally._sum_sq[diag_indices, :, :] = self.sum_sq
|
||||
if self.mean is not None:
|
||||
new_tally._mean = np.zeros(new_shape, dtype=np.float64)
|
||||
new_tally._mean = np.zeros(self.shape, dtype=np.float64)
|
||||
new_tally._mean[diag_indices, :, :] = self.mean
|
||||
if self.std_dev is not None:
|
||||
new_tally._std_dev = np.zeros(new_shape, dtype=np.float64)
|
||||
new_tally._std_dev = np.zeros(self.shape, dtype=np.float64)
|
||||
new_tally._std_dev[diag_indices, :, :] = self.std_dev
|
||||
|
||||
# Correct each Filter's stride
|
||||
|
|
@ -2834,6 +2887,10 @@ class Tally(object):
|
|||
filter.stride = stride
|
||||
stride *= filter.num_bins
|
||||
|
||||
# If original tally was sparse, sparsify the diagonalized tally
|
||||
if self.sparse:
|
||||
new_tally.sparsify
|
||||
|
||||
return new_tally
|
||||
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue