Actual source code: Distribution.hh
petsc-3.4.5 2014-06-29
1: #ifndef included_ALE_Distribution_hh
2: #define included_ALE_Distribution_hh
4: #ifndef included_ALE_Mesh_hh
5: #include <sieve/Mesh.hh>
6: #endif
8: #ifndef included_ALE_Completion_hh
9: #include <sieve/Completion.hh>
10: #endif
12: #ifndef included_ALE_SectionCompletion_hh
13: #include <sieve/SectionCompletion.hh>
14: #endif
16: // Attempt to unify all of the distribution mechanisms:
17: // one to many (distributeMesh)
18: // many to one (unifyMesh)
19: // many to many (Numbering)
20: // as well as things being distributed
21: // Section
22: // Sieve (This sends two sections, the points and cones)
23: // Numbering (Should be an integer section)
24: // Global Order (should be an integer section with extra methods)
25: //
26: // 0) Create the new object to hold the communicated data
27: //
28: // 1) Create Overlap
29: // There may be special ways to do this based upon what we know at the time
30: //
31: // 2) Create send and receive sections over the interface
32: // These have a flat topology now, consisting only of the overlap nodes
33: // We could make a full topology on the overlap (maybe it is necessary for higher order)
34: //
35: // 3) Communication section
36: // Create sizer sections on interface (uses constant sizer)
37: // Communicate sizes on interface (uses custom filler)
38: // Fill send section
39: // sendSection->startCommunication();
40: // recvSection->startCommunication();
41: // sendSection->endCommunication();
42: // recvSection->endCommunication();
43: //
44: // Create section on interface (uses previous sizer)
45: // Communicate values on interface (uses custom filler)
46: // Same stuff as above
47: //
48: // 4) Update new section with old local values (can be done in between the communication?)
49: // Loop over patches in new topology
50: // Loop over chart from patch in old atlas
51: // If this point is in the new sieve from patch
52: // Set to old fiber dimension
53: // Order and allocate new section
54: // Repeat loop, but update values
55: //
56: // 5) Update new section with old received values
57: // Loop over patches in discrete topology of receive section (these are ranks)
58: // Loop over base of discrete sieve (we should transform this to a chart to match above)
59: // Get new patch from overlap, or should the receive patches be <rank, patch>?
60: // Guaranteed to be in the new sieve from patch (but we could check anyway)
61: // Set to recevied fiber dimension
62: // Order and allocate new section
63: // Repeat loop, but update values
64: //
65: // 6) Synchronize PETSc tags (can I get around this?)
66: namespace ALE {
67: template<typename Mesh, typename Partitioner = ALE::Partitioner<> >
68: class DistributionNew {
69: public:
70: typedef Partitioner partitioner_type;
71: typedef typename Mesh::point_type point_type;
72: typedef OrientedPoint<point_type> oriented_point_type;
73: typedef typename Partitioner::part_type rank_type;
74: typedef ALE::ISection<rank_type, point_type> partition_type;
75: typedef ALE::Section<ALE::Pair<int, point_type>, point_type> cones_type;
76: typedef ALE::Section<ALE::Pair<int, point_type>, oriented_point_type> oriented_cones_type;
77: public:
78: template<typename Sieve, typename NewSieve, typename Renumbering, typename SendOverlap, typename RecvOverlap>
79: static Obj<cones_type> completeCones(const Obj<Sieve>& sieve, const Obj<NewSieve>& newSieve, Renumbering& renumbering, const Obj<SendOverlap>& sendMeshOverlap, const Obj<RecvOverlap>& recvMeshOverlap) {
80: typedef ALE::ConeSection<Sieve> cones_wrapper_type;
81: Obj<cones_wrapper_type> cones = new cones_wrapper_type(sieve);
82: Obj<cones_type> overlapCones = new cones_type(sieve->comm(), sieve->debug());
84: ALE::Pullback::SimpleCopy::copy(sendMeshOverlap, recvMeshOverlap, cones, overlapCones);
85: if (sieve->debug()) {overlapCones->view("Overlap Cones");}
86: // Inserts cones into parallelMesh (must renumber here)
87: ALE::Pullback::InsertionBinaryFusion::fuse(overlapCones, recvMeshOverlap, renumbering, newSieve);
88: return overlapCones;
89: }
90: template<typename Sieve, typename NewSieve, typename SendOverlap, typename RecvOverlap>
91: static Obj<oriented_cones_type> completeConesV(const Obj<Sieve>& sieve, const Obj<NewSieve>& newSieve, const Obj<SendOverlap>& sendMeshOverlap, const Obj<RecvOverlap>& recvMeshOverlap) {
92: typedef ALE::OrientedConeSectionV<Sieve> oriented_cones_wrapper_type;
93: Obj<oriented_cones_wrapper_type> cones = new oriented_cones_wrapper_type(sieve);
94: Obj<oriented_cones_type> overlapCones = new oriented_cones_type(sieve->comm(), sieve->debug());
96: ALE::Pullback::SimpleCopy::copy(sendMeshOverlap, recvMeshOverlap, cones, overlapCones);
97: if (sieve->debug()) {overlapCones->view("Overlap Cones");}
98: ALE::Pullback::InsertionBinaryFusion::fuse(overlapCones, recvMeshOverlap, newSieve);
99: return overlapCones;
100: }
101: template<typename Sieve, typename NewSieve, typename Renumbering, typename SendOverlap, typename RecvOverlap>
102: static Obj<oriented_cones_type> completeConesV(const Obj<Sieve>& sieve, const Obj<NewSieve>& newSieve, Renumbering& renumbering, const Obj<SendOverlap>& sendMeshOverlap, const Obj<RecvOverlap>& recvMeshOverlap) {
103: typedef ALE::OrientedConeSectionV<Sieve> oriented_cones_wrapper_type;
104: Obj<oriented_cones_wrapper_type> cones = new oriented_cones_wrapper_type(sieve);
105: Obj<oriented_cones_type> overlapCones = new oriented_cones_type(sieve->comm(), sieve->debug());
107: ALE::Pullback::SimpleCopy::copy(sendMeshOverlap, recvMeshOverlap, cones, overlapCones);
108: if (sieve->debug()) {overlapCones->view("Overlap Cones");}
109: // Inserts cones into parallelMesh (must renumber here)
110: ALE::Pullback::InsertionBinaryFusion::fuse(overlapCones, recvMeshOverlap, renumbering, newSieve);
111: return overlapCones;
112: }
113: // Given a partition of sieve points, copy the mesh pieces to each process and fuse into the new mesh
114: // Return overlaps for the cone communication
115: template<typename Renumbering, typename NewMesh, typename SendOverlap, typename RecvOverlap>
116: static void completeMesh(const Obj<Mesh>& mesh, const Obj<partition_type>& partition, Renumbering& renumbering, const Obj<NewMesh>& newMesh, const Obj<SendOverlap>& sendMeshOverlap, const Obj<RecvOverlap>& recvMeshOverlap) {
117: typedef ALE::Sifter<rank_type,rank_type,rank_type> part_send_overlap_type;
118: typedef ALE::Sifter<rank_type,rank_type,rank_type> part_recv_overlap_type;
119: const Obj<part_send_overlap_type> sendOverlap = new part_send_overlap_type(partition->comm());
120: const Obj<part_recv_overlap_type> recvOverlap = new part_recv_overlap_type(partition->comm());
122: // Create overlap for partition points
123: // TODO: This needs to be generalized for multiple sources
124: Partitioner::createDistributionPartOverlap(sendOverlap, recvOverlap);
125: // Communicate partition pieces to processes
126: Obj<partition_type> overlapPartition = new partition_type(partition->comm(), partition->debug());
128: overlapPartition->setChart(partition->getChart());
129: ALE::Pullback::SimpleCopy::copy(sendOverlap, recvOverlap, partition, overlapPartition);
130: // Create renumbering
131: const int rank = partition->commRank();
132: const point_type *localPoints = partition->restrictPoint(rank);
133: const int numLocalPoints = partition->getFiberDimension(rank);
135: for(point_type p = 0; p < numLocalPoints; ++p) {
136: renumbering[localPoints[p]] = p;
137: }
138: const Obj<typename part_recv_overlap_type::traits::baseSequence> rPoints = recvOverlap->base();
139: point_type localPoint = numLocalPoints;
141: for(typename part_recv_overlap_type::traits::baseSequence::iterator p_iter = rPoints->begin(); p_iter != rPoints->end(); ++p_iter) {
142: const Obj<typename part_recv_overlap_type::coneSequence>& ranks = recvOverlap->cone(*p_iter);
143: const rank_type& remotePartPoint = ranks->begin().color();
144: const point_type *points = overlapPartition->restrictPoint(remotePartPoint);
145: const int numPoints = overlapPartition->getFiberDimension(remotePartPoint);
147: for(int i = 0; i < numPoints; ++i) {
148: renumbering[points[i]] = localPoint++;
149: }
150: }
151: // Create mesh overlap from partition overlap
152: // TODO: Generalize to redistribution (receive from multiple sources)
153: Partitioner::createDistributionMeshOverlap(partition, recvOverlap, renumbering, overlapPartition, sendMeshOverlap, recvMeshOverlap);
154: // Send cones
155: completeCones(mesh->getSieve(), newMesh->getSieve(), renumbering, sendMeshOverlap, recvMeshOverlap);
156: }
157: template<typename Renumbering, typename NewMesh, typename SendOverlap, typename RecvOverlap>
158: static void completeBaseV(const Obj<Mesh>& mesh, const Obj<partition_type>& partition, Renumbering& renumbering, const Obj<NewMesh>& newMesh, const Obj<SendOverlap>& sendMeshOverlap, const Obj<RecvOverlap>& recvMeshOverlap) {
159: typedef ALE::Sifter<rank_type,rank_type,rank_type> part_send_overlap_type;
160: typedef ALE::Sifter<rank_type,rank_type,rank_type> part_recv_overlap_type;
161: const Obj<part_send_overlap_type> sendOverlap = new part_send_overlap_type(partition->comm());
162: const Obj<part_recv_overlap_type> recvOverlap = new part_recv_overlap_type(partition->comm());
164: // Create overlap for partition points
165: // TODO: This needs to be generalized for multiple sources
166: Partitioner::createDistributionPartOverlap(sendOverlap, recvOverlap);
167: // Communicate partition pieces to processes
168: Obj<partition_type> overlapPartition = new partition_type(partition->comm(), partition->debug());
170: overlapPartition->setChart(partition->getChart());
171: ALE::Pullback::SimpleCopy::copy(sendOverlap, recvOverlap, partition, overlapPartition);
172: // Create renumbering
173: const int rank = partition->commRank();
174: const point_type *localPoints = partition->restrictPoint(rank);
175: const int numLocalPoints = partition->getFiberDimension(rank);
177: for(point_type p = 0; p < numLocalPoints; ++p) {
178: ///std::cout <<"["<<partition->commRank()<<"]: local renumbering " << localPoints[p] << " --> " << p << std::endl;
179: renumbering[localPoints[p]] = p;
180: }
181: const Obj<typename part_recv_overlap_type::traits::baseSequence> rPoints = recvOverlap->base();
182: point_type localPoint = numLocalPoints;
184: for(typename part_recv_overlap_type::traits::baseSequence::iterator p_iter = rPoints->begin(); p_iter != rPoints->end(); ++p_iter) {
185: const Obj<typename part_recv_overlap_type::coneSequence>& ranks = recvOverlap->cone(*p_iter);
186: const rank_type& remotePartPoint = ranks->begin().color();
187: const point_type *points = overlapPartition->restrictPoint(remotePartPoint);
188: const int numPoints = overlapPartition->getFiberDimension(remotePartPoint);
190: for(int i = 0; i < numPoints; ++i) {
191: ///std::cout <<"["<<partition->commRank()<<"]: remote renumbering " << points[i] << " --> " << localPoint << std::endl;
192: renumbering[points[i]] = localPoint++;
193: }
194: }
195: newMesh->getSieve()->setChart(typename NewMesh::sieve_type::chart_type(0, renumbering.size()));
196: // Create mesh overlap from partition overlap
197: // TODO: Generalize to redistribution (receive from multiple sources)
198: Partitioner::createDistributionMeshOverlap(partition, recvOverlap, renumbering, overlapPartition, sendMeshOverlap, recvMeshOverlap);
199: }
200: template<typename NewMesh, typename Renumbering, typename SendOverlap, typename RecvOverlap>
201: static Obj<partition_type> distributeMesh(const Obj<Mesh>& mesh, const Obj<NewMesh>& newMesh, Renumbering& renumbering, const Obj<SendOverlap>& sendMeshOverlap, const Obj<RecvOverlap>& recvMeshOverlap, const int height = 0) {
202: const Obj<partition_type> cellPartition = new partition_type(mesh->comm(), 0, mesh->commSize(), mesh->debug());
203: const Obj<partition_type> partition = new partition_type(mesh->comm(), 0, mesh->commSize(), mesh->debug());
205: // Create the cell partition
206: Partitioner::createPartition(mesh, cellPartition, height);
207: if (mesh->debug()) {
208: PetscViewer viewer;
211: cellPartition->view("Cell Partition");
212: PetscViewerCreate(mesh->comm(), &viewer);CHKERRXX(ierr);
213: PetscViewerSetType(viewer, PETSCVIEWERASCII);CHKERRXX(ierr);
214: PetscViewerFileSetName(viewer, "mesh.vtk");CHKERRXX(ierr);
215: ///TODO MeshView_Sieve_Ascii(mesh, cellPartition, viewer);CHKERRXX(ierr);
216: PetscViewerDestroy(&viewer);CHKERRXX(ierr);
217: }
218: // Close the partition over sieve points
219: Partitioner::createPartitionClosure(mesh, cellPartition, partition, height);
220: if (mesh->debug()) {partition->view("Partition");}
221: // Create the remote meshes
222: completeMesh(mesh, partition, renumbering, newMesh, sendMeshOverlap, recvMeshOverlap);
223: // Create the local mesh
224: Partitioner::createLocalMesh(mesh, partition, renumbering, newMesh, height);
225: newMesh->stratify();
226: return partition;
227: }
228: template<typename NewMesh, typename Renumbering, typename SendOverlap, typename RecvOverlap>
229: static Obj<partition_type> distributeMeshAndSections(const Obj<Mesh>& mesh, const Obj<NewMesh>& newMesh, Renumbering& renumbering, const Obj<SendOverlap>& sendMeshOverlap, const Obj<RecvOverlap>& recvMeshOverlap, const int height = 0) {
230: Obj<partition_type> partition = distributeMesh(mesh, newMesh, renumbering, sendMeshOverlap, recvMeshOverlap, height);
232: // Distribute the coordinates
233: const Obj<typename Mesh::real_section_type>& coordinates = mesh->getRealSection("coordinates");
234: const Obj<typename Mesh::real_section_type>& parallelCoordinates = newMesh->getRealSection("coordinates");
236: newMesh->setupCoordinates(parallelCoordinates);
237: distributeSection(coordinates, partition, renumbering, sendMeshOverlap, recvMeshOverlap, parallelCoordinates);
238: // Distribute other sections
239: if (mesh->getRealSections()->size() > 1) {
240: Obj<std::set<std::string> > names = mesh->getRealSections();
242: for(std::set<std::string>::const_iterator n_iter = names->begin(); n_iter != names->end(); ++n_iter) {
243: if (*n_iter == "coordinates") continue;
244: distributeSection(mesh->getRealSection(*n_iter), partition, renumbering, sendMeshOverlap, recvMeshOverlap, newMesh->getRealSection(*n_iter));
245: }
246: }
247: if (mesh->getIntSections()->size() > 0) {
248: Obj<std::set<std::string> > names = mesh->getIntSections();
250: for(std::set<std::string>::const_iterator n_iter = names->begin(); n_iter != names->end(); ++n_iter) {
251: distributeSection(mesh->getIntSection(*n_iter), partition, renumbering, sendMeshOverlap, recvMeshOverlap, newMesh->getIntSection(*n_iter));
252: }
253: }
254: if (mesh->getArrowSections()->size() > 1) {
255: throw ALE::Exception("Need to distribute more arrow sections");
256: }
257: // Distribute labels
258: const typename Mesh::labels_type& labels = mesh->getLabels();
260: for(typename Mesh::labels_type::const_iterator l_iter = labels.begin(); l_iter != labels.end(); ++l_iter) {
261: if (newMesh->hasLabel(l_iter->first)) continue;
262: const Obj<typename Mesh::label_type>& origLabel = l_iter->second;
263: const Obj<typename Mesh::label_type>& newLabel = newMesh->createLabel(l_iter->first);
264: // Get remote labels
265: ALE::New::Completion<Mesh,typename Mesh::point_type>::scatterCones(origLabel, newLabel, sendMeshOverlap, recvMeshOverlap, renumbering);
266: // Create local label
267: newLabel->add(origLabel, newMesh->getSieve(), renumbering);
268: }
269: return partition;
270: }
271: template<typename NewMesh, typename Renumbering, typename SendOverlap, typename RecvOverlap>
272: static Obj<partition_type> distributeMeshV(const Obj<Mesh>& mesh, const Obj<NewMesh>& newMesh, Renumbering& renumbering, const Obj<SendOverlap>& sendMeshOverlap, const Obj<RecvOverlap>& recvMeshOverlap, const int height = 0) {
273: const Obj<partition_type> cellPartition = new partition_type(mesh->comm(), 0, mesh->commSize(), mesh->debug());
274: const Obj<partition_type> partition = new partition_type(mesh->comm(), 0, mesh->commSize(), mesh->debug());
276: PETSc::Log::Event("DistributeMesh").begin();
277: // Create the cell partition
278: Partitioner::createPartitionV(mesh, cellPartition, height);
279: if (mesh->debug()) {
280: PetscViewer viewer;
283: cellPartition->view("Cell Partition");
284: PetscViewerCreate(mesh->comm(), &viewer);CHKERRXX(ierr);
285: PetscViewerSetType(viewer, PETSCVIEWERASCII);CHKERRXX(ierr);
286: PetscViewerFileSetName(viewer, "mesh.vtk");CHKERRXX(ierr);
287: ///TODO MeshView_Sieve_Ascii(mesh, cellPartition, viewer);CHKERRXX(ierr);
288: PetscViewerDestroy(&viewer);CHKERRXX(ierr);
289: }
290: // Close the partition over sieve points
291: Partitioner::createPartitionClosureV(mesh, cellPartition, partition, height);
292: if (mesh->debug()) {partition->view("Partition");}
293: // Create the remote bases
294: completeBaseV(mesh, partition, renumbering, newMesh, sendMeshOverlap, recvMeshOverlap);
295: // Size the local mesh
296: Partitioner::sizeLocalMeshV(mesh, partition, renumbering, newMesh, height);
297: // Create the remote meshes
298: completeConesV(mesh->getSieve(), newMesh->getSieve(), renumbering, sendMeshOverlap, recvMeshOverlap);
299: // Create the local mesh
300: Partitioner::createLocalMeshV(mesh, partition, renumbering, newMesh, height);
301: newMesh->getSieve()->symmetrize();
302: newMesh->stratify();
303: PETSc::Log::Event("DistributeMesh").end();
304: return partition;
305: }
306: // distributeMeshV:
307: // createPartitionV (can be dumb)
308: // createPartitionClosureV (should be low memory)
309: // completeBaseV ( have not decided )
310: // Partitioner::createDistributionPartOverlap (low memory)
311: // copy points to partitions (uses small overlap and fake sections)
312: // renumber (map is potentially big, can measure)
313: // Partitioner::createDistributionMeshOverlap (should be large for distribution)
314: // sendMeshOverlap is localPoint--- remotePoint --->remoteRank
315: // recvMeshOverlap is remoteRank--- remotePoint --->localPoint
316: // sizeLocalMeshV (should be low memory)
317: // completeConesV ( have not decided )
318: // createLocalMesh (should be low memory)
319: // symmetrize
320: // stratify
321: template<typename NewMesh>
322: static void distributeMeshAndSectionsV(const Obj<Mesh>& mesh, const Obj<NewMesh>& newMesh) {
323: typedef typename Mesh::point_type point_type;
325: const Obj<typename Mesh::send_overlap_type> sendMeshOverlap = new typename Mesh::send_overlap_type(mesh->comm(), mesh->debug());
326: const Obj<typename Mesh::recv_overlap_type> recvMeshOverlap = new typename Mesh::recv_overlap_type(mesh->comm(), mesh->debug());
327: std::map<point_type,point_type>& renumbering = newMesh->getRenumbering();
328: // Distribute the mesh
329: Obj<partition_type> partition = distributeMeshV(mesh, newMesh, renumbering, sendMeshOverlap, recvMeshOverlap);
330: if (mesh->debug()) {
331: std::cout << "["<<mesh->commRank()<<"]: Mesh Renumbering:" << std::endl;
332: for(typename Mesh::renumbering_type::const_iterator r_iter = renumbering.begin(); r_iter != renumbering.end(); ++r_iter) {
333: std::cout << "["<<mesh->commRank()<<"]: global point " << r_iter->first << " --> " << " local point " << r_iter->second << std::endl;
334: }
335: }
336: // Distribute the coordinates
337: PETSc::Log::Event("DistributeCoords").begin();
338: const Obj<typename Mesh::real_section_type>& coordinates = mesh->getRealSection("coordinates");
339: const Obj<typename Mesh::real_section_type>& parallelCoordinates = newMesh->getRealSection("coordinates");
341: newMesh->setupCoordinates(parallelCoordinates);
342: distributeSection(coordinates, partition, renumbering, sendMeshOverlap, recvMeshOverlap, parallelCoordinates);
343: PETSc::Log::Event("DistributeCoords").end();
344: // Distribute other sections
345: if (mesh->getRealSections()->size() > 1) {
346: PETSc::Log::Event("DistributeRealSec").begin();
347: Obj<std::set<std::string> > names = mesh->getRealSections();
348: int n = 0;
350: for(std::set<std::string>::const_iterator n_iter = names->begin(); n_iter != names->end(); ++n_iter) {
351: if (*n_iter == "coordinates") continue;
352: std::cout << "ERROR: Did not distribute real section " << *n_iter << std::endl;
353: ++n;
354: }
355: PETSc::Log::Event("DistributeRealSec").end();
356: if (n) {throw ALE::Exception("Need to distribute more real sections");}
357: }
358: if (mesh->getIntSections()->size() > 0) {
359: PETSc::Log::Event("DistributeIntSec").begin();
360: Obj<std::set<std::string> > names = mesh->getIntSections();
362: for(std::set<std::string>::const_iterator n_iter = names->begin(); n_iter != names->end(); ++n_iter) {
363: const Obj<typename Mesh::int_section_type>& section = mesh->getIntSection(*n_iter);
364: const Obj<typename Mesh::int_section_type>& newSection = newMesh->getIntSection(*n_iter);
366: // We assume all integer sections are complete sections
367: newSection->setChart(newMesh->getSieve()->getChart());
368: distributeSection(section, partition, renumbering, sendMeshOverlap, recvMeshOverlap, newSection);
369: }
370: PETSc::Log::Event("DistributeIntSec").end();
371: }
372: if (mesh->getArrowSections()->size() > 1) {
373: throw ALE::Exception("Need to distribute more arrow sections");
374: }
375: // Distribute labels
376: PETSc::Log::Event("DistributeLabels").begin();
377: const typename Mesh::labels_type& labels = mesh->getLabels();
379: for(typename Mesh::labels_type::const_iterator l_iter = labels.begin(); l_iter != labels.end(); ++l_iter) {
380: if (newMesh->hasLabel(l_iter->first)) continue;
381: const Obj<typename Mesh::label_type>& origLabel = l_iter->second;
382: const Obj<typename Mesh::label_type>& newLabel = newMesh->createLabel(l_iter->first);
384: #ifdef IMESH_NEW_LABELS
385: newLabel->setChart(newMesh->getSieve()->getChart());
386: // Size the local mesh
387: Partitioner::sizeLocalSieveV(origLabel, partition, renumbering, newLabel);
388: // Create the remote meshes
389: completeConesV(origLabel, newLabel, renumbering, sendMeshOverlap, recvMeshOverlap);
390: // Create the local mesh
391: Partitioner::createLocalSieveV(origLabel, partition, renumbering, newLabel);
392: newLabel->symmetrize();
393: #else
394: distributeLabelV(newMesh->getSieve(), origLabel, partition, renumbering, sendMeshOverlap, recvMeshOverlap, newLabel);
395: #endif
396: }
397: PETSc::Log::Event("DistributeLabels").end();
398: // Create the parallel overlap
399: PETSc::Log::Event("CreateOverlap").begin();
400: Obj<typename Mesh::send_overlap_type> sendParallelMeshOverlap = newMesh->getSendOverlap();
401: Obj<typename Mesh::recv_overlap_type> recvParallelMeshOverlap = newMesh->getRecvOverlap();
402: // Can I figure this out in a nicer way?
403: ALE::SetFromMap<std::map<point_type,point_type> > globalPoints(renumbering);
405: ALE::OverlapBuilder<>::constructOverlap(globalPoints, renumbering, sendParallelMeshOverlap, recvParallelMeshOverlap);
406: newMesh->setCalculatedOverlap(true);
407: PETSc::Log::Event("CreateOverlap").end();
408: }
409: template<typename Label, typename Partition, typename Renumbering, typename SendOverlap, typename RecvOverlap, typename NewLabel>
410: static void distributeLabel(const Obj<typename Mesh::sieve_type>& sieve, const Obj<Label>& l, const Obj<Partition>& partition, Renumbering& renumbering, const Obj<SendOverlap>& sendOverlap, const Obj<RecvOverlap>& recvOverlap, const Obj<NewLabel>& newL) {
411: Partitioner::createLocalSifter(l, partition, renumbering, newL);
412: //completeCones(l, newL, renumbering, sendMeshOverlap, recvMeshOverlap);
413: {
414: typedef ALE::UniformSection<point_type, int> cones_type;
415: typedef ALE::LabelSection<typename Mesh::sieve_type, Label> cones_wrapper_type;
416: Obj<cones_wrapper_type> cones = new cones_wrapper_type(sieve, l);
417: Obj<cones_type> overlapCones = new cones_type(l->comm(), l->debug());
419: ALE::Pullback::SimpleCopy::copy(sendOverlap, recvOverlap, cones, overlapCones);
420: if (l->debug()) {overlapCones->view("Overlap Label Values");}
421: // Inserts cones into newL (must renumber here)
422: //ALE::Pullback::InsertionBinaryFusion::fuse(overlapCones, recvOverlap, renumbering, newSieve);
423: {
424: typedef typename cones_type::point_type overlap_point_type;
425: const Obj<typename RecvOverlap::baseSequence> rPoints = recvOverlap->base();
426: const typename RecvOverlap::baseSequence::iterator rEnd = rPoints->end();
428: for(typename RecvOverlap::baseSequence::iterator p_iter = rPoints->begin(); p_iter != rEnd; ++p_iter) {
429: const Obj<typename RecvOverlap::coneSequence>& points = recvOverlap->cone(*p_iter);
430: const typename RecvOverlap::target_type& localPoint = *p_iter;
431: const typename cones_type::point_type& remotePoint = points->begin().color();
432: const overlap_point_type overlapPoint = overlap_point_type(remotePoint.second, remotePoint.first);
433: const int size = overlapCones->getFiberDimension(overlapPoint);
434: const typename cones_type::value_type *values = overlapCones->restrictPoint(overlapPoint);
436: newL->clearCone(localPoint);
437: for(int i = 0; i < size; ++i) {newL->addCone(values[i], localPoint);}
438: }
439: }
440: }
441: }
442: template<typename Label, typename Partition, typename Renumbering, typename SendOverlap, typename RecvOverlap, typename NewLabel>
443: static void distributeLabelV(const Obj<typename Mesh::sieve_type>& sieve, const Obj<Label>& l, const Obj<Partition>& partition, Renumbering& renumbering, const Obj<SendOverlap>& sendOverlap, const Obj<RecvOverlap>& recvOverlap, const Obj<NewLabel>& newL) {
444: Partitioner::createLocalSifter(l, partition, renumbering, newL);
445: //completeCones(l, newL, renumbering, sendMeshOverlap, recvMeshOverlap);
446: {
447: typedef typename Label::alloc_type::template rebind<int>::other alloc_type;
448: typedef LabelBaseSectionV<typename Mesh::sieve_type, Label, alloc_type> atlas_type;
449: typedef ALE::UniformSection<ALE::Pair<int, point_type>, int> cones_type;
450: typedef ALE::LabelSection<typename Mesh::sieve_type, Label, alloc_type, atlas_type> cones_wrapper_type;
451: Obj<cones_wrapper_type> cones = new cones_wrapper_type(sieve, l);
452: Obj<cones_type> overlapCones = new cones_type(l->comm(), l->debug());
454: ALE::Pullback::SimpleCopy::copy(sendOverlap, recvOverlap, cones, overlapCones);
455: if (l->debug()) {overlapCones->view("Overlap Label Values");}
456: // Inserts cones into newL (must renumber here)
457: //ALE::Pullback::InsertionBinaryFusion::fuse(overlapCones, recvOverlap, renumbering, newSieve);
458: {
459: typedef typename cones_type::point_type overlap_point_type;
460: const typename RecvOverlap::capSequence::iterator rBegin = recvOverlap->capBegin();
461: const typename RecvOverlap::capSequence::iterator rEnd = recvOverlap->capEnd();
463: for(typename RecvOverlap::capSequence::iterator r_iter = rBegin; r_iter != rEnd; ++r_iter) {
464: const int rank = *r_iter;
465: const typename RecvOverlap::supportSequence::iterator pBegin = recvOverlap->supportBegin(*r_iter);
466: const typename RecvOverlap::supportSequence::iterator pEnd = recvOverlap->supportEnd(*r_iter);
468: for(typename RecvOverlap::supportSequence::iterator p_iter = pBegin; p_iter != pEnd; ++p_iter) {
469: const typename RecvOverlap::target_type& localPoint = *p_iter;
470: const typename RecvOverlap::target_type& remotePoint = p_iter.color();
471: const overlap_point_type overlapPoint = overlap_point_type(rank, remotePoint);
472: const int size = overlapCones->getFiberDimension(overlapPoint);
473: const typename cones_type::value_type *values = overlapCones->restrictPoint(overlapPoint);
475: newL->clearCone(localPoint);
476: for(int i = 0; i < size; ++i) {newL->addCone(values[i], localPoint);}
477: }
478: }
479: }
480: }
481: }
482: template<typename Section, typename Partition, typename Renumbering, typename SendOverlap, typename RecvOverlap, typename NewSection>
483: static void distributeSection(const Obj<Section>& s, const Obj<Partition>& partition, Renumbering& renumbering, const Obj<SendOverlap>& sendOverlap, const Obj<RecvOverlap>& recvOverlap, const Obj<NewSection>& newS) {
484: Partitioner::createLocalSection(s, partition, renumbering, newS);
485: ALE::Completion::completeSection(sendOverlap, recvOverlap, s, newS);
486: }
487: template<typename NewMesh, typename Renumbering, typename SendOverlap, typename RecvOverlap>
488: static Obj<partition_type> unifyMesh(const Obj<Mesh>& mesh, const Obj<NewMesh>& newMesh, Renumbering& renumbering, const Obj<SendOverlap>& sendMeshOverlap, const Obj<RecvOverlap>& recvMeshOverlap) {
489: const Obj<partition_type> cellPartition = new partition_type(mesh->comm(), 0, mesh->commSize(), mesh->debug());
490: const Obj<partition_type> partition = new partition_type(mesh->comm(), 0, mesh->commSize(), mesh->debug());
491: const Obj<typename Mesh::label_sequence>& cells = mesh->heightStratum(0);
492: const typename Mesh::label_sequence::iterator cEnd = cells->end();
493: typename Mesh::point_type *values = new typename Mesh::point_type[cells->size()];
494: int c = 0;
496: cellPartition->setFiberDimension(0, cells->size());
497: cellPartition->allocatePoint();
498: for(typename Mesh::label_sequence::iterator c_iter = cells->begin(); c_iter != cEnd; ++c_iter, ++c) {
499: values[c] = *c_iter;
500: }
501: cellPartition->updatePoint(0, values);
502: delete [] values;
503: // Close the partition over sieve points
504: Partitioner::createPartitionClosure(mesh, cellPartition, partition);
505: // Create the remote meshes
506: completeMesh(mesh, partition, renumbering, newMesh, sendMeshOverlap, recvMeshOverlap);
507: // Create the local mesh
508: Partitioner::createLocalMesh(mesh, partition, renumbering, newMesh);
509: newMesh->stratify();
510: newMesh->view("Unified mesh");
511: return partition;
512: }
513: static Obj<Mesh> unifyMesh(const Obj<Mesh>& mesh) {
514: typedef ALE::Sifter<point_type,rank_type,point_type> mesh_send_overlap_type;
515: typedef ALE::Sifter<rank_type,point_type,point_type> mesh_recv_overlap_type;
516: const Obj<Mesh> newMesh = new Mesh(mesh->comm(), mesh->getDimension(), mesh->debug());
517: const Obj<typename Mesh::sieve_type> newSieve = new typename Mesh::sieve_type(mesh->comm(), mesh->debug());
518: const Obj<mesh_send_overlap_type> sendMeshOverlap = new mesh_send_overlap_type(mesh->comm(), mesh->debug());
519: const Obj<mesh_recv_overlap_type> recvMeshOverlap = new mesh_recv_overlap_type(mesh->comm(), mesh->debug());
520: std::map<point_type,point_type> renumbering;
522: newMesh->setSieve(newSieve);
523: const Obj<partition_type> partition = unifyMesh(mesh, newMesh, renumbering, sendMeshOverlap, recvMeshOverlap);
524: // Unify coordinates
525: const Obj<typename Mesh::real_section_type>& coordinates = mesh->getRealSection("coordinates");
526: const Obj<typename Mesh::real_section_type>& newCoordinates = newMesh->getRealSection("coordinates");
528: newMesh->setupCoordinates(newCoordinates);
529: distributeSection(coordinates, partition, renumbering, sendMeshOverlap, recvMeshOverlap, newCoordinates);
530: // Unify labels
531: const typename Mesh::labels_type& labels = mesh->getLabels();
533: for(typename Mesh::labels_type::const_iterator l_iter = labels.begin(); l_iter != labels.end(); ++l_iter) {
534: if (newMesh->hasLabel(l_iter->first)) continue;
535: const Obj<typename Mesh::label_type>& label = l_iter->second;
536: const Obj<typename Mesh::label_type>& newLabel = newMesh->createLabel(l_iter->first);
538: //completeCones(label, newLabel, renumbering, sendMeshOverlap, recvMeshOverlap);
539: {
540: typedef ALE::UniformSection<point_type, int> cones_type;
541: typedef ALE::LabelSection<typename Mesh::sieve_type,typename Mesh::label_type> cones_wrapper_type;
542: Obj<cones_wrapper_type> cones = new cones_wrapper_type(mesh->getSieve(), label);
543: Obj<cones_type> overlapCones = new cones_type(label->comm(), label->debug());
545: ALE::Pullback::SimpleCopy::copy(sendMeshOverlap, recvMeshOverlap, cones, overlapCones);
546: if (label->debug()) {overlapCones->view("Overlap Label Values");}
547: // Inserts cones into parallelMesh (must renumber here)
548: //ALE::Pullback::InsertionBinaryFusion::fuse(overlapCones, recvMeshOverlap, renumbering, newSieve);
549: {
550: const Obj<typename mesh_recv_overlap_type::baseSequence> rPoints = recvMeshOverlap->base();
552: for(typename mesh_recv_overlap_type::baseSequence::iterator p_iter = rPoints->begin(); p_iter != rPoints->end(); ++p_iter) {
553: const Obj<typename mesh_recv_overlap_type::coneSequence>& points = recvMeshOverlap->cone(*p_iter);
554: const typename mesh_recv_overlap_type::target_type& localPoint = *p_iter;
555: const typename cones_type::point_type& remotePoint = points->begin().color();
556: const int size = overlapCones->getFiberDimension(remotePoint);
557: const typename cones_type::value_type *values = overlapCones->restrictPoint(remotePoint);
559: newLabel->clearCone(localPoint);
560: for(int i = 0; i < size; ++i) {newLabel->addCone(values[i], localPoint);}
561: }
562: }
563: }
564: //newLabel->add(label, newSieve);
565: Partitioner::createLocalSifter(label, partition, renumbering, newLabel);
566: newLabel->view(l_iter->first.c_str());
567: }
568: return newMesh;
569: }
570: };
571: template<typename Bundle_>
572: class Distribution {
573: public:
574: typedef Bundle_ bundle_type;
575: typedef typename bundle_type::sieve_type sieve_type;
576: typedef typename bundle_type::point_type point_type;
577: typedef typename bundle_type::alloc_type alloc_type;
578: typedef typename bundle_type::send_overlap_type send_overlap_type;
579: typedef typename bundle_type::recv_overlap_type recv_overlap_type;
580: typedef typename ALE::New::Completion<bundle_type, typename sieve_type::point_type> sieveCompletion;
581: typedef typename ALE::New::SectionCompletion<bundle_type, typename bundle_type::real_section_type::value_type> sectionCompletion;
582: public:
585: static void createPartitionOverlap(const Obj<bundle_type>& bundle, const Obj<send_overlap_type>& sendOverlap, const Obj<recv_overlap_type>& recvOverlap) {
586: const Obj<send_overlap_type>& topSendOverlap = bundle->getSendOverlap();
587: const Obj<recv_overlap_type>& topRecvOverlap = bundle->getRecvOverlap();
588: const Obj<typename send_overlap_type::traits::baseSequence> base = topSendOverlap->base();
589: const Obj<typename recv_overlap_type::traits::capSequence> cap = topRecvOverlap->cap();
590: const int rank = bundle->commRank();
592: if (base->empty()) {
593: if (rank == 0) {
594: for(int p = 1; p < bundle->commSize(); p++) {
595: // The arrow is from local partition point p (source) to remote partition point p (color) on rank p (target)
596: sendOverlap->addCone(p, p, p);
597: }
598: }
599: } else {
600: for(typename send_overlap_type::traits::baseSequence::iterator b_iter = base->begin(); b_iter != base->end(); ++b_iter) {
601: const int& p = *b_iter;
602: // The arrow is from local partition point p (source) to remote partition point p (color) on rank p (target)
603: sendOverlap->addCone(p, p, p);
604: }
605: }
606: if (cap->empty()) {
607: if (rank != 0) {
608: // The arrow is from local partition point rank (color) on rank 0 (source) to remote partition point rank (target)
609: recvOverlap->addCone(0, rank, rank);
610: }
611: } else {
612: for(typename recv_overlap_type::traits::capSequence::iterator c_iter = cap->begin(); c_iter != cap->end(); ++c_iter) {
613: const int& p = *c_iter;
614: // The arrow is from local partition point rank (color) on rank p (source) to remote partition point rank (target)
615: recvOverlap->addCone(p, rank, rank);
616: }
617: }
618: };
621: template<typename Partitioner>
622: static typename Partitioner::part_type *createAssignment(const Obj<bundle_type>& bundle, const int dim, const Obj<send_overlap_type>& sendOverlap, const Obj<recv_overlap_type>& recvOverlap, const int height = 0) {
623: // 1) Form partition point overlap a priori
624: createPartitionOverlap(bundle, sendOverlap, recvOverlap);
625: if (bundle->debug()) {
626: sendOverlap->view("Send overlap for partition");
627: recvOverlap->view("Receive overlap for partition");
628: }
629: // 2) Partition the mesh
630: if (height == 0) {
631: return Partitioner::partitionSieve(bundle, dim);
632: } else if (height == 1) {
633: return Partitioner::partitionSieveByFace(bundle, dim);
634: }
635: throw ALE::Exception("Invalid partition height");
636: }
639: // Partition a bundle on process 0 and scatter to all processes
640: static void scatterBundle(const Obj<bundle_type>& bundle, const int dim, const Obj<bundle_type>& bundleNew, const Obj<send_overlap_type>& sendOverlap, const Obj<recv_overlap_type>& recvOverlap, const std::string& partitioner, const int height = 0, const Obj<bundle_type>& subBundle = NULL, const Obj<bundle_type>& subBundleNew = NULL) {
641: if (height == 0) {
642: if (partitioner == "chaco") {
643: #ifdef PETSC_HAVE_CHACO
644: typedef typename ALE::New::Chaco::Partitioner<bundle_type> Partitioner;
645: typedef typename ALE::New::Partitioner<bundle_type> GenPartitioner;
646: typedef typename Partitioner::part_type part_type;
648: part_type *assignment = scatterBundle<Partitioner>(bundle, dim, bundleNew, sendOverlap, recvOverlap, height);
649: if (!subBundle.isNull() && !subBundleNew.isNull()) {
650: part_type *subAssignment = GenPartitioner::subordinatePartition(bundle, 1, subBundle, assignment);
651: const Obj<sieve_type>& sieve = subBundle->getSieve();
652: const Obj<sieve_type>& sieveNew = new typename ALE::Mesh<PetscInt,PetscScalar>::sieve_type(subBundle->comm(), subBundle->debug());
653: const int numCells = subBundle->heightStratum(height)->size();
655: subBundleNew->setSieve(sieveNew);
656: sieveCompletion::scatterSieve(subBundle, sieve, dim, sieveNew, sendOverlap, recvOverlap, height, numCells, subAssignment);
657: subBundleNew->stratify();
658: if (subAssignment != NULL) delete [] subAssignment;
659: }
660: if (assignment != NULL) delete [] assignment;
661: #else
662: throw ALE::Exception("Chaco is not installed. Reconfigure with the flag --download-chaco");
663: #endif
664: } else if (partitioner == "parmetis") {
665: #ifdef PETSC_HAVE_PARMETIS
666: typedef typename ALE::New::ParMetis::Partitioner<bundle_type> Partitioner;
667: typedef typename ALE::New::Partitioner<bundle_type> GenPartitioner;
668: typedef typename Partitioner::part_type part_type;
670: part_type *assignment = scatterBundle<Partitioner>(bundle, dim, bundleNew, sendOverlap, recvOverlap, height);
671: if (!subBundle.isNull() && !subBundleNew.isNull()) {
672: part_type *subAssignment = GenPartitioner::subordinatePartition(bundle, 1, subBundle, assignment);
673: const Obj<sieve_type>& sieve = subBundle->getSieve();
674: const Obj<sieve_type>& sieveNew = new typename ALE::Mesh<PetscInt,PetscScalar>::sieve_type(subBundle->comm(), subBundle->debug());
675: const int numCells = subBundle->heightStratum(height)->size();
677: subBundleNew->setSieve(sieveNew);
678: sieveCompletion::scatterSieve(subBundle, sieve, dim, sieveNew, sendOverlap, recvOverlap, height, numCells, subAssignment);
679: subBundleNew->stratify();
680: if (subAssignment != NULL) delete [] subAssignment;
681: }
682: if (assignment != NULL) delete [] assignment;
683: #else
684: throw ALE::Exception("ParMetis is not installed. Reconfigure with the flag --download-parmetis");
685: #endif
686: } else {
687: throw ALE::Exception("Unknown partitioner");
688: }
689: } else if (height == 1) {
690: if (partitioner == "zoltan") {
691: #ifdef PETSC_HAVE_ZOLTAN
692: typedef typename ALE::New::Zoltan::Partitioner<bundle_type> Partitioner;
693: typedef typename Partitioner::part_type part_type;
695: part_type *assignment = scatterBundle<Partitioner>(bundle, dim, bundleNew, sendOverlap, recvOverlap, height);
696: if (assignment != NULL) delete [] assignment;
697: #else
698: throw ALE::Exception("Zoltan is not installed. Reconfigure with the flag --download-zoltan");
699: #endif
700: } else if (partitioner == "parmetis") {
701: #ifdef PETSC_HAVE_PARMETIS
702: typedef typename ALE::New::ParMetis::Partitioner<bundle_type> Partitioner;
703: typedef typename Partitioner::part_type part_type;
705: part_type *assignment = scatterBundle<Partitioner>(bundle, dim, bundleNew, sendOverlap, recvOverlap, height);
706: if (assignment != NULL) delete [] assignment;
707: #else
708: throw ALE::Exception("ParMetis is not installed. Reconfigure with the flag --download-parmetis");
709: #endif
710: } else {
711: throw ALE::Exception("Unknown partitioner");
712: }
713: } else {
714: throw ALE::Exception("Invalid partition height");
715: }
716: }
717: template<typename Partitioner>
718: static typename Partitioner::part_type *scatterBundle(const Obj<bundle_type>& bundle, const int dim, const Obj<bundle_type>& bundleNew, const Obj<send_overlap_type>& sendOverlap, const Obj<recv_overlap_type>& recvOverlap, const int height = 0) {
719: typename Partitioner::part_type *assignment = createAssignment<Partitioner>(bundle, dim, sendOverlap, recvOverlap, height);
720: const Obj<sieve_type>& sieve = bundle->getSieve();
721: const Obj<sieve_type>& sieveNew = bundleNew->getSieve();
722: const int numPoints = bundle->heightStratum(height)->size();
724: sieveCompletion::scatterSieve(bundle, sieve, dim, sieveNew, sendOverlap, recvOverlap, height, numPoints, assignment);
725: bundleNew->stratify();
726: return assignment;
727: }
730: static Obj<ALE::Mesh<PetscInt,PetscScalar> > distributeMesh(const Obj<ALE::Mesh<PetscInt,PetscScalar> >& serialMesh, const int height = 0, const std::string& partitioner = "chaco") {
731: typedef ALE::Mesh<PetscInt,PetscScalar> FlexMesh;
732: MPI_Comm comm = serialMesh->comm();
733: const int dim = serialMesh->getDimension();
734: Obj<FlexMesh> parallelMesh = new FlexMesh(comm, dim, serialMesh->debug());
735: const Obj<FlexMesh::sieve_type>& parallelSieve = new FlexMesh::sieve_type(comm, serialMesh->debug());
737: ALE_LOG_EVENT_BEGIN;
738: parallelMesh->setSieve(parallelSieve);
739: if (serialMesh->debug()) {serialMesh->view("Serial mesh");}
741: // Distribute cones
742: Obj<send_overlap_type> sendOverlap = new send_overlap_type(comm, serialMesh->debug());
743: Obj<recv_overlap_type> recvOverlap = new recv_overlap_type(comm, serialMesh->debug());
744: scatterBundle(serialMesh, dim, parallelMesh, sendOverlap, recvOverlap, partitioner, height);
745: parallelMesh->setDistSendOverlap(sendOverlap);
746: parallelMesh->setDistRecvOverlap(recvOverlap);
748: // Distribute labels
749: const typename bundle_type::labels_type& labels = serialMesh->getLabels();
751: for(typename bundle_type::labels_type::const_iterator l_iter = labels.begin(); l_iter != labels.end(); ++l_iter) {
752: if (parallelMesh->hasLabel(l_iter->first)) continue;
753: const Obj<typename bundle_type::label_type>& serialLabel = l_iter->second;
754: const Obj<typename bundle_type::label_type>& parallelLabel = parallelMesh->createLabel(l_iter->first);
755: // Create local label
756: #define NEW_LABEL
757: #ifdef NEW_LABEL
758: parallelLabel->add(serialLabel, parallelSieve);
759: #else
760: const Obj<typename bundle_type::label_type::traits::baseSequence>& base = serialLabel->base();
762: for(typename bundle_type::label_type::traits::baseSequence::iterator b_iter = base->begin(); b_iter != base->end(); ++b_iter) {
763: if (parallelSieve->capContains(*b_iter) || parallelSieve->baseContains(*b_iter)) {
764: parallelLabel->addArrow(*serialLabel->cone(*b_iter)->begin(), *b_iter);
765: }
766: }
767: #endif
768: // Get remote labels
769: sieveCompletion::scatterCones(serialLabel, parallelLabel, sendOverlap, recvOverlap);
770: }
772: // Distribute sections
773: Obj<std::set<std::string> > sections = serialMesh->getRealSections();
775: for(std::set<std::string>::iterator name = sections->begin(); name != sections->end(); ++name) {
776: parallelMesh->setRealSection(*name, distributeSection(serialMesh->getRealSection(*name), parallelMesh, sendOverlap, recvOverlap));
777: }
778: sections = serialMesh->getIntSections();
779: for(std::set<std::string>::iterator name = sections->begin(); name != sections->end(); ++name) {
780: parallelMesh->setIntSection(*name, distributeSection(serialMesh->getIntSection(*name), parallelMesh, sendOverlap, recvOverlap));
781: }
782: sections = serialMesh->getArrowSections();
784: for(std::set<std::string>::iterator name = sections->begin(); name != sections->end(); ++name) {
785: parallelMesh->setArrowSection(*name, distributeArrowSection(serialMesh->getArrowSection(*name), serialMesh, parallelMesh, sendOverlap, recvOverlap));
786: }
787: if (parallelMesh->debug()) {parallelMesh->view("Parallel Mesh");}
788: ALE_LOG_EVENT_END;
789: return parallelMesh;
790: }
793: template<typename Section>
794: static void updateSectionLocal(const Obj<Section>& oldSection, const Obj<bundle_type>& newBundle, const Obj<Section>& newSection) {
795: const Obj<typename bundle_type::sieve_type>& newSieve = newBundle->getSieve();
796: const typename Section::atlas_type::chart_type& oldChart = oldSection->getChart();
798: for(typename Section::atlas_type::chart_type::const_iterator c_iter = oldChart.begin(); c_iter != oldChart.end(); ++c_iter) {
799: if (newSieve->capContains(*c_iter) || newSieve->baseContains(*c_iter)) {
800: newSection->setFiberDimension(*c_iter, oldSection->getFiberDimension(*c_iter));
801: }
802: }
803: newBundle->allocate(newSection);
804: const typename Section::atlas_type::chart_type& newChart = newSection->getChart();
806: for(typename Section::atlas_type::chart_type::const_iterator c_iter = newChart.begin(); c_iter != newChart.end(); ++c_iter) {
807: newSection->updatePointAll(*c_iter, oldSection->restrictPoint(*c_iter));
808: }
809: }
812: template<typename RecvSection, typename Section>
813: static void updateSectionRemote(const Obj<recv_overlap_type>& recvOverlap, const Obj<RecvSection>& recvSection, const Obj<bundle_type>& newBundle, const Obj<Section>& newSection) {
814: Obj<typename recv_overlap_type::traits::baseSequence> recvPoints = recvOverlap->base();
816: for(typename recv_overlap_type::traits::baseSequence::iterator r_iter = recvPoints->begin(); r_iter != recvPoints->end(); ++r_iter) {
817: const Obj<typename recv_overlap_type::traits::coneSequence>& recvPatches = recvOverlap->cone(*r_iter);
818: const typename recv_overlap_type::traits::coneSequence::iterator end = recvPatches->end();
820: for(typename recv_overlap_type::traits::coneSequence::iterator p_iter = recvPatches->begin(); p_iter != end; ++p_iter) {
821: newSection->addPoint(*r_iter, recvSection->getSection(*p_iter)->getFiberDimension(*r_iter));
822: }
823: }
824: newBundle->reallocate(newSection);
825: for(typename recv_overlap_type::traits::baseSequence::iterator r_iter = recvPoints->begin(); r_iter != recvPoints->end(); ++r_iter) {
826: const Obj<typename recv_overlap_type::traits::coneSequence>& recvPatches = recvOverlap->cone(*r_iter);
827: const typename recv_overlap_type::traits::coneSequence::iterator end = recvPatches->end();
829: for(typename recv_overlap_type::traits::coneSequence::iterator p_iter = recvPatches->begin(); p_iter != end; ++p_iter) {
830: if (recvSection->getSection(*p_iter)->getFiberDimension(*r_iter)) {
831: newSection->updatePointAll(*r_iter, recvSection->getSection(*p_iter)->restrictPoint(*r_iter));
832: }
833: }
834: }
835: }
838: template<typename Section>
839: static Obj<Section> distributeSection(const Obj<Section>& serialSection, const Obj<bundle_type>& parallelBundle, const Obj<send_overlap_type>& sendOverlap, const Obj<recv_overlap_type>& recvOverlap) {
840: if (serialSection->debug()) {
841: serialSection->view("Serial Section");
842: }
843: typedef typename alloc_type::template rebind<typename Section::value_type>::other value_alloc_type;
844: typedef ALE::Field<send_overlap_type, int, ALE::Section<point_type, typename Section::value_type, value_alloc_type> > send_section_type;
845: typedef ALE::Field<recv_overlap_type, int, ALE::Section<point_type, typename Section::value_type, value_alloc_type> > recv_section_type;
846: typedef ALE::New::SizeSection<Section> SectionSizer;
847: Obj<Section> parallelSection = new Section(serialSection->comm(), serialSection->debug());
848: const Obj<send_section_type> sendSection = new send_section_type(serialSection->comm(), serialSection->debug());
849: const Obj<recv_section_type> recvSection = new recv_section_type(serialSection->comm(), sendSection->getTag(), serialSection->debug());
850: const Obj<SectionSizer> sizer = new SectionSizer(serialSection);
852: updateSectionLocal(serialSection, parallelBundle, parallelSection);
853: sectionCompletion::completeSection(sendOverlap, recvOverlap, sizer, serialSection, sendSection, recvSection);
854: updateSectionRemote(recvOverlap, recvSection, parallelBundle, parallelSection);
855: if (parallelSection->debug()) {
856: parallelSection->view("Parallel Section");
857: }
858: return parallelSection;
859: }
862: template<typename Section>
863: static void updateArrowSectionLocal(const Obj<Section>& oldSection, const Obj<bundle_type>& newBundle, const Obj<Section>& newSection) {
864: const Obj<typename bundle_type::sieve_type>& newSieve = newBundle->getSieve();
865: const typename Section::atlas_type::chart_type& oldChart = oldSection->getChart();
867: for(typename Section::atlas_type::chart_type::const_iterator c_iter = oldChart.begin(); c_iter != oldChart.end(); ++c_iter) {
868: // Dmitry should provide a Sieve::contains(MinimalArrow) method
869: if (newSieve->capContains(c_iter->source) && newSieve->baseContains(c_iter->target)) {
870: newSection->setFiberDimension(*c_iter, oldSection->getFiberDimension(*c_iter));
871: }
872: }
873: //newBundle->allocate(newSection);
874: const typename Section::atlas_type::chart_type& newChart = newSection->getChart();
876: for(typename Section::atlas_type::chart_type::const_iterator c_iter = newChart.begin(); c_iter != newChart.end(); ++c_iter) {
877: newSection->updatePointAll(*c_iter, oldSection->restrictPoint(*c_iter));
878: }
879: }
882: template<typename RecvSection, typename Section>
883: static void updateArrowSectionRemote(const Obj<recv_overlap_type>& recvOverlap, const Obj<RecvSection>& recvSection, const Obj<bundle_type>& newBundle, const Obj<Section>& newSection) {
884: Obj<typename recv_overlap_type::traits::baseSequence> recvPoints = recvOverlap->base();
886: for(typename recv_overlap_type::traits::baseSequence::iterator r_iter = recvPoints->begin(); r_iter != recvPoints->end(); ++r_iter) {
887: const Obj<typename bundle_type::sieve_type::traits::coneSequence>& cone = newBundle->getSieve()->cone(*r_iter);
888: const typename bundle_type::sieve_type::traits::coneSequence::iterator end = cone->end();
890: for(typename bundle_type::sieve_type::traits::coneSequence::iterator c_iter = cone->begin(); c_iter != end; ++c_iter) {
891: newSection->setFiberDimension(typename Section::point_type(*c_iter, *r_iter), 1);
892: }
893: }
894: //newBundle->reallocate(newSection);
895: for(typename recv_overlap_type::traits::baseSequence::iterator r_iter = recvPoints->begin(); r_iter != recvPoints->end(); ++r_iter) {
896: const Obj<typename recv_overlap_type::traits::coneSequence>& recvPatches = recvOverlap->cone(*r_iter);
897: const typename recv_overlap_type::traits::coneSequence::iterator recvEnd = recvPatches->end();
899: for(typename recv_overlap_type::traits::coneSequence::iterator p_iter = recvPatches->begin(); p_iter != recvEnd; ++p_iter) {
900: const Obj<typename RecvSection::section_type>& section = recvSection->getSection(*p_iter);
902: if (section->getFiberDimension(*r_iter)) {
903: const Obj<typename bundle_type::sieve_type::traits::coneSequence>& cone = newBundle->getSieve()->cone(*r_iter);
904: const typename bundle_type::sieve_type::traits::coneSequence::iterator end = cone->end();
905: const typename RecvSection::value_type *values = section->restrictPoint(*r_iter);
906: int c = -1;
908: for(typename bundle_type::sieve_type::traits::coneSequence::iterator c_iter = cone->begin(); c_iter != end; ++c_iter) {
909: newSection->updatePoint(typename Section::point_type(*c_iter, *r_iter), &values[++c]);
910: }
911: }
912: }
913: }
914: }
917: template<typename Section>
918: static Obj<Section> distributeArrowSection(const Obj<Section>& serialSection, const Obj<bundle_type>& serialBundle, const Obj<bundle_type>& parallelBundle, const Obj<send_overlap_type>& sendOverlap, const Obj<recv_overlap_type>& recvOverlap) {
919: if (serialSection->debug()) {
920: serialSection->view("Serial ArrowSection");
921: }
922: typedef typename alloc_type::template rebind<typename Section::value_type>::other value_alloc_type;
923: typedef ALE::Field<send_overlap_type, int, ALE::Section<point_type, typename Section::value_type, value_alloc_type> > send_section_type;
924: typedef ALE::Field<recv_overlap_type, int, ALE::Section<point_type, typename Section::value_type, value_alloc_type> > recv_section_type;
925: typedef ALE::New::ConeSizeSection<bundle_type, sieve_type> SectionSizer;
926: typedef ALE::New::ArrowSection<sieve_type, Section> ArrowFiller;
927: Obj<Section> parallelSection = new Section(serialSection->comm(), serialSection->debug());
928: const Obj<send_section_type> sendSection = new send_section_type(serialSection->comm(), serialSection->debug());
929: const Obj<recv_section_type> recvSection = new recv_section_type(serialSection->comm(), sendSection->getTag(), serialSection->debug());
930: const Obj<SectionSizer> sizer = new SectionSizer(serialBundle, serialBundle->getSieve());
931: const Obj<ArrowFiller> filler = new ArrowFiller(serialBundle->getSieve(), serialSection);
933: updateArrowSectionLocal(serialSection, parallelBundle, parallelSection);
934: sectionCompletion::completeSection(sendOverlap, recvOverlap, sizer, filler, sendSection, recvSection);
935: updateArrowSectionRemote(recvOverlap, recvSection, parallelBundle, parallelSection);
936: if (parallelSection->debug()) {
937: parallelSection->view("Parallel ArrowSection");
938: }
939: return parallelSection;
940: }
941: static void unifyBundle(const Obj<bundle_type>& bundle, const int dim, const Obj<bundle_type>& bundleNew, const Obj<send_overlap_type>& sendOverlap, const Obj<recv_overlap_type>& recvOverlap) {
942: typedef int part_type;
943: const Obj<sieve_type>& sieve = bundle->getSieve();
944: const Obj<sieve_type>& sieveNew = bundleNew->getSieve();
945: const int rank = bundle->commRank();
946: const int debug = bundle->debug();
948: // 1) Form partition point overlap a priori
949: if (rank == 0) {
950: for(int p = 1; p < sieve->commSize(); p++) {
951: // The arrow is from remote partition point 0 on rank p to local partition point 0
952: recvOverlap->addCone(p, 0, 0);
953: }
954: } else {
955: // The arrow is from local partition point 0 to remote partition point 0 on rank 0
956: sendOverlap->addCone(0, 0, 0);
957: }
958: if (debug) {
959: sendOverlap->view("Send overlap for partition");
960: recvOverlap->view("Receive overlap for partition");
961: }
962: // 2) Partition the mesh
963: int numCells = bundle->heightStratum(0)->size();
964: part_type *assignment = new part_type[numCells];
966: for(int c = 0; c < numCells; ++c) {
967: assignment[c] = 0;
968: }
969: // 3) Scatter the sieve
970: sieveCompletion::scatterSieve(bundle, sieve, dim, sieveNew, sendOverlap, recvOverlap, 0, numCells, assignment);
971: bundleNew->stratify();
972: // 4) Cleanup
973: if (assignment != NULL) delete [] assignment;
974: }
977: static Obj<ALE::Mesh<PetscInt,PetscScalar> > unifyMesh(const Obj<ALE::Mesh<PetscInt,PetscScalar> >& parallelMesh) {
978: typedef ALE::Mesh<PetscInt,PetscScalar> FlexMesh;
979: const int dim = parallelMesh->getDimension();
980: Obj<FlexMesh> serialMesh = new FlexMesh(parallelMesh->comm(), dim, parallelMesh->debug());
981: const Obj<FlexMesh::sieve_type>& serialSieve = new FlexMesh::sieve_type(parallelMesh->comm(), parallelMesh->debug());
983: ALE_LOG_EVENT_BEGIN;
984: serialMesh->setSieve(serialSieve);
985: if (parallelMesh->debug()) {
986: parallelMesh->view("Parallel topology");
987: }
989: // Unify cones
990: Obj<send_overlap_type> sendOverlap = new send_overlap_type(serialMesh->comm(), serialMesh->debug());
991: Obj<recv_overlap_type> recvOverlap = new recv_overlap_type(serialMesh->comm(), serialMesh->debug());
992: unifyBundle(parallelMesh, dim, serialMesh, sendOverlap, recvOverlap);
993: serialMesh->setDistSendOverlap(sendOverlap);
994: serialMesh->setDistRecvOverlap(recvOverlap);
996: // Unify labels
997: const typename bundle_type::labels_type& labels = parallelMesh->getLabels();
999: for(typename bundle_type::labels_type::const_iterator l_iter = labels.begin(); l_iter != labels.end(); ++l_iter) {
1000: if (serialMesh->hasLabel(l_iter->first)) continue;
1001: const Obj<typename bundle_type::label_type>& parallelLabel = l_iter->second;
1002: const Obj<typename bundle_type::label_type>& serialLabel = serialMesh->createLabel(l_iter->first);
1004: sieveCompletion::scatterCones(parallelLabel, serialLabel, sendOverlap, recvOverlap);
1005: }
1007: // Unify coordinates
1008: Obj<std::set<std::string> > sections = parallelMesh->getRealSections();
1010: for(std::set<std::string>::iterator name = sections->begin(); name != sections->end(); ++name) {
1011: serialMesh->setRealSection(*name, distributeSection(parallelMesh->getRealSection(*name), serialMesh, sendOverlap, recvOverlap));
1012: }
1013: sections = parallelMesh->getIntSections();
1014: for(std::set<std::string>::iterator name = sections->begin(); name != sections->end(); ++name) {
1015: serialMesh->setIntSection(*name, distributeSection(parallelMesh->getIntSection(*name), serialMesh, sendOverlap, recvOverlap));
1016: }
1017: sections = parallelMesh->getArrowSections();
1018: for(std::set<std::string>::iterator name = sections->begin(); name != sections->end(); ++name) {
1019: serialMesh->setArrowSection(*name, distributeArrowSection(parallelMesh->getArrowSection(*name), parallelMesh, serialMesh, sendOverlap, recvOverlap));
1020: }
1021: if (serialMesh->debug()) {serialMesh->view("Serial Mesh");}
1022: ALE_LOG_EVENT_END;
1023: return serialMesh;
1024: }
1025: public: // Do not like these
1028: // This is just crappy. We could introduce another phase to find out exactly what
1029: // indices people do not have in the global order after communication
1030: template<typename OrigSendOverlap, typename OrigRecvOverlap, typename SendSection, typename RecvSection>
1031: static void updateOverlap(const Obj<OrigSendOverlap>& origSendOverlap, const Obj<OrigRecvOverlap>& origRecvOverlap, const Obj<SendSection>& sendSection, const Obj<RecvSection>& recvSection, const Obj<send_overlap_type>& sendOverlap, const Obj<recv_overlap_type>& recvOverlap) {
1032: const typename SendSection::sheaf_type& sendRanks = sendSection->getPatches();
1033: const typename RecvSection::sheaf_type& recvRanks = recvSection->getPatches();
1035: for(typename SendSection::sheaf_type::const_iterator p_iter = sendRanks.begin(); p_iter != sendRanks.end(); ++p_iter) {
1036: const typename SendSection::patch_type& rank = p_iter->first;
1037: const Obj<typename SendSection::section_type>& section = p_iter->second;
1038: const typename SendSection::section_type::chart_type& chart = section->getChart();
1040: for(typename SendSection::section_type::chart_type::const_iterator b_iter = chart.begin(); b_iter != chart.end(); ++b_iter) {
1041: const typename SendSection::value_type *points = section->restrictPoint(*b_iter);
1042: const int size = section->getFiberDimension(*b_iter);
1044: for(int p = 0; p < size; p++) {
1045: if (origSendOverlap->support(points[p])->size() == 0) {
1046: sendOverlap->addArrow(points[p], rank, points[p]);
1047: }
1048: }
1049: }
1050: }
1051: for(typename RecvSection::sheaf_type::const_iterator p_iter = recvRanks.begin(); p_iter != recvRanks.end(); ++p_iter) {
1052: const typename RecvSection::patch_type& rank = p_iter->first;
1053: const Obj<typename RecvSection::section_type>& section = p_iter->second;
1054: const typename RecvSection::section_type::chart_type& chart = section->getChart();
1056: for(typename RecvSection::section_type::chart_type::const_iterator b_iter = chart.begin(); b_iter != chart.end(); ++b_iter) {
1057: const typename RecvSection::value_type *points = section->restrictPoint(*b_iter);
1058: const int size = section->getFiberDimension(*b_iter);
1060: for(int p = 0; p < size; p++) {
1061: if (origRecvOverlap->support(rank, points[p])->size() == 0) {
1062: recvOverlap->addArrow(rank, points[p], points[p]);
1063: }
1064: }
1065: }
1066: }
1067: }
1070: template<typename RecvOverlap, typename RecvSection>
1071: static void updateSieve(const Obj<RecvOverlap>& recvOverlap, const Obj<RecvSection>& recvSection, const Obj<sieve_type>& sieve) {
1072: #if 1
1073: Obj<typename RecvOverlap::traits::baseSequence> recvPoints = recvOverlap->base();
1075: for(typename RecvOverlap::traits::baseSequence::iterator p_iter = recvPoints->begin(); p_iter != recvPoints->end(); ++p_iter) {
1076: const Obj<typename RecvOverlap::traits::coneSequence>& ranks = recvOverlap->cone(*p_iter);
1077: const typename RecvOverlap::target_type& localPoint = *p_iter;
1079: for(typename RecvOverlap::traits::coneSequence::iterator r_iter = ranks->begin(); r_iter != ranks->end(); ++r_iter) {
1080: const typename RecvOverlap::target_type& remotePoint = r_iter.color();
1081: const int rank = *r_iter;
1082: const Obj<typename RecvSection::section_type>& section = recvSection->getSection(rank);
1083: const typename RecvSection::value_type *points = section->restrictPoint(remotePoint);
1084: const int size = section->getFiberDimension(remotePoint);
1085: int c = 0;
1087: ///std::cout << "["<<recvSection->commRank()<<"]: Receiving " << size << " points from rank " << rank << std::endl;
1088: for(int p = 0; p < size; p++) {
1089: // rank -- remote point --> local point
1090: if (recvOverlap->support(rank, points[p])->size()) {
1091: sieve->addArrow(*recvOverlap->support(rank, points[p])->begin(), localPoint, c);
1092: ///std::cout << "["<<recvSection->commRank()<<"]: 1Adding arrow " << *recvOverlap->support(rank, points[p])->begin() << "("<<points[p]<<") --> " << localPoint << std::endl;
1093: } else {
1094: sieve->addArrow(points[p], localPoint, c);
1095: ///std::cout << "["<<recvSection->commRank()<<"]: 2Adding arrow " << points[p] << " --> " << localPoint << std::endl;
1096: }
1097: }
1098: }
1099: }
1100: #else
1101: const typename RecvSection::sheaf_type& ranks = recvSection->getPatches();
1103: for(typename RecvSection::sheaf_type::const_iterator p_iter = ranks.begin(); p_iter != ranks.end(); ++p_iter) {
1104: const Obj<typename RecvSection::section_type>& section = p_iter->second;
1105: const typename RecvSection::section_type::chart_type& chart = section->getChart();
1107: for(typename RecvSection::section_type::chart_type::const_iterator b_iter = chart.begin(); b_iter != chart.end(); ++b_iter) {
1108: const typename RecvSection::value_type *points = section->restrictPoint(*b_iter);
1109: int size = section->getFiberDimension(*b_iter);
1110: int c = 0;
1112: std::cout << "["<<recvSection->commRank()<<"]: Receiving " << size << " points from rank " << p_iter->first << std::endl;
1113: for(int p = 0; p < size; p++) {
1114: //sieve->addArrow(points[p], *b_iter, c++);
1115: sieve->addArrow(points[p], *b_iter, c);
1116: std::cout << "["<<recvSection->commRank()<<"]: Adding arrow " << points[p] << " --> " << *b_iter << std::endl;
1117: }
1118: }
1119: }
1120: #endif
1121: }
1124: template<typename SendOverlap, typename RecvOverlap, typename SendSection, typename RecvSection>
1125: static void coneCompletion(const Obj<SendOverlap>& sendOverlap, const Obj<RecvOverlap>& recvOverlap, const Obj<bundle_type>& bundle, const Obj<SendSection>& sendSection, const Obj<RecvSection>& recvSection) {
1126: if (sendOverlap->commSize() == 1) return;
1127: // Distribute cones
1128: const Obj<sieve_type>& sieve = bundle->getSieve();
1129: const Obj<typename sieveCompletion::topology_type> secTopology = sieveCompletion::completion::createSendTopology(sendOverlap);
1130: const Obj<typename sieveCompletion::cone_size_section> coneSizeSection = new typename sieveCompletion::cone_size_section(bundle, sieve);
1131: const Obj<typename sieveCompletion::cone_section> coneSection = new typename sieveCompletion::cone_section(sieve);
1132: sieveCompletion::completion::completeSection(sendOverlap, recvOverlap, coneSizeSection, coneSection, sendSection, recvSection);
1133: // Update cones
1134: updateSieve(recvOverlap, recvSection, sieve);
1135: }
1138: template<typename Section>
1139: static void completeSection(const Obj<bundle_type>& bundle, const Obj<Section>& section) {
1140: typedef typename Distribution<bundle_type>::sieveCompletion sieveCompletion;
1141: typedef typename bundle_type::send_overlap_type send_overlap_type;
1142: typedef typename bundle_type::recv_overlap_type recv_overlap_type;
1143: typedef typename Section::value_type value_type;
1144: typedef typename alloc_type::template rebind<typename Section::value_type>::other value_alloc_type;
1145: typedef typename ALE::Field<send_overlap_type, int, ALE::Section<point_type, value_type, value_alloc_type> > send_section_type;
1146: typedef typename ALE::Field<recv_overlap_type, int, ALE::Section<point_type, value_type, value_alloc_type> > recv_section_type;
1147: typedef ALE::New::SizeSection<Section> SectionSizer;
1148: const int debug = section->debug();
1150: bundle->constructOverlap();
1151: const Obj<send_overlap_type> sendOverlap = bundle->getSendOverlap();
1152: const Obj<recv_overlap_type> recvOverlap = bundle->getRecvOverlap();
1153: const Obj<send_section_type> sendSection = new send_section_type(section->comm(), section->debug());
1154: const Obj<recv_section_type> recvSection = new recv_section_type(section->comm(), sendSection->getTag(), section->debug());
1155: const Obj<SectionSizer> sizer = new SectionSizer(section);
1157: sectionCompletion::completeSection(sendOverlap, recvOverlap, sizer, section, sendSection, recvSection);
1158: // Update section with remote data
1159: const Obj<typename recv_overlap_type::traits::baseSequence> recvPoints = bundle->getRecvOverlap()->base();
1161: for(typename recv_overlap_type::traits::baseSequence::iterator r_iter = recvPoints->begin(); r_iter != recvPoints->end(); ++r_iter) {
1162: const Obj<typename recv_overlap_type::traits::coneSequence>& recvPatches = recvOverlap->cone(*r_iter);
1163: const typename recv_overlap_type::traits::coneSequence::iterator end = recvPatches->end();
1165: for(typename recv_overlap_type::traits::coneSequence::iterator p_iter = recvPatches->begin(); p_iter != end; ++p_iter) {
1166: if (recvSection->getSection(*p_iter)->getFiberDimension(p_iter.color())) {
1167: if (debug) {std::cout << "["<<section->commRank()<<"]Completed point " << *r_iter << std::endl;}
1168: section->updateAddPoint(*r_iter, recvSection->getSection(*p_iter)->restrictPoint(p_iter.color()));
1169: }
1170: }
1171: }
1172: }
1173: };
1174: }
1175: #endif