Beispiel #1
0
 def __init__(self, mesh, partition):
     # First reorder the mesh, so partitions are no longer distributed
     self.__partitionStart = []
     sum = 0
     for i in range(len(partition)):
         self.__partitionStart.append(sum)
         sum += partition.size(i)
     
     nextPos = copy.copy(self.__partitionStart)
     old2new = []
     for p in partition:
         old2new.append(nextPos[p])
         nextPos[p] += 1
         
     self.__mesh = ReorderedMesh(mesh, old2new)
     self.__partition = ReorderedPartition(partition, old2new)
     
     self.__old2new = [None] * len(self.__mesh.elements())
     
     # Run Zoltan for every partition
     for p in range(len(partition)):
         self.__zoltanError = ''
         try:
             zoltan = subprocess.Popen(['mpiexec', '-n', '1',
                     os.path.join(os.path.dirname(__file__), 'zoltan', 'zoltan'),
                     str(partition.size(p))],
                 stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
         except OSError:
             raise Exception('Could not run mpiexec. Please provide correct $PATH')
     
         threading.Thread(target=self.__feedElements, args=(zoltan.stdin, p)).start()
         outThread = threading.Thread(target=self.__readZoltanOrder, args=(zoltan.stdout, p))
         outThread.start()
         errorThread = threading.Thread(target=self.__readZoltanError, args=(zoltan.stderr,))
         errorThread.start()
     
         if zoltan.wait():
             errorThread.join()
             raise Exception(self.__zoltanError.strip())
     
         outThread.join()
         errorThread.join()
     
     # Create the reordered mesh
     self.__mesh = ReorderedMesh(self.__mesh, self.__old2new)
Beispiel #2
0
class Reorderer:
    """Reorders a partitioned mesh using Zoltan"""
    
    def __init__(self, mesh, partition):
        # First reorder the mesh, so partitions are no longer distributed
        self.__partitionStart = []
        sum = 0
        for i in range(len(partition)):
            self.__partitionStart.append(sum)
            sum += partition.size(i)
        
        nextPos = copy.copy(self.__partitionStart)
        old2new = []
        for p in partition:
            old2new.append(nextPos[p])
            nextPos[p] += 1
            
        self.__mesh = ReorderedMesh(mesh, old2new)
        self.__partition = ReorderedPartition(partition, old2new)
        
        self.__old2new = [None] * len(self.__mesh.elements())
        
        # Run Zoltan for every partition
        for p in range(len(partition)):
            self.__zoltanError = ''
            try:
                zoltan = subprocess.Popen(['mpiexec', '-n', '1',
                        os.path.join(os.path.dirname(__file__), 'zoltan', 'zoltan'),
                        str(partition.size(p))],
                    stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
            except OSError:
                raise Exception('Could not run mpiexec. Please provide correct $PATH')
        
            threading.Thread(target=self.__feedElements, args=(zoltan.stdin, p)).start()
            outThread = threading.Thread(target=self.__readZoltanOrder, args=(zoltan.stdout, p))
            outThread.start()
            errorThread = threading.Thread(target=self.__readZoltanError, args=(zoltan.stderr,))
            errorThread.start()
        
            if zoltan.wait():
                errorThread.join()
                raise Exception(self.__zoltanError.strip())
        
            outThread.join()
            errorThread.join()
        
        # Create the reordered mesh
        self.__mesh = ReorderedMesh(self.__mesh, self.__old2new)
        
    def __feedElements(self, stdin, partition):
        """Writes the element coordinates to stdin of the zoltan process"""
        
        for element in self.__mesh.elements()[self.__partitionStart[partition]:
                self.__partitionStart[partition]+self.__partition.size(partition)]:
            coords = [sum(c) / 4 for c in zip(self.__mesh.coords()[element[0]],
                self.__mesh.coords()[element[1]], self.__mesh.coords()[element[2]],
                self.__mesh.coords()[element[3]])]
            try:
                print >> stdin, coords[0], coords[1], coords[2]
            except IOError:
                # Something went wrong, zoltan should report an error to stderr
                break
            
    def __readZoltanOrder(self, stdout, partition):
        """Reads the Zoltan stdout stream and creates the ordering"""
        
        for line in stdout:
            try:
                new, old = map(int, line.split())
                self.__old2new[old+self.__partitionStart[partition]] = new+self.__partitionStart[partition]
            except Exception:
                # Something went wrong, we check for inconsistent values later
                pass
            
    def __readZoltanError(self, stderr):
        """Reads the Zoltan error stream"""
        
        for line in stderr:
            self.__zoltanError += line + os.linesep
        
    def mesh(self):
        return self.__mesh
    
    def partition(self):
        return self.__partition