39 #ifndef MESH_PARTITIONER_H 40 #define MESH_PARTITIONER_H 1
47 #include <Epetra_MpiComm.h> 50 #include <lifev/core/LifeV.hpp> 51 #include <lifev/core/util/Switch.hpp> 52 #include <lifev/core/mesh/MeshElementMarked.hpp> 53 #include <lifev/core/util/LifeDebug.hpp> 54 #include <lifev/core/fem/DOF.hpp> 55 #include <lifev/core/mesh/MeshEntity.hpp> 56 #include <lifev/core/util/LifeChrono.hpp> 57 #include <lifev/core/array/GhostHandler.hpp> 74 template<
typename MeshType>
80 typedef MeshType mesh_Type;
81 typedef std::shared_ptr<MeshType> meshPtr_Type;
82 typedef std::vector<Int> idList_Type;
83 typedef std::vector<idList_Type> graph_Type;
84 typedef std::shared_ptr<graph_Type> graphPtr_Type;
85 typedef std::vector<meshPtr_Type> partMesh_Type;
86 typedef std::shared_ptr<partMesh_Type> partMeshPtr_Type;
106 MeshPartitioner ( meshPtr_Type& mesh,
107 std::shared_ptr<Epetra_Comm>& comm,
108 Epetra_Map* interfaceMap = 0,
109 Epetra_Map* interfaceMapRep = 0 );
112 virtual ~MeshPartitioner() {}
130 void doPartition ( meshPtr_Type& mesh,
131 std::shared_ptr<Epetra_Comm>& comm,
132 Epetra_Map* interfaceMap = 0,
133 Epetra_Map* interfaceMapRep = 0 );
144 void setup (
UInt numPartitions, std::shared_ptr<Epetra_Comm> comm);
162 void attachUnpartitionedMesh (meshPtr_Type& mesh, Epetra_Map* interfaceMap = 0,
163 Epetra_Map* interfaceMapRep = 0);
170 void releaseUnpartitionedMesh();
176 void doPartitionGraph();
182 void doPartitionMesh();
185 void fillEntityPID();
191 return (*M_meshPartitions) [k];
198 void showMe (std::ostream& output = std::cout)
const;
204 const std::vector<Int>& vertexDistribution()
const 206 return M_vertexDistribution;
209 const meshPtr_Type& meshPartition()
const 211 return (*M_meshPartitions) [0];
213 meshPtr_Type& meshPartition()
215 return (*M_meshPartitions) [0];
218 const partMeshPtr_Type& meshPartitions()
const 220 return M_meshPartitions;
223 const std::vector<Int>& graphVertexLocations()
const 225 return M_graphVertexLocations;
228 const graphPtr_Type& elementDomains()
const 230 return M_elementDomains;
232 graphPtr_Type& elementDomains()
234 return M_elementDomains;
237 const std::shared_ptr<Epetra_Comm>& comm()
const 247 void setPartitionOverlap (
UInt const overlap )
249 M_partitionOverlap = overlap;
256 MeshPartitioner (
const MeshPartitioner&);
257 MeshPartitioner& operator= (
const MeshPartitioner&);
278 void distributeElements (
UInt numElements);
286 void findRepeatedFacesFSI();
297 void partitionConnectivityGraph (
UInt numParts);
303 void matchFluidPartitionsFSI();
309 void redistributeElements();
316 void constructLocalMesh();
322 void constructNodes();
328 void constructElements();
334 void constructRidges();
340 void constructFacets();
355 void markGhostEntities();
361 partMeshPtr_Type M_meshPartitions;
362 std::vector<Int> M_vertexDistribution;
363 std::vector<Int> M_adjacencyGraphKeys;
364 std::vector<Int> M_adjacencyGraphValues;
365 std::shared_ptr<Epetra_Comm> M_comm;
368 std::vector<std::vector<Int> > M_localNodes;
369 std::vector<std::set<Int> > M_localRidges;
370 std::vector<std::set<Int> > M_localFacets;
371 std::vector<std::vector<Int> > M_localElements;
372 std::vector<std::map<Int, Int> > M_globalToLocalNode;
373 std::vector<std::map<Int, Int> > M_globalToLocalElement;
374 std::vector<UInt> M_nBoundaryPoints;
375 std::vector<UInt> M_nBoundaryRidges;
376 std::vector<UInt> M_nBoundaryFacets;
379 meshPtr_Type M_originalMesh;
380 Epetra_Map* M_interfaceMap;
381 Epetra_Map* M_interfaceMapRep;
387 std::shared_ptr<std::vector<Int> > M_repeatedFacet;
388 std::shared_ptr<std::vector<Int> > M_isOnProc;
389 std::vector<Int> M_graphVertexLocations;
390 graphPtr_Type M_elementDomains;
397 idList_Type elements;
415 template <
typename MeshType >
416 MeshPartitioner < MeshType >::
422 template <
typename MeshType >
423 MeshPartitioner < MeshType >::
424 MeshPartitioner ( meshPtr_Type& mesh, std::shared_ptr<Epetra_Comm>& comm,
425 Epetra_Map* interfaceMap, Epetra_Map* interfaceMapRep)
428 doPartition ( mesh, comm, interfaceMap, interfaceMapRep );
431 template <
typename MeshType >
433 MeshPartitioner < MeshType >::
437 M_localNodes.resize ( M_numPartitions );
438 M_localRidges.resize ( M_numPartitions );
439 M_localFacets.resize ( M_numPartitions );
440 M_localElements.resize ( M_numPartitions );
441 M_globalToLocalNode.resize ( M_numPartitions );
442 M_globalToLocalElement.resize ( M_numPartitions );
443 M_nBoundaryPoints.resize ( M_numPartitions );
444 M_nBoundaryRidges.resize ( M_numPartitions );
445 M_nBoundaryFacets.resize ( M_numPartitions );
446 M_elementDomains.reset (
new graph_Type );
447 M_serialMode =
false;
448 M_partitionOverlap = 0;
455 M_elementVertices = MeshType::elementShape_Type::S_numVertices;
456 M_elementFacets = MeshType::elementShape_Type::S_numFacets;
457 M_elementRidges = MeshType::elementShape_Type::S_numRidges;
458 M_facetVertices = MeshType::facetShape_Type::S_numVertices;
462 template <
typename MeshType >
464 MeshPartitioner < MeshType >::
465 doPartition ( meshPtr_Type& mesh, std::shared_ptr<Epetra_Comm>& comm,
466 Epetra_Map* interfaceMap, Epetra_Map* interfaceMapRep )
469 M_originalMesh = mesh;
470 M_interfaceMap = interfaceMap;
471 M_interfaceMapRep = interfaceMapRep;
473 M_me = M_comm->MyPID();
475 meshPtr_Type newMesh (
new MeshType ( comm ) );
476 newMesh->setIsPartitioned (
true );
477 M_meshPartitions.reset (
new partMesh_Type ( M_numPartitions, newMesh ) );
488 template<
typename MeshType>
489 void MeshPartitioner<MeshType>::setup (
UInt numPartitions, std::shared_ptr<Epetra_Comm> comm)
493 M_me = M_comm->MyPID();
495 M_numPartitions = numPartitions;
497 M_meshPartitions.reset (
new partMesh_Type);
498 meshPtr_Type newMesh;
499 for (
UInt i = 0; i < M_numPartitions; ++i)
501 newMesh.reset (
new MeshType ( comm ) );
502 newMesh->setIsPartitioned (
true );
503 M_meshPartitions->push_back (newMesh);
507 M_elementDomains.reset (
new graph_Type);
509 M_localNodes.resize (M_numPartitions);
510 M_localRidges.resize (M_numPartitions);
511 M_localFacets.resize (M_numPartitions);
512 M_localElements.resize (M_numPartitions);
513 M_globalToLocalNode.resize (M_numPartitions);
514 M_globalToLocalElement.resize (M_numPartitions);
515 M_nBoundaryPoints.resize (M_numPartitions);
516 M_nBoundaryRidges.resize (M_numPartitions);
517 M_nBoundaryFacets.resize (M_numPartitions);
520 template<
typename MeshType>
521 void MeshPartitioner<MeshType>::update()
523 M_numPartitions = M_elementDomains->size();
527 for (
UInt i = 0; i < M_numPartitions; ++i)
529 numElements += (*M_elementDomains) [i].size();
533 M_graphVertexLocations.resize (numElements);
534 for (std::vector<std::vector<Int> >::iterator it1 = M_elementDomains->begin();
535 it1 != M_elementDomains->end(); ++it1)
537 for (std::vector<Int>::iterator it2 = it1->begin();
538 it2 != it1->end(); ++it2)
540 M_graphVertexLocations[*it2] =
static_cast<Int> ( (it1 - M_elementDomains->begin() ) );
545 template<
typename MeshType>
546 void MeshPartitioner<MeshType>::attachUnpartitionedMesh (meshPtr_Type& mesh,
547 Epetra_Map* interfaceMap,
548 Epetra_Map* interfaceMapRep)
550 M_originalMesh = mesh;
551 M_interfaceMap = interfaceMap;
552 M_interfaceMapRep = interfaceMapRep;
555 template<
typename MeshType>
556 void MeshPartitioner<MeshType>::releaseUnpartitionedMesh()
558 M_originalMesh.reset();
560 M_interfaceMapRep = 0;
563 template<
typename MeshType>
564 void MeshPartitioner<MeshType>::doPartitionGraph()
566 distributeElements (M_originalMesh->numElements() );
569 findRepeatedFacesFSI();
571 partitionConnectivityGraph (M_numPartitions);
574 matchFluidPartitionsFSI();
578 template<
typename MeshType>
579 void MeshPartitioner<MeshType>::doPartitionMesh()
585 constructLocalMesh();
618 template<
typename MeshType>
619 void MeshPartitioner<MeshType>::showMe (std::ostream& output)
const 621 output <<
"Number of partitions: " << M_numPartitions << std::endl;
622 output <<
"Serial mode:" << M_serialMode << std::endl;
629 template<
typename MeshType>
630 void MeshPartitioner<MeshType>::distributeElements (
UInt numElements)
633 Int numProcessors = M_comm->NumProc();
634 M_me = M_comm->MyPID();
639 M_vertexDistribution.resize (numProcessors + 1);
640 M_vertexDistribution[0] = 0;
642 UInt k = numElements;
645 for (
Int i = 0; i < numProcessors; ++i)
647 UInt l = k / (numProcessors - i);
648 M_vertexDistribution[i + 1] = M_vertexDistribution[i] + l;
651 ASSERT (k == 0,
"At this point we should have 0 volumes left") ;
654 template<
typename MeshType>
655 void MeshPartitioner<MeshType>::findRepeatedFacesFSI()
657 std::vector<Int> myRepeatedFacet;
658 std::shared_ptr<std::vector<Int> > myIsOnProc;
660 myIsOnProc.reset (
new std::vector<Int> (M_originalMesh->numElements() ) );
663 bool myFacet (
false);
665 for (UInt h = 0; h < M_originalMesh->numElements(); ++h)
667 (*myIsOnProc) [h] = -1;
674 for (UInt ie = 0; ie < M_originalMesh->numElements(); ++ie)
676 for (UInt ifacet = 0; ifacet < M_elementFacets; ++ifacet)
678 UInt facet = M_originalMesh->localFacetId (ie, ifacet);
679 UInt vol = M_originalMesh->facet (facet).firstAdjacentElementIdentity();
682 vol = M_originalMesh->facet (facet).secondAdjacentElementIdentity();
689 for (Int ipoint = 0; ipoint <
static_cast<Int> (M_facetVertices); ++ipoint)
691 myFacetRep = ( (M_interfaceMap->LID (
static_cast<EpetraInt_Type> (M_originalMesh->facet (facet).point (ipoint).id() ) )
693 (M_interfaceMapRep->LID (
static_cast<EpetraInt_Type> (M_originalMesh->facet (facet).point (ipoint).id() ) )
696 (M_interfaceMap->LID (
static_cast<EpetraInt_Type> (M_originalMesh->facet (facet).point (ipoint).id() ) ) != -1);
704 myRepeatedFacet.push_back (1);
708 myRepeatedFacet.push_back (0);
713 (*myIsOnProc) [ie] = M_me;
718 M_repeatedFacet.reset (
new std::vector<Int> (myRepeatedFacet.size() ) );
719 M_isOnProc.reset (
new std::vector<Int> (*myIsOnProc) );
722 std::shared_ptr<Epetra_MpiComm> mpiComm = std::dynamic_pointer_cast <Epetra_MpiComm> ( M_comm );
723 MPI_Allreduce ( &myRepeatedFacet[0], & (*M_repeatedFacet) [0], myRepeatedFacet.size(),
724 MPI_INT, MPI_SUM, mpiComm->Comm() );
725 MPI_Allreduce ( & (*myIsOnProc) [0], & (*M_isOnProc) [0], myIsOnProc->size(),
726 MPI_INT, MPI_MAX, mpiComm->Comm() );
729 template<
typename MeshType>
730 void MeshPartitioner<MeshType>::partitionConnectivityGraph (
UInt numParts)
735 M_graphVertexLocations.resize ( M_vertexDistribution[M_comm->NumProc()] - M_vertexDistribution[0], M_comm->NumProc() );
742 UInt localStart = M_vertexDistribution[M_me];
743 UInt localEnd = M_vertexDistribution[M_me + 1];
747 std::vector<Int> graphEdgeWeights;
749 M_adjacencyGraphKeys.resize (0);
750 M_adjacencyGraphKeys.push_back (0);
754 for (
UInt ie = localStart; ie < localEnd; ++ie)
756 for (
UInt ifacet = 0; ifacet < M_elementFacets; ++ifacet)
759 UInt facet = M_originalMesh->localFacetId (ie, ifacet);
761 UInt elem = M_originalMesh->facet (facet).firstAdjacentElementIdentity();
764 elem = M_originalMesh->facet (facet).secondAdjacentElementIdentity();
770 M_adjacencyGraphValues.push_back (elem);
774 if ( (*M_repeatedFacet) [sum])
776 graphEdgeWeights.push_back (0);
780 graphEdgeWeights.push_back (10);
788 M_adjacencyGraphKeys.push_back (sum);
797 Int* weightVector = 0;
815 std::vector<Int> options (3, 0);
822 std::vector<
float> tpwgts (ncon * numParts, 1. / numParts);
824 std::vector<
float> ubvec (ncon, 1.05);
826 std::shared_ptr<Epetra_MpiComm> mpiComm = std::dynamic_pointer_cast <Epetra_MpiComm> (M_comm);
827 MPI_Comm MPIcomm = mpiComm->Comm();
830 MPI_Comm_size (MPIcomm, &nprocs);
839 Int numberParts = (
Int) numParts;
842 if (graphEdgeWeights.size() > 0)
844 adjwgtPtr =
static_cast<Int*> (&graphEdgeWeights[0]);
846 ParMETIS_V3_PartKway (
static_cast<Int*> (&M_vertexDistribution[0]),
847 static_cast<Int*> (&M_adjacencyGraphKeys[0]),
848 static_cast<Int*> (&M_adjacencyGraphValues[0]),
849 weightVector, adjwgtPtr, &weightFlag, &numflag,
850 &ncon, &numberParts, &tpwgts[0], &ubvec[0],
851 &options[0], &cutGraphEdges, &M_graphVertexLocations[localStart],
856 Int nProc = M_comm->NumProc();
859 for (
Int proc = 0; proc < nProc; proc++ )
861 UInt procStart = M_vertexDistribution[ proc ];
862 UInt procLength = M_vertexDistribution[ proc + 1 ] - M_vertexDistribution[ proc ];
863 M_comm->Broadcast ( &M_graphVertexLocations[ procStart ], procLength, proc );
868 (*M_elementDomains).resize (numParts);
871 for (UInt ii = 0; ii < M_graphVertexLocations.size(); ++ii)
874 (*M_elementDomains) [ M_graphVertexLocations[ ii ] ].push_back ( ii );
878 template<
typename MeshType>
879 void MeshPartitioner<MeshType>::matchFluidPartitionsFSI()
881 std::shared_ptr<Epetra_MpiComm> mpiComm = std::dynamic_pointer_cast <Epetra_MpiComm> (M_comm);
882 MPI_Comm MPIcomm = mpiComm->Comm();
884 MPI_Comm_size (MPIcomm, &numProcesses);
886 std::vector<Int> procOrder (numProcesses);
887 std::vector<std::vector<UInt> > myMatchesForProc (numProcesses);
888 std::vector<std::vector<UInt> > matchesForProc (numProcesses);
889 std::vector<
bool> orderingError (numProcesses);
891 for (
Int i = 0; i < numProcesses ; ++i)
893 orderingError[i] =
false;
894 for (
Int j = 0; j < numProcesses ; ++j)
896 myMatchesForProc[i].push_back (0);
897 matchesForProc[i].push_back (0);
901 for (UInt kk = 0; kk < M_graphVertexLocations.size(); ++kk)
903 if ( (*M_isOnProc) [kk + M_vertexDistribution[M_me]] != -1)
905 ++myMatchesForProc[M_graphVertexLocations[kk]][ (*M_isOnProc) [kk + M_vertexDistribution[M_me]]];
909 for (
UInt j = 0; (
Int) j < numProcesses; ++j)
911 MPI_Allreduce (&myMatchesForProc[j][0], &matchesForProc[j][0], numProcesses,
912 MPI_INT, MPI_SUM, MPIcomm);
917 Int suitableProcess = -1;
920 for (
Int ii = 0; ii < numProcesses; ++ii)
922 if (matchesForProc[M_me][ii] > max)
924 suitableProcess = ii;
925 max = matchesForProc[M_me][ii];
929 ASSERT (suitableProcess != -1,
"one partition is without interface nodes!");
930 procOrder[M_me] = suitableProcess;
934 std::vector<UInt> maxs (numProcesses);
936 for (
Int j = 0; j < numProcesses ; ++j)
938 MPI_Bcast (&maxs[j], 1, MPI_INT, j, MPIcomm);
941 std::vector<std::pair<UInt, Int> > procIndex (numProcesses);
942 for (
Int k = 0; k < numProcesses; ++k)
944 procIndex[k] = std::make_pair ( maxs[k], k);
947 std::sort (procIndex.begin(), procIndex.end() );
949 for (
Int l = 0; l < numProcesses; ++l)
951 for (
Int l = 0; l < numProcesses; ++l)
953 for (
Int j = 0; j < numProcesses ; ++j)
955 MPI_Bcast ( &procOrder[j], 1, MPI_INT, j, MPIcomm);
960 std::vector< std::vector<Int> > locProc2 ( (*M_elementDomains) );
961 for (
Int j = numProcesses - 1; j >= 0 ; --j)
963 if (orderingError[procOrder[procIndex[j].second]] ==
false)
965 (*M_elementDomains) [procOrder[procIndex[j].second]] = locProc2[procIndex[j].second];
969 std::cout <<
"Ordering error when assigning the processor" 970 << M_me <<
" to the partition," << std::endl
971 <<
" parmetis did a bad job." << std::endl;
972 for (
Int i = numProcesses - 1; i >= 0; --i)
974 if (orderingError[procIndex[i].second] ==
false)
977 procOrder[procIndex[j].second] = procIndex[i].second;
978 (*M_elementDomains) [procIndex[i].second] = locProc2[procIndex[j].second];
983 orderingError[procOrder[procIndex[j].second]] =
true;
987 template<
typename MeshType>
988 void MeshPartitioner<MeshType>::redistributeElements()
990 std::shared_ptr<Epetra_MpiComm> mpiComm = std::dynamic_pointer_cast <Epetra_MpiComm> (M_comm);
991 MPI_Comm MPIcomm = mpiComm->Comm();
993 MPI_Comm_size (MPIcomm, &numProcesses);
996 std::vector<Int> sendSize ( numProcesses );
997 std::vector<Int> receiveSize ( numProcesses );
1007 for (
Int iproc = 0; iproc < numProcesses; ++iproc)
1009 sendSize[iproc] = (*M_elementDomains) [iproc].size();
1011 MPI_Alltoall ( &sendSize[ 0 ], 1, MPI_INT, &receiveSize[ 0 ], 1, MPI_INT, MPIcomm );
1013 for (
Int iproc = 0; iproc < numProcesses; ++iproc)
1015 if (
static_cast<
Int> (M_me) != iproc)
1017 size = sendSize[iproc];
1023 Int sizePart = size;
1026 while (sizePart > maxInt)
1029 sizePart = size / incr;
1032 MPI_Send (&incr, 1, MPI_INT, iproc, 20, MPIcomm);
1033 MPI_Send (&sizePart, 1, MPI_INT, iproc, 30, MPIcomm);
1035 for (
Int kk = 0; kk < incr; ++kk)
1037 MPI_Send (&pos, 1, MPI_INT, iproc, 100 + kk, MPIcomm);
1038 MPI_Send (& (*M_elementDomains) [iproc][pos], sizePart, MPI_INT, iproc,
1039 5000000 + kk, MPIcomm);
1040 pos = pos + sizePart;
1043 Int resto = size % incr;
1045 MPI_Send (&resto, 1, MPI_INT, iproc, 80, MPIcomm);
1049 MPI_Send (&pos, 1, MPI_INT, iproc, 40, MPIcomm);
1050 MPI_Send (& (*M_elementDomains) [iproc][pos], resto, MPI_INT, iproc, 50, MPIcomm);
1057 MPI_Send (& (*M_elementDomains) [iproc][0], size, MPI_INT, iproc, 60, MPIcomm);
1063 for (
Int jproc = 0; jproc < numProcesses; ++jproc)
1067 size = receiveSize[jproc];
1068 std::vector<Int> stack (size, 0);
1072 Int sizePart, pos, incr;
1074 MPI_Recv (&incr, 1, MPI_INT, jproc, 20, MPIcomm, &status);
1075 MPI_Recv (&sizePart, 1, MPI_INT, jproc, 30, MPIcomm, &status);
1077 for (
Int kk = 0; kk < incr; ++kk)
1079 MPI_Recv (&pos, 1, MPI_INT, jproc, 100 + kk, MPIcomm, &status);
1080 MPI_Recv (&stack[pos], sizePart , MPI_INT, jproc, 5000000 + kk, MPIcomm, &status);
1083 MPI_Recv (&resto, 1, MPI_INT, jproc, 80, MPIcomm, &status);
1087 MPI_Recv (&pos, 1, MPI_INT, jproc, 40, MPIcomm, &status);
1088 MPI_Recv (&stack[pos], resto, MPI_INT, jproc, 50, MPIcomm, &status);
1095 MPI_Recv (&stack[0], size , MPI_INT, jproc, 60, MPIcomm, &status);
1098 for (
Int jj = 0; jj < size; ++jj)
1100 (*M_elementDomains) [M_me].push_back (stack[jj]);
1108 template<
typename MeshType>
1109 void MeshPartitioner<MeshType>::constructLocalMesh()
1113 std::cout <<
"Building local mesh ..." << std::endl;
1116 std::map<Int, Int>::iterator im;
1122 for (
UInt i = 0; i < M_numPartitions; ++i)
1127 UInt me = M_serialMode ? i : M_me;
1129 for (UInt jj = 0; jj < (*M_elementDomains) [me].size(); ++jj)
1131 ielem = (*M_elementDomains) [me][jj];
1132 M_localElements[i].push_back (ielem);
1135 for (UInt ii = 0; ii < M_elementVertices; ++ii)
1137 inode = M_originalMesh->element (ielem).point (ii).id();
1138 im = M_globalToLocalNode[i].find (inode);
1141 if (im == M_globalToLocalNode[i].end() )
1143 M_globalToLocalNode[i].insert (std::make_pair (inode, count) );
1146 M_localNodes[i].push_back (M_originalMesh->element (ielem).point (ii).id() );
1151 for (UInt ii = 0; ii < M_elementRidges; ++ii)
1154 M_localRidges[i].insert (M_originalMesh->localRidgeId (ielem, ii) );
1158 for (UInt ii = 0; ii < M_elementFacets; ++ii)
1161 M_localFacets[i].insert (M_originalMesh->localFacetId (ielem, ii) );
1167 template<
typename MeshType>
1168 void MeshPartitioner<MeshType>::constructNodes()
1171 for (
UInt i = 0; i < M_numPartitions; ++i)
1173 std::vector<Int>::iterator it;
1175 M_nBoundaryPoints[i] = 0;
1176 (*M_meshPartitions) [i]->pointList.reserve (M_localNodes[i].size() );
1178 (*M_meshPartitions) [i]->_bPoints.reserve (M_originalMesh->numBPoints() * M_localNodes[i].size() /
1179 M_originalMesh->numBPoints() );
1183 typename MeshType::point_Type* pp = 0;
1187 for (it = M_localNodes[i].begin(); it != M_localNodes[i].end(); ++it, ++inode)
1190 bool boundary = M_originalMesh->isBoundaryPoint (*it);
1191 M_nBoundaryPoints[i] += boundary;
1193 pp = & (*M_meshPartitions) [i]->addPoint ( boundary,
false );
1194 *pp = M_originalMesh->point ( *it );
1196 pp->setLocalId ( inode );
1202 template<
typename MeshType>
1203 void MeshPartitioner<MeshType>::constructElements()
1206 for (
UInt i = 0; i < M_numPartitions; ++i)
1208 std::map<Int, Int>::iterator im;
1209 std::vector<Int>::iterator it;
1213 typename MeshType::element_Type* pv = 0;
1215 (*M_meshPartitions) [i]->elementList().reserve (M_localElements[i].size() );
1220 for (it = M_localElements[i].begin(); it != M_localElements[i].end(); ++it, ++count)
1222 pv = & ( (*M_meshPartitions) [i]->addElement() );
1223 *pv = M_originalMesh->element (*it);
1224 pv->setLocalId (count);
1226 M_globalToLocalElement[i].insert (std::make_pair ( pv->id(), pv -> localId() ) );
1228 for (ID id = 0; id < M_elementVertices; ++id)
1230 inode = M_originalMesh->element (*it).point (id).id();
1234 im = M_globalToLocalNode[i].find (inode);
1235 pv->setPoint (id, (*M_meshPartitions) [i]->point ( (*im).second ) );
1241 template<
typename MeshType>
1242 void MeshPartitioner<MeshType>::constructRidges()
1244 if (mesh_Type::S_geoDimensions == 2)
1246 M_nBoundaryRidges = M_nBoundaryPoints;
1248 else if (mesh_Type::S_geoDimensions == 3)
1251 for (
UInt i = 0; i < M_numPartitions; ++i)
1253 std::map<Int, Int>::iterator im;
1254 std::set<Int>::iterator is;
1256 typename MeshType::ridge_Type* pe;
1260 M_nBoundaryRidges[i] = 0;
1261 (*M_meshPartitions) [i]->ridgeList().reserve (M_localRidges[i].size() );
1264 for (is = M_localRidges[i].begin(); is != M_localRidges[i].end(); ++is, ++count)
1267 bool boundary = (M_originalMesh->isBoundaryRidge (*is) );
1270 M_nBoundaryRidges[i] += boundary;
1272 pe = & (*M_meshPartitions) [i]->addRidge (boundary);
1273 *pe = M_originalMesh->ridge ( *is );
1275 pe->setLocalId (count);
1277 for (ID id = 0; id < 2; ++id)
1279 inode = M_originalMesh->ridge (*is).point (id).id();
1283 im = M_globalToLocalNode[i].find (inode);
1284 pe->setPoint (id, (*M_meshPartitions) [i]->pointList ( (*im).second) );
1292 template<
typename MeshType>
1293 void MeshPartitioner<MeshType>::constructFacets()
1296 for (
UInt i = 0; i < M_numPartitions; ++i)
1298 std::map<Int, Int>::iterator im;
1299 std::set<Int>::iterator is;
1301 typename MeshType::facet_Type* pf = 0;
1306 M_nBoundaryFacets[i] = 0;
1307 (*M_meshPartitions) [i]->facetList().reserve (M_localFacets[i].size() );
1310 for (is = M_localFacets[i].begin(); is != M_localFacets[i].end(); ++is, ++count)
1313 bool boundary = (M_originalMesh->isBoundaryFacet (*is) );
1315 M_nBoundaryFacets[i] += boundary;
1318 Int elem1 = M_originalMesh->facet (*is).firstAdjacentElementIdentity();
1319 Int elem2 = M_originalMesh->facet (*is).secondAdjacentElementIdentity();
1322 im = M_globalToLocalElement[i].find (elem1);
1326 if (im == M_globalToLocalElement[i].end() )
1328 localElem1 = NotAnId;
1332 localElem1 = (*im).second;
1335 im = M_globalToLocalElement[i].find (elem2);
1338 if (im == M_globalToLocalElement[i].end() )
1340 localElem2 = NotAnId;
1344 localElem2 = (*im).second;
1347 pf = & (*M_meshPartitions) [i]->addFacet (boundary);
1348 *pf = M_originalMesh->facet ( *is );
1350 pf->setLocalId ( count );
1352 for (ID id = 0; id < M_originalMesh->facet (*is).S_numLocalVertices; ++id)
1354 inode = pf->point (id).id();
1355 im = M_globalToLocalNode[i].find (inode);
1356 pf->setPoint (id, (*M_meshPartitions) [i]->pointList ( (*im).second) );
1360 ID ghostElem = ( localElem1 == NotAnId ) ? elem1 : elem2;
1362 if ( !boundary && ( localElem1 == NotAnId || localElem2 == NotAnId ) )
1365 pf->setFlag ( EntityFlags::SUBDOMAIN_INTERFACE );
1367 for ( UInt pointOnFacet = 0; pointOnFacet < MeshType::facet_Type::S_numLocalPoints; pointOnFacet++ )
1369 (*M_meshPartitions) [i]->point ( pf->point ( pointOnFacet ).localId() ).setFlag ( EntityFlags::SUBDOMAIN_INTERFACE );
1382 ASSERT ( (localElem1 != NotAnId) || (localElem2 != NotAnId),
"A hanging facet in mesh partitioner!");
1384 if ( localElem1 == NotAnId )
1386 pf->firstAdjacentElementIdentity() = localElem2;
1387 pf->firstAdjacentElementPosition() = M_originalMesh->facet (*is).secondAdjacentElementPosition();
1388 pf->secondAdjacentElementIdentity() = ghostElem;
1389 pf->secondAdjacentElementPosition() = NotAnId;
1390 pf->reversePoints();
1392 else if ( localElem2 == NotAnId )
1394 pf->firstAdjacentElementIdentity() = localElem1;
1395 pf->firstAdjacentElementPosition() = M_originalMesh->facet (*is).firstAdjacentElementPosition();
1396 pf->secondAdjacentElementIdentity() = ghostElem;
1397 pf->secondAdjacentElementPosition() = NotAnId;
1401 pf->firstAdjacentElementIdentity() = localElem1;
1402 pf->firstAdjacentElementPosition() = M_originalMesh->facet (*is).firstAdjacentElementPosition();
1403 pf->secondAdjacentElementIdentity() = localElem2;
1404 pf->secondAdjacentElementPosition() = M_originalMesh->facet (*is).secondAdjacentElementPosition();
1408 (*M_meshPartitions) [i]->setLinkSwitch (
"HAS_ALL_FACETS");
1409 (*M_meshPartitions) [i]->setLinkSwitch (
"FACETS_HAVE_ADIACENCY");
1414 template<
typename MeshType>
1415 void MeshPartitioner<MeshType>::finalSetup()
1417 for (
UInt i = 0; i < M_numPartitions; ++i)
1419 UInt nElements = M_localElements[i].size();
1420 UInt nNodes = M_localNodes[i].size();
1421 UInt nRidges = M_localRidges[i].size();
1422 UInt nFacets = M_localFacets[i].size();
1424 (*M_meshPartitions) [i]->setMaxNumPoints (nNodes,
true);
1425 (*M_meshPartitions) [i]->setMaxNumRidges (nRidges,
true);
1426 (*M_meshPartitions) [i]->setMaxNumFacets (nFacets,
true);
1427 (*M_meshPartitions) [i]->setMaxNumElements ( nElements,
true);
1429 (*M_meshPartitions) [i]->setMaxNumGlobalPoints (M_originalMesh->numPoints() );
1430 (*M_meshPartitions) [i]->setNumGlobalVertices (M_originalMesh->numVertices() );
1431 (*M_meshPartitions) [i]->setMaxNumGlobalRidges (M_originalMesh->numRidges() );
1432 (*M_meshPartitions) [i]->setMaxNumGlobalFacets (M_originalMesh->numFacets() );
1434 (*M_meshPartitions) [i]->setMaxNumGlobalElements (M_originalMesh->numElements() );
1435 (*M_meshPartitions) [i]->setNumBoundaryFacets (M_nBoundaryFacets[i]);
1437 (*M_meshPartitions) [i]->setNumBPoints (M_nBoundaryPoints[i]);
1438 (*M_meshPartitions) [i]->setNumBoundaryRidges (M_nBoundaryRidges[i]);
1440 (*M_meshPartitions) [i]->setNumVertices (nNodes );
1441 (*M_meshPartitions) [i]->setNumBVertices (M_nBoundaryPoints[i]);
1443 if (MeshType::S_geoDimensions == 3)
1445 (*M_meshPartitions) [i]->updateElementRidges();
1448 (*M_meshPartitions) [i]->updateElementFacets();
1450 #ifdef HAVE_LIFEV_DEBUG 1453 debugStream (4000) <<
"Created local mesh number " << i <<
"\n";
1457 debugStream (4000) <<
"Rank " << M_me <<
" created local mesh.\n";
1463 template<
typename MeshType>
1464 void MeshPartitioner<MeshType>::execute()
1469 distributeElements (M_originalMesh->numElements() );
1488 findRepeatedFacesFSI();
1493 partitionConnectivityGraph (M_comm->NumProc() );
1498 matchFluidPartitionsFSI();
1502 #ifdef HAVE_LIFEV_DEBUG 1503 debugStream (4000) << M_me <<
" has " << (*M_elementDomains) [M_me].size() <<
" elements.\n";
1507 if ( M_partitionOverlap > 0 )
1510 gh.extendGraphFE ( M_elementDomains, M_entityPID.points, M_partitionOverlap );
1519 releaseUnpartitionedMesh();
1528 template<
typename MeshType>
1529 void MeshPartitioner<MeshType>::fillEntityPID ()
1531 Int numParts = (M_numPartitions > 1) ? M_numPartitions : M_comm->NumProc();
1534 M_entityPID.points.resize ( M_originalMesh->numPoints(), 0 );
1535 M_entityPID.elements.resize ( M_originalMesh->numElements(), 0 );
1536 M_entityPID.facets.resize ( M_originalMesh->numFacets(), 0 );
1537 M_entityPID.ridges.resize ( M_originalMesh->numRidges(), 0 );
1541 for (
Int p = 1; p < numParts; p++ )
1543 for ( UInt e = 0; e < (*M_elementDomains) [ p ].size(); e++ )
1546 for ( UInt k = 0; k < mesh_Type::element_Type::S_numPoints; k++ )
1548 const ID& pointID = M_originalMesh->element ( (*M_elementDomains) [ p ][ e ] ).point ( k ).id();
1550 M_entityPID.points[ pointID ] = std::max ( M_entityPID.points[ pointID ], p );
1554 const ID& elemID = M_originalMesh->element ( (*M_elementDomains) [ p ][ e ] ).id();
1556 M_entityPID.elements[ elemID ] = p;
1559 for ( UInt k = 0; k < mesh_Type::element_Type::S_numFacets; k++ )
1561 const ID& facetID = M_originalMesh->facet ( M_originalMesh->localFacetId ( elemID, k ) ).id();
1563 M_entityPID.facets[ facetID ] = std::max ( M_entityPID.facets[ facetID ], p );
1567 for ( UInt k = 0; k < mesh_Type::element_Type::S_numRidges; k++ )
1569 const ID& ridgeID = M_originalMesh->ridge ( M_originalMesh->localRidgeId ( elemID, k ) ).id();
1571 M_entityPID.ridges[ ridgeID ] = std::max ( M_entityPID.ridges[ ridgeID ], p );
1577 template<
typename MeshType>
1578 void MeshPartitioner<MeshType>::markGhostEntities()
1583 for (
UInt i = 0; i < M_numPartitions; ++i)
1585 Int const procId = (M_numPartitions > 1) ? i : M_me;
1586 for ( UInt e = 0; e < (*M_meshPartitions) [ i ]->numElements(); e++ )
1588 typename MeshType::element_Type& element = (*M_meshPartitions) [ i ]->element ( e );
1589 if ( M_entityPID.elements[ element.id() ] != procId )
1591 element.setFlag ( EntityFlags::GHOST );
1595 for ( UInt f = 0; f < (*M_meshPartitions) [ i ]->numFacets(); f++ )
1597 typename MeshType::facet_Type& facet = (*M_meshPartitions) [ i ]->facet ( f );
1598 if ( M_entityPID.facets[ facet.id() ] != procId )
1600 facet.setFlag ( EntityFlags::GHOST );
1604 for ( UInt r = 0; r < (*M_meshPartitions) [ i ]->numRidges(); r++ )
1606 typename MeshType::ridge_Type& ridge = (*M_meshPartitions) [ i ]->ridge ( r );
1607 if ( M_entityPID.ridges[ ridge.id() ] != procId )
1609 ridge.setFlag ( EntityFlags::GHOST );
1613 for ( UInt p = 0; p < (*M_meshPartitions) [ i ]->numPoints(); p++ )
1615 typename MeshType::point_Type& point = (*M_meshPartitions) [ i ]->point ( p );
1616 if ( M_entityPID.points[ point.id() ] != procId )
1618 point.setFlag ( EntityFlags::GHOST );
1622 clearVector ( M_entityPID.elements );
1623 clearVector ( M_entityPID.facets );
1624 clearVector ( M_entityPID.ridges );
1625 clearVector ( M_entityPID.points );
1628 template<
typename MeshType>
1629 void MeshPartitioner<MeshType>::cleanUp()
1631 clearVector ( M_vertexDistribution );
1632 clearVector ( M_adjacencyGraphKeys );
1633 clearVector ( M_adjacencyGraphValues );
1634 clearVector ( M_localNodes );
1635 clearVector ( M_localRidges );
1636 clearVector ( M_localFacets );
1637 clearVector ( M_localElements );
1638 clearVector ( M_nBoundaryPoints );
1639 clearVector ( M_nBoundaryRidges );
1640 clearVector ( M_nBoundaryFacets );
1641 clearVector ( M_graphVertexLocations );
1642 clearVector ( M_globalToLocalNode );
1643 clearVector ( M_globalToLocalElement );
int32_type Int
Generic integer data.
void updateInverseJacobian(const UInt &iQuadPt)
#define LIFEV_DEPRECATED(func)
void importFromHDF5(std::string const &fileName="ghostmap")
Import neighbor lists to an hdf5 file.
uint32_type UInt
generic unsigned integer (used mainly for addressing)