Ejemplo n.º 1
0
def collect_pieces(skel):
    global _rank
    global _size
    # Gather minimal info for element polygons (to display Skeleton at #0)
    # Only the #0 will store the gathered information.
    # no. of nodes & no. of elements
    nnodes = mpitools.Allgather_Int(skel.nnodes())
    #RCL: Use maxnnodes as base offset for the indices of non-corner mesh nodes
    skel.maxnnodes = max(nnodes)
    nelems = mpitools.Allgather_Int(skel.nelements())
    myCoords = list(
        reduce(
        lambda x,y: x+y, [(skel.nodePosition(nd)[0],
                           skel.nodePosition(nd)[1])
                          for nd in skel.node_iterator()]
        ))

    coordSizes = [i*2 for i in nnodes]
    allCoords = mpitools.Allgather_DoubleVec(myCoords,
                                             size_known=coordSizes)
    # allCoords = [[(x0,y0),(x1,y1), ...], [...], ...]
    allCoords = [ [(allCoords[i][2*j],allCoords[i][2*j+1])
                   for j in range(nnodes[i])]
                  for i in range(_size) ]
    # element connectivity signature
    myEConSigs = [el.nnodes() for el in skel.element_iterator()]
    allEConSigs = mpitools.Allgather_IntVec(myEConSigs, size_known=nelems)
    # element connectivity
    myECons = [ [skel.node_index_dict[nd.getIndex()] for nd in el.nodes]
                for el in skel.element_iterator()]
    myECons = reduce(lambda x,y: x+y, myECons)
    conSizes = [reduce(lambda x,y: x+y, aECS) for aECS in allEConSigs]
    temp = mpitools.Allgather_IntVec(myECons, size_known=conSizes)

    def listrize(list, signature):
        nsig = len(signature)
        count = 0
        output = [[] for i in range(nsig)]
        for i in range(nsig):
            for j in range(signature[i]):
                output[i].append(list[count])
                count += 1
        return output

    allECons = [listrize(temp[i], allEConSigs[i]) for i in range(_size)]
    if _rank == 0:
        skel.all_skeletons = {"nodes": allCoords,
                              "elements": allECons}
Ejemplo n.º 2
0
    def createWorkOrder(self, activeNodes):
        global _rank
        global _size

        # First the data collection
        nnodes = mpitools.Allgather_Int(len(activeNodes))
        allnodes = mpitools.Allgather_IntVec(
            [n.getIndex() for n in activeNodes], size_known=nnodes)
        allsignatures = mpitools.Allgather_IntVec(
            [n.nshared() for n in activeNodes], size_known=nnodes)
        nshared = [reduce(lambda x, y: x + y, s) for s in allsignatures]
        myshared = [n.sharedWith() for n in activeNodes]
        myshared = reduce(lambda x, y: x + y, myshared)
        allshared = mpitools.Allgather_IntVec(myshared, size_known=nshared)

        def listrize(list, signature):
            nsig = len(signature)
            count = 0
            output = [[] for i in range(nsig)]
            for i in range(nsig):
                for j in range(signature[i]):
                    output[i].append(list[count])
                    count += 1
            return output

        for i in range(len(allshared)):
            allshared[i] = listrize(allshared[i], allsignatures[i])

        scheduler = Scheduler(nnodes, allnodes, allshared, self)
        self.mywork = scheduler(_rank)
Ejemplo n.º 3
0
def collect_pieces(femesh):

    # Build dictionary (instead of using the mesh assigned indices (via index() or get_index())
    #  which are unique but may have gaps)
    nodedict = {}
    i = 0
    for node in femesh.node_iterator():
        nodedict[node.index()] = i
        i += 1

    global _rank
    global _size
    # Gather minimal info for element polygons (to display mesh Skeleton at #0)
    # Only the #0 will store the reconstituted information.

    #RCL: Collect number of nodes from each process into an array.
    # One gets this for nnodes: [nnodes0, nnodes1, ...]
    nnodes = mpitools.Allgather_Int(femesh.nnodes())

    #RCL: Same for the elements.
    # One gets this for nelems: [nelems0, nelems1, ...]
    nelems = mpitools.Allgather_Int(femesh.nelements())
    myCoords = reduce(lambda x, y: x + y,
                      [[nd.position().x, nd.position().y]
                       for nd in femesh.node_iterator()])

    coordSizes = [i * 2 for i in nnodes]
    #RCL: Collect (x,y) coordinates of nodes from each process
    # coordSizes contains the array of number of coordinates (counting x and y separately) from each process
    # The return value is a 2-D array, indexed first by the process number(?)
    # One gets this for allCoords: [[x0,y0,x1,y1,...], [x0',y0',x1',y1',...], ...]
    allCoords = mpitools.Allgather_DoubleVec(myCoords, size_known=coordSizes)

    #RCL: One gets the following format after the list comprehension operations
    # allCoords = [[(x0,y0),(x1,y1), ...], [...], ...]
    allCoords = [[(allCoords[i][2 * j], allCoords[i][2 * j + 1])
                  for j in range(nnodes[i])] for i in range(_size)]

    # element connectivity signature
    myEConSigs = [len(el.perimeter()) for el in femesh.element_iterator()]
    #RCL: One gets this for allEConSigs: [[elnnodes0,elnnodes1,...],[elnnodes0',elnnodes1',...],...]
    allEConSigs = mpitools.Allgather_IntVec(myEConSigs, size_known=nelems)

    # element connectivity
    #RCL: nodedict must be a map to the 0-based indices of the nodes
    myECons = [[nodedict[nd.index()] for nd in el.node_iterator()]
               for el in femesh.element_iterator()]
    myECons = reduce(lambda x, y: x + y, myECons)

    #RCL: conSizes looks like [[elnnodes0+elnnodes1+...],[elnnodes0'+elnnodes1'+...],...]
    conSizes = [reduce(lambda x, y: x + y, aECS) for aECS in allEConSigs]

    #RCL: temp looks like
    # [[el0_nodeindex1,el0_nodeindex2,...el1_nodeindex1,el1_nodeindex2,...],[el0'_nodeindex1,el0'_nodeindex2,...,el1'_nodeindex1,el1'_nodeindex2,...],...]
    temp = mpitools.Allgather_IntVec(myECons, size_known=conSizes)

    #RCL: The connectivity information could still be shrunk, but its hard...
    # If we store the nodes for each element, duplicate nodes results. Storage becomes ~4*(number of (double x and double y))

    def listrize(list, signature):
        #RCL: nsig is the number of elements if allEConsigs[i] is passed as signature
        nsig = len(signature)
        count = 0
        output = [[] for i in range(nsig)]
        for i in range(nsig):
            for j in range(signature[i]):
                output[i].append(list[count])
                count += 1
        return output

    #RCL: allECons looks like [[[nodeindex1,nodeindex2,...],[nodeindex1',nodeindex2',...],...], [], ...]
    allECons = [listrize(temp[i], allEConSigs[i]) for i in range(_size)]
    if _rank == 0:
        femesh.all_meshskeletons = {"nodes": allCoords, "elements": allECons}
Ejemplo n.º 4
0
def _refinement(self, skeleton, newSkeleton, context):
    global _rank
    if _rank == 0:
        pBar = progressbar.getProgress()

    markedEdges = refine.EdgeMarkings()
    self.newEdgeNodes = {}  # allows sharing of new edge nodes

    # Primary marking
    self.targets(skeleton, context, self.degree.divisions, markedEdges,
                 self.criterion)
    # Additional marking -- only for (conservative) bisection at this point.
    self.degree.markExtras(skeleton, markedEdges)

    # Now, share the marking information on the boundary
    shareMarkings(markedEdges, skeleton)

    # Refine elements and segments
    segmentdict = {}  # which segments have been handled already.
    elements = skeleton.elements

    # At this point, to properly update progress bar, every process has
    # loop over the same range(maxn).
    # TODO: Is progress bar not supposed to work within IPC call?
    n = len(elements)
    alln = mpitools.Allgather_Int(n)
    maxn = max(alln)
    nelem = 0
    ntotal = reduce(lambda x, y: x + y, alln)
    for ii in range(maxn):
        try:
            oldElement = elements[ii]
            count = 1

            oldnnodes = oldElement.nnodes()
            # Get list of number of subdivisions on each edge ("marks")
            marks = markedEdges.getMarks(oldElement)
            # Find the canonical order for the marks. (The order is
            # ambiguous due to the arbitrary choice of the starting
            # edge.  Finding the canonical order allows the refinement
            # rule to be found in the rule table.)  rotation is the
            # offset into the elements node list required to match the
            # refinement rule to the element's marked edges.
            # signature is the canonical ordering of the marks.
            rotation, signature = refine.findSignature(marks)
            # Create new nodes along the subdivided element edges
            edgenodes = [
                self.getNewEdgeNodes(oldElement.nodes[i],
                                     oldElement.nodes[(i + 1) % oldnnodes],
                                     marks[i], newSkeleton, skeleton)
                for i in range(oldnnodes)
            ]
            # Create new elements
            newElements = self.rules[signature].apply(oldElement, rotation,
                                                      edgenodes, newSkeleton,
                                                      self.alpha)
            # If the old element's homogeneity is "1", it's safe to say that
            # new elements' homogeneities are "1".
            if oldElement.homogeneity(skeleton.MS) == 1.:
                for el in newElements:
                    el.copyHomogeneity(oldElement)

            # The calls to Skeleton.newElement() made by the
            # refinement rules have created new SkeletonSegments in
            # newSkeleton, but have not set the parentage of those
            # segments.  We have to fix that here.
            for newElement in newElements:
                for segment in newElement.getSegments(newSkeleton):
                    # Only look at each segment once.
                    if not segmentdict.has_key(segment):
                        segmentdict[segment] = 1
                        pseg = refine.findParentSegment(
                            skeleton, newElement, segment, edgenodes)
                        if pseg:
                            pseg.add_child(segment)
                            segment.add_parent(pseg)

        except IndexError:
            count = 0

        # No. of elements done.
        nelem_step = mpitools.Allgather_Int(count)
        nelem += reduce(lambda x, y: x + y, nelem_step)
        if _rank == 0:
            if pBar.query_stop():
                pBar.set_failure()
                pBar.set_message("Failed")
                mpitools.Isend_Bool(False, range(1, _size))
                return None
            else:
                pBar.set_progress(1.0 * (nelem) / ntotal)
                pBar.set_message("refining skeleton: %d/%d" % (nelem, ntotal))
                mpitools.Isend_Bool(True, range(1, _size))
        else:
            if not mpitools.Recv_Bool(0):
                return

    # New nodes that are created from the segments that are shared,
    # have to be informed bertween sharers.
    shareCommonNodes(self, markedEdges, skeleton, newSkeleton)
    # Collecting Skeletons
    skeletonIPC.collect_pieces(newSkeleton)

    newSkeleton.cleanUp()
    ##    report_skeleton(newSkeleton)
    ##    if _rank == 0:
    ##        debug.fmsg(newSkeleton.all_skeletons)
    return newSkeleton