Beispiel #1
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
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