diff --git a/openmc/mgxs/mgxs.py b/openmc/mgxs/mgxs.py
index 1b451affc9..e9ce00254d 100644
--- a/openmc/mgxs/mgxs.py
+++ b/openmc/mgxs/mgxs.py
@@ -92,7 +92,7 @@ class MGXS(object):
xs_tally : Tally
Derived tally for the multi-group cross section. This attribute
is None unless the multi-group cross section has been computed.
- num_sumbdomains : Integral
+ num_subdomains : Integral
The number of subdomains is unity for 'material', 'cell' and 'universe'
domain types. When the This is equal to the number of cell instances
for 'distribcell' domain types (it is equal to unity prior to loading
@@ -790,7 +790,7 @@ class MGXS(object):
# Reshape condensed data arrays with one dimension for all filters
new_shape = \
- (tally.num_filter_bins, tally.num_nuclides, tally.num_score_bins,)
+ (tally.num_filter_bins, tally.num_nuclides, tally.num_scores,)
mean = np.reshape(mean, new_shape)
std_dev = np.reshape(std_dev, new_shape)
@@ -874,7 +874,7 @@ class MGXS(object):
# Reshape averaged data arrays with one dimension for all filters
new_shape = \
- (tally.num_filter_bins, tally.num_nuclides, tally.num_score_bins,)
+ (tally.num_filter_bins, tally.num_nuclides, tally.num_scores,)
mean = np.reshape(mean, new_shape)
std_dev = np.reshape(std_dev, new_shape)
@@ -1458,7 +1458,7 @@ class AbsorptionXS(MGXS):
class CaptureXS(MGXS):
"""A capture multi-group cross section.
- The Neutron capture reaction rate is defined as the difference between
+ The neutron capture reaction rate is defined as the difference between
OpenMC's 'absorption' and 'fission' reaction rate score types. This includes
not only radiative capture, but all forms of neutron disappearance aside
from fission (e.g., MT > 100).
@@ -1760,8 +1760,8 @@ class ScatterMatrixXS(MGXS):
if self.correction == 'P0':
scatter_p1 = self.tallies['scatter-P1']
scatter_p1 = scatter_p1.get_slice(scores=['scatter-P1'])
- energy_filter = copy.deepcopy(self.tallies['scatter'].
- find_filter('energy'))
+ energy_filter = self.tallies['scatter'].find_filter('energy')
+ energy_filter = copy.deepcopy(energy_filter)
scatter_p1 = scatter_p1.diagonalize_filter(energy_filter)
rxn_tally = self.tallies['scatter'] - scatter_p1
else:
diff --git a/openmc/statepoint.py b/openmc/statepoint.py
index 2edf9badd4..845937f594 100644
--- a/openmc/statepoint.py
+++ b/openmc/statepoint.py
@@ -9,9 +9,9 @@ if sys.version > '3':
class StatePoint(object):
- """State information on a simulation at a certain point in time (at the end of a
- given batch). Statepoints can be used to analyze tally results as well as
- restart a simulation.
+ """State information on a simulation at a certain point in time (at the end
+ of a given batch). Statepoints can be used to analyze tally results as well
+ as restart a simulation.
Attributes
----------
@@ -391,15 +391,10 @@ class StatePoint(object):
nuclide = openmc.Nuclide(name.decode().strip())
tally.add_nuclide(nuclide)
- # Read score bins
- n_score_bins = self._f['{0}{1}/n_score_bins'.format(base, tally_key)].value
-
- tally.num_score_bins = n_score_bins
-
scores = self._f['{0}{1}/score_bins'.format(
base, tally_key)].value
- n_user_scores = self._f['{0}{1}/n_user_score_bins'
- .format(base, tally_key)].value
+ n_score_bins = self._f['{0}{1}/n_score_bins'
+ .format(base, tally_key)].value
# Compute and set the filter strides
for i in range(n_filters):
diff --git a/openmc/summary.py b/openmc/summary.py
index bc6551e7cb..45742b0c8a 100644
--- a/openmc/summary.py
+++ b/openmc/summary.py
@@ -1,4 +1,5 @@
import numpy as np
+import re
import openmc
from openmc.region import Region
@@ -520,12 +521,19 @@ class Summary(object):
# Create Tally object and assign basic properties
tally = openmc.Tally(tally_id, tally_name)
+ # Read scattering moment order strings (e.g., P3, Y-1,2, etc.)
+ moments = self._f['{0}/moment_orders'.format(subbase)].value
+
# Read score metadata
scores = self._f['{0}/score_bins'.format(subbase)].value
- for score in scores:
- tally.add_score(score.decode())
- num_score_bins = self._f['{0}/n_score_bins'.format(subbase)][...]
- tally.num_score_bins = num_score_bins
+ for j, score in enumerate(scores):
+ score = score.decode()
+
+ # If this is a moment, use generic moment order
+ pattern = r'-n$|-pn$|-yn$'
+ score = re.sub(pattern, '-' + moments[j].decode(), score)
+
+ tally.add_score(score)
# Read filter metadata
num_filters = self._f['{0}/n_filters'.format(subbase)].value
diff --git a/openmc/tallies.py b/openmc/tallies.py
index 0954122d80..040cbb278d 100644
--- a/openmc/tallies.py
+++ b/openmc/tallies.py
@@ -25,8 +25,14 @@ if sys.version_info[0] >= 3:
# "Static" variable for auto-generated Tally IDs
AUTO_TALLY_ID = 10000
+# The tally arithmetic product types. The tensor product performs the full
+# cross product of the data in two tallies with respect to a specified axis
+# (filters, nuclides, or scores). The entrywise product performs the arithmetic
+# operation entrywise across the entries in two tallies with respect to a
+# specified axis.
_PRODUCT_TYPES = ['tensor', 'entrywise']
+
def reset_auto_tally_id():
global AUTO_TALLY_ID
AUTO_TALLY_ID = 10000
@@ -60,10 +66,6 @@ class Tally(object):
Type of estimator for the tally
triggers : list of openmc.trigger.Trigger
List of tally triggers
- num_score_bins : Integral
- Total number of scores, accounting for the fact that a single
- user-specified score, e.g. scatter-P3 or flux-Y2,2, might have multiple
- bins
num_scores : Integral
Total number of user-specified scores
num_filter_bins : Integral
@@ -104,7 +106,6 @@ class Tally(object):
self._estimator = None
self._triggers = []
- self._num_score_bins = 0
self._num_realizations = 0
self._with_summary = False
@@ -128,7 +129,6 @@ class Tally(object):
clone.id = self.id
clone.name = self.name
clone.estimator = self.estimator
- clone.num_score_bins = self.num_score_bins
clone.num_realizations = self.num_realizations
clone._sum = copy.deepcopy(self._sum, memo)
clone._sum_sq = copy.deepcopy(self._sum_sq, memo)
@@ -258,10 +258,6 @@ class Tally(object):
def num_scores(self):
return len(self._scores)
- @property
- def num_score_bins(self):
- return self._num_score_bins
-
@property
def num_filter_bins(self):
num_bins = 1
@@ -275,12 +271,12 @@ class Tally(object):
def num_bins(self):
num_bins = self.num_filter_bins
num_bins *= self.num_nuclides
- num_bins *= self.num_score_bins
+ num_bins *= self.num_scores
return num_bins
@property
def shape(self):
- return (self.num_filter_bins, self.num_nuclides, self.num_score_bins)
+ return (self.num_filter_bins, self.num_nuclides, self.num_scores)
@property
def estimator(self):
@@ -496,9 +492,13 @@ class Tally(object):
'not a string'.format(score, self.id)
raise ValueError(msg)
- # If the score is already in the Tally, don't add it again
+ # If the score is already in the Tally, raise an error
if score in self.scores:
- return
+ msg = 'Unable to add a duplicate score {0} to Tally ID="{1}" ' \
+ 'since duplicate scores are not supported in the OpenMC ' \
+ 'Python API'.format(score, self.id)
+ raise ValueError(msg)
+
# Normal score strings
if isinstance(score, basestring):
self._scores.append(score.strip())
@@ -506,10 +506,6 @@ class Tally(object):
else:
self._scores.append(score)
- @num_score_bins.setter
- def num_score_bins(self, num_score_bins):
- self._num_score_bins = num_score_bins
-
@num_realizations.setter
def num_realizations(self, num_realizations):
cv.check_type('number of realizations', num_realizations, Integral)
@@ -723,9 +719,10 @@ class Tally(object):
merged_tally.filters[i] = merged_filter
break
- # Add scores from second tally to merged tally
+ # Add unique scores from second tally to merged tally
for score in tally.scores:
- merged_tally.add_score(score)
+ if score not in merged_tally.scores:
+ merged_tally.add_score(score)
# Add triggers from second tally to merged tally
for trigger in tally.triggers:
@@ -1091,7 +1088,12 @@ class Tally(object):
"""
- cv.check_iterable_type('scores', scores, basestring)
+ for score in scores:
+ if not isinstance(score, (basestring, CrossScore)):
+ msg = 'Unable to get score indices for score "{0}" in Tally ' \
+ 'ID="{1}" since it is not a string or CrossScore'\
+ .format(score, self.id)
+ raise ValueError(msg)
# Determine the score indices from any of the requested scores
if scores:
@@ -1356,7 +1358,7 @@ class Tally(object):
for filter in self.filters:
new_shape += (filter.num_bins, )
new_shape += (self.num_nuclides,)
- new_shape += (self.num_score_bins,)
+ new_shape += (self.num_scores,)
# Reshape the data with one dimension for each filter
data = np.reshape(data, new_shape)
@@ -1503,20 +1505,20 @@ class Tally(object):
# Pickle the Tally results to a file
pickle.dump(tally_results, open(filename, 'wb'))
- def hybrid_product(self, other, binary_op, filter_product='None',
- nuclide_product='None', score_product='None'):
+ def hybrid_product(self, other, binary_op, filter_product=None,
+ nuclide_product=None, score_product=None):
"""Combines filters, scores and nuclides with another tally.
- This is a helper method for the tally arithmetic methods. It is called a
- "hybrid product" because it performs a combination of tensor
- (or Kronecker) and entrywise (or Hadamard) products. The filters,
- nuclides, and scores from both tallies are combined using an entrywise
+ This is a helper method for the tally arithmetic operator overloaded
+ methods. It is called a "hybrid product" because it performs a
+ combination of tensor (or Kronecker) and entrywise (or Hadamard)
+ products. The filters from both tallies are combined using an entrywise
(or Hadamard) product on matching filters. By default, if all nuclides
are identical in the two tallies, the entrywise product is performed
- across nuclides; else the tensor product is performed. By default, if all
- scores are identical in the two tallies, the entrywise product is
- performed across scores; else the tensor product is performed. Users can
- also call the method explicitly and specify the desired product.
+ across nuclides; else the tensor product is performed. By default, if
+ all scores are identical in the two tallies, the entrywise product is
+ performed across scores; else the tensor product is performed. Users
+ can also call the method explicitly and specify the desired product.
Parameters
----------
@@ -1524,17 +1526,17 @@ class Tally(object):
The tally on the right hand side of the hybrid product
binary_op : {'+', '-', '*', '/', '^'}
The binary operation in the hybrid product
- filter_product : str, optional
+ filter_product : {'tensor', 'entrywise' or None}
The type of product (tensor or entrywise) to be performed between
filter data. The default is the entrywise product. Currently only
the entrywise product is supported since a tally cannot contain
- two of the same tallies.
- nuclide_product : str, optional
+ two of the same filter.
+ nuclide_product : {'tensor', 'entrywise' or None}
The type of product (tensor or entrywise) to be performed between
nuclide data. The default is the entrywise product if all nuclides
between the two tallies are the same; otherwise the default is
the tensor product.
- score_product : str, optional
+ score_product : {'tensor', 'entrywise' or None}
The type of product (tensor or entrywise) to be performed between
score data. The default is the entrywise product if all scores
between the two tallies are the same; otherwise the default is
@@ -1554,22 +1556,22 @@ class Tally(object):
"""
# Set default value for filter product if it was not set
- if filter_product == 'None':
+ if filter_product is None:
filter_product = 'entrywise'
elif filter_product == 'tensor':
msg = 'Unable to perform Tally arithmetic with a tensor product' \
- 'for the filter data as this not currently supported.'
+ 'for the filter data as this is not currently supported.'
raise ValueError(msg)
# Set default value for nuclide product if it was not set
- if nuclide_product == 'None':
+ if nuclide_product is None:
if self.nuclides == other.nuclides:
nuclide_product = 'entrywise'
else:
nuclide_product = 'tensor'
# Set default value for score product if it was not set
- if score_product == 'None':
+ if score_product is None:
if self.scores == other.scores:
score_product = 'entrywise'
else:
@@ -1597,10 +1599,7 @@ class Tally(object):
# Query the mean and std dev so the tally data is read in from file
# if it has not already been read in.
- self.mean
- self.std_dev
- other.mean
- other.std_dev
+ self.mean, self.std_dev, other.mean, other.std_dev
# Create copies of self and other tallies to rearrange for tally
# arithmetic
@@ -1661,7 +1660,7 @@ class Tally(object):
# Add filters to the new tally
if filter_product == 'entrywise':
for self_filter in self_copy.filters:
- new_tally.filters.append(self_filter)
+ new_tally.add_filter(self_filter)
else:
all_filters = [self_copy.filters, other_copy.filters]
for self_filter, other_filter in itertools.product(*all_filters):
@@ -1671,7 +1670,7 @@ class Tally(object):
# Add nuclides to the new tally
if nuclide_product == 'entrywise':
for self_nuclide in self_copy.nuclides:
- new_tally.nuclides.append(self_nuclide)
+ new_tally.add_nuclide(self_nuclide)
else:
all_nuclides = [self_copy.nuclides, other_copy.nuclides]
for self_nuclide, other_nuclide in itertools.product(*all_nuclides):
@@ -1681,19 +1680,16 @@ class Tally(object):
# Add scores to the new tally
if score_product == 'entrywise':
- new_tally.num_score_bins = self_copy.num_score_bins
for self_score in self_copy.scores:
new_tally.add_score(self_score)
else:
- new_tally.num_score_bins = \
- self_copy.num_score_bins * other_copy.num_score_bins
all_scores = [self_copy.scores, other_copy.scores]
for self_score, other_score in itertools.product(*all_scores):
new_score = CrossScore(self_score, other_score, binary_op)
new_tally.add_score(new_score)
# Correct each Filter's stride
- stride = new_tally.num_nuclides * new_tally.num_score_bins
+ stride = new_tally.num_nuclides * new_tally.num_scores
for filter in reversed(new_tally.filters):
filter.stride = stride
stride *= filter.num_bins
@@ -1715,13 +1711,13 @@ class Tally(object):
----------
other : Tally
The tally to outer product with this tally
- filter_product : str
- The type of product (tensor or entrywise) to be performed between
- filter data.
- nuclide_product : str
+ filter_product : {'entrywise'}
+ The type of product to be performed between filter data. Currently,
+ only the entrywise product is supported for the filter product.
+ nuclide_product : {'tensor', 'entrywise'}
The type of product (tensor or entrywise) to be performed between
nuclide data.
- score_product : str
+ score_product : {'tensor', 'entrywise'}
The type of product (tensor or entrywise) to be performed between
score data.
Returns
@@ -1757,7 +1753,7 @@ class Tally(object):
# If necessary, swap other filter
if other_index != i:
- other.swap_filters(filter, other.filters[i], inplace=True)
+ other._swap_filters(filter, other.filters[i])
# Repeat and tile the data by nuclide in preparation for performing
# the tensor product across nuclides.
@@ -1800,27 +1796,23 @@ class Tally(object):
# Align other nuclides with self nuclides
for i, nuclide in enumerate(self.nuclides):
- other_index = other.nuclides.index(nuclide)
+ other_index = other.get_nuclide_index(nuclide)
# 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.
if score_product == 'tensor':
- self._mean = \
- np.repeat(self.mean, other.num_score_bins, axis=2)
- self._std_dev = \
- np.repeat(self.std_dev, other.num_score_bins, axis=2)
- other._mean = \
- np.tile(other.mean, (1, 1, self.num_score_bins))
- other._std_dev = \
- np.tile(other.std_dev, (1, 1, self.num_score_bins))
+ self._mean = np.repeat(self.mean, other.num_scores, axis=2)
+ self._std_dev = np.repeat(self.std_dev, other.num_scores, axis=2)
+ other._mean = np.tile(other.mean, (1, 1, self.num_scores))
+ other._std_dev = np.tile(other.std_dev, (1, 1, self.num_scores))
- # Add scores to each tally such that each tally contains the complete
- # set of scores necessary to perform an entrywise product. New scores
- # added to a tally will be set to zero.
+ # Add scores to each tally such that each tally contains the complete set
+ # of scores necessary to perform an entrywise product. New scores added
+ # to a tally will be set to zero.
else:
# Get the set of scores that each tally is missing
@@ -1831,18 +1823,14 @@ class Tally(object):
# Add scores present in self but not in other to other
for score in other_missing_scores:
- other._mean = \
- np.insert(other.mean, other.num_score_bins, 0, axis=2)
- other._std_dev = \
- np.insert(other.std_dev, other.num_score_bins, 0, axis=2)
+ other._mean = np.insert(other.mean, other.num_scores, 0, axis=2)
+ other._std_dev = np.insert(other.std_dev, other.num_scores, 0, axis=2)
other.add_score(score)
# Add scores present in other but not in self to self
for score in self_missing_scores:
- self._mean = \
- np.insert(self.mean, self.num_score_bins, 0, axis=2)
- self._std_dev = \
- np.insert(self.std_dev, self.num_score_bins, 0, axis=2)
+ self._mean = np.insert(self.mean, self.num_scores, 0, axis=2)
+ self._std_dev = np.insert(self.std_dev, self.num_scores, 0, axis=2)
self.add_score(score)
# Align other scores with self scores
@@ -1851,42 +1839,35 @@ class Tally(object):
# If necessary, swap other score
if other_index != i:
- other.swap_scores(score, other.scores[i])
+ other._swap_scores(score, other.scores[i])
# Correct the stride for other filters
- stride = other.num_nuclides * other.num_score_bins
+ stride = other.num_nuclides * other.num_scores
for filter in reversed(other.filters):
filter.stride = stride
stride *= filter.num_bins
# Correct the stride for self filters
- stride = self.num_nuclides * self.num_score_bins
+ stride = self.num_nuclides * self.num_scores
for filter in reversed(self.filters):
filter.stride = stride
stride *= filter.num_bins
- # Deep copy the mean and std dev data
- self_mean = copy.deepcopy(self.mean)
- self_std_dev = copy.deepcopy(self.std_dev)
- other_mean = copy.deepcopy(other.mean)
- other_std_dev = copy.deepcopy(other.std_dev)
-
data = {}
data['self'] = {}
data['other'] = {}
- data['self']['mean'] = self_mean
- data['other']['mean'] = other_mean
- data['self']['std. dev.'] = self_std_dev
- data['other']['std. dev.'] = other_std_dev
-
+ data['self']['mean'] = self.mean
+ data['other']['mean'] = other.mean
+ data['self']['std. dev.'] = self.std_dev
+ data['other']['std. dev.'] = other.std_dev
return data
- def swap_filters(self, filter1, filter2, inplace=False):
+ def _swap_filters(self, filter1, filter2):
"""Reverse the ordering of two filters in this tally
This is a helper method for tally arithmetic which helps align the data
- in two tallies with shared filters. This method copies this tally and
- reverses the order of the two filters.
+ in two tallies with shared filters. This method reverses the order of
+ the two filters in place.
Parameters
----------
@@ -1896,16 +1877,6 @@ class Tally(object):
filter2 : Filter
The filter to swap with filter1
- inplace : bool, optional
- Whether to perform operation inplace or return new tally with the
- filters swapped.
-
- Returns
- -------
- swap_tally
- If inplace is false, a copy of this tally with the filters swapped.
- Otherwise, nothing is returned.
-
Raises
------
ValueError
@@ -1923,6 +1894,7 @@ class Tally(object):
cv.check_type('filter1', filter1, Filter)
cv.check_type('filter2', filter2, Filter)
+ # Check that the filters exist in the tally and are not the same
if filter1 == filter2:
msg = 'Unable to swap a filter with itself'
raise ValueError(msg)
@@ -1935,25 +1907,15 @@ class Tally(object):
'does not contain such a filter'.format(filter2.type, self.id)
raise ValueError(msg)
- # Create a copy of the tally that preserves the original data formatting
- # throughout swapping process
- tally_copy = copy.deepcopy(self)
-
- # Set the swap tally
- if inplace:
- swap_tally = self
- else:
- swap_tally = copy.deepcopy(self)
-
# Swap the filters in the copied version of this Tally
- filter1_index = swap_tally.filters.index(filter1)
- filter2_index = swap_tally.filters.index(filter2)
- swap_tally.filters[filter1_index] = filter2
- swap_tally.filters[filter2_index] = filter1
+ filter1_index = self.filters.index(filter1)
+ filter2_index = self.filters.index(filter2)
+ self.filters[filter1_index] = filter2
+ self.filters[filter2_index] = filter1
# Update the strides for each of the filters
- stride = swap_tally.num_nuclides * swap_tally.num_score_bins
- for filter in reversed(swap_tally.filters):
+ stride = self.num_nuclides * self.num_scores
+ for filter in reversed(self.filters):
filter.stride = stride
stride *= filter.num_bins
@@ -1964,51 +1926,30 @@ class Tally(object):
else:
filter1_bins = [(filter1.get_bin(i)) for i in range(filter1.num_bins)]
- if filter1.type == 'distribcell':
+ if filter2.type == 'distribcell':
filter2_bins = np.arange(filter2.num_bins)
else:
filter2_bins = [filter2.get_bin(i) for i in range(filter2.num_bins)]
- # Adjust the sum data array to relect the new filter order
- if swap_tally.sum is not None:
- for bin1, bin2 in itertools.product(filter1_bins, filter2_bins):
- filter_bins = [(bin1,), (bin2,)]
- data = tally_copy.get_values(
- filters=filters, filter_bins=filter_bins, value='sum')
- indices = swap_tally.get_filter_indices(filters, filter_bins)
- swap_tally.sum[indices, :, :] = data
-
- # Adjust the sum_sq data array to relect the new filter order
- if swap_tally.sum_sq is not None:
- for bin1, bin2 in itertools.product(filter1_bins, filter2_bins):
- filter_bins = [(bin1,), (bin2,)]
- data = tally_copy.get_values(
- filters=filters, filter_bins=filter_bins, value='sum_sq')
- indices = swap_tally.get_filter_indices(filters, filter_bins)
- swap_tally.sum_sq[indices, :, :] = data
-
# Adjust the mean data array to relect the new filter order
- if swap_tally.mean is not None:
+ if self.mean is not None:
for bin1, bin2 in itertools.product(filter1_bins, filter2_bins):
filter_bins = [(bin1,), (bin2,)]
- data = tally_copy.get_values(
+ data = self.get_values(
filters=filters, filter_bins=filter_bins, value='mean')
- indices = swap_tally.get_filter_indices(filters, filter_bins)
- swap_tally._mean[indices, :, :] = data
+ indices = self.get_filter_indices(filters, filter_bins)
+ self._mean[indices, :, :] = data
# Adjust the std_dev data array to relect the new filter order
- if swap_tally.std_dev is not None:
+ if self.std_dev is not None:
for bin1, bin2 in itertools.product(filter1_bins, filter2_bins):
filter_bins = [(bin1,), (bin2,)]
- data = tally_copy.get_values(
+ data = self.get_values(
filters=filters, filter_bins=filter_bins, value='std_dev')
- indices = swap_tally.get_filter_indices(filters, filter_bins)
- swap_tally._std_dev[indices, :, :] = data
+ indices = self.get_filter_indices(filters, filter_bins)
+ self._std_dev[indices, :, :] = data
- if not inplace:
- return swap_tally
-
- def swap_nuclides(self, nuclide1, nuclide2):
+ def _swap_nuclides(self, nuclide1, nuclide2):
"""Reverse the ordering of two nuclides in this tally
This is a helper method for tally arithmetic which helps align the data
@@ -2037,45 +1978,57 @@ class Tally(object):
'since it does not contain any results.'.format(self.id)
raise ValueError(msg)
+ cv.check_type('nuclide1', nuclide1, Nuclide)
+ cv.check_type('nuclide2', nuclide2, Nuclide)
+
+ # Check that the nuclides exist in the tally and are not the same
+ if nuclide1 == nuclide2:
+ msg = 'Unable to swap a nuclide with itself'
+ raise ValueError(msg)
+ elif nuclide1 not in self.nuclides:
+ msg = 'Unable to swap nuclide1 "{0}" in Tally ID="{1}" since it ' \
+ 'does not contain such a nuclide'\
+ .format(nuclide1.name, self.id)
+ raise ValueError(msg)
+ elif nuclide2 not in self.nuclides:
+ msg = 'Unable to swap "{0}" nuclide2 in Tally ID="{1}" since it ' \
+ 'does not contain such a nuclide'\
+ .format(nuclide2.name, self.id)
+ raise ValueError(msg)
+
# Swap the nuclides in the Tally
- nuclide1_index = self.nuclides.index(nuclide1)
- nuclide2_index = self.nuclides.index(nuclide2)
+ nuclide1_index = self.get_nuclide_index(nuclide1)
+ nuclide2_index = self.get_nuclide_index(nuclide2)
self.nuclides[nuclide1_index] = nuclide2
self.nuclides[nuclide2_index] = nuclide1
- # Copy the tally data
- self_mean = copy.deepcopy(self.mean)
- self_std_dev = copy.deepcopy(self.std_dev)
+ # Adjust the mean data array to relect the new nuclide order
+ if self.mean is not None:
+ nuclide1_mean = self._mean[:, nuclide1_index, :].copy()
+ nuclide2_mean = self._mean[:, nuclide2_index, :].copy()
+ self._mean[:, nuclide2_index, :] = nuclide1_mean
+ self._mean[:, nuclide1_index, :] = nuclide2_mean
- # Swap nuclide 1 in place of nuclide 2
- self._mean = np.delete(self.mean, nuclide2_index, axis=1)
- self._mean = np.insert(self.mean, nuclide2_index,
- self_mean[:,nuclide1_index,:], axis=1)
- self._std_dev = np.delete(self.std_dev, nuclide2_index, axis=1)
- self._std_dev = np.insert(self.std_dev, nuclide2_index,
- self_mean[:,nuclide1_index,:], axis=1)
+ # Adjust the std_dev data array to relect the new nuclide order
+ if self.std_dev is not None:
+ nuclide1_std_dev = self._std_dev[:, nuclide1_index, :].copy()
+ nuclide2_std_dev = self._std_dev[:, nuclide2_index, :].copy()
+ self._std_dev[:, nuclide2_index, :] = nuclide1_std_dev
+ self._std_dev[:, nuclide1_index, :] = nuclide2_std_dev
- # Swap nuclide 2 in place of nuclide 1
- self._mean = np.delete(self.mean, nuclide1_index, axis=1)
- self._mean = np.insert(self.mean, nuclide1_index,
- self_mean[:,nuclide2_index,:], axis=1)
- self._std_dev = np.delete(self.std_dev, nuclide1_index, axis=1)
- self._std_dev = np.insert(self.std_dev, nuclide1_index,
- self_mean[:,nuclide2_index,:], axis=1)
-
- def swap_scores(self, score1, score2):
+ def _swap_scores(self, score1, score2):
"""Reverse the ordering of two scores in this tally
This is a helper method for tally arithmetic which helps align the data
- in two tallies with shared scores. This method copies reverses the order
+ in two tallies with shared scores. This method reverses the order
of the two scores in place.
Parameters
----------
- score1 : Score
+ score1 : str or CrossScore
The score to swap with score2
- score2 : Score
+ score2 : str or CrossScore
The score to swap with score1
Raises
@@ -2092,31 +2045,48 @@ class Tally(object):
'since it does not contain any results.'.format(self.id)
raise ValueError(msg)
+ # Check that the scores are valid
+ if not isinstance(score1, (basestring, CrossScore)):
+ msg = 'Unable to swap score1 "{0}" in Tally ID="{1}" since it is ' \
+ 'not a string or CrossScore'.format(score1, self.id)
+ raise ValueError(msg)
+ elif not isinstance(score2, (basestring, CrossScore)):
+ msg = 'Unable to swap score2 "{0}" in Tally ID="{1}" since it is ' \
+ 'not a string or CrossScore'.format(score2, self.id)
+ raise ValueError(msg)
+
+ # Check that the scores exist in the tally and are not the same
+ if score1 == score2:
+ msg = 'Unable to swap a score with itself'
+ raise ValueError(msg)
+ elif score1 not in self.scores:
+ msg = 'Unable to swap score1 "{0}" in Tally ID="{1}" since it ' \
+ 'does not contain such a score'.format(score1, self.id)
+ raise ValueError(msg)
+ elif score2 not in self.scores:
+ msg = 'Unable to swap score2 "{0}" in Tally ID="{1}" since it ' \
+ 'does not contain such a score'.format(score2, self.id)
+ raise ValueError(msg)
+
# Swap the scores in the Tally
- score1_index = self.scores.index(score1)
- score2_index = self.scores.index(score2)
+ score1_index = self.get_score_index(score1)
+ score2_index = self.get_score_index(score2)
self.scores[score1_index] = score2
self.scores[score2_index] = score1
- # Copy the tally data
- self_mean = copy.deepcopy(self.mean)
- self_std_dev = copy.deepcopy(self.std_dev)
+ # Adjust the mean data array to relect the new nuclide order
+ if self.mean is not None:
+ score1_mean = self._mean[:, :, score1_index].copy()
+ score2_mean = self._mean[:, :, score2_index].copy()
+ self._mean[:, :, score2_index] = score1_mean
+ self._mean[:, :, score1_index] = score2_mean
- # Swap score 1 in place of score 2
- self._mean = np.delete(self.mean, score2_index, axis=2)
- self._mean = np.insert(self.mean, score2_index,
- self_mean[:,:,score1_index], axis=2)
- self._std_dev = np.delete(self.std_dev, score2_index, axis=2)
- self._std_dev = np.insert(self.std_dev, score2_index,
- self_mean[:,:,score1_index], axis=2)
-
- # Swap score 2 in place of score 1
- self._mean = np.delete(self.mean, score1_index, axis=2)
- self._mean = np.insert(self.mean, score1_index,
- self_mean[:,:,score2_index], axis=2)
- self._std_dev = np.delete(self.std_dev, score1_index, axis=2)
- self._std_dev = np.insert(self.std_dev, score1_index,
- self_mean[:,:,score2_index], axis=2)
+ # Adjust the std_dev data array to relect the new nuclide order
+ if self.std_dev is not None:
+ score1_std_dev = self._std_dev[:, :, score1_index].copy()
+ score2_std_dev = self._std_dev[:, :, score2_index].copy()
+ self._std_dev[:, :, score2_index] = score1_std_dev
+ self._std_dev[:, :, score1_index] = score2_std_dev
def __add__(self, other):
"""Adds this tally to another tally or scalar value.
@@ -2176,7 +2146,6 @@ class Tally(object):
new_tally.estimator = self.estimator
new_tally.with_summary = self.with_summary
new_tally.num_realization = self.num_realizations
- new_tally.num_score_bins = self.num_score_bins
for filter in self.filters:
new_tally.add_filter(filter)
@@ -2251,7 +2220,6 @@ class Tally(object):
new_tally.estimator = self.estimator
new_tally.with_summary = self.with_summary
new_tally.num_realization = self.num_realizations
- new_tally.num_score_bins = self.num_score_bins
for filter in self.filters:
new_tally.add_filter(filter)
@@ -2327,7 +2295,6 @@ class Tally(object):
new_tally.estimator = self.estimator
new_tally.with_summary = self.with_summary
new_tally.num_realization = self.num_realizations
- new_tally.num_score_bins = self.num_score_bins
for filter in self.filters:
new_tally.add_filter(filter)
@@ -2403,7 +2370,6 @@ class Tally(object):
new_tally.estimator = self.estimator
new_tally.with_summary = self.with_summary
new_tally.num_realization = self.num_realizations
- new_tally.num_score_bins = self.num_score_bins
for filter in self.filters:
new_tally.add_filter(filter)
@@ -2483,7 +2449,6 @@ class Tally(object):
new_tally.estimator = self.estimator
new_tally.with_summary = self.with_summary
new_tally.num_realization = self.num_realizations
- new_tally.num_score_bins = self.num_score_bins
for filter in self.filters:
new_tally.add_filter(filter)
@@ -2688,7 +2653,6 @@ class Tally(object):
# Loop over indices in reverse to remove excluded scores
for score_index in reversed(score_indices):
new_tally.remove_score(self.scores[score_index])
- new_tally.num_score_bins -= 1
# NUCLIDES
if nuclides:
@@ -2728,7 +2692,7 @@ class Tally(object):
filter.num_bins = len(filter_bins[i])
# Correct each Filter's stride
- stride = new_tally.num_nuclides * new_tally.num_score_bins
+ stride = new_tally.num_nuclides * new_tally.num_scores
for filter in reversed(new_tally.filters):
filter.stride = stride
stride *= filter.num_bins
@@ -2878,7 +2842,8 @@ class Tally(object):
# Determine the shape of data in the new diagonalized Tally
num_filter_bins = new_tally.num_filter_bins
num_nuclides = new_tally.num_nuclides
- num_score_bins = new_tally.num_score_bins
+ num_scores = new_tally.num_scores
+ new_shape = (num_filter_bins, num_nuclides, num_scores)
# Determine "base" indices along the new "diagonal", and the factor
# by which the "base" indices should be repeated to account for all
@@ -2908,7 +2873,7 @@ class Tally(object):
new_tally._std_dev[diag_indices, :, :] = self.std_dev
# Correct each Filter's stride
- stride = new_tally.num_nuclides * new_tally.num_score_bins
+ stride = new_tally.num_nuclides * new_tally.num_scores
for filter in reversed(new_tally.filters):
filter.stride = stride
stride *= filter.num_bins
diff --git a/src/summary.F90 b/src/summary.F90
index cb005d3be5..217c454b81 100644
--- a/src/summary.F90
+++ b/src/summary.F90
@@ -484,8 +484,10 @@ contains
subroutine write_tallies(file_id)
integer(HID_T), intent(in) :: file_id
- integer :: i, j
+ integer :: i, j, k
integer :: i_list, i_xs
+ integer :: n_order ! loop index for moment orders
+ integer :: nm_order ! loop index for Ynm moment orders
integer(HID_T) :: tallies_group
integer(HID_T) :: mesh_group
integer(HID_T) :: tally_group
@@ -664,6 +666,37 @@ contains
deallocate(str_array)
+ ! Write explicit moment order strings for each score bin
+ k = 1
+ allocate(str_array(t%n_score_bins))
+ MOMENT_LOOP: do j = 1, t%n_user_score_bins
+ select case(t%score_bins(k))
+ case (SCORE_SCATTER_N, SCORE_NU_SCATTER_N)
+ str_array(k) = 'P' // trim(to_str(t%moment_order(k)))
+ k = k + 1
+ case (SCORE_SCATTER_PN, SCORE_NU_SCATTER_PN)
+ do n_order = 0, t%moment_order(k)
+ str_array(k) = 'P' // trim(to_str(n_order))
+ k = k + 1
+ end do
+ case (SCORE_SCATTER_YN, SCORE_NU_SCATTER_YN, SCORE_FLUX_YN, &
+ SCORE_TOTAL_YN)
+ do n_order = 0, t%moment_order(k)
+ do nm_order = -n_order, n_order
+ str_array(k) = 'Y' // trim(to_str(n_order)) // ',' // &
+ trim(to_str(nm_order))
+ k = k + 1
+ end do
+ end do
+ case default
+ str_array(k) = ''
+ k = k + 1
+ end select
+ end do MOMENT_LOOP
+
+ call write_dataset(tally_group, "moment_orders", str_array)
+ deallocate(str_array)
+
call close_group(tally_group)
end do TALLY_METADATA
diff --git a/tests/test_many_scores/results_true.dat b/tests/test_many_scores/results_true.dat
index 0d5dd6e32e..ae5430e30a 100644
--- a/tests/test_many_scores/results_true.dat
+++ b/tests/test_many_scores/results_true.dat
@@ -11,18 +11,6 @@ tally 1:
2.483728E+01
5.102293E-01
8.710841E-02
-8.628000E+00
-2.481430E+01
-9.329009E-01
-2.902534E-01
-5.102293E-01
-8.710841E-02
-5.087118E-01
-8.657086E-02
-8.632000E+00
-2.483728E+01
-9.328366E-01
-2.902108E-01
5.087118E-01
8.657086E-02
9.212024E+00
diff --git a/tests/test_many_scores/tallies.xml b/tests/test_many_scores/tallies.xml
index 2df5597d04..b8a154f1ac 100644
--- a/tests/test_many_scores/tallies.xml
+++ b/tests/test_many_scores/tallies.xml
@@ -4,9 +4,9 @@
- flux total scatter nu-scatter scatter-2 scatter-p2 nu-scatter-2
- nu-scatter-p2 transport n1n absorption nu-fission kappa-fission
- flux-y2 total-y2 scatter-y2 nu-scatter-y2 events delayed-nu-fission
+ flux total scatter nu-scatter scatter-2 nu-scatter-2 transport n1n
+ absorption nu-fission kappa-fission flux-y2 total-y2 scatter-y2
+ nu-scatter-y2 events delayed-nu-fission
diff --git a/tests/test_score_MT/inputs_true.dat b/tests/test_score_MT/inputs_true.dat
index 3789a69cba..b361c28cf2 100644
--- a/tests/test_score_MT/inputs_true.dat
+++ b/tests/test_score_MT/inputs_true.dat
@@ -1 +1 @@
-63295b9d510370e65e63a3db627d47d286f5479e53c8eabeda9a5cb25ffe35becb636835aadad11691e34c23292fe11b5f688daee76d76ceac4b5dfd2f9ede4c
\ No newline at end of file
+7270299e4a4dde19d250825b0124fa36b60df847f046e058ccdfc74d4690beaaaaf387e050f596cb3445caf793d6a390ddb2d19650a3dccd4eb60056ae3b1477
\ No newline at end of file
diff --git a/tests/test_score_MT/results_true.dat b/tests/test_score_MT/results_true.dat
index 44656963f0..04b9c5ca50 100644
--- a/tests/test_score_MT/results_true.dat
+++ b/tests/test_score_MT/results_true.dat
@@ -7,10 +7,6 @@ tally 1:
0.000000E+00
0.000000E+00
0.000000E+00
-0.000000E+00
-0.000000E+00
-1.538090E-03
-1.381456E-06
1.538090E-03
1.381456E-06
3.974412E-01
@@ -19,16 +15,12 @@ tally 1:
3.796357E-01
5.252455E-06
2.290531E-11
-5.252455E-06
-2.290531E-11
3.359792E-02
2.267331E-04
2.459115E-02
1.233078E-04
0.000000E+00
0.000000E+00
-0.000000E+00
-0.000000E+00
7.004005E-05
1.748739E-09
8.104946E-02
@@ -42,18 +34,12 @@ tally 2:
0.000000E+00
0.000000E+00
0.000000E+00
-0.000000E+00
-0.000000E+00
-0.000000E+00
-0.000000E+00
2.000000E-01
9.000000E-03
0.000000E+00
0.000000E+00
0.000000E+00
0.000000E+00
-0.000000E+00
-0.000000E+00
2.000000E-02
2.000000E-04
0.000000E+00
@@ -64,8 +50,6 @@ tally 2:
0.000000E+00
0.000000E+00
0.000000E+00
-0.000000E+00
-0.000000E+00
tally 3:
0.000000E+00
0.000000E+00
@@ -73,10 +57,6 @@ tally 3:
0.000000E+00
0.000000E+00
0.000000E+00
-0.000000E+00
-0.000000E+00
-1.408027E-03
-1.849607E-06
1.408027E-03
1.849607E-06
3.946436E-01
@@ -85,16 +65,12 @@ tally 3:
3.382059E-01
2.179241E-05
4.749090E-10
-2.179241E-05
-4.749090E-10
3.146594E-02
2.159308E-04
4.278352E-02
4.094478E-04
0.000000E+00
0.000000E+00
-0.000000E+00
-0.000000E+00
1.736514E-04
1.245171E-08
7.989710E-02
diff --git a/tests/test_score_MT/test_score_MT.py b/tests/test_score_MT/test_score_MT.py
index dae86d418c..fb8aa7cfb4 100644
--- a/tests/test_score_MT/test_score_MT.py
+++ b/tests/test_score_MT/test_score_MT.py
@@ -12,7 +12,6 @@ class ScoreMTTestHarness(PyAPITestHarness):
filt = openmc.Filter(type='cell', bins=(10, 21, 22, 23))
tallies = [openmc.Tally(tally_id=i) for i in range(1, 4)]
[t.add_filter(filt) for t in tallies]
- [t.add_score('n2n') for t in tallies]
[t.add_score('16') for t in tallies]
[t.add_score('51') for t in tallies]
[t.add_score('102') for t in tallies]
diff --git a/tests/test_tally_arithmetic/geometry.xml b/tests/test_tally_arithmetic/geometry.xml
deleted file mode 100644
index bc56030e18..0000000000
--- a/tests/test_tally_arithmetic/geometry.xml
+++ /dev/null
@@ -1,8 +0,0 @@
-
-
-
-
-
-
-
-
diff --git a/tests/test_tally_arithmetic/inputs_true.dat b/tests/test_tally_arithmetic/inputs_true.dat
new file mode 100644
index 0000000000..8e8838131a
--- /dev/null
+++ b/tests/test_tally_arithmetic/inputs_true.dat
@@ -0,0 +1 @@
+df6318b76cd37a29ef9dd09da48a70c191ed07c1a2ceb75eb502ab35086c31250872406f22c2587edfcee16f67dd95c81db012ccd728710ed2509084438aea56
\ No newline at end of file
diff --git a/tests/test_tally_arithmetic/materials.xml b/tests/test_tally_arithmetic/materials.xml
deleted file mode 100644
index e7947a92da..0000000000
--- a/tests/test_tally_arithmetic/materials.xml
+++ /dev/null
@@ -1,11 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
diff --git a/tests/test_tally_arithmetic/results_true.dat b/tests/test_tally_arithmetic/results_true.dat
index 23dd38cfb6..ded2efa665 100644
--- a/tests/test_tally_arithmetic/results_true.dat
+++ b/tests/test_tally_arithmetic/results_true.dat
@@ -1,53 +1,134 @@
-Tally
- ID = 10000
- Name = (tally 1 + tally 2)
- Filters =
- cell [1]
- energy [ 0. 20.]
- material [1]
- Nuclides = (U-235 + U-235) (U-235 + Pu-239) (U-238 + U-235) (U-238 + Pu-239)
- Scores = [(fission + fission), (fission + absorption), (nu-fission + fission), (nu-fission + absorption)]
- Estimator = tracklength
-[[[ 0.07510122 0.07839105 0.13713377 0.1404236 ]
- [ 0.0916553 0.09321683 0.15368785 0.15524938]
- [ 0.04596277 0.0492526 0.06126275 0.06455259]
- [ 0.06251685 0.06407838 0.07781683 0.07937836]]]Tally
- ID = 10001
- Name = (tally 1 - tally 2)
- Filters =
- cell [1]
- energy [ 0. 20.]
- material [1]
- Nuclides = (U-235 - U-235) (U-235 - Pu-239) (U-238 - U-235) (U-238 - Pu-239)
- Scores = [(fission - fission), (fission - absorption), (nu-fission - fission), (nu-fission - absorption)]
- Estimator = tracklength
-[[[ 0. -0.00328983 0.06203255 0.05874271]
- [-0.01655408 -0.01811561 0.04547847 0.04391694]
- [-0.02913845 -0.03242829 -0.01383847 -0.0171283 ]
- [-0.04569253 -0.04725406 -0.03039255 -0.03195408]]]Tally
- ID = 10002
- Name = (tally 1 * tally 2)
- Filters =
- cell [1]
- energy [ 0. 20.]
- material [1]
- Nuclides = (U-235 * U-235) (U-235 * Pu-239) (U-238 * U-235) (U-238 * Pu-239)
- Scores = [(fission * fission), (fission * absorption), (nu-fission * fission), (nu-fission * absorption)]
- Estimator = tracklength
-[[[ 0.00141005 0.00153358 0.00373941 0.00406702]
- [ 0.00203166 0.0020903 0.00538792 0.00554342]
- [ 0.00031588 0.00034356 0.00089041 0.00096841]
- [ 0.00045514 0.00046827 0.00128294 0.00131997]]]Tally
- ID = 10003
- Name = (tally 1 / tally 2)
- Filters =
- cell [1]
- energy [ 0. 20.]
- material [1]
- Nuclides = (U-235 / U-235) (U-235 / Pu-239) (U-238 / U-235) (U-238 / Pu-239)
- Scores = [(fission / fission), (fission / absorption), (nu-fission / fission), (nu-fission / absorption)]
- Estimator = tracklength
-[[[ 1. 0.91944666 2.65197177 2.4383466 ]
- [ 0.69403611 0.67456727 1.84056418 1.78893335]
- [ 0.22402189 0.20597618 0.63147153 0.58060439]
- [ 0.15547928 0.15111784 0.43826405 0.42597002]]]
\ No newline at end of file
+[[[ 8.90240785e-05 8.31464209e-11 4.41507090e-05 4.12357364e-11]
+ [ 7.29618709e-05 5.98879928e-05 3.61847984e-05 2.97009235e-05]
+ [ 4.69276830e-05 4.38293656e-11 2.35903380e-05 2.20328275e-11]
+ [ 3.84607356e-05 3.15690405e-05 1.93340411e-05 1.58696166e-05]]
+
+ [[ 8.90240785e-05 8.31464209e-11 4.41507090e-05 4.12357364e-11]
+ [ 7.29618709e-05 5.98879928e-05 3.61847984e-05 2.97009235e-05]
+ [ 4.69276830e-05 4.38293656e-11 2.35903380e-05 2.20328275e-11]
+ [ 3.84607356e-05 3.15690405e-05 1.93340411e-05 1.58696166e-05]]
+
+ [[ 8.90240785e-05 8.31464209e-11 4.41507090e-05 4.12357364e-11]
+ [ 7.29618709e-05 5.98879928e-05 3.61847984e-05 2.97009235e-05]
+ [ 4.69276830e-05 4.38293656e-11 2.35903380e-05 2.20328275e-11]
+ [ 3.84607356e-05 3.15690405e-05 1.93340411e-05 1.58696166e-05]]
+
+ ...,
+ [[ 0.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00]
+ [ 0.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00]
+ [ 0.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00]
+ [ 0.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00]]
+
+ [[ 0.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00]
+ [ 0.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00]
+ [ 0.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00]
+ [ 0.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00]]
+
+ [[ 0.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00]
+ [ 0.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00]
+ [ 0.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00]
+ [ 0.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00]]][[[ 8.90240785e-05 8.31464209e-11 4.41507090e-05 4.12357364e-11]
+ [ 7.29618709e-05 5.98879928e-05 3.61847984e-05 2.97009235e-05]
+ [ 4.69276830e-05 4.38293656e-11 2.35903380e-05 2.20328275e-11]
+ [ 3.84607356e-05 3.15690405e-05 1.93340411e-05 1.58696166e-05]]
+
+ [[ 8.90240785e-05 8.31464209e-11 4.41507090e-05 4.12357364e-11]
+ [ 7.29618709e-05 5.98879928e-05 3.61847984e-05 2.97009235e-05]
+ [ 4.69276830e-05 4.38293656e-11 2.35903380e-05 2.20328275e-11]
+ [ 3.84607356e-05 3.15690405e-05 1.93340411e-05 1.58696166e-05]]
+
+ [[ 8.90240785e-05 8.31464209e-11 4.41507090e-05 4.12357364e-11]
+ [ 7.29618709e-05 5.98879928e-05 3.61847984e-05 2.97009235e-05]
+ [ 4.69276830e-05 4.38293656e-11 2.35903380e-05 2.20328275e-11]
+ [ 3.84607356e-05 3.15690405e-05 1.93340411e-05 1.58696166e-05]]
+
+ ...,
+ [[ 0.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00]
+ [ 0.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00]
+ [ 0.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00]
+ [ 0.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00]]
+
+ [[ 0.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00]
+ [ 0.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00]
+ [ 0.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00]
+ [ 0.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00]]
+
+ [[ 0.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00]
+ [ 0.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00]
+ [ 0.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00]
+ [ 0.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00]]][[[ 7.29618709e-05 5.98879928e-05 3.61847984e-05 2.97009235e-05]
+ [ 0.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00]
+ [ 0.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00]]
+
+ [[ 7.29618709e-05 5.98879928e-05 3.61847984e-05 2.97009235e-05]
+ [ 0.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00]
+ [ 0.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00]]
+
+ [[ 7.29618709e-05 5.98879928e-05 3.61847984e-05 2.97009235e-05]
+ [ 0.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00]
+ [ 0.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00]]
+
+ ...,
+ [[ 0.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00]
+ [ 0.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00]
+ [ 0.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00]]
+
+ [[ 0.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00]
+ [ 0.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00]
+ [ 0.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00]]
+
+ [[ 0.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00]
+ [ 0.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00]
+ [ 0.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00]]][[[ 0.00000000e+00 4.41507090e-05 0.00000000e+00]
+ [ 0.00000000e+00 3.61847984e-05 0.00000000e+00]
+ [ 0.00000000e+00 2.35903380e-05 0.00000000e+00]
+ [ 0.00000000e+00 1.93340411e-05 0.00000000e+00]]
+
+ [[ 0.00000000e+00 4.41507090e-05 0.00000000e+00]
+ [ 0.00000000e+00 3.61847984e-05 0.00000000e+00]
+ [ 0.00000000e+00 2.35903380e-05 0.00000000e+00]
+ [ 0.00000000e+00 1.93340411e-05 0.00000000e+00]]
+
+ [[ 0.00000000e+00 4.41507090e-05 0.00000000e+00]
+ [ 0.00000000e+00 3.61847984e-05 0.00000000e+00]
+ [ 0.00000000e+00 2.35903380e-05 0.00000000e+00]
+ [ 0.00000000e+00 1.93340411e-05 0.00000000e+00]]
+
+ ...,
+ [[ 0.00000000e+00 0.00000000e+00 0.00000000e+00]
+ [ 0.00000000e+00 0.00000000e+00 0.00000000e+00]
+ [ 0.00000000e+00 0.00000000e+00 0.00000000e+00]
+ [ 0.00000000e+00 0.00000000e+00 0.00000000e+00]]
+
+ [[ 0.00000000e+00 0.00000000e+00 0.00000000e+00]
+ [ 0.00000000e+00 0.00000000e+00 0.00000000e+00]
+ [ 0.00000000e+00 0.00000000e+00 0.00000000e+00]
+ [ 0.00000000e+00 0.00000000e+00 0.00000000e+00]]
+
+ [[ 0.00000000e+00 0.00000000e+00 0.00000000e+00]
+ [ 0.00000000e+00 0.00000000e+00 0.00000000e+00]
+ [ 0.00000000e+00 0.00000000e+00 0.00000000e+00]
+ [ 0.00000000e+00 0.00000000e+00 0.00000000e+00]]][[[ 0.00000000e+00 3.61847984e-05 0.00000000e+00]
+ [ 0.00000000e+00 0.00000000e+00 0.00000000e+00]
+ [ 0.00000000e+00 0.00000000e+00 0.00000000e+00]]
+
+ [[ 0.00000000e+00 3.61847984e-05 0.00000000e+00]
+ [ 0.00000000e+00 0.00000000e+00 0.00000000e+00]
+ [ 0.00000000e+00 0.00000000e+00 0.00000000e+00]]
+
+ [[ 0.00000000e+00 3.61847984e-05 0.00000000e+00]
+ [ 0.00000000e+00 0.00000000e+00 0.00000000e+00]
+ [ 0.00000000e+00 0.00000000e+00 0.00000000e+00]]
+
+ ...,
+ [[ 0.00000000e+00 0.00000000e+00 0.00000000e+00]
+ [ 0.00000000e+00 0.00000000e+00 0.00000000e+00]
+ [ 0.00000000e+00 0.00000000e+00 0.00000000e+00]]
+
+ [[ 0.00000000e+00 0.00000000e+00 0.00000000e+00]
+ [ 0.00000000e+00 0.00000000e+00 0.00000000e+00]
+ [ 0.00000000e+00 0.00000000e+00 0.00000000e+00]]
+
+ [[ 0.00000000e+00 0.00000000e+00 0.00000000e+00]
+ [ 0.00000000e+00 0.00000000e+00 0.00000000e+00]
+ [ 0.00000000e+00 0.00000000e+00 0.00000000e+00]]]
\ No newline at end of file
diff --git a/tests/test_tally_arithmetic/settings.xml b/tests/test_tally_arithmetic/settings.xml
deleted file mode 100644
index a69dde686a..0000000000
--- a/tests/test_tally_arithmetic/settings.xml
+++ /dev/null
@@ -1,18 +0,0 @@
-
-
-
-
- 10
- 5
- 1000
-
-
-
-
- -4 -4 -4 4 4 4
-
-
-
-
-
-
diff --git a/tests/test_tally_arithmetic/tallies.xml b/tests/test_tally_arithmetic/tallies.xml
deleted file mode 100644
index 2a2eb48361..0000000000
--- a/tests/test_tally_arithmetic/tallies.xml
+++ /dev/null
@@ -1,15 +0,0 @@
-
-
-
-
-
- U-235 U-238
- fission nu-fission
-
-
-
-
- U-235 Pu-239
- fission absorption
-
-
diff --git a/tests/test_tally_arithmetic/test_tally_arithmetic.py b/tests/test_tally_arithmetic/test_tally_arithmetic.py
index 2f49061f96..6643fd5a22 100644
--- a/tests/test_tally_arithmetic/test_tally_arithmetic.py
+++ b/tests/test_tally_arithmetic/test_tally_arithmetic.py
@@ -5,11 +5,64 @@ import sys
import glob
import hashlib
sys.path.insert(0, os.pardir)
-from testing_harness import TestHarness
+from testing_harness import PyAPITestHarness
import openmc
-class TallyArithmeticTestHarness(TestHarness):
+class TallyArithmeticTestHarness(PyAPITestHarness):
+ def _build_inputs(self):
+
+ # The summary.h5 file needs to be created to read in the tallies
+ self._input_set.settings.output = {'summary': True}
+
+ # Initialize the tallies file
+ tallies_file = openmc.TalliesFile()
+
+ # Initialize the nuclides
+ u235 = openmc.Nuclide('U-235')
+ u238 = openmc.Nuclide('U-238')
+ pu239 = openmc.Nuclide('Pu-239')
+
+ # Initialize Mesh
+ mesh = openmc.Mesh(mesh_id=1)
+ mesh.type = 'regular'
+ mesh.dimension = [2, 2, 2]
+ mesh.lower_left = [-160.0, -160.0, -183.0]
+ mesh.upper_right = [160.0, 160.0, 183.0]
+
+ # Initialize the filters
+ energy_filter = openmc.Filter(type='energy', bins=(0.0, 0.253e-6,
+ 1.0e-3, 1.0, 20.0))
+ material_filter = openmc.Filter(type='material', bins=(1, 3))
+ distrib_filter = openmc.Filter(type='distribcell', bins=(60))
+ mesh_filter = openmc.Filter(type='mesh')
+ mesh_filter.mesh = mesh
+
+ # Initialized the tallies
+ tally = openmc.Tally(name='tally 1')
+ tally.add_filter(material_filter)
+ tally.add_filter(energy_filter)
+ tally.add_filter(distrib_filter)
+ tally.add_score('nu-fission')
+ tally.add_score('total')
+ tally.add_nuclide(u235)
+ tally.add_nuclide(pu239)
+ tallies_file.add_tally(tally)
+
+ tally = openmc.Tally(name='tally 2')
+ tally.add_filter(energy_filter)
+ tally.add_filter(mesh_filter)
+ tally.add_score('total')
+ tally.add_score('fission')
+ tally.add_nuclide(u238)
+ tally.add_nuclide(u235)
+ tallies_file.add_tally(tally)
+ tallies_file.add_mesh(mesh)
+
+ # Export tallies to file
+ self._input_set.tallies = tallies_file
+ super(TallyArithmeticTestHarness, self)._build_inputs()
+
def _get_results(self, hash_output=False):
"""Digest info in the statepoint and return as a string."""
@@ -28,20 +81,23 @@ class TallyArithmeticTestHarness(TestHarness):
# Perform all the tally arithmetic operations and output results
outstr = ''
- tally_3 = tally_1 + tally_2
- outstr += repr(tally_3)
- outstr += str(tally_3.mean)
-
- tally_3 = tally_1 - tally_2
- outstr += repr(tally_3)
- outstr += str(tally_3.mean)
-
tally_3 = tally_1 * tally_2
- outstr += repr(tally_3)
outstr += str(tally_3.mean)
- tally_3 = tally_1 / tally_2
- outstr += repr(tally_3)
+ tally_3 = tally_1.hybrid_product(tally_2, '*', 'entrywise', 'tensor',
+ 'tensor')
+ outstr += str(tally_3.mean)
+
+ tally_3 = tally_1.hybrid_product(tally_2, '*', 'entrywise', 'entrywise',
+ 'tensor')
+ outstr += str(tally_3.mean)
+
+ tally_3 = tally_1.hybrid_product(tally_2, '*', 'entrywise', 'tensor',
+ 'entrywise')
+ outstr += str(tally_3.mean)
+
+ tally_3 = tally_1.hybrid_product(tally_2, '*', 'entrywise', 'entrywise',
+ 'entrywise')
outstr += str(tally_3.mean)
print(outstr)
@@ -54,6 +110,11 @@ class TallyArithmeticTestHarness(TestHarness):
return outstr
+ def _cleanup(self):
+ super(TallyArithmeticTestHarness, self)._cleanup()
+ f = os.path.join(os.getcwd(), 'tallies.xml')
+ if os.path.exists(f): os.remove(f)
+
if __name__ == '__main__':
harness = TallyArithmeticTestHarness('statepoint.10.h5', True)
harness.main()