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}
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)
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}
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