From 9b152b0ddf91d5b2efbf8fe81a80d6310728ddfa Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Tue, 2 Feb 2016 10:07:08 -0600 Subject: [PATCH 01/11] Add property setters for Tally.scores, nuclides, filters, triggers --- examples/python/basic/build-xml.py | 23 +- .../python/lattice/hexagonal/build-xml.py | 4 +- examples/python/lattice/nested/build-xml.py | 4 +- examples/python/lattice/simple/build-xml.py | 8 +- examples/python/pincell/build-xml.py | 7 +- openmc/checkvalue.py | 16 +- openmc/mgxs/mgxs.py | 20 +- openmc/statepoint.py | 6 +- openmc/summary.py | 6 +- openmc/tallies.py | 229 +++++++++--------- openmc/trigger.py | 35 ++- tests/test_tallies/test_tallies.py | 149 +++++------- .../test_tally_aggregation.py | 10 +- .../test_tally_arithmetic.py | 19 +- 14 files changed, 257 insertions(+), 279 deletions(-) diff --git a/examples/python/basic/build-xml.py b/examples/python/basic/build-xml.py index 97591c9920..eb8fbd23f5 100644 --- a/examples/python/basic/build-xml.py +++ b/examples/python/basic/build-xml.py @@ -109,29 +109,20 @@ energyout_filter = openmc.Filter(type='energyout', bins=[0., 20.]) # Instantiate the first Tally first_tally = openmc.Tally(tally_id=1, name='first tally') -first_tally.add_filter(cell_filter) -scores = ['total', 'scatter', 'nu-scatter', \ +first_tally.filters = [cell_filter] +scores = ['total', 'scatter', 'nu-scatter', 'absorption', 'fission', 'nu-fission'] -for score in scores: - first_tally.add_score(score) +first_tally.scores = scores # Instantiate the second Tally second_tally = openmc.Tally(tally_id=2, name='second tally') -second_tally.add_filter(cell_filter) -second_tally.add_filter(energy_filter) -scores = ['total', 'scatter', 'nu-scatter', \ - 'absorption', 'fission', 'nu-fission'] -for score in scores: - second_tally.add_score(score) +second_tally.filters = [cell_filter, energy_filter] +second_tally.scores = scores # Instantiate the third Tally third_tally = openmc.Tally(tally_id=3, name='third tally') -third_tally.add_filter(cell_filter) -third_tally.add_filter(energy_filter) -third_tally.add_filter(energyout_filter) -scores = ['scatter', 'nu-scatter', 'nu-fission'] -for score in scores: - third_tally.add_score(score) +third_tally.filters = [cell_filter, energy_filter, energyout_filter] +third_tally.scores = ['scatter', 'nu-scatter', 'nu-fission'] # Instantiate a TalliesFile, register all Tallies, and export to XML tallies_file = openmc.TalliesFile() diff --git a/examples/python/lattice/hexagonal/build-xml.py b/examples/python/lattice/hexagonal/build-xml.py index 1125e8ce04..d1144cd918 100644 --- a/examples/python/lattice/hexagonal/build-xml.py +++ b/examples/python/lattice/hexagonal/build-xml.py @@ -166,8 +166,8 @@ plot_file.export_to_xml() # Instantiate a distribcell Tally tally = openmc.Tally(tally_id=1) -tally.add_filter(openmc.Filter(type='distribcell', bins=[cell2.id])) -tally.add_score('total') +tally.filters = [openmc.Filter(type='distribcell', bins=[cell2.id])] +tally.scores = ['total'] # Instantiate a TalliesFile, register Tally/Mesh, and export to XML tallies_file = openmc.TalliesFile() diff --git a/examples/python/lattice/nested/build-xml.py b/examples/python/lattice/nested/build-xml.py index 389af8e9b7..e4ac848396 100644 --- a/examples/python/lattice/nested/build-xml.py +++ b/examples/python/lattice/nested/build-xml.py @@ -175,8 +175,8 @@ mesh_filter.mesh = mesh # Instantiate the Tally tally = openmc.Tally(tally_id=1) -tally.add_filter(mesh_filter) -tally.add_score('total') +tally.filters = [mesh_filter] +tally.scores = ['total'] # Instantiate a TalliesFile, register Tally/Mesh, and export to XML tallies_file = openmc.TalliesFile() diff --git a/examples/python/lattice/simple/build-xml.py b/examples/python/lattice/simple/build-xml.py index e648c3d5b3..78ee61eb46 100644 --- a/examples/python/lattice/simple/build-xml.py +++ b/examples/python/lattice/simple/build-xml.py @@ -167,13 +167,13 @@ mesh_filter.mesh = mesh # Instantiate tally Trigger trigger = openmc.Trigger(trigger_type='rel_err', threshold=1E-2) -trigger.add_score('all') +trigger.scores = ['all'] # Instantiate the Tally tally = openmc.Tally(tally_id=1) -tally.add_filter(mesh_filter) -tally.add_score('total') -tally.add_trigger(trigger) +tally.filters = [mesh_filter] +tally.scores = ['total'] +tally.triggers = [trigger] # Instantiate a TalliesFile, register Tally/Mesh, and export to XML tallies_file = openmc.TalliesFile() diff --git a/examples/python/pincell/build-xml.py b/examples/python/pincell/build-xml.py index ca71b04e5c..aa87148381 100644 --- a/examples/python/pincell/build-xml.py +++ b/examples/python/pincell/build-xml.py @@ -196,11 +196,8 @@ mesh_filter.mesh = mesh # Instantiate the Tally tally = openmc.Tally(tally_id=1, name='tally 1') -tally.add_filter(energy_filter) -tally.add_filter(mesh_filter) -tally.add_score('flux') -tally.add_score('fission') -tally.add_score('nu-fission') +tally.filters = [energy_filter, mesh_filter] +tally.scores = ['flux', 'fission', 'nu-fission'] # Instantiate a TalliesFile, register all Tallies, and export to XML tallies_file = openmc.TalliesFile() diff --git a/openmc/checkvalue.py b/openmc/checkvalue.py index 787052f5d6..0e9dc9ef4b 100644 --- a/openmc/checkvalue.py +++ b/openmc/checkvalue.py @@ -41,9 +41,9 @@ def check_type(name, value, expected_type, expected_iter_type=None): Description of value being checked value : object Object to check type of - expected_type : type + expected_type : type or Iterable of type type to check object against - expected_iter_type : type or None, optional + expected_iter_type : type or Iterable of type or None, optional Expected type of each element in value, assuming it is iterable. If None, no check will be performed. @@ -57,9 +57,15 @@ def check_type(name, value, expected_type, expected_iter_type=None): if expected_iter_type: for item in value: if not _isinstance(item, expected_iter_type): - msg = 'Unable to set "{0}" to "{1}" since each item must be ' \ - 'of type "{2}"'.format(name, value, - expected_iter_type.__name__) + if isinstance(expected_iter_type, Iterable): + msg = 'Unable to set "{0}" to "{1}" since each item must be ' \ + 'one of the following types: "{2}"'.format( + name, value, ', '.join([t.__name__ for t in + expected_iter_type])) + else: + msg = 'Unable to set "{0}" to "{1}" since each item must be ' \ + 'of type "{2}"'.format(name, value, + expected_iter_type.__name__) raise ValueError(msg) diff --git a/openmc/mgxs/mgxs.py b/openmc/mgxs/mgxs.py index 875a82c468..ad987d70f1 100644 --- a/openmc/mgxs/mgxs.py +++ b/openmc/mgxs/mgxs.py @@ -510,27 +510,27 @@ class MGXS(object): # Create each Tally needed to compute the multi group cross section for score, key, filters in zip(scores, keys, all_filters): self.tallies[key] = openmc.Tally(name=self.name) - self.tallies[key].add_score(score) + self.tallies[key].scores.append(score) self.tallies[key].estimator = estimator - self.tallies[key].add_filter(domain_filter) + self.tallies[key].filters.append(domain_filter) # If a tally trigger was specified, add it to each tally if self.tally_trigger: trigger_clone = copy.deepcopy(self.tally_trigger) - trigger_clone.add_score(score) - self.tallies[key].add_trigger(trigger_clone) + trigger_clone.scores.append(score) + self.tallies[key].triggers.append(trigger_clone) # Add all non-domain specific Filters (e.g., 'energy') to the Tally for add_filter in filters: - self.tallies[key].add_filter(add_filter) + self.tallies[key].filters.append(add_filter) # If this is a by-nuclide cross-section, add all nuclides to Tally if self.by_nuclide and score != 'flux': all_nuclides = self.domain.get_all_nuclides() for nuclide in all_nuclides: - self.tallies[key].add_nuclide(nuclide) + self.tallies[key].nuclides.append(nuclide) else: - self.tallies[key].add_nuclide('total') + self.tallies[key].nuclides.append('total') def _compute_xs(self): """Performs generic cleanup after a subclass' uses tally arithmetic to @@ -552,7 +552,7 @@ class MGXS(object): self.xs_tally._nuclides = [] nuclides = self.domain.get_all_nuclides() for nuclide in nuclides: - self.xs_tally.add_nuclide(openmc.Nuclide(nuclide)) + self.xs_tally.nuclides.append(openmc.Nuclide(nuclide)) # Remove NaNs which may have resulted from divide-by-zero operations self.xs_tally._mean = np.nan_to_num(self.xs_tally.mean) @@ -2087,7 +2087,7 @@ class Chi(MGXS): super(Chi, self)._compute_xs() # Add the coarse energy filter back to the nu-fission tally - nu_fission_in.add_filter(energy_filter) + nu_fission_in.filters.append(energy_filter) return self._xs_tally @@ -2179,7 +2179,7 @@ class Chi(MGXS): xs_tally = nu_fission_out / nu_fission_in # Add the coarse energy filter back to the nu-fission tally - nu_fission_in.add_filter(energy_filter) + nu_fission_in.filters.append(energy_filter) xs = xs_tally.get_values(filters=filters, filter_bins=filter_bins, value=value) diff --git a/openmc/statepoint.py b/openmc/statepoint.py index f5b5b2e72d..05a3896110 100644 --- a/openmc/statepoint.py +++ b/openmc/statepoint.py @@ -389,7 +389,7 @@ class StatePoint(object): new_filter.mesh = self.meshes[key] # Add Filter to the Tally - tally.add_filter(new_filter) + tally.filters.append(new_filter) # Read Nuclide bins nuclide_names = \ @@ -398,7 +398,7 @@ class StatePoint(object): # Add all Nuclides to the Tally for name in nuclide_names: nuclide = openmc.Nuclide(name.decode().strip()) - tally.add_nuclide(nuclide) + tally.nuclides.append(nuclide) scores = self._f['{0}{1}/score_bins'.format( base, tally_key)].value @@ -425,7 +425,7 @@ class StatePoint(object): pattern = r'-n$|-pn$|-yn$' score = re.sub(pattern, '-' + moments[j].decode(), score) - tally.add_score(score) + tally.scores.append(score) # Add Tally to the global dictionary of all Tallies tally.sparse = self.sparse diff --git a/openmc/summary.py b/openmc/summary.py index d22e367c95..a4d1d694c9 100644 --- a/openmc/summary.py +++ b/openmc/summary.py @@ -276,7 +276,7 @@ class Summary(object): # Get the distribcell index ind = self._f['geometry/cells'][key]['distribcell_index'].value if ind != 0: - cell.distribcell_index = ind + cell.distribcell_index = ind # Add the Cell to the global dictionary of all Cells self.cells[index] = cell @@ -539,7 +539,7 @@ class Summary(object): # 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) + tally.scores.append(score) # Read filter metadata num_filters = self._f['{0}/n_filters'.format(subbase)].value @@ -560,7 +560,7 @@ class Summary(object): new_filter.num_bins = num_bins # Add Filter to the Tally - tally.add_filter(new_filter) + tally.filters.append(new_filter) # Add Tally to the global dictionary of all Tallies self.tallies[tally_id] = tally diff --git a/openmc/tallies.py b/openmc/tallies.py index d1666694fe..f471dbdf37 100644 --- a/openmc/tallies.py +++ b/openmc/tallies.py @@ -7,8 +7,9 @@ import os import pickle import itertools from numbers import Integral, Real -from xml.etree import ElementTree as ET import sys +import warnings +from xml.etree import ElementTree as ET import numpy as np @@ -18,10 +19,13 @@ from openmc.filter import _FILTER_TYPES import openmc.checkvalue as cv from openmc.clean_xml import * - if sys.version_info[0] >= 3: basestring = str + +# DeprecationWarning filter for the Tally.add_*(...) methods +warnings.simplefilter('always', DeprecationWarning) + # "Static" variable for auto-generated Tally IDs AUTO_TALLY_ID = 10000 @@ -75,7 +79,7 @@ class Tally(object): num_bins : Integral Total number of bins for the tally shape : 3-tuple of Integral - The shape of the tally data array ordered as the number of filter bins, + The shape of the tally data array ordered as the number of filter bins, nuclide bins and score bins num_realizations : Integral Total number of realizations @@ -145,19 +149,19 @@ class Tally(object): clone._filters = [] for self_filter in self.filters: - clone.add_filter(copy.deepcopy(self_filter, memo)) + clone.filters.append(copy.deepcopy(self_filter, memo)) clone._nuclides = [] for nuclide in self.nuclides: - clone.add_nuclide(copy.deepcopy(nuclide, memo)) + clone.nuclides.append(copy.deepcopy(nuclide, memo)) clone._scores = [] for score in self.scores: - clone.add_score(score) + clone.scores.append(score) clone._triggers = [] for trigger in self.triggers: - clone.add_trigger(trigger) + clone.triggers.append(trigger) memo[id(self)] = clone @@ -423,6 +427,11 @@ class Tally(object): ['analog', 'tracklength', 'collision']) self._estimator = estimator + @triggers.setter + def triggers(self, triggers): + cv.check_type('tally triggers', trigger, Iterable, Trigger) + self._triggers = triggers + def add_trigger(self, trigger): """Add a tally trigger to the tally @@ -433,13 +442,11 @@ class Tally(object): """ - if not isinstance(trigger, Trigger): - msg = 'Unable to add a tally trigger for Tally ID="{0}" to ' \ - 'since "{1}" is not a Trigger'.format(self.id, trigger) - raise ValueError(msg) - - if trigger not in self.triggers: - self.triggers.append(trigger) + warnings.warn("Tally.add_trigger(...) has been deprecated and may be " + "removed in a future version. Tally triggers should be " + "defined using the triggers property directly.", + DeprecationWarning) + self.triggers.append(trigger) @id.setter def id(self, tally_id): @@ -460,6 +467,55 @@ class Tally(object): else: self._name = '' + @filters.setter + def filters(self, filters): + cv.check_type('tally filters', filters, Iterable, + (Filter, CrossFilter, AggregateFilter)) + + # If the filter is already in the Tally, raise an error + for i, f in enumerate(filters[:-1]): + if f in filters[i+1:]: + msg = 'Unable to add a duplicate filter "{0}" to Tally ID="{1}" ' \ + 'since duplicate filters are not supported in the OpenMC ' \ + 'Python API'.format(f, self.id) + raise ValueError(msg) + + self._filters = filters + + @nuclides.setter + def nuclides(self, nuclides): + cv.check_type('tally nuclides', nuclides, Iterable, + (basestring, Nuclide, CrossNuclide, AggregateNuclide)) + + # If the nuclide is already in the Tally, raise an error + for i, nuclide in enumerate(nuclides[:-1]): + if nuclide in nuclides[i+1:]: + msg = 'Unable to add a duplicate nuclide "{0}" to Tally ID="{1}" ' \ + 'since duplicate nuclides are not supported in the OpenMC ' \ + 'Python API'.format(nuclide, self.id) + raise ValueError(msg) + + self._nuclides = nuclides + + @scores.setter + def scores(self, scores): + cv.check_type('tally scores', scores, Iterable, + (basestring, CrossScore, AggregateScore)) + + for i, score in enumerate(scores[:-1]): + # If the score is already in the Tally, raise an error + if score in scores[i+1:]: + 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) + + # If score is a string, strip whitespace + if isinstance(score, basestring): + scores[i] = score.strip() + + self._scores = scores + def add_filter(self, new_filter): """Add a filter to the tally @@ -475,19 +531,11 @@ class Tally(object): """ - if not isinstance(new_filter, (Filter, CrossFilter, AggregateFilter)): - msg = 'Unable to add Filter "{0}" to Tally ID="{1}" since it is ' \ - 'not a Filter object'.format(new_filter, self.id) - raise ValueError(msg) - - # If the filter is already in the Tally, raise an error - if new_filter in self.filters: - msg = 'Unable to add a duplicate filter "{0}" to Tally ID="{1}" ' \ - 'since duplicate filters are not supported in the OpenMC ' \ - 'Python API'.format(new_filter, self.id) - raise ValueError(msg) - - self._filters.append(new_filter) + warnings.warn("Tally.add_filter(...) has been deprecated and may be " + "removed in a future version. Tally filters should be " + "defined using the filters property directly.", + DeprecationWarning) + self.filters.append(new_filter) def add_nuclide(self, nuclide): """Specify that scores for a particular nuclide should be accumulated @@ -504,20 +552,11 @@ class Tally(object): """ - if not isinstance(nuclide, (basestring, Nuclide, - CrossNuclide, AggregateNuclide)): - msg = 'Unable to add nuclide "{0}" to Tally ID="{1}" since it is ' \ - 'not a Nuclide object'.format(nuclide) - raise ValueError(msg) - - # If the nuclide is already in the Tally, raise an error - if nuclide in self.nuclides: - msg = 'Unable to add a duplicate nuclide "{0}" to Tally ID="{1}" ' \ - 'since duplicate nuclides are not supported in the OpenMC ' \ - 'Python API'.format(nuclide, self.id) - raise ValueError(msg) - - self._nuclides.append(nuclide) + warnings.warn("Tally.add_nuclide(...) has been deprecated and may be " + "removed in a future version. Tally nuclides should be " + "defined using the nuclides property directly.", + DeprecationWarning) + self.nuclides.append(nuclide) def add_score(self, score): """Specify a quantity to be scored @@ -533,24 +572,11 @@ class Tally(object): """ - if not isinstance(score, (basestring, CrossScore, AggregateScore)): - msg = 'Unable to add score "{0}" to Tally ID="{1}" since it is ' \ - 'not a string'.format(score, self.id) - raise ValueError(msg) - - # If the score is already in the Tally, raise an error - if score in self.scores: - 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()) - # CrossScores and AggrgateScore - else: - self._scores.append(score) + warnings.warn("Tally.add_score(...) has been deprecated and may be " + "removed in a future version. Tally scores should be " + "defined using the scores property directly.", + DeprecationWarning) + self.scores.append(score) @num_realizations.setter def num_realizations(self, num_realizations): @@ -771,11 +797,11 @@ class Tally(object): # Add unique scores from second tally to merged tally for score in tally.scores: if score not in merged_tally.scores: - merged_tally.add_score(score) + merged_tally.scores.append(score) # Add triggers from second tally to merged tally for trigger in tally.triggers: - merged_tally.add_trigger(trigger) + merged_tally.triggers.append(trigger) return merged_tally @@ -1723,33 +1749,33 @@ class Tally(object): # Add filters to the new tally if filter_product == 'entrywise': for self_filter in self_copy.filters: - new_tally.add_filter(self_filter) + new_tally.filters.append(self_filter) else: all_filters = [self_copy.filters, other_copy.filters] for self_filter, other_filter in itertools.product(*all_filters): new_filter = CrossFilter(self_filter, other_filter, binary_op) - new_tally.add_filter(new_filter) + new_tally.filters.append(new_filter) # Add nuclides to the new tally if nuclide_product == 'entrywise': for self_nuclide in self_copy.nuclides: - new_tally.add_nuclide(self_nuclide) + new_tally.nuclides.append(self_nuclide) else: all_nuclides = [self_copy.nuclides, other_copy.nuclides] for self_nuclide, other_nuclide in itertools.product(*all_nuclides): new_nuclide = \ CrossNuclide(self_nuclide, other_nuclide, binary_op) - new_tally.add_nuclide(new_nuclide) + new_tally.nuclides.append(new_nuclide) # Add scores to the new tally if score_product == 'entrywise': for self_score in self_copy.scores: - new_tally.add_score(self_score) + new_tally.scores.append(self_score) else: 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) + new_tally.scores.append(new_score) # Update the new tally's filter strides new_tally._update_filter_strides() @@ -1812,14 +1838,14 @@ class Tally(object): filter_copy = copy.deepcopy(other_filter) other._mean = np.repeat(other.mean, filter_copy.num_bins, axis=0) other._std_dev = np.repeat(other.std_dev, filter_copy.num_bins, axis=0) - other.add_filter(filter_copy) + other.filters.append(filter_copy) # Add filters present in other but not in self to self for self_filter in self_missing_filters: filter_copy = copy.deepcopy(self_filter) self._mean = np.repeat(self.mean, filter_copy.num_bins, axis=0) self._std_dev = np.repeat(self.std_dev, filter_copy.num_bins, axis=0) - self.add_filter(filter_copy) + self.filters.append(filter_copy) # Align other filters with self filters for i, self_filter in enumerate(self.filters): @@ -1842,7 +1868,7 @@ class Tally(object): np.tile(other.std_dev, (1, self.num_nuclides, 1)) # Add nuclides to each tally such that each tally contains the complete - # set of nuclides necessary to perform an entrywise product. New + # set of nuclides necessary to perform an entrywise product. New # nuclides added to a tally will have all their scores set to zero. else: @@ -1858,7 +1884,7 @@ class Tally(object): np.insert(other.mean, other.num_nuclides, 0, axis=1) other._std_dev = \ np.insert(other.std_dev, other.num_nuclides, 0, axis=1) - other.add_nuclide(nuclide) + other.nuclides.append(nuclide) # Add nuclides present in other but not in self to self for nuclide in self_missing_nuclides: @@ -1866,7 +1892,7 @@ class Tally(object): np.insert(self.mean, self.num_nuclides, 0, axis=1) self._std_dev = \ np.insert(self.std_dev, self.num_nuclides, 0, axis=1) - self.add_nuclide(nuclide) + self.nuclides.append(nuclide) # Align other nuclides with self nuclides for i, nuclide in enumerate(self.nuclides): @@ -1899,13 +1925,13 @@ class Tally(object): for score in other_missing_scores: 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) + other.scores.append(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_scores, 0, axis=2) self._std_dev = np.insert(self.std_dev, self.num_scores, 0, axis=2) - self.add_score(score) + self.scores.append(score) # Align other scores with self scores for i, score in enumerate(self.scores): @@ -2210,12 +2236,9 @@ class Tally(object): new_tally.with_summary = self.with_summary new_tally.num_realization = self.num_realizations - for self_filter in self.filters: - new_tally.add_filter(self_filter) - for nuclide in self.nuclides: - new_tally.add_nuclide(nuclide) - for score in self.scores: - new_tally.add_score(score) + new_tally.filters = self.filters + new_tally.nuclides = self.nuclides + new_tally.scores = self.scores # If this tally operand is sparse, sparsify the new tally new_tally.sparse = self.sparse @@ -2284,12 +2307,9 @@ class Tally(object): new_tally.with_summary = self.with_summary new_tally.num_realization = self.num_realizations - for self_filter in self.filters: - new_tally.add_filter(self_filter) - for nuclide in self.nuclides: - new_tally.add_nuclide(nuclide) - for score in self.scores: - new_tally.add_score(score) + new_tally.filters = self.filters + new_tally.nuclides = self.nuclides + new_tally.scores = self.scores # If this tally operand is sparse, sparsify the new tally new_tally.sparse = self.sparse @@ -2359,12 +2379,9 @@ class Tally(object): new_tally.with_summary = self.with_summary new_tally.num_realization = self.num_realizations - for self_filter in self.filters: - new_tally.add_filter(self_filter) - for nuclide in self.nuclides: - new_tally.add_nuclide(nuclide) - for score in self.scores: - new_tally.add_score(score) + new_tally.filters = self.filters + new_tally.nuclides = self.nuclides + new_tally.scores = self.scores # If this tally operand is sparse, sparsify the new tally new_tally.sparse = self.sparse @@ -2434,12 +2451,9 @@ class Tally(object): new_tally.with_summary = self.with_summary new_tally.num_realization = self.num_realizations - for self_filter in self.filters: - new_tally.add_filter(self_filter) - for nuclide in self.nuclides: - new_tally.add_nuclide(nuclide) - for score in self.scores: - new_tally.add_score(score) + new_tally.filters = self.filters + new_tally.nuclides = self.nuclides + new_tally.scores = self.scores # If this tally operand is sparse, sparsify the new tally new_tally.sparse = self.sparse @@ -2513,12 +2527,9 @@ class Tally(object): new_tally.with_summary = self.with_summary new_tally.num_realization = self.num_realizations - for self_filter in self.filters: - new_tally.add_filter(self_filter) - for nuclide in self.nuclides: - new_tally.add_nuclide(nuclide) - for score in self.scores: - new_tally.add_score(score) + new_tally.filters = self.filters + new_tally.nuclides = self.nuclides + new_tally.scores = self.scores # If original tally was sparse, sparsify the exponentiated tally new_tally.sparse = self.sparse @@ -2853,11 +2864,11 @@ class Tally(object): if not remove_filter: filter_sum = \ AggregateFilter(self_filter, filter_bins, 'sum') - tally_sum.add_filter(filter_sum) + tally_sum.filters.append(filter_sum) # Add a copy of each filter not summed across to the tally sum else: - tally_sum.add_filter(copy.deepcopy(self_filter)) + tally_sum.filters.append(copy.deepcopy(self_filter)) # Add a copy of this tally's filters to the tally sum else: @@ -2875,7 +2886,7 @@ class Tally(object): # Add AggregateNuclide to the tally sum nuclide_sum = AggregateNuclide(nuclides, 'sum') - tally_sum.add_nuclide(nuclide_sum) + tally_sum.nuclides.append(nuclide_sum) # Add a copy of this tally's nuclides to the tally sum else: @@ -2893,7 +2904,7 @@ class Tally(object): # Add AggregateScore to the tally sum score_sum = AggregateScore(scores, 'sum') - tally_sum.add_score(score_sum) + tally_sum.scores.append(score_sum) # Add a copy of this tally's scores to the tally sum else: @@ -2946,7 +2957,7 @@ class Tally(object): # Add the new filter to a copy of this Tally new_tally = copy.deepcopy(self) - new_tally.add_filter(new_filter) + new_tally.filters.append(new_filter) # Determine "base" indices along the new "diagonal", and the factor # by which the "base" indices should be repeated to account for all diff --git a/openmc/trigger.py b/openmc/trigger.py index bcac8c31c6..f03703328b 100644 --- a/openmc/trigger.py +++ b/openmc/trigger.py @@ -1,6 +1,7 @@ from numbers import Real from xml.etree import ElementTree as ET import sys +import warnings from openmc.checkvalue import check_type, check_value @@ -8,6 +9,10 @@ if sys.version_info[0] >= 3: basestring = str +# DeprecationWarning filter for the Trigger.add_score(...) method +warnings.simplefilter('always', DeprecationWarning) + + class Trigger(object): """A criterion for when to finish a simulation based on tally uncertainties. @@ -46,9 +51,7 @@ class Trigger(object): clone._trigger_type = self._trigger_type clone._threshold = self._threshold - clone._scores = [] - for score in self._scores: - clone.add_score(score) + clone.scores = self.scores memo[id(self)] = clone @@ -97,6 +100,17 @@ class Trigger(object): check_type('tally trigger threshold', threshold, Real) self._threshold = threshold + @scores.setter + def scores(self, scores): + cv.check_type('trigger scores', scores, Iterable, basestring) + + # Set scores making sure not to have duplicates + self._scores = [] + for score in scores: + if score not in self._scores: + self._scores.append(score) + + def add_score(self, score): """Add a score to the list of scores to be checked against the trigger. @@ -107,16 +121,11 @@ class Trigger(object): """ - if not isinstance(score, basestring): - msg = 'Unable to add score "{0}" to tally trigger since ' \ - 'it is not a string'.format(score) - raise ValueError(msg) - - # If the score is already in the Tally, don't add it again - if score in self._scores: - return - else: - self._scores.append(score) + warnings.warn("Trigger.add_score(...) has been deprecated and may be " + "removed in a future version. Tally trigger scores should " + "be defined using the scores property directly.", + DeprecationWarning) + self.scores.append(score) def get_trigger_xml(self, element): """Return XML representation of the trigger diff --git a/tests/test_tallies/test_tallies.py b/tests/test_tallies/test_tallies.py index 9fca93bcab..81e8641dec 100644 --- a/tests/test_tallies/test_tallies.py +++ b/tests/test_tallies/test_tallies.py @@ -23,19 +23,19 @@ class TalliesTestHarness(PyAPITestHarness): azimuthal_bins = (-3.1416, -1.8850, -0.6283, 0.6283, 1.8850, 3.1416) azimuthal_filter1 = Filter(type='azimuthal', bins=azimuthal_bins) azimuthal_tally1 = Tally() - azimuthal_tally1.add_filter(azimuthal_filter1) - azimuthal_tally1.add_score('flux') + azimuthal_tally1.filters = [azimuthal_filter1] + azimuthal_tally1.scores = ['flux'] azimuthal_tally1.estimator = 'tracklength' azimuthal_tally2 = Tally() - azimuthal_tally2.add_filter(azimuthal_filter1) - azimuthal_tally2.add_score('flux') + azimuthal_tally2.filters = [azimuthal_filter1] + azimuthal_tally2.scores = ['flux'] azimuthal_tally2.estimator = 'analog' azimuthal_filter2 = Filter(type='azimuthal', bins=(5,)) azimuthal_tally3 = Tally() - azimuthal_tally3.add_filter(azimuthal_filter2) - azimuthal_tally3.add_score('flux') + azimuthal_tally3.filters = [azimuthal_filter2] + azimuthal_tally3.scores = ['flux'] azimuthal_tally3.estimator = 'tracklength' mesh_2x2 = Mesh(mesh_id=1) @@ -44,154 +44,129 @@ class TalliesTestHarness(PyAPITestHarness): mesh_2x2.dimension = [2, 2] mesh_filter = Filter(type='mesh', bins=(1,)) azimuthal_tally4 = Tally() - azimuthal_tally4.add_filter(azimuthal_filter2) - azimuthal_tally4.add_filter(mesh_filter) - azimuthal_tally4.add_score('flux') + azimuthal_tally4.filters = [azimuthal_filter2, mesh_filter] + azimuthal_tally4.scores = ['flux'] azimuthal_tally4.estimator = 'tracklength' cellborn_tally = Tally() - cellborn_tally.add_filter(Filter(type='cellborn', bins=(10, 21, 22, 23))) - cellborn_tally.add_score('total') + cellborn_tally.filters = [Filter(type='cellborn', bins=(10, 21, 22, 23))] + cellborn_tally.scores = ['total'] dg_tally = Tally() - dg_tally.add_filter(Filter(type='delayedgroup', bins=(1, 2, 3, 4, 5, 6))) - dg_tally.add_score('delayed-nu-fission') + dg_tally.filters = [Filter(type='delayedgroup', bins=(1, 2, 3, 4, 5, 6))] + dg_tally.scores = ['delayed-nu-fission'] four_groups = (0.0, 0.253e-6, 1.0e-3, 1.0, 20.0) energy_filter = Filter(type='energy', bins=four_groups) energy_tally = Tally() - energy_tally.add_filter(energy_filter) - energy_tally.add_score('total') + energy_tally.filters = [energy_filter] + energy_tally.scores = ['total'] energyout_filter = Filter(type='energyout', bins=four_groups) energyout_tally = Tally() - energyout_tally.add_filter(energyout_filter) - energyout_tally.add_score('scatter') + energyout_tally.filters = [energyout_filter] + energyout_tally.scores = ['scatter'] transfer_tally = Tally() - transfer_tally.add_filter(energy_filter) - transfer_tally.add_filter(energyout_filter) - transfer_tally.add_score('scatter') - transfer_tally.add_score('nu-fission') + transfer_tally.filters = [energy_filter, energyout_filter] + transfer_tally.scores = ['scatter', 'nu-fission'] material_tally = Tally() - material_tally.add_filter(Filter(type='material', bins=(1, 2, 3, 4))) - material_tally.add_score('total') + material_tally.filters = [Filter(type='material', bins=(1, 2, 3, 4))] + material_tally.scores = ['total'] mu_tally1 = Tally() - mu_tally1.add_filter(Filter(type='mu', bins=(-1.0, -0.5, 0.0, 0.5, 1.0))) - mu_tally1.add_score('scatter') - mu_tally1.add_score('nu-scatter') + mu_tally1.filters = [Filter(type='mu', bins=(-1.0, -0.5, 0.0, 0.5, 1.0))] + mu_tally1.scores = ['scatter', 'nu-scatter'] mu_filter = Filter(type='mu', bins=(5,)) mu_tally2 = Tally() - mu_tally2.add_filter(mu_filter) - mu_tally2.add_score('scatter') - mu_tally2.add_score('nu-scatter') + mu_tally2.filters = [mu_filter] + mu_tally2.scores = ['scatter', 'nu-scatter'] mu_tally3 = Tally() - mu_tally3.add_filter(mu_filter) - mu_tally3.add_filter(mesh_filter) - mu_tally3.add_score('scatter') - mu_tally3.add_score('nu-scatter') + mu_tally3.filters = [mu_filter, mesh_filter] + mu_tally3.scores = ['scatter', 'nu-scatter'] polar_bins = (0.0, 0.6283, 1.2566, 1.8850, 2.5132, 3.1416) polar_filter = Filter(type='polar', bins=polar_bins) polar_tally1 = Tally() - polar_tally1.add_filter(polar_filter) - polar_tally1.add_score('flux') + polar_tally1.filters = [polar_filter] + polar_tally1.scores = ['flux'] polar_tally1.estimator = 'tracklength' polar_tally2 = Tally() - polar_tally2.add_filter(polar_filter) - polar_tally2.add_score('flux') + polar_tally2.filters = [polar_filter] + polar_tally2.scores = ['flux'] polar_tally2.estimator = 'analog' polar_filter2 = Filter(type='polar', bins=(5,)) polar_tally3 = Tally() - polar_tally3.add_filter(polar_filter2) - polar_tally3.add_score('flux') + polar_tally3.filters = [polar_filter2] + polar_tally3.scores = ['flux'] polar_tally3.estimator = 'tracklength' polar_tally4 = Tally() - polar_tally4.add_filter(polar_filter2) - polar_tally4.add_filter(mesh_filter) - polar_tally4.add_score('flux') + polar_tally4.filters = [polar_filter2, mesh_filter] + polar_tally4.scores = ['flux'] polar_tally4.estimator = 'tracklength' universe_tally = Tally() - universe_tally.add_filter(Filter(type='universe', bins=(1, 2, 3, 4))) - universe_tally.add_score('total') + universe_tally.filters = [Filter(type='universe', bins=(1, 2, 3, 4))] + universe_tally.scores = ['total'] cell_filter = Filter(type='cell', bins=(10, 21, 22, 23)) score_tallies = [Tally(), Tally(), Tally()] for t in score_tallies: - t.add_filter(cell_filter) - t.add_score('absorption') - t.add_score('delayed-nu-fission') - t.add_score('events') - t.add_score('fission') - t.add_score('inverse-velocity') - t.add_score('kappa-fission') - t.add_score('(n,2n)') - t.add_score('(n,n1)') - t.add_score('(n,gamma)') - t.add_score('nu-fission') - t.add_score('scatter') - t.add_score('elastic') - t.add_score('total') + t.filters = [cell_filter] + t.scores = ['absorption', 'delayed-nu-fission', 'events', 'fission', + 'inverse-velocity', 'kappa-fission', '(n,2n)', '(n,n1)', + '(n,gamma)', 'nu-fission', 'scatter', 'elastic', 'total'] score_tallies[0].estimator = 'tracklength' score_tallies[1].estimator = 'analog' score_tallies[2].estimator = 'collision' cell_filter2 = Filter(type='cell', bins=(21, 22, 23, 27, 28, 29)) flux_tallies = [Tally() for i in range(4)] - [t.add_filter(cell_filter2) for t in flux_tallies] - flux_tallies[0].add_score('flux') - [t.add_score('flux-y5') for t in flux_tallies[1:]] + for t in flux_tallies: + t.filters = [cell_filter2] + flux_tallies[0].scores = ['flux'] + for t in flux_tallies[1:]: + t.scores = ['flux-y5'] flux_tallies[1].estimator = 'tracklength' flux_tallies[2].estimator = 'analog' flux_tallies[3].estimator = 'collision' scatter_tally1 = Tally() - scatter_tally1.add_filter(cell_filter) - scatter_tally1.add_score('scatter') - scatter_tally1.add_score('scatter-1') - scatter_tally1.add_score('scatter-2') - scatter_tally1.add_score('scatter-3') - scatter_tally1.add_score('scatter-4') - scatter_tally1.add_score('nu-scatter') - scatter_tally1.add_score('nu-scatter-1') - scatter_tally1.add_score('nu-scatter-2') - scatter_tally1.add_score('nu-scatter-3') - scatter_tally1.add_score('nu-scatter-4') + scatter_tally1.filters = [cell_filter] + scatter_tally1.scores = ['scatter', 'scatter-1', 'scatter-2', 'scatter-3', + 'scatter-4', 'nu-scatter', 'nu-scatter-1', + 'nu-scatter-2', 'nu-scatter-3', 'nu-scatter-4'] scatter_tally2 = Tally() - scatter_tally2.add_filter(cell_filter) - scatter_tally2.add_score('scatter-p4') - scatter_tally2.add_score('scatter-y4') - scatter_tally2.add_score('nu-scatter-p4') - scatter_tally2.add_score('nu-scatter-y3') + scatter_tally2.filters = [cell_filter] + scatter_tally2.scores = ['scatter-p4', 'scatter-y4', 'nu-scatter-p4', + 'nu-scatter-y3'] total_tallies = [Tally() for i in range(4)] - [t.add_filter(cell_filter) for t in total_tallies] - total_tallies[0].add_score('total') - [t.add_score('total-y4') for t in total_tallies[1:]] - [t.add_nuclide('U-235') for t in total_tallies[1:]] - [t.add_nuclide('total') for t in total_tallies[1:]] + for t in total_tallies: + t.filters = [cell_filter] + total_tallies[0].scores = ['total'] + for t in total_tallies[1:]: + t.scores = ['total-y4'] + t.nuclides = ['U-235', 'total'] total_tallies[1].estimator = 'tracklength' total_tallies[2].estimator = 'analog' total_tallies[3].estimator = 'collision' questionable_tally = Tally() - questionable_tally.add_score('transport') - questionable_tally.add_score('n1n') + questionable_tally.scores = ['transport', 'n1n'] all_nuclide_tallies = [Tally(), Tally()] for t in all_nuclide_tallies: - t.add_filter(cell_filter) - t.add_nuclide('all') - t.add_score('total') + t.filters = [cell_filter] + t.nuclides = ['all'] + t.scores = ['total'] all_nuclide_tallies[0].estimator = 'tracklength' all_nuclide_tallies[0].estimator = 'collision' diff --git a/tests/test_tally_aggregation/test_tally_aggregation.py b/tests/test_tally_aggregation/test_tally_aggregation.py index a5c8d94141..7d682b6986 100644 --- a/tests/test_tally_aggregation/test_tally_aggregation.py +++ b/tests/test_tally_aggregation/test_tally_aggregation.py @@ -30,13 +30,9 @@ class TallyAggregationTestHarness(PyAPITestHarness): # Initialized the tallies tally = openmc.Tally(name='distribcell tally') - 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(u238) - tally.add_nuclide(pu239) + tally.filters = [energy_filter, distrib_filter] + tally.scores = ['nu-fission', 'total'] + tally.nuclides = [u235, u238, pu239] tallies_file.add_tally(tally) # Export tallies to file diff --git a/tests/test_tally_arithmetic/test_tally_arithmetic.py b/tests/test_tally_arithmetic/test_tally_arithmetic.py index 1954334b7f..cf8d012e8c 100644 --- a/tests/test_tally_arithmetic/test_tally_arithmetic.py +++ b/tests/test_tally_arithmetic/test_tally_arithmetic.py @@ -40,22 +40,15 @@ class TallyArithmeticTestHarness(PyAPITestHarness): # 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) + tally.filters = [material_filter, energy_filter, distrib_filter] + tally.scores = ['nu-fission', 'total'] + tally.nuclides = [u235, 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) + tally.filters = [energy_filter, mesh_filter] + tally.scores = ['total', 'fission'] + tally.nuclides = [u238, u235] tallies_file.add_tally(tally) tallies_file.add_mesh(mesh) From 72659506e06d6df8b47186e7878196b5bbb56457 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Thu, 18 Feb 2016 11:27:09 -0600 Subject: [PATCH 02/11] Use universal newlines in openmc.Executor --- openmc/executor.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/openmc/executor.py b/openmc/executor.py index 58cb912465..214517d6ed 100644 --- a/openmc/executor.py +++ b/openmc/executor.py @@ -27,7 +27,8 @@ class Executor(object): # Launch a subprocess to run OpenMC p = subprocess.Popen(command, shell=True, cwd=self._working_directory, - stdout=subprocess.PIPE) + stdout=subprocess.PIPE, + universal_newlines=True) # Capture and re-print OpenMC output in real-time while True: From 5fef6f4f66aed7ee26173c7e5deac96de10de2ff Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Thu, 18 Feb 2016 11:30:39 -0600 Subject: [PATCH 03/11] Remove warnings filter for DeprecationWarning --- openmc/tallies.py | 3 --- openmc/trigger.py | 4 ---- openmc/universe.py | 3 --- 3 files changed, 10 deletions(-) diff --git a/openmc/tallies.py b/openmc/tallies.py index f471dbdf37..f938ae708e 100644 --- a/openmc/tallies.py +++ b/openmc/tallies.py @@ -23,9 +23,6 @@ if sys.version_info[0] >= 3: basestring = str -# DeprecationWarning filter for the Tally.add_*(...) methods -warnings.simplefilter('always', DeprecationWarning) - # "Static" variable for auto-generated Tally IDs AUTO_TALLY_ID = 10000 diff --git a/openmc/trigger.py b/openmc/trigger.py index f03703328b..ce7d432c2e 100644 --- a/openmc/trigger.py +++ b/openmc/trigger.py @@ -9,10 +9,6 @@ if sys.version_info[0] >= 3: basestring = str -# DeprecationWarning filter for the Trigger.add_score(...) method -warnings.simplefilter('always', DeprecationWarning) - - class Trigger(object): """A criterion for when to finish a simulation based on tally uncertainties. diff --git a/openmc/universe.py b/openmc/universe.py index 74c438615c..9a1effdde1 100644 --- a/openmc/universe.py +++ b/openmc/universe.py @@ -16,9 +16,6 @@ if sys.version_info[0] >= 3: basestring = str -# DeprecationWarning filter for the Cell.add_surface(...) method -warnings.simplefilter('always', DeprecationWarning) - # A static variable for auto-generated Cell IDs AUTO_CELL_ID = 10000 From 1e674ebbdbc2aa7b0d3f6b1946a2e9ad4e14515a Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Tue, 23 Feb 2016 09:48:42 -0600 Subject: [PATCH 04/11] Have setters for scores, nuclide, filters, and triggers expect a MutableSequence --- openmc/tallies.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/openmc/tallies.py b/openmc/tallies.py index f938ae708e..a808c11dc6 100644 --- a/openmc/tallies.py +++ b/openmc/tallies.py @@ -1,6 +1,6 @@ from __future__ import division -from collections import Iterable, defaultdict +from collections import Iterable, MutableSequence, defaultdict import copy from functools import partial import os @@ -426,7 +426,7 @@ class Tally(object): @triggers.setter def triggers(self, triggers): - cv.check_type('tally triggers', trigger, Iterable, Trigger) + cv.check_type('tally triggers', trigger, MutableSequence, Trigger) self._triggers = triggers def add_trigger(self, trigger): @@ -466,7 +466,7 @@ class Tally(object): @filters.setter def filters(self, filters): - cv.check_type('tally filters', filters, Iterable, + cv.check_type('tally filters', filters, MutableSequence, (Filter, CrossFilter, AggregateFilter)) # If the filter is already in the Tally, raise an error @@ -481,7 +481,7 @@ class Tally(object): @nuclides.setter def nuclides(self, nuclides): - cv.check_type('tally nuclides', nuclides, Iterable, + cv.check_type('tally nuclides', nuclides, MutableSequence, (basestring, Nuclide, CrossNuclide, AggregateNuclide)) # If the nuclide is already in the Tally, raise an error @@ -496,7 +496,7 @@ class Tally(object): @scores.setter def scores(self, scores): - cv.check_type('tally scores', scores, Iterable, + cv.check_type('tally scores', scores, MutableSequence, (basestring, CrossScore, AggregateScore)) for i, score in enumerate(scores[:-1]): From a4ed73fc113619269c21db6ead8b5845fde1d712 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Tue, 23 Feb 2016 10:48:47 -0600 Subject: [PATCH 05/11] Update Jupyter notebooks based on Tally property changes --- .../pythonapi/examples/mgxs-part-iii.ipynb | 5 +- .../examples/pandas-dataframes.ipynb | 22 +- .../pythonapi/examples/post-processing.ipynb | 5 +- .../pythonapi/examples/tally-arithmetic.ipynb | 455 +++++++++--------- 4 files changed, 237 insertions(+), 250 deletions(-) diff --git a/docs/source/pythonapi/examples/mgxs-part-iii.ipynb b/docs/source/pythonapi/examples/mgxs-part-iii.ipynb index dcb496160e..c3f19aa226 100644 --- a/docs/source/pythonapi/examples/mgxs-part-iii.ipynb +++ b/docs/source/pythonapi/examples/mgxs-part-iii.ipynb @@ -689,9 +689,8 @@ "\n", "# Instantiate the Tally\n", "tally = openmc.Tally(name='mesh tally')\n", - "tally.add_filter(mesh_filter)\n", - "tally.add_score('fission')\n", - "tally.add_score('nu-fission')\n", + "tally.filters = [mesh_filter]\n", + "tally.scores = ['fission', 'nu-fission']\n", "\n", "# Add mesh and Tally to TalliesFile\n", "tallies_file.add_mesh(mesh)\n", diff --git a/docs/source/pythonapi/examples/pandas-dataframes.ipynb b/docs/source/pythonapi/examples/pandas-dataframes.ipynb index ac5d4e4109..85f64ff6fa 100644 --- a/docs/source/pythonapi/examples/pandas-dataframes.ipynb +++ b/docs/source/pythonapi/examples/pandas-dataframes.ipynb @@ -453,10 +453,8 @@ "\n", "# Instantiate the Tally\n", "tally = openmc.Tally(name='mesh tally')\n", - "tally.add_filter(mesh_filter)\n", - "tally.add_filter(energy_filter)\n", - "tally.add_score('fission')\n", - "tally.add_score('nu-fission')\n", + "tally.filters = [mesh_filter, energy_filter]\n", + "tally.scores = ['fission', 'nu-fission']\n", "\n", "# Add mesh and Tally to TalliesFile\n", "tallies_file.add_mesh(mesh)\n", @@ -483,10 +481,9 @@ "\n", "# Instantiate the tally\n", "tally = openmc.Tally(name='cell tally')\n", - "tally.add_filter(cell_filter)\n", - "tally.add_score('scatter-y2')\n", - "tally.add_nuclide(u235)\n", - "tally.add_nuclide(u238)\n", + "tally.filters = [cell_filter]\n", + "tally.scores = ['scatter-y2']\n", + "tally.nuclides = [u235, u238]\n", "\n", "# Add mesh and tally to TalliesFile\n", "tallies_file.add_tally(tally)" @@ -512,14 +509,13 @@ "\n", "# Instantiate tally Trigger for kicks\n", "trigger = openmc.Trigger(trigger_type='std_dev', threshold=5e-5)\n", - "trigger.add_score('absorption')\n", + "trigger.scores = ['absorption']\n", "\n", "# Instantiate the Tally\n", "tally = openmc.Tally(name='distribcell tally')\n", - "tally.add_filter(distribcell_filter)\n", - "tally.add_score('absorption')\n", - "tally.add_score('scatter')\n", - "tally.add_trigger(trigger)\n", + "tally.filters = [distribcell_filter]\n", + "tally.scores = ['absorption', 'scatter']\n", + "tally.triggers = [trigger]\n", "\n", "# Add mesh and tally to TalliesFile\n", "tallies_file.add_tally(tally)" diff --git a/docs/source/pythonapi/examples/post-processing.ipynb b/docs/source/pythonapi/examples/post-processing.ipynb index 7fbca68644..6526f03077 100644 --- a/docs/source/pythonapi/examples/post-processing.ipynb +++ b/docs/source/pythonapi/examples/post-processing.ipynb @@ -408,9 +408,8 @@ "\n", "# Create mesh tally to score flux and fission rate\n", "tally = openmc.Tally(name='flux')\n", - "tally.add_filter(mesh_filter)\n", - "tally.add_score('flux')\n", - "tally.add_score('fission')\n", + "tally.filters = [mesh_filter]\n", + "tally.scores = ['flux', 'fission']\n", "tallies_file.add_tally(tally)" ] }, diff --git a/docs/source/pythonapi/examples/tally-arithmetic.ipynb b/docs/source/pythonapi/examples/tally-arithmetic.ipynb index 3a61b09790..d1325e4878 100644 --- a/docs/source/pythonapi/examples/tally-arithmetic.ipynb +++ b/docs/source/pythonapi/examples/tally-arithmetic.ipynb @@ -418,29 +418,25 @@ "\n", "# Instantiate flux Tally in moderator and fuel\n", "tally = openmc.Tally(name='flux')\n", - "tally.add_filter(openmc.Filter(type='cell', bins=[fuel_cell.id, moderator_cell.id]))\n", - "tally.add_filter(energy_filter)\n", - "tally.add_score('flux')\n", + "tally.filters = [openmc.Filter(type='cell', bins=[fuel_cell.id, moderator_cell.id]),\n", + " energy_filter]\n", + "tally.scores = ['flux']\n", "tallies_file.add_tally(tally)\n", "\n", "# Instantiate reaction rate Tally in fuel\n", "tally = openmc.Tally(name='fuel rxn rates')\n", - "tally.add_filter(openmc.Filter(type='cell', bins=[fuel_cell.id]))\n", - "tally.add_filter(energy_filter)\n", - "tally.add_score('nu-fission')\n", - "tally.add_score('scatter')\n", - "tally.add_nuclide(u238)\n", - "tally.add_nuclide(u235)\n", + "tally.filters = [openmc.Filter(type='cell', bins=[fuel_cell.id]),\n", + " energy_filter]\n", + "tally.scores = ['nu-fission', 'scatter']\n", + "tally.nuclides = [u238, u235]\n", "tallies_file.add_tally(tally)\n", "\n", "# Instantiate reaction rate Tally in moderator\n", "tally = openmc.Tally(name='moderator rxn rates')\n", - "tally.add_filter(openmc.Filter(type='cell', bins=[moderator_cell.id]))\n", - "tally.add_filter(energy_filter)\n", - "tally.add_score('absorption')\n", - "tally.add_score('total')\n", - "tally.add_nuclide(o16)\n", - "tally.add_nuclide(h1)\n", + "tally.filters = [openmc.Filter(type='cell', bins=[moderator_cell.id])]\n", + "tally.filters.append(energy_filter)\n", + "tally.scores = ['absorption', 'total']\n", + "tally.nuclides = [o16, h1]\n", "tallies_file.add_tally(tally)" ] }, @@ -455,8 +451,8 @@ "# K-Eigenvalue (infinity) tallies\n", "fiss_rate = openmc.Tally(name='fiss. rate')\n", "abs_rate = openmc.Tally(name='abs. rate')\n", - "fiss_rate.add_score('nu-fission')\n", - "abs_rate.add_score('absorption')\n", + "fiss_rate.scores = ['nu-fission']\n", + "abs_rate.scores = ['absorption']\n", "tallies_file.add_tally(fiss_rate)\n", "tallies_file.add_tally(abs_rate)" ] @@ -471,8 +467,8 @@ "source": [ "# Resonance Escape Probability tallies\n", "therm_abs_rate = openmc.Tally(name='therm. abs. rate')\n", - "therm_abs_rate.add_score('absorption')\n", - "therm_abs_rate.add_filter(openmc.Filter(type='energy', bins=[0., 0.625e-6]))\n", + "therm_abs_rate.scores = ['absorption']\n", + "therm_abs_rate.filters = [openmc.Filter(type='energy', bins=[0., 0.625e-6])]\n", "tallies_file.add_tally(therm_abs_rate)" ] }, @@ -486,9 +482,9 @@ "source": [ "# Thermal Flux Utilization tallies\n", "fuel_therm_abs_rate = openmc.Tally(name='fuel therm. abs. rate')\n", - "fuel_therm_abs_rate.add_score('absorption')\n", - "fuel_therm_abs_rate.add_filter(openmc.Filter(type='energy', bins=[0., 0.625e-6]))\n", - "fuel_therm_abs_rate.add_filter(openmc.Filter(type='cell', bins=[fuel_cell.id]))\n", + "fuel_therm_abs_rate.scores = ['absorption']\n", + "fuel_therm_abs_rate.filters = [openmc.Filter(type='energy', bins=[0., 0.625e-6]),\n", + " openmc.Filter(type='cell', bins=[fuel_cell.id])]\n", "tallies_file.add_tally(fuel_therm_abs_rate)" ] }, @@ -502,8 +498,8 @@ "source": [ "# Fast Fission Factor tallies\n", "therm_fiss_rate = openmc.Tally(name='therm. fiss. rate')\n", - "therm_fiss_rate.add_score('nu-fission')\n", - "therm_fiss_rate.add_filter(openmc.Filter(type='energy', bins=[0., 0.625e-6]))\n", + "therm_fiss_rate.scores = ['nu-fission']\n", + "therm_fiss_rate.filters = [openmc.Filter(type='energy', bins=[0., 0.625e-6])]\n", "tallies_file.add_tally(therm_fiss_rate)" ] }, @@ -520,12 +516,10 @@ "\n", "# Instantiate flux Tally in moderator and fuel\n", "tally = openmc.Tally(name='need-to-slice')\n", - "tally.add_filter(openmc.Filter(type='cell', bins=[fuel_cell.id, moderator_cell.id]))\n", - "tally.add_filter(energy_filter)\n", - "tally.add_score('nu-fission')\n", - "tally.add_score('scatter')\n", - "tally.add_nuclide(h1)\n", - "tally.add_nuclide(u238)\n", + "tally.filters = [openmc.Filter(type='cell', bins=[fuel_cell.id, moderator_cell.id]),\n", + " energy_filter]\n", + "tally.scores = ['nu-fission', 'scatter']\n", + "tally.nuclides = [h1, u238]\n", "tallies_file.add_tally(tally)" ] }, @@ -533,7 +527,7 @@ "cell_type": "code", "execution_count": 22, "metadata": { - "collapsed": true + "collapsed": false }, "outputs": [], "source": [ @@ -576,9 +570,8 @@ " Copyright: 2011-2015 Massachusetts Institute of Technology\n", " License: http://mit-crpg.github.io/openmc/license.html\n", " Version: 0.7.1\n", - " Git SHA1: 34381b40a9445a727e360873aaa6ef892af1cb6a\n", - " Date/Time: 2016-02-07 16:05:17\n", - " MPI Processes: 1\n", + " Git SHA1: b9efc990c7eb58f4a41524d59ae73396c9929436\n", + " Date/Time: 2016-02-23 10:52:44\n", "\n", " ===========================================================================\n", " ========================> INITIALIZATION <=========================\n", @@ -634,20 +627,20 @@ "\n", " =======================> TIMING STATISTICS <=======================\n", "\n", - " Total time for initialization = 3.4700E-01 seconds\n", - " Reading cross sections = 9.1000E-02 seconds\n", - " Total time in simulation = 7.3920E+00 seconds\n", - " Time in transport only = 7.3820E+00 seconds\n", - " Time in inactive batches = 1.0930E+00 seconds\n", - " Time in active batches = 6.2990E+00 seconds\n", - " Time synchronizing fission bank = 2.0000E-03 seconds\n", - " Sampling source sites = 1.0000E-03 seconds\n", - " SEND/RECV source sites = 0.0000E+00 seconds\n", + " Total time for initialization = 8.4700E-01 seconds\n", + " Reading cross sections = 5.8300E-01 seconds\n", + " Total time in simulation = 1.6037E+01 seconds\n", + " Time in transport only = 1.6026E+01 seconds\n", + " Time in inactive batches = 2.3070E+00 seconds\n", + " Time in active batches = 1.3730E+01 seconds\n", + " Time synchronizing fission bank = 5.0000E-03 seconds\n", + " Sampling source sites = 4.0000E-03 seconds\n", + " SEND/RECV source sites = 1.0000E-03 seconds\n", " Time accumulating tallies = 0.0000E+00 seconds\n", - " Total time for finalization = 2.0000E-03 seconds\n", - " Total time elapsed = 7.7510E+00 seconds\n", - " Calculation Rate (inactive) = 11436.4 neutrons/second\n", - " Calculation Rate (active) = 5953.33 neutrons/second\n", + " Total time for finalization = 3.0000E-03 seconds\n", + " Total time elapsed = 1.6899E+01 seconds\n", + " Calculation Rate (inactive) = 5418.29 neutrons/second\n", + " Calculation Rate (active) = 2731.25 neutrons/second\n", "\n", " ============================> RESULTS <============================\n", "\n", @@ -759,10 +752,10 @@ " \n", " \n", " 0\n", - " total\n", - " (nu-fission / absorption)\n", - " 1.040166\n", - " 0.009069\n", + " total\n", + " (nu-fission / absorption)\n", + " 1.040166\n", + " 0.009069\n", " \n", " \n", "\n", @@ -821,12 +814,12 @@ " \n", " \n", " 0\n", - " 0\n", - " 0.000001\n", - " total\n", - " absorption\n", - " 0.694707\n", - " 0.006699\n", + " 0\n", + " 0.000001\n", + " total\n", + " absorption\n", + " 0.694707\n", + " 0.006699\n", " \n", " \n", "\n", @@ -883,12 +876,12 @@ " \n", " \n", " 0\n", - " 0\n", - " 0.000001\n", - " total\n", - " nu-fission\n", - " 1.201216\n", - " 0.012288\n", + " 0\n", + " 0.000001\n", + " total\n", + " nu-fission\n", + " 1.201216\n", + " 0.012288\n", " \n", " \n", "\n", @@ -947,13 +940,13 @@ " \n", " \n", " 0\n", - " 0\n", - " 0.000001\n", - " 10000\n", - " total\n", - " absorption\n", - " 0.74925\n", - " 0.008257\n", + " 0\n", + " 0.000001\n", + " 10000\n", + " total\n", + " absorption\n", + " 0.74925\n", + " 0.008257\n", " \n", " \n", "\n", @@ -1013,13 +1006,13 @@ " \n", " \n", " 0\n", - " 0\n", - " 0.000001\n", - " 10000\n", - " total\n", - " (nu-fission / absorption)\n", - " 1.663616\n", - " 0.018624\n", + " 0\n", + " 0.000001\n", + " 10000\n", + " total\n", + " (nu-fission / absorption)\n", + " 1.663616\n", + " 0.018624\n", " \n", " \n", "\n", @@ -1078,13 +1071,13 @@ " \n", " \n", " 0\n", - " 0\n", - " 0.000001\n", - " 10000\n", - " total\n", - " (((absorption * nu-fission) * absorption) * (n...\n", - " 1.040166\n", - " 0.021928\n", + " 0\n", + " 0.000001\n", + " 10000\n", + " total\n", + " (((absorption * nu-fission) * absorption) * (n...\n", + " 1.040166\n", + " 0.021928\n", " \n", " \n", "\n", @@ -1160,83 +1153,83 @@ " \n", " \n", " 0\n", - " 10000\n", - " 0.000000\n", - " 0.000001\n", - " (U-238 / total)\n", - " (nu-fission / flux)\n", - " 0.000001\n", - " 7.377419e-09\n", + " 10000\n", + " 0.000000\n", + " 0.000001\n", + " (U-238 / total)\n", + " (nu-fission / flux)\n", + " 0.000001\n", + " 7.377419e-09\n", " \n", " \n", " 1\n", - " 10000\n", - " 0.000000\n", - " 0.000001\n", - " (U-238 / total)\n", - " (scatter / flux)\n", - " 0.209989\n", - " 2.303838e-03\n", + " 10000\n", + " 0.000000\n", + " 0.000001\n", + " (U-238 / total)\n", + " (scatter / flux)\n", + " 0.209989\n", + " 2.303838e-03\n", " \n", " \n", " 2\n", - " 10000\n", - " 0.000000\n", - " 0.000001\n", - " (U-235 / total)\n", - " (nu-fission / flux)\n", - " 0.356420\n", - " 3.951669e-03\n", + " 10000\n", + " 0.000000\n", + " 0.000001\n", + " (U-235 / total)\n", + " (nu-fission / flux)\n", + " 0.356420\n", + " 3.951669e-03\n", " \n", " \n", " 3\n", - " 10000\n", - " 0.000000\n", - " 0.000001\n", - " (U-235 / total)\n", - " (scatter / flux)\n", - " 0.005555\n", - " 6.101004e-05\n", + " 10000\n", + " 0.000000\n", + " 0.000001\n", + " (U-235 / total)\n", + " (scatter / flux)\n", + " 0.005555\n", + " 6.101004e-05\n", " \n", " \n", " 4\n", - " 10000\n", - " 0.000001\n", - " 20.000000\n", - " (U-238 / total)\n", - " (nu-fission / flux)\n", - " 0.007155\n", - " 8.053460e-05\n", + " 10000\n", + " 0.000001\n", + " 20.000000\n", + " (U-238 / total)\n", + " (nu-fission / flux)\n", + " 0.007155\n", + " 8.053460e-05\n", " \n", " \n", " 5\n", - " 10000\n", - " 0.000001\n", - " 20.000000\n", - " (U-238 / total)\n", - " (scatter / flux)\n", - " 0.227770\n", - " 1.079289e-03\n", + " 10000\n", + " 0.000001\n", + " 20.000000\n", + " (U-238 / total)\n", + " (scatter / flux)\n", + " 0.227770\n", + " 1.079289e-03\n", " \n", " \n", " 6\n", - " 10000\n", - " 0.000001\n", - " 20.000000\n", - " (U-235 / total)\n", - " (nu-fission / flux)\n", - " 0.008067\n", - " 5.254797e-05\n", + " 10000\n", + " 0.000001\n", + " 20.000000\n", + " (U-235 / total)\n", + " (nu-fission / flux)\n", + " 0.008067\n", + " 5.254797e-05\n", " \n", " \n", " 7\n", - " 10000\n", - " 0.000001\n", - " 20.000000\n", - " (U-235 / total)\n", - " (scatter / flux)\n", - " 0.003367\n", - " 1.647058e-05\n", + " 10000\n", + " 0.000001\n", + " 20.000000\n", + " (U-235 / total)\n", + " (scatter / flux)\n", + " 0.003367\n", + " 1.647058e-05\n", " \n", " \n", "\n", @@ -1395,43 +1388,43 @@ " \n", " \n", " 0\n", - " 10000\n", - " 0.000000\n", - " 0.000001\n", - " U-238\n", - " nu-fission\n", - " 0.000002\n", - " 1.283958e-08\n", + " 10000\n", + " 0.000000\n", + " 0.000001\n", + " U-238\n", + " nu-fission\n", + " 0.000002\n", + " 1.283958e-08\n", " \n", " \n", " 1\n", - " 10000\n", - " 0.000000\n", - " 0.000001\n", - " U-235\n", - " nu-fission\n", - " 0.868553\n", - " 6.880390e-03\n", + " 10000\n", + " 0.000000\n", + " 0.000001\n", + " U-235\n", + " nu-fission\n", + " 0.868553\n", + " 6.880390e-03\n", " \n", " \n", " 2\n", - " 10000\n", - " 0.000001\n", - " 20.000000\n", - " U-238\n", - " nu-fission\n", - " 0.082149\n", - " 8.837250e-04\n", + " 10000\n", + " 0.000001\n", + " 20.000000\n", + " U-238\n", + " nu-fission\n", + " 0.082149\n", + " 8.837250e-04\n", " \n", " \n", " 3\n", - " 10000\n", - " 0.000001\n", - " 20.000000\n", - " U-235\n", - " nu-fission\n", - " 0.092618\n", - " 5.195308e-04\n", + " 10000\n", + " 0.000001\n", + " 20.000000\n", + " U-235\n", + " nu-fission\n", + " 0.092618\n", + " 5.195308e-04\n", " \n", " \n", "\n", @@ -1489,93 +1482,93 @@ " \n", " \n", " 0\n", - " 10002\n", - " 1.000000e-08\n", - " 0.000000\n", - " H-1\n", - " scatter\n", - " 4.619398\n", - " 0.040124\n", + " 10002\n", + " 1.000000e-08\n", + " 0.000000\n", + " H-1\n", + " scatter\n", + " 4.619398\n", + " 0.040124\n", " \n", " \n", " 1\n", - " 10002\n", - " 1.080060e-07\n", - " 0.000001\n", - " H-1\n", - " scatter\n", - " 2.030757\n", - " 0.011239\n", + " 10002\n", + " 1.080060e-07\n", + " 0.000001\n", + " H-1\n", + " scatter\n", + " 2.030757\n", + " 0.011239\n", " \n", " \n", " 2\n", - " 10002\n", - " 1.166529e-06\n", - " 0.000013\n", - " H-1\n", - " scatter\n", - " 1.658488\n", - " 0.009777\n", + " 10002\n", + " 1.166529e-06\n", + " 0.000013\n", + " H-1\n", + " scatter\n", + " 1.658488\n", + " 0.009777\n", " \n", " \n", " 3\n", - " 10002\n", - " 1.259921e-05\n", - " 0.000136\n", - " H-1\n", - " scatter\n", - " 1.853002\n", - " 0.007378\n", + " 10002\n", + " 1.259921e-05\n", + " 0.000136\n", + " H-1\n", + " scatter\n", + " 1.853002\n", + " 0.007378\n", " \n", " \n", " 4\n", - " 10002\n", - " 1.360790e-04\n", - " 0.001470\n", - " H-1\n", - " scatter\n", - " 2.050773\n", - " 0.012484\n", + " 10002\n", + " 1.360790e-04\n", + " 0.001470\n", + " H-1\n", + " scatter\n", + " 2.050773\n", + " 0.012484\n", " \n", " \n", " 5\n", - " 10002\n", - " 1.469734e-03\n", - " 0.015874\n", - " H-1\n", - " scatter\n", - " 2.131759\n", - " 0.007821\n", + " 10002\n", + " 1.469734e-03\n", + " 0.015874\n", + " H-1\n", + " scatter\n", + " 2.131759\n", + " 0.007821\n", " \n", " \n", " 6\n", - " 10002\n", - " 1.587401e-02\n", - " 0.171449\n", - " H-1\n", - " scatter\n", - " 2.213710\n", - " 0.015159\n", + " 10002\n", + " 1.587401e-02\n", + " 0.171449\n", + " H-1\n", + " scatter\n", + " 2.213710\n", + " 0.015159\n", " \n", " \n", " 7\n", - " 10002\n", - " 1.714488e-01\n", - " 1.851749\n", - " H-1\n", - " scatter\n", - " 2.011925\n", - " 0.009406\n", + " 10002\n", + " 1.714488e-01\n", + " 1.851749\n", + " H-1\n", + " scatter\n", + " 2.011925\n", + " 0.009406\n", " \n", " \n", " 8\n", - " 10002\n", - " 1.851749e+00\n", - " 20.000000\n", - " H-1\n", - " scatter\n", - " 0.371280\n", - " 0.003949\n", + " 10002\n", + " 1.851749e+00\n", + " 20.000000\n", + " H-1\n", + " scatter\n", + " 0.371280\n", + " 0.003949\n", " \n", " \n", "\n", From 2f3059930d15684c400893dad092d9d9e59c9870 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Tue, 23 Feb 2016 11:05:15 -0600 Subject: [PATCH 06/11] Add note about deprecation of add_ methods in documentation --- openmc/tallies.py | 16 ++++++++++++++++ openmc/universe.py | 4 ++++ 2 files changed, 20 insertions(+) diff --git a/openmc/tallies.py b/openmc/tallies.py index a808c11dc6..343062aa84 100644 --- a/openmc/tallies.py +++ b/openmc/tallies.py @@ -432,6 +432,10 @@ class Tally(object): def add_trigger(self, trigger): """Add a tally trigger to the tally + .. deprecated:: 0.8 + Use the Tally.triggers property directly, i.e., + Tally.triggers.append(...) + Parameters ---------- trigger : openmc.trigger.Trigger @@ -516,6 +520,10 @@ class Tally(object): def add_filter(self, new_filter): """Add a filter to the tally + .. deprecated:: 0.8 + Use the Tally.filters property directly, i.e., + Tally.filters.append(...) + Parameters ---------- new_filter : Filter, CrossFilter or AggregateFilter @@ -537,6 +545,10 @@ class Tally(object): def add_nuclide(self, nuclide): """Specify that scores for a particular nuclide should be accumulated + .. deprecated:: 0.8 + Use the Tally.nuclides property directly, i.e., + Tally.nuclides.append(...) + Parameters ---------- nuclide : str, Nuclide, CrossNuclide or AggregateNuclide @@ -558,6 +570,10 @@ class Tally(object): def add_score(self, score): """Specify a quantity to be scored + .. deprecated:: 0.8 + Use the Tally.scores property directly, i.e., + Tally.scores.append(...) + Parameters ---------- score : str, CrossScore or AggregateScore diff --git a/openmc/universe.py b/openmc/universe.py index 9a1effdde1..1729aa7e23 100644 --- a/openmc/universe.py +++ b/openmc/universe.py @@ -257,6 +257,10 @@ class Cell(object): """Add a half-space to the list of half-spaces whose intersection defines the cell. + .. deprecated:: 0.7.1 + Use the Cell.region property to directly specify a Region + expression. + Parameters ---------- surface : openmc.surface.Surface From b8c1ab68e90b794c1789996045273ba5459be4e4 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Tue, 8 Mar 2016 21:54:07 -0600 Subject: [PATCH 07/11] Introduce CheckedList for type-checking Tally attributes that are lists --- openmc/checkvalue.py | 56 ++++++++++++++++++++++++++++++++++++++++++-- openmc/tallies.py | 34 +++++++++++++++------------ 2 files changed, 73 insertions(+), 17 deletions(-) diff --git a/openmc/checkvalue.py b/openmc/checkvalue.py index 0e9dc9ef4b..53d77036ab 100644 --- a/openmc/checkvalue.py +++ b/openmc/checkvalue.py @@ -50,8 +50,13 @@ def check_type(name, value, expected_type, expected_iter_type=None): """ if not _isinstance(value, expected_type): - msg = 'Unable to set "{0}" to "{1}" which is not of type "{2}"'.format( - name, value, expected_type.__name__) + if isinstance(expected_type, Iterable): + msg = 'Unable to set "{0}" to "{1}" which is not one of the ' \ + 'following types: "{2}"'.format(name, value, ', '.join( + [t.__name__ for t in expected_type])) + else: + msg = 'Unable to set "{0}" to "{1}" which is not of type "{2}"'.format( + name, value, expected_type.__name__) raise ValueError(msg) if expected_iter_type: @@ -251,3 +256,50 @@ def check_greater_than(name, value, minimum, equality=False): msg = 'Unable to set "{0}" to "{1}" since it is less than ' \ 'or equal to "{2}"'.format(name, value, minimum) raise ValueError(msg) + + +class CheckedList(list): + """A list for which each element is type-checked as it's added + + Parameters + ---------- + expected_type : type or Iterable of type + Type(s) which each element should be + name : str + Name of data being checked + items : Iterable, optional + Items to initialize the list with + + """ + + def __init__(self, expected_type, name, items=[]): + self.expected_type = expected_type + self.name = name + for item in items: + self.append(item) + + def append(self, item): + """Append item to list + + Parameters + ---------- + item : object + Item to append + + """ + check_type(self.name, item, self.expected_type) + super(CheckedList, self).append(item) + + def insert(self, index, item): + """Insert item before index + + Parameters + ---------- + index : int + Index in list + item : object + Item to insert + + """ + check_type(self.name, item, self.expected_type) + super(CheckedList, self).insert(index, item) diff --git a/openmc/tallies.py b/openmc/tallies.py index 343062aa84..9d6ed4b7f1 100644 --- a/openmc/tallies.py +++ b/openmc/tallies.py @@ -33,6 +33,12 @@ AUTO_TALLY_ID = 10000 # specified axis. _PRODUCT_TYPES = ['tensor', 'entrywise'] +# The following indicate acceptable types when setting Tally.scores, +# Tally.nuclides, and Tally.filters +_SCORE_CLASSES = (basestring, CrossScore, AggregateScore) +_NUCLIDE_CLASSES = (basestring, Nuclide, CrossNuclide, AggregateNuclide) +_FILTER_CLASSES = (Filter, CrossFilter, AggregateFilter) + def reset_auto_tally_id(): global AUTO_TALLY_ID @@ -103,11 +109,11 @@ class Tally(object): # Initialize Tally class attributes self.id = tally_id self.name = name - self._filters = [] - self._nuclides = [] - self._scores = [] + self._filters = cv.CheckedList(_FILTER_CLASSES, 'tally filters') + self._nuclides = cv.CheckedList(_NUCLIDE_CLASSES, 'tally nuclides') + self._scores = cv.CheckedList(_SCORE_CLASSES, 'tally scores') self._estimator = None - self._triggers = [] + self._triggers = cv.CheckedList(Trigger, 'tally triggers') self._num_realizations = 0 self._with_summary = False @@ -426,8 +432,8 @@ class Tally(object): @triggers.setter def triggers(self, triggers): - cv.check_type('tally triggers', trigger, MutableSequence, Trigger) - self._triggers = triggers + cv.check_type('tally triggers', triggers, MutableSequence) + self._triggers = cv.CheckedList(Trigger, 'tally triggers', triggers) def add_trigger(self, trigger): """Add a tally trigger to the tally @@ -470,8 +476,7 @@ class Tally(object): @filters.setter def filters(self, filters): - cv.check_type('tally filters', filters, MutableSequence, - (Filter, CrossFilter, AggregateFilter)) + cv.check_type('tally filters', filters, MutableSequence) # If the filter is already in the Tally, raise an error for i, f in enumerate(filters[:-1]): @@ -481,12 +486,11 @@ class Tally(object): 'Python API'.format(f, self.id) raise ValueError(msg) - self._filters = filters + self._filters = cv.CheckedList(_FILTER_CLASSES, 'tally filters', filters) @nuclides.setter def nuclides(self, nuclides): - cv.check_type('tally nuclides', nuclides, MutableSequence, - (basestring, Nuclide, CrossNuclide, AggregateNuclide)) + cv.check_type('tally nuclides', nuclides, MutableSequence) # If the nuclide is already in the Tally, raise an error for i, nuclide in enumerate(nuclides[:-1]): @@ -496,12 +500,12 @@ class Tally(object): 'Python API'.format(nuclide, self.id) raise ValueError(msg) - self._nuclides = nuclides + self._nuclides = cv.CheckedList(_NUCLIDE_CLASSES, 'tally nuclides', + nuclides) @scores.setter def scores(self, scores): - cv.check_type('tally scores', scores, MutableSequence, - (basestring, CrossScore, AggregateScore)) + cv.check_type('tally scores', scores, MutableSequence) for i, score in enumerate(scores[:-1]): # If the score is already in the Tally, raise an error @@ -515,7 +519,7 @@ class Tally(object): if isinstance(score, basestring): scores[i] = score.strip() - self._scores = scores + self._scores = cv.CheckedList(_SCORE_CLASSES, 'tally scores', scores) def add_filter(self, new_filter): """Add a filter to the tally From 809eff970a85ae8ae2ae286a6217a28015893880 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Wed, 9 Mar 2016 08:25:47 -0600 Subject: [PATCH 08/11] Respond to @wbinventor comments on #593 --- .../pythonapi/examples/tally-arithmetic.ipynb | 12 ++--- openmc/mgxs/mgxs.py | 6 +-- openmc/tallies.py | 48 +++++++++---------- 3 files changed, 33 insertions(+), 33 deletions(-) diff --git a/docs/source/pythonapi/examples/tally-arithmetic.ipynb b/docs/source/pythonapi/examples/tally-arithmetic.ipynb index d1325e4878..bbadd1ac4d 100644 --- a/docs/source/pythonapi/examples/tally-arithmetic.ipynb +++ b/docs/source/pythonapi/examples/tally-arithmetic.ipynb @@ -418,15 +418,15 @@ "\n", "# Instantiate flux Tally in moderator and fuel\n", "tally = openmc.Tally(name='flux')\n", - "tally.filters = [openmc.Filter(type='cell', bins=[fuel_cell.id, moderator_cell.id]),\n", - " energy_filter]\n", + "tally.filters = [openmc.Filter(type='cell', bins=[fuel_cell.id, moderator_cell.id])]\n", + "tally.filters.append(energy_filter)\n", "tally.scores = ['flux']\n", "tallies_file.add_tally(tally)\n", "\n", "# Instantiate reaction rate Tally in fuel\n", "tally = openmc.Tally(name='fuel rxn rates')\n", - "tally.filters = [openmc.Filter(type='cell', bins=[fuel_cell.id]),\n", - " energy_filter]\n", + "tally.filters = [openmc.Filter(type='cell', bins=[fuel_cell.id])]\n", + "tally.filters.append(energy_filter)\n", "tally.scores = ['nu-fission', 'scatter']\n", "tally.nuclides = [u238, u235]\n", "tallies_file.add_tally(tally)\n", @@ -516,8 +516,8 @@ "\n", "# Instantiate flux Tally in moderator and fuel\n", "tally = openmc.Tally(name='need-to-slice')\n", - "tally.filters = [openmc.Filter(type='cell', bins=[fuel_cell.id, moderator_cell.id]),\n", - " energy_filter]\n", + "tally.filters = [openmc.Filter(type='cell', bins=[fuel_cell.id, moderator_cell.id])]\n", + "tally.filters.append(energy_filter)\n", "tally.scores = ['nu-fission', 'scatter']\n", "tally.nuclides = [h1, u238]\n", "tallies_file.add_tally(tally)" diff --git a/openmc/mgxs/mgxs.py b/openmc/mgxs/mgxs.py index ad987d70f1..68d34dce38 100644 --- a/openmc/mgxs/mgxs.py +++ b/openmc/mgxs/mgxs.py @@ -510,14 +510,14 @@ class MGXS(object): # Create each Tally needed to compute the multi group cross section for score, key, filters in zip(scores, keys, all_filters): self.tallies[key] = openmc.Tally(name=self.name) - self.tallies[key].scores.append(score) + self.tallies[key].scores = [score] self.tallies[key].estimator = estimator - self.tallies[key].filters.append(domain_filter) + self.tallies[key].filters = [domain_filter] # If a tally trigger was specified, add it to each tally if self.tally_trigger: trigger_clone = copy.deepcopy(self.tally_trigger) - trigger_clone.scores.append(score) + trigger_clone.scores = [score] self.tallies[key].triggers.append(trigger_clone) # Add all non-domain specific Filters (e.g., 'energy') to the Tally diff --git a/openmc/tallies.py b/openmc/tallies.py index 9d6ed4b7f1..d565121555 100644 --- a/openmc/tallies.py +++ b/openmc/tallies.py @@ -449,9 +449,9 @@ class Tally(object): """ - warnings.warn("Tally.add_trigger(...) has been deprecated and may be " - "removed in a future version. Tally triggers should be " - "defined using the triggers property directly.", + warnings.warn('Tally.add_trigger(...) has been deprecated and may be ' + 'removed in a future version. Tally triggers should be ' + 'defined using the triggers property directly.', DeprecationWarning) self.triggers.append(trigger) @@ -540,9 +540,9 @@ class Tally(object): """ - warnings.warn("Tally.add_filter(...) has been deprecated and may be " - "removed in a future version. Tally filters should be " - "defined using the filters property directly.", + warnings.warn('Tally.add_filter(...) has been deprecated and may be ' + 'removed in a future version. Tally filters should be ' + 'defined using the filters property directly.', DeprecationWarning) self.filters.append(new_filter) @@ -565,9 +565,9 @@ class Tally(object): """ - warnings.warn("Tally.add_nuclide(...) has been deprecated and may be " - "removed in a future version. Tally nuclides should be " - "defined using the nuclides property directly.", + warnings.warn('Tally.add_nuclide(...) has been deprecated and may be ' + 'removed in a future version. Tally nuclides should be ' + 'defined using the nuclides property directly.', DeprecationWarning) self.nuclides.append(nuclide) @@ -589,9 +589,9 @@ class Tally(object): """ - warnings.warn("Tally.add_score(...) has been deprecated and may be " - "removed in a future version. Tally scores should be " - "defined using the scores property directly.", + warnings.warn('Tally.add_score(...) has been deprecated and may be ' + 'removed in a future version. Tally scores should be ' + 'defined using the scores property directly.', DeprecationWarning) self.scores.append(score) @@ -2324,9 +2324,9 @@ class Tally(object): new_tally.with_summary = self.with_summary new_tally.num_realization = self.num_realizations - new_tally.filters = self.filters - new_tally.nuclides = self.nuclides - new_tally.scores = self.scores + new_tally.filters = copy.deepcopy(self.filters) + new_tally.nuclides = copy.deepcopy(self.nuclides) + new_tally.scores = copy.deepcopy(self.scores) # If this tally operand is sparse, sparsify the new tally new_tally.sparse = self.sparse @@ -2396,9 +2396,9 @@ class Tally(object): new_tally.with_summary = self.with_summary new_tally.num_realization = self.num_realizations - new_tally.filters = self.filters - new_tally.nuclides = self.nuclides - new_tally.scores = self.scores + new_tally.filters = copy.deepcopy(self.filters) + new_tally.nuclides = copy.deepcopy(self.nuclides) + new_tally.scores = copy.deepcopy(self.scores) # If this tally operand is sparse, sparsify the new tally new_tally.sparse = self.sparse @@ -2468,9 +2468,9 @@ class Tally(object): new_tally.with_summary = self.with_summary new_tally.num_realization = self.num_realizations - new_tally.filters = self.filters - new_tally.nuclides = self.nuclides - new_tally.scores = self.scores + new_tally.filters = copy.deepcopy(self.filters) + new_tally.nuclides = copy.deepcopy(self.nuclides) + new_tally.scores = copy.deepcopy(self.scores) # If this tally operand is sparse, sparsify the new tally new_tally.sparse = self.sparse @@ -2544,9 +2544,9 @@ class Tally(object): new_tally.with_summary = self.with_summary new_tally.num_realization = self.num_realizations - new_tally.filters = self.filters - new_tally.nuclides = self.nuclides - new_tally.scores = self.scores + new_tally.filters = copy.deepcopy(self.filters) + new_tally.nuclides = copy.deepcopy(self.nuclides) + new_tally.scores = copy.deepcopy(self.scores) # If original tally was sparse, sparsify the exponentiated tally new_tally.sparse = self.sparse From 0138f0c4a26f8c54809de51e30344ef15f1d8642 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Wed, 9 Mar 2016 08:47:14 -0600 Subject: [PATCH 09/11] Indicate minimum version of pandas in setup.py --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index 87fdff68cf..e66b0b7a0f 100644 --- a/setup.py +++ b/setup.py @@ -36,7 +36,7 @@ if have_setuptools: # Optional dependencies 'extras_require': { - 'pandas': ['pandas'], + 'pandas': ['pandas>=0.17.0'], 'sparse' : ['scipy'], 'vtk': ['vtk', 'silomesh'], 'validate': ['lxml'] From 7c2890baec4e3a873f45be54c9d89a3cb703ec64 Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Wed, 9 Mar 2016 08:50:38 -0600 Subject: [PATCH 10/11] Change a few double quotes to single quotes in openmc.trigger --- openmc/trigger.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/openmc/trigger.py b/openmc/trigger.py index ce7d432c2e..ad2e9d6814 100644 --- a/openmc/trigger.py +++ b/openmc/trigger.py @@ -117,9 +117,9 @@ class Trigger(object): """ - warnings.warn("Trigger.add_score(...) has been deprecated and may be " - "removed in a future version. Tally trigger scores should " - "be defined using the scores property directly.", + warnings.warn('Trigger.add_score(...) has been deprecated and may be ' + 'removed in a future version. Tally trigger scores should ' + 'be defined using the scores property directly.', DeprecationWarning) self.scores.append(score) From ff49b0eaac50038c4faf79b3209516b3262b442d Mon Sep 17 00:00:00 2001 From: Paul Romano Date: Wed, 9 Mar 2016 08:53:22 -0600 Subject: [PATCH 11/11] deepcopy some more filters, scores, nuclides --- openmc/tallies.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/openmc/tallies.py b/openmc/tallies.py index 73a69bbcf8..1e47811e34 100644 --- a/openmc/tallies.py +++ b/openmc/tallies.py @@ -2504,9 +2504,9 @@ class Tally(object): new_tally.with_summary = self.with_summary new_tally.num_realization = self.num_realizations - new_tally.filters = self.filters - new_tally.nuclides = self.nuclides - new_tally.scores = self.scores + new_tally.filters = copy.deepcopy(self.filters) + new_tally.nuclides = copy.deepcopy(self.nuclides) + new_tally.scores = copy.deepcopy(self.scores) # If this tally operand is sparse, sparsify the new tally new_tally.sparse = self.sparse