From 4b654c2be0f7f9447f3363662e911f1ab1f2faad Mon Sep 17 00:00:00 2001 From: Patrick Shriwise Date: Tue, 5 Mar 2019 10:21:11 -0600 Subject: [PATCH] Moving to memoization pattern instead of singleton class. --- openmc/cell.py | 25 ++++++++++++------------ openmc/geometry.py | 10 +++++----- openmc/geomtrack.py | 46 --------------------------------------------- openmc/lattice.py | 36 ++++++++++++++++------------------- openmc/universe.py | 22 +++++++++++----------- 5 files changed, 44 insertions(+), 95 deletions(-) delete mode 100644 openmc/geomtrack.py diff --git a/openmc/cell.py b/openmc/cell.py index dd3d22ed15..36f772ff50 100644 --- a/openmc/cell.py +++ b/openmc/cell.py @@ -16,8 +16,6 @@ from openmc.region import Region, Intersection, Complement from openmc._xml import get_text from .mixin import IDManagerMixin -from .geomtrack import ElementTracker - class Cell(IDManagerMixin): r"""A region of space defined as the intersection of half-space created by quadric surfaces. @@ -464,8 +462,8 @@ class Cell(IDManagerMixin): return memo[self] - def create_xml_subelement(self, xml_element): - et = ElementTracker() + def create_xml_subelement(self, xml_element, memo=None): + element = ET.Element("cell") element.set("id", str(self.id)) @@ -484,7 +482,7 @@ class Cell(IDManagerMixin): elif self.fill_type in ('universe', 'lattice'): element.set("fill", str(self.fill.id)) - self.fill.create_xml_subelement(xml_element) + self.fill.create_xml_subelement(xml_element, memo) if self.region is not None: # Set the region attribute with the region specification @@ -500,22 +498,23 @@ class Cell(IDManagerMixin): # tree. When it reaches a leaf (a Halfspace), it creates a # element for the corresponding surface if none has been created # thus far. - def create_surface_elements(node, element): - et = ElementTracker() + def create_surface_elements(node, element, memo=None): if isinstance(node, Halfspace): path = "./surface[@id='{}']".format(node.surface.id) - if node.surface.id not in et.surfaces: - et.add_surface(node.surface.id) - xml_element.append(node.surface.to_xml_element()) + if memo and node.surface.id in memo['surfaces']: + return + if memo: + memo['surfaces'].add(node.surface.id) + xml_element.append(node.surface.to_xml_element()) elif isinstance(node, Complement): - create_surface_elements(node.node, element) + create_surface_elements(node.node, element, memo) else: for subnode in node: - create_surface_elements(subnode, element) + create_surface_elements(subnode, element, memo) # Call the recursive function from the top node - create_surface_elements(self.region, xml_element) + create_surface_elements(self.region, xml_element, memo) if self.temperature is not None: if isinstance(self.temperature, Iterable): diff --git a/openmc/geometry.py b/openmc/geometry.py index 61032d9a80..28fcb3fc0c 100644 --- a/openmc/geometry.py +++ b/openmc/geometry.py @@ -10,8 +10,6 @@ import openmc import openmc._xml as xml from openmc.checkvalue import check_type -from .geomtrack import ElementTracker - class Geometry(object): """Geometry representing a collection of surfaces, cells, and universes. @@ -89,11 +87,13 @@ class Geometry(object): """ # Create XML representation - et = ElementTracker() - et.reset() + memo = {'cells' : set(), + 'surfaces' : set(), + 'lattices' : set(), + 'universes' : set()} root_element = ET.Element("geometry") - self.root_universe.create_xml_subelement(root_element) + self.root_universe.create_xml_subelement(root_element, memo) # Sort the elements in the file root_element[:] = sorted(root_element, key=lambda x: ( diff --git a/openmc/geomtrack.py b/openmc/geomtrack.py deleted file mode 100644 index f2230ce7d3..0000000000 --- a/openmc/geomtrack.py +++ /dev/null @@ -1,46 +0,0 @@ - -class ElementTracker: - class __ElementTracker: - def __init__(self): - self.cells = set() - self.surfaces = set() - self.lattices = set() - self.universes = set() - - def update(self, element_type, element_id): - if element_type == "cell": - self.cells.add(element_id) - elif element_type == "surface": - self.surfaces.add(element_id) - elif element_type == "lattice": - self.lattices.add(element_id) - elif element_type == "universe": - self.universes.add(element_id) - - def add_cell(self, cell_id): - self.update("cell", cell_id) - - def add_surface(self, surface_id): - self.update("surface", surface_id) - - def add_lattice(self, lattice_id): - self.update("lattice", lattice_id) - - def add_universe(self, universe_id): - self.update("universe", universe_id) - - def reset(self): - self.cells = set() - self.surfaces = set() - self.lattices = set() - self.universes = set() - - instance = None - - def __init__(self): - if not ElementTracker.instance: - ElementTracker.instance = ElementTracker.__ElementTracker() - else: - pass - def __getattr__(self, name): - return getattr(self.instance, name) diff --git a/openmc/lattice.py b/openmc/lattice.py index c1ce4c6a22..985fec86e0 100644 --- a/openmc/lattice.py +++ b/openmc/lattice.py @@ -13,8 +13,6 @@ import openmc from openmc._xml import get_text from openmc.mixin import IDManagerMixin -from .geomtrack import ElementTracker - class Lattice(IDManagerMixin, metaclass=ABCMeta): """A repeating structure wherein each element is a universe. @@ -754,17 +752,16 @@ class RectLattice(Lattice): 0 <= idx[1] < self.shape[1] and 0 <= idx[2] < self.shape[2]) - def create_xml_subelement(self, xml_element): - et = ElementTracker() + def create_xml_subelement(self, xml_element, memo=None): # Determine if XML element already contains subelement for this Lattice path = './lattice[@id=\'{0}\']'.format(self._id) test = xml_element.find(path) # If the element does contain the Lattice subelement, then return - if self._id in et.lattices: + if memo and self._id in memo['lattices']: return - else: - et.add_lattice(self._id) + if memo: + memo['lattices'].add(self._id) lattice_subelement = ET.Element("lattice") lattice_subelement.set("id", str(self._id)) @@ -780,7 +777,7 @@ class RectLattice(Lattice): if self._outer is not None: outer = ET.SubElement(lattice_subelement, "outer") outer.text = '{0}'.format(self._outer._id) - self._outer.create_xml_subelement(xml_element) + self._outer.create_xml_subelement(xml_element, memo) # Export Lattice cell dimensions dimension = ET.SubElement(lattice_subelement, "dimension") @@ -804,7 +801,7 @@ class RectLattice(Lattice): universe_ids += '{0} '.format(universe._id) # Create XML subelement for this Universe - universe.create_xml_subelement(xml_element) + universe.create_xml_subelement(xml_element, memo) # Add newline character when we reach end of row of cells universe_ids += '\n' @@ -822,7 +819,7 @@ class RectLattice(Lattice): universe_ids += '{0} '.format(universe._id) # Create XML subelement for this Universe - universe.create_xml_subelement(xml_element) + universe.create_xml_subelement(xml_element, memo) # Add newline character when we reach end of row of cells universe_ids += '\n' @@ -1277,17 +1274,16 @@ class HexLattice(Lattice): else: return g < self.num_rings and 0 <= idx[2] < self.num_axial - def create_xml_subelement(self, xml_element): - et = ElementTracker() + def create_xml_subelement(self, xml_element, memo=None): # Determine if XML element already contains subelement for this Lattice path = './hex_lattice[@id=\'{0}\']'.format(self._id) test = xml_element.find(path) # If the element does contain the Lattice subelement, then return - if self._id in et.lattices: + if memo and self._id in memo['lattices']: return - else: - et.add_lattice(self._id) + if memo: + memo['lattices'].add(self._id) lattice_subelement = ET.Element("hex_lattice") lattice_subelement.set("id", str(self._id)) @@ -1303,7 +1299,7 @@ class HexLattice(Lattice): if self._outer is not None: outer = ET.SubElement(lattice_subelement, "outer") outer.text = '{0}'.format(self._outer._id) - self._outer.create_xml_subelement(xml_element) + self._outer.create_xml_subelement(xml_element, memo) lattice_subelement.set("n_rings", str(self._num_rings)) # If orientation is "x" export it to XML @@ -1325,13 +1321,13 @@ class HexLattice(Lattice): for z in range(self._num_axial): # Initialize the center universe. universe = self._universes[z][-1][0] - universe.create_xml_subelement(xml_element) + universe.create_xml_subelement(xml_element, memo) # Initialize the remaining universes. for r in range(self._num_rings-1): for theta in range(6*(self._num_rings - 1 - r)): universe = self._universes[z][r][theta] - universe.create_xml_subelement(xml_element) + universe.create_xml_subelement(xml_element, memo) # Get a string representation of the universe IDs. slices.append(self._repr_axial_slice(self._universes[z])) @@ -1343,13 +1339,13 @@ class HexLattice(Lattice): else: # Initialize the center universe. universe = self._universes[-1][0] - universe.create_xml_subelement(xml_element) + universe.create_xml_subelement(xml_element, memo) # Initialize the remaining universes. for r in range(self._num_rings - 1): for theta in range(6*(self._num_rings - 1 - r)): universe = self._universes[r][theta] - universe.create_xml_subelement(xml_element) + universe.create_xml_subelement(xml_element, memo) # Get a string representation of the universe IDs. universe_ids = self._repr_axial_slice(self._universes) diff --git a/openmc/universe.py b/openmc/universe.py index 876883cea0..7a9411ecf3 100644 --- a/openmc/universe.py +++ b/openmc/universe.py @@ -12,8 +12,6 @@ import openmc.checkvalue as cv from openmc.plots import _SVG_COLORS from openmc.mixin import IDManagerMixin -from .geomtrack import ElementTracker - class Universe(IDManagerMixin): """A collection of cells that can be repeated. @@ -513,21 +511,23 @@ class Universe(IDManagerMixin): return memo[self] - def create_xml_subelement(self, xml_element): - et = ElementTracker() + def create_xml_subelement(self, xml_element, memo=None): # Iterate over all Cells for cell_id, cell in self._cells.items(): path = "./cell[@id='{}']".format(cell_id) # If the cell was not already written, write it - if cell_id not in et.cells: - et.add_cell(cell_id) - # Create XML subelement for this Cell - cell_element = cell.create_xml_subelement(xml_element) + if memo and cell_id in memo['cells']: + continue + if memo: + memo['cells'].add(cell_id) - # Append the Universe ID to the subelement and add to Element - cell_element.set("universe", str(self._id)) - xml_element.append(cell_element) + # Create XML subelement for this Cell + cell_element = cell.create_xml_subelement(xml_element, memo) + + # Append the Universe ID to the subelement and add to Element + cell_element.set("universe", str(self._id)) + xml_element.append(cell_element) def _determine_paths(self, path='', instances_only=False): """Count the number of instances for each cell in the universe, and