Repository: openmc-dev/openmc

Issue:
Remove unnecessary tally data from summary.h5
The tally data in summary.h5 is mostly redundant.  The only significant pieces of data that could not be found in statepoint.h5 are tally names and distribcell paths.  With this PR, only names are stored in the `tallies` group of summary.h5.  The distribcell paths are now stored on the cells.  This has the nice benefit that you can now get distribcell paths for your cells that use distribmats but do not appear in a distribcell filter.



Discussion:

Resolving patch:
diff --git a/openmc/cell.py b/openmc/cell.py
--- a/openmc/cell.py
+++ b/openmc/cell.py
@@ -85,6 +85,9 @@ class Cell(object):
         Array of offsets used for distributed cell searches
     distribcell_index : int
         Index of this cell in distribcell arrays
+    distribcell_paths : list of str
+        The paths traversed through the CSG tree to reach each distribcell
+        instance
     volume_information : dict
         Estimate of the volume and total number of atoms of each nuclide from a
         stochastic volume calculation. This information is set with the
@@ -104,6 +107,7 @@ def __init__(self, cell_id=None, name='', fill=None, region=None):
         self._translation = None
         self._offsets = None
         self._distribcell_index = None
+        self._distribcell_paths = None
         self._volume_information = None
 
     def __contains__(self, point):
@@ -217,6 +221,10 @@ def offsets(self):
     def distribcell_index(self):
         return self._distribcell_index
 
+    @property
+    def distribcell_paths(self):
+        return self._distribcell_paths
+
     @property
     def volume_information(self):
         return self._volume_information
@@ -316,6 +324,12 @@ def distribcell_index(self, ind):
         cv.check_type('distribcell index', ind, Integral)
         self._distribcell_index = ind
 
+    @distribcell_paths.setter
+    def distribcell_paths(self, distribcell_paths):
+        cv.check_iterable_type('distribcell_paths', distribcell_paths,
+                               basestring)
+        self._distribcell_paths = distribcell_paths
+
     def add_surface(self, surface, halfspace):
         """Add a half-space to the list of half-spaces whose intersection defines the
         cell.
diff --git a/openmc/statepoint.py b/openmc/statepoint.py
--- a/openmc/statepoint.py
+++ b/openmc/statepoint.py
@@ -691,19 +691,10 @@ def link_with_summary(self, summary):
             raise ValueError(msg)
 
         for tally_id, tally in self.tallies.items():
-            summary_tally = summary.tallies[tally_id]
-            tally.name = summary_tally.name
+            tally.name = summary.tally_names[tally_id]
             tally.with_summary = True
 
             for tally_filter in tally.filters:
-                summary_filter = summary_tally.find_filter(tally_filter.type)
-
-                if tally_filter.type == 'surface':
-                    surface_ids = []
-                    for bin in tally_filter.bins:
-                        surface_ids.append(bin)
-                    tally_filter.bins = surface_ids
-
                 if tally_filter.type in ['cell', 'distribcell']:
                     distribcell_ids = []
                     for bin in tally_filter.bins:
@@ -711,8 +702,9 @@ def link_with_summary(self, summary):
                     tally_filter.bins = distribcell_ids
 
                 if tally_filter.type == 'distribcell':
-                    tally_filter.distribcell_paths = \
-                        summary_filter.distribcell_paths
+                    cell_id = tally_filter.bins[0]
+                    cell = summary.get_cell_by_id(cell_id)
+                    tally_filter.distribcell_paths = cell.distribcell_paths
 
                 if tally_filter.type == 'universe':
                     universe_ids = []
diff --git a/openmc/summary.py b/openmc/summary.py
--- a/openmc/summary.py
+++ b/openmc/summary.py
@@ -297,10 +297,13 @@ def _read_cells(self):
                 cell.region = Region.from_expression(
                     region, {s.id: s for s in self.surfaces.values()})
 
-            # Get the distribcell index
-            ind = self._f['geometry/cells'][key]['distribcell_index'].value
-            if ind != 0:
+            # Get the distribcell data
+            if 'distribcell_index' in self._f['geometry/cells'][key]:
+                ind = self._f['geometry/cells'][key]['distribcell_index'].value
                 cell.distribcell_index = ind
+                paths = self._f['geometry/cells'][key]['paths'][...]
+                paths = [str(path.decode()) for path in paths]
+                cell.distribcell_paths = paths
 
             # Add the Cell to the global dictionary of all Cells
             self.cells[index] = cell
@@ -520,18 +523,15 @@ def _finalize_geometry(self):
         self.openmc_geometry.root_universe = root_universe
 
     def _read_tallies(self):
-        # Initialize dictionaries for the Tallies
+        # Initialize a dictionary for the tally names
         # Keys     - Tally IDs
-        # Values   - Tally objects
-        self.tallies = {}
+        # Values   - Tally names
+        self.tally_names = {}
 
         # Read the number of tallies
         if 'tallies' not in self._f:
-            self.n_tallies = 0
             return
 
-        self.n_tallies = self._f['tallies/n_tallies'].value
-
         # OpenMC Tally keys
         all_keys = self._f['tallies/'].keys()
         tally_keys = [key for key in all_keys if 'tally' in key]
@@ -545,52 +545,7 @@ def _read_tallies(self):
 
             # Read Tally name metadata
             tally_name = self._f['{0}/name'.format(subbase)].value.decode()
-
-            # Create Tally object and assign basic properties
-            tally = openmc.Tally(tally_id, tally_name)
-
-            # Read scattering moment order strings (e.g., P3, Y1,2, etc.)
-            moments = self._f['{0}/moment_orders'.format(subbase)].value
-
-            # Read score metadata
-            scores = self._f['{0}/score_bins'.format(subbase)].value
-            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.scores.append(score)
-
-            # Read filter metadata
-            num_filters = self._f['{0}/n_filters'.format(subbase)].value
-
-            # Initialize all Filters
-            for j in range(1, num_filters+1):
-                subsubbase = '{0}/filter {1}'.format(subbase, j)
-
-                # Read filter type (e.g., "cell", "energy", etc.)
-                filter_type = self._f['{0}/type'.format(subsubbase)].value.decode()
-
-                # Read the filter bins
-                num_bins = self._f['{0}/n_bins'.format(subsubbase)].value
-                bins = self._f['{0}/bins'.format(subsubbase)][...]
-
-                # Create Filter object
-                new_filter = openmc.Filter(filter_type, bins)
-                new_filter.num_bins = num_bins
-
-                # Read in distribcell paths
-                if filter_type == 'distribcell':
-                    paths = self._f['{0}/paths'.format(subsubbase)][...]
-                    paths = [str(path.decode()) for path in paths]
-                    new_filter.distribcell_paths = paths
-
-                # Add Filter to the Tally
-                tally.filters.append(new_filter)
-
-            # Add Tally to the global dictionary of all Tallies
-            self.tallies[tally_id] = tally
+            self.tally_names[tally_id] = tally_name
 
     def add_volume_information(self, volume_calc):
         """Add volume information to the geometry within the summary file


Test patch: