5#ifndef DUNE_ISTL_REPARTITION_HH
6#define DUNE_ISTL_REPARTITION_HH
50#if HAVE_PARMETIS && defined(REALTYPEWIDTH)
56#if HAVE_PARMETIS && defined(IDXTYPEWIDTH)
58#elif HAVE_PARMETIS && defined(HAVE_SCOTCH_NUM_TYPE)
59 using idx_t = SCOTCH_Num;
82 template<
class G,
class T1,
class T2>
86 typedef typename IndexSet::LocalIndex::Attribute Attribute;
88 IndexSet& indexSet = oocomm.indexSet();
91 std::size_t sum=0, needed = graph.noVertices()-indexSet.size();
95 for(
int i=0; i<oocomm.communicator().
size(); ++i)
104 auto end = indexSet.
end();
105 for(
auto it = indexSet.begin(); it !=
end; ++it)
111 maxgi=oocomm.communicator().
max(maxgi);
114 for(
int i=0; i<oocomm.communicator().
rank(); ++i)
115 maxgi=maxgi+neededall[i];
120 indexSet.beginResize();
122 for(
auto vertex = graph.begin(), vend=graph.end(); vertex != vend; ++vertex) {
123 const typename IndexSet::IndexPair*
pair=lookup.
pair(*vertex);
131 indexSet.endResize();
135 oocomm.freeGlobalLookup();
136 oocomm.buildGlobalLookup();
146 class ParmetisDuneIndexMap
149 template<
class Graph,
class OOComm>
150 ParmetisDuneIndexMap(
const Graph& graph,
const OOComm& com);
151 int toParmetis(
int i)
const
153 return duneToParmetis[i];
155 int toLocalParmetis(
int i)
const
157 return duneToParmetis[i]-base_;
161 return duneToParmetis[i];
163 int toDune(
int i)
const
165 return parmetisToDune[i];
169 return parmetisToDune.size();
184 template<
class G,
class OOComm>
185 ParmetisDuneIndexMap::ParmetisDuneIndexMap(
const G& graph,
const OOComm& oocomm)
186 : duneToParmetis(graph.noVertices(), -1), vtxDist_(oocomm.
communicator().
size()+1)
188 int npes=oocomm.communicator().size(), mype=oocomm.communicator().rank();
190 typedef typename OOComm::OwnerSet OwnerSet;
193 auto end = oocomm.indexSet().end();
195 if (OwnerSet::contains(
index->local().attribute())) {
199 parmetisToDune.resize(numOfOwnVtx);
202 MPI_Allgather(&numOfOwnVtx, 1, MPI_INT, &(globalNumOfVtx[0]), 1, MPI_INT, oocomm.communicator());
206 for(
int i=0; i<npes; i++) {
208 base += globalNumOfVtx[i];
210 vtxDist_[i+1] = vtxDist_[i] + globalNumOfVtx[i];
216 std::cout << oocomm.communicator().rank()<<
" vtxDist: ";
217 for(
int i=0; i<= npes; ++i)
226 auto vend = graph.end();
227 for(
auto vertex = graph.begin(); vertex != vend; ++vertex) {
228 const typename OOComm::ParallelIndexSet::IndexPair*
index=oocomm.globalLookup().pair(*vertex);
230 if (OwnerSet::contains(
index->local().attribute())) {
232 parmetisToDune[base-base_]=
index->local();
233 duneToParmetis[
index->local()] = base++;
243 std::cout <<oocomm.communicator().rank()<<
": before ";
248 oocomm.copyOwnerToAll(duneToParmetis,duneToParmetis);
250 std::cout <<oocomm.communicator().rank()<<
": after ";
265 template<
class Flags,
class IS>
270 for(
auto i=idxset.begin(),
end=idxset.end(); i!=
end; ++i)
271 if(Flags::contains(i->local().attribute()))
272 ++sizes[toPart[i->local()]];
276 interfaces()[i->first].first.reserve(i->second);
279 for(
auto i=idxset.begin(),
end=idxset.end(); i!=
end; ++i)
280 if(Flags::contains(i->local().attribute()))
281 interfaces()[toPart[i->local()]].first.add(i->local());
292 template<
typename TG>
296 for(
auto idx=indices.begin(); idx!= indices.end(); ++idx) {
324 MPI_Pack(&s, 1, MPITraits<std::size_t>::getType(), sendBuf, buffersize, &pos, comm);
325 MPI_Pack(&(ownerVec[0]), s, MPITraits<GI>::getType(), sendBuf, buffersize, &pos, comm);
326 s = overlapVec.
size();
327 MPI_Pack(&s, 1, MPITraits<std::size_t>::getType(), sendBuf, buffersize, &pos, comm);
328 for(
auto i=overlapVec.
begin(),
end= overlapVec.
end(); i !=
end; ++i)
329 MPI_Pack(
const_cast<GI*
>(&(*i)), 1, MPITraits<GI>::getType(), sendBuf, buffersize, &pos, comm);
332 MPI_Pack(&s, 1, MPITraits<std::size_t>::getType(), sendBuf, buffersize, &pos, comm);
334 for(
auto i=neighbors.
begin(),
end= neighbors.
end(); i !=
end; ++i)
335 MPI_Pack(
const_cast<int*
>(&(*i)), 1, MPI_INT, sendBuf, buffersize, &pos, comm);
351 MPI_Unpack(recvBuf, bufferSize, &pos, &
size, 1, MPITraits<std::size_t>::getType(), comm);
352 inf.reserveSpaceForReceiveInterface(from,
size);
356 MPI_Unpack(recvBuf, bufferSize, &pos, &gi, 1, MPITraits<GI>::getType(), comm);
360 MPI_Unpack(recvBuf, bufferSize, &pos, &
size, 1, MPITraits<std::size_t>::getType(), comm);
365 MPI_Unpack(recvBuf, bufferSize, &pos, &gi, 1, MPITraits<GI>::getType(), comm);
366 ipos=overlapVec.
insert(ipos, gi);
369 MPI_Unpack(recvBuf, bufferSize, &pos, &
size, 1, MPITraits<std::size_t>::getType(), comm);
374 MPI_Unpack(recvBuf, bufferSize, &pos, &n, 1, MPI_INT, comm);
375 npos=neighbors.
insert(npos, n);
393 void getDomain(
const MPI_Comm& comm, T *part,
int numOfOwnVtx,
int nparts,
int *myDomain,
std::vector<int> &domainMapping) {
395 MPI_Comm_size(comm, &npes);
396 MPI_Comm_rank(comm, &mype);
406 domainMapping.
assign(domainMapping.
size(), -1);
409 for (i=0; i<numOfOwnVtx; i++) {
416 int *buf =
new int[nparts];
417 for (i=0; i<nparts; i++) {
419 domainMatrix[mype*nparts+i] = domain[i];
422 int src = (mype-1+npes)%npes;
423 int dest = (mype+1)%npes;
425 for (i=0; i<npes-1; i++) {
426 MPI_Sendrecv_replace(buf, nparts, MPI_INT, dest, 0, src, 0, comm, &status);
428 pe = ((mype-1-i)+npes)%npes;
429 for(j=0; j<nparts; j++) {
431 domainMatrix[pe*nparts+j] = buf[j];
439 int maxOccurance = 0;
443 for(i=0; i<nparts; i++) {
444 for(j=0; j<npes; j++) {
446 if (assigned[j]==0) {
447 if (maxOccurance < domainMatrix[j*nparts+i]) {
448 maxOccurance = domainMatrix[j*nparts+i];
456 domainMapping[i] = pe;
473 for(
auto udomain = unassigned.
begin(),
474 end = unassigned.
end(); udomain !=
end; ++udomain)
477 assert(next_free != assigned.end());
478 domainMapping[*udomain] = next_free-assigned.
begin();
486 bool operator()(
const T& t1,
const T& t2)
const
508 if(ownerVec.
size()>0)
510 auto old=ownerVec.
begin();
511 for(
auto i=old+1,
end=ownerVec.
end(); i !=
end; old=i++)
513 if(i->first==old->first)
515 std::cerr<<
"Value at indes"<<old-ownerVec.
begin()<<
" is the same as at index "
516 <<i-ownerVec.
begin()<<
" ["<<old->first<<
","<<old->second<<
"]==["
517 <<i->first<<
","<<i->second<<
"]"<<
std::endl;
525 auto v=ownerVec.
begin(), vend=ownerVec.
end();
526 for(
auto s=overlapSet.
begin(), send=overlapSet.
end(); s!=send;)
528 while(v!=vend && v->first<*s) ++v;
529 if(v!=vend && v->first==*s) {
534 overlapSet.
erase(tmp);
554 template<
class OwnerSet,
class Graph,
class IS,
class GI>
556 typename Graph::VertexDescriptor vtx,
const IS& indexSet,
558 for(
auto edge=g.beginEdges(vtx),
end=g.endEdges(vtx); edge!=
end; ++edge)
560 const typename IS::IndexPair* pindex = indexSet.pair(edge.target());
562 if(part[pindex->local()]!=toPe || !OwnerSet::contains(pindex->local().attribute()))
565 neighbor.
insert(pindex->global());
566 neighborProcs.
insert(part[pindex->local()]);
571 template<
class T,
class I>
577 template<
class T,
class I>
588 redist.reserveSpaceForReceiveInterface(proc, ownerVec.
size());
609 template<
class OwnerSet,
class G,
class IS,
class T,
class GI>
610 void getOwnerOverlapVec(
const G& graph,
std::vector<int>& part, IS& indexSet,
612 RedistributeInterface& redist,
std::set<int>& neighborProcs) {
615 if(OwnerSet::contains(
index->local().attribute()))
617 if(part[
index->local()]==toPe)
619 getNeighbor<OwnerSet>(graph, part,
index->local(), indexSet,
620 toPe, overlapSet, neighborProcs);
621 my_push_back(ownerVec,
index->global(), toPe);
625 reserve(ownerVec, redist, toPe);
636 template<
class F,
class IS>
637 inline bool isOwner(IS& indexSet,
int index) {
639 const typename IS::IndexPair* pindex=indexSet.pair(
index);
642 return F::contains(pindex->local().attribute());
646 class BaseEdgeFunctor
649 BaseEdgeFunctor(Metis::idx_t* adj,
const ParmetisDuneIndexMap& data)
650 : i_(), adj_(adj), data_(
data)
658 adj_[i_] = data_.toParmetis(edge.target());
669 const ParmetisDuneIndexMap& data_;
674 :
public BaseEdgeFunctor
676 EdgeFunctor(Metis::idx_t* adj,
const ParmetisDuneIndexMap& data,
std::size_t)
677 : BaseEdgeFunctor(adj,
data)
680 Metis::idx_t* getWeights()
687 template<
class G,
class V,
class E,
class VM,
class EM>
688 class EdgeFunctor<
Dune::Amg::PropertiesGraph<G,V,E,VM,EM> >
689 :
public BaseEdgeFunctor
692 EdgeFunctor(Metis::idx_t* adj,
const ParmetisDuneIndexMap& data,
std::size_t s)
693 : BaseEdgeFunctor(adj,
data)
695 weight_=
new Metis::idx_t[s];
701 weight_[
index()]=edge.properties().depends() ? 3 : 1;
702 BaseEdgeFunctor::operator()(edge);
704 Metis::idx_t* getWeights()
713 Metis::idx_t* weight_;
731 template<
class F,
class G,
class IS,
class EW>
732 void getAdjArrays(G& graph, IS& indexSet, Metis::idx_t *xadj,
736 auto vend = graph.end();
738 for(
auto vertex = graph.begin(); vertex != vend; ++vertex) {
739 if (isOwner<F>(indexSet,*vertex)) {
741 auto eend = vertex.end();
742 xadj[j] = ew.index();
744 for(
auto edge = vertex.begin(); edge != eend; ++edge) {
749 xadj[j] = ew.index();
753 template<
class G,
class T1,
class T2>
757 RedistributeInterface& redistInf,
760#ifndef METIS_VER_MAJOR
764 void METIS_PartGraphKway(
int *nvtxs, Metis::idx_t *xadj, Metis::idx_t *adjncy, Metis::idx_t *vwgt,
765 Metis::idx_t *adjwgt,
int *wgtflag,
int *numflag,
int *nparts,
766 int *options,
int *edgecut, Metis::idx_t *part);
768 void METIS_PartGraphRecursive(
int *nvtxs, Metis::idx_t *xadj, Metis::idx_t *adjncy, Metis::idx_t *vwgt,
769 Metis::idx_t *adjwgt,
int *wgtflag,
int *numflag,
int *nparts,
770 int *options,
int *edgecut, Metis::idx_t *part);
775 template<
class S,
class T>
778 for(T *cur=array, *
end=array+l; cur!=
end; ++cur)
782 template<
class S,
class T>
784 T* adjncy,
bool checkSymmetry)
790 if(
static_cast<S
>(xadj[vtx])>noEdges || signbit(xadj[vtx])) {
791 std::cerr <<
"Check graph: xadj["<<vtx<<
"]="<<xadj[vtx]<<
" (>"
795 if(
static_cast<S
>(xadj[vtx+1])>noEdges || signbit(xadj[vtx+1])) {
796 std::cerr <<
"Check graph: xadj["<<vtx+1<<
"]="<<xadj[vtx+1]<<
" (>"
802 if(signbit(adjncy[i]) || ((
std::size_t)adjncy[i])>gnoVtx) {
803 std::cerr<<
" Edge "<<adjncy[i]<<
" out of range ["<<0<<
","<<noVtx<<
")"
813 for(
Metis::idx_t j=xadj[target]; j< xadj[target+1]; ++j)
826 template<
class M,
class T1,
class T2>
833 if(verbose && oocomm.communicator().
rank()==0)
834 std::cout<<
"Repartitioning from "<<oocomm.communicator().
size()
837 int rank = oocomm.communicator().
rank();
839 int* part =
new int[1];
852 int noNeighbours = oocomm.remoteIndices().
neighbours();
854 for(
auto n= oocomm.remoteIndices().
begin(); n != oocomm.remoteIndices().
end();
875 for(
int i=0; i<oocomm.communicator().
size(); ++i)
877 vtxdist[oocomm.communicator().
size()]=oocomm.communicator().
size();
880 xadj[1]=noNeighbours;
921 for(
auto n= oocomm.remoteIndices().
begin(); n != oocomm.remoteIndices().
end();
923 if(n->first != rank) {
932 vtxdist[oocomm.communicator().
size()],
933 noNeighbours, xadj, adjncy,
false));
942 for(
int i=0; i<nparts; ++i)
943 tpwgts[i]=1.0/nparts;
944 MPI_Comm comm=oocomm.communicator();
960 oocomm.communicator().
barrier();
961 if(verbose && oocomm.communicator().
rank()==0)
965#ifdef PARALLEL_PARTITION
973 ParMETIS_V3_PartKway(vtxdist, xadj, adjncy,
974 vwgt, adjwgt, &wgtflag,
975 &numflag, &ncon, &nparts, tpwgts, &ubvec,
options, &edgecut, part,
977 if(verbose && oocomm.communicator().
rank()==0)
984 noedges =
new int[oocomm.communicator().
size()];
987 MPI_Allgather(&noNeighbours,1,MPI_INT,noedges,1, MPI_INT,oocomm.communicator());
989 if(verbose && oocomm.communicator().
rank()==0)
1005 std::size_t localNoVtx=vtxdist[rank+1]-vtxdist[rank];
1007 std::size_t gxadjlen = vtxdist[oocomm.communicator().
size()]-vtxdist[0]+oocomm.communicator().
size();
1013 displ =
new int[oocomm.communicator().
size()];
1014 xdispl =
new int[oocomm.communicator().
size()];
1015 noxs =
new int[oocomm.communicator().
size()];
1016 vdispl =
new int[oocomm.communicator().
size()];
1017 novs =
new int[oocomm.communicator().
size()];
1019 for(
int i=0; i < oocomm.communicator().
size(); ++i) {
1020 noxs[i]=vtxdist[i+1]-vtxdist[i]+1;
1021 novs[i]=vtxdist[i+1]-vtxdist[i];
1026 for(
int *xcurr = xdispl, *vcurr = vdispl, *
end=vdispl+oocomm.communicator().
size();
1027 vcurr!=
end; ++vcurr, ++xcurr, ++so, ++offset) {
1029 *xcurr = offset + *so;
1035 for(
int *curr=noedges, *
end=noedges+oocomm.communicator().
size()-1;
1036 curr!=
end; ++curr) {
1047 for(
int *curr=noedges, *
end=noedges+oocomm.communicator().
size();
1052 Dune::dinfo<<
"gxadjlen: "<<gxadjlen<<
" noVertices: "<<noVertices
1063 if(verbose && oocomm.communicator().
rank()==0)
1082 if(verbose && oocomm.communicator().
rank()==0)
1095 for(
int i=1; i<oocomm.communicator().
size(); ++i) {
1097 int lprev = vtxdist[i]-vtxdist[i-1];
1098 int l = vtxdist[i+1]-vtxdist[i];
1100 assert((start+l+offset)-gxadj<=
static_cast<Metis::idx_t>(gxadjlen));
1116 if(verbose && oocomm.communicator().
rank()==0)
1121 gxadj, gadjncy,
true));
1124 if(verbose && oocomm.communicator().
rank()==0)
1127#if METIS_VER_MAJOR >= 5
1130 METIS_SetDefaultOptions(moptions);
1131 moptions[METIS_OPTION_NUMBERING] = numflag;
1132 METIS_PartGraphRecursive(&noVertices, &ncon, gxadj, gadjncy, gvwgt, NULL, gadjwgt,
1133 &nparts, NULL, NULL, moptions, &edgecut, gpart);
1135 int options[5] = {0, 1, 1, 3, 3};
1137 METIS_PartGraphRecursive(&noVertices, gxadj, gadjncy, gvwgt, gadjwgt, &wgtflag,
1138 &numflag, &nparts,
options, &edgecut, gpart);
1141 if(verbose && oocomm.communicator().
rank()==0)
1186 oocomm.copyOwnerToAll(realpart, realpart);
1188 if(verbose && oocomm.communicator().
rank()==0)
1193 oocomm.buildGlobalLookup(
mat.N());
1196 if(verbose && oocomm.communicator().
rank()==0)
1201 int noNeighbours=oocomm.remoteIndices().
neighbours();
1202 noNeighbours = oocomm.communicator().
sum(noNeighbours)
1203 / oocomm.communicator().
size();
1204 if(oocomm.communicator().
rank()==0)
1209 if(verbose && oocomm.communicator().
rank()==0)
1232 template<
class G,
class T1,
class T2>
1240 MPI_Comm comm=oocomm.communicator();
1241 oocomm.buildGlobalLookup(graph.noVertices());
1244 if(verbose && oocomm.communicator().
rank()==0)
1252 double t1=0.0, t2=0.0, t3=0.0, t4=0.0, tSum=0.0;
1257 int mype = oocomm.communicator().
rank();
1280 typedef typename OOComm::OwnerSet OwnerSet;
1285 ParmetisDuneIndexMap indexMap(graph,oocomm);
1287 for(
std::size_t i=0; i < indexMap.numOfOwnVtx(); ++i)
1291 if(oocomm.communicator().
rank()==0 && nparts>1)
1292 std::cerr<<
"ParMETIS not activated. Will repartition to 1 domain instead of requested "
1302 EdgeFunctor<G> ef(adjncy, indexMap, graph.noEdges());
1303 getAdjArrays<OwnerSet>(graph, oocomm.globalLookup(), xadj, ef);
1312 for(
int i=0; i<nparts; ++i)
1313 tpwgts[i]=1.0/nparts;
1322 wgtflag = (ef.getWeights()!=NULL) ? 1 : 0;
1331 std::cout<<
"Testing ParMETIS_V3_PartKway with options[1-2] = {"
1333 <<ncon<<
", Nparts: "<<nparts<<
std::endl;
1344 oocomm.communicator().
barrier();
1345 if(oocomm.communicator().
rank()==0)
1353 ParMETIS_V3_PartKway(indexMap.vtxDist(), xadj, adjncy,
1354 NULL, ef.getWeights(), &wgtflag,
1355 &numflag, &ncon, &nparts, tpwgts, ubvec,
options, &edgecut, part, &
const_cast<MPI_Comm&
>(comm));
1371 for(
int i=0; i < indexMap.vtxDist()[mype+1]-indexMap.vtxDist()[mype]; ++i) {
1375 std::cout<<
"Testing ParMETIS_V3_PartKway with options[1-2] = {"
1377 <<ncon<<
", Nparts: "<<nparts<<
std::endl;
1388 oocomm.communicator().
barrier();
1389 if(oocomm.communicator().
rank()==0)
1397 for(
std::size_t i=0; i<indexMap.numOfOwnVtx(); ++i)
1409 getDomain(comm, part, indexMap.numOfOwnVtx(), nparts, &myDomain, domainMapping);
1416 for(
auto j : range(nparts)) {
1417 std::cout<<
" do: "<<j<<
" pe: "<<domainMapping[j]<<
" ";
1430 if(OwnerSet::contains(
index->local().attribute())) {
1431 setPartition[
index->local()]=domainMapping[part[i++]];
1435 oocomm.copyOwnerToAll(setPartition, setPartition);
1438 if (SolverCategory::category(oocomm) ==
1439 static_cast<int>(SolverCategory::nonoverlapping))
1440 oocomm.copyCopyToAll(setPartition, setPartition);
1444 oocomm.communicator().
barrier();
1445 if(oocomm.communicator().
rank()==0)
1453 template<
class G,
class T1,
class T2>
1461 typedef typename OOComm::OwnerSet OwnerSet;
1492 int npes = oocomm.communicator().
size();
1501 int mype = oocomm.communicator().
rank();
1505 for(
auto i=setPartition.
begin(), iend = setPartition.
end(); i!=iend; ++i)
1508 noSendTo = tsendTo.
size();
1509 sendTo =
new int[noSendTo];
1511 for(
auto i=tsendTo.
begin(); i != tsendTo.
end(); ++i, ++idx)
1516 int* gnoSend=
new int[oocomm.communicator().
size()];
1517 int* gsendToDispl =
new int[oocomm.communicator().
size()+1];
1519 MPI_Allgather(&noSendTo, 1, MPI_INT, gnoSend, 1,
1520 MPI_INT, oocomm.communicator());
1523 int totalNoRecv = 0;
1524 for(
int i=0; i<npes; ++i)
1525 totalNoRecv += gnoSend[i];
1527 int *gsendTo =
new int[totalNoRecv];
1531 for(
int i=0; i<npes; ++i)
1532 gsendToDispl[i+1]=gsendToDispl[i]+gnoSend[i];
1535 MPI_Allgatherv(sendTo, noSendTo, MPI_INT, gsendTo, gnoSend, gsendToDispl,
1536 MPI_INT, oocomm.communicator());
1539 for(
int proc=0; proc < npes; ++proc)
1540 for(
int i=gsendToDispl[proc]; i < gsendToDispl[proc+1]; ++i)
1541 if(gsendTo[i]==mype)
1544 bool existentOnNextLevel = recvFrom.
size()>0;
1548 delete[] gsendToDispl;
1553 if(recvFrom.
size()) {
1555 for(
auto i=recvFrom.
begin(); i!= recvFrom.
end(); ++i) {
1562 for(
int i=0; i<noSendTo; i++) {
1569 if(oocomm.communicator().
rank()==0)
1570 std::cout<<
" Communicating the receive information took "<<
1585 typedef typename OOComm::ParallelIndexSet::GlobalIndex GI;
1589 GlobalVector sendOwnerVec;
1596 char **sendBuffers=
new char*[noSendTo];
1597 MPI_Request *requests =
new MPI_Request[noSendTo];
1600 for(
int i=0; i < noSendTo; ++i) {
1602 sendOwnerVec.
clear();
1603 sendOverlapSet.
clear();
1607 getOwnerOverlapVec<OwnerSet>(graph, setPartition, oocomm.globalLookup(),
1608 mype, sendTo[i], sendOwnerVec, sendOverlapSet, redistInf,
1620 buffersize += tsize;
1622 buffersize += tsize;
1623 MPI_Pack_size(neighbors.
size(), MPI_INT, oocomm.communicator(), &tsize);
1624 buffersize += tsize;
1626 sendBuffers[i] =
new char[buffersize];
1629 std::cout<<mype<<
" sending "<<sendOwnerVec.size()<<
" owner and "<<
1630 sendOverlapSet.
size()<<
" overlap to "<<sendTo[i]<<
" buffersize="<<buffersize<<
std::endl;
1632 createSendBuf(sendOwnerVec, sendOverlapSet, neighbors, sendBuffers[i], buffersize, oocomm.communicator());
1633 MPI_Issend(sendBuffers[i], buffersize, MPI_PACKED, sendTo[i], 99, oocomm.communicator(), requests+i);
1637 oocomm.communicator().
barrier();
1638 if(oocomm.communicator().
rank()==0)
1645 int noRecv = recvFrom.
size();
1646 int oldbuffersize=0;
1651 MPI_Probe(MPI_ANY_SOURCE, 99, oocomm.communicator(), &stat);
1653 MPI_Get_count(&stat, MPI_PACKED, &buffersize);
1655 if(oldbuffersize<buffersize) {
1658 recvBuf =
new char[buffersize];
1659 oldbuffersize = buffersize;
1661 MPI_Recv(recvBuf, buffersize, MPI_PACKED, stat.MPI_SOURCE, 99, oocomm.communicator(), &stat);
1662 saveRecvBuf(recvBuf, buffersize, myOwnerVec, myOverlapSet, myNeighbors, redistInf,
1663 stat.MPI_SOURCE, oocomm.communicator());
1672 MPI_Status *statuses =
new MPI_Status[noSendTo];
1673 int send = MPI_Waitall(noSendTo, requests, statuses);
1676 if(send==MPI_ERR_IN_STATUS) {
1679 for(
int i=0; i< noSendTo; i++)
1680 if(statuses[i].MPI_ERROR!=MPI_SUCCESS) {
1683 MPI_Error_string(statuses[i].MPI_ERROR,
message, &messageLength);
1684 std::cerr<<
" source="<<statuses[i].MPI_SOURCE<<
" message: ";
1685 for(
int j = 0; j < messageLength; j++)
1692 oocomm.communicator().
barrier();
1693 if(oocomm.communicator().
rank()==0)
1694 std::cout<<
" Receiving and saving took "<<
1699 for(
int i=0; i < noSendTo; ++i)
1700 delete[] sendBuffers[i];
1702 delete[] sendBuffers;
1717 if (!existentOnNextLevel) {
1719 color= MPI_UNDEFINED;
1721 MPI_Comm outputComm;
1723 MPI_Comm_split(oocomm.communicator(), color, oocomm.communicator().
rank(), &outputComm);
1724 outcomm = std::make_shared<OOComm>(outputComm,SolverCategory::category(oocomm),
true);
1727 int newrank=outcomm->communicator().rank();
1728 int *newranks=
new int[oocomm.communicator().
size()];
1732 typename OOComm::ParallelIndexSet& outputIndexSet = outcomm->indexSet();
1734 MPI_Allgather(&newrank, 1, MPI_INT, newranks, 1,
1735 MPI_INT, oocomm.communicator());
1739 for(
auto i=myNeighbors.
begin(),
end=myNeighbors.
end();
1741 assert(newranks[*i]>=0);
1747 for(
auto i=myNeighbors.
begin(),
end=myNeighbors.
end();
1753 myNeighbors.
clear();
1756 oocomm.communicator().
barrier();
1757 if(oocomm.communicator().
rank()==0)
1758 std::cout<<
" Calculating new neighbours ("<<tneighbors.
size()<<
") took "<<
1764 outputIndexSet.beginResize();
1772 using LocalIndexT =
typename OOComm::ParallelIndexSet::LocalIndex;
1773 for(
auto g=myOwnerVec.
begin(),
end =myOwnerVec.
end(); g!=
end; ++g, ++i ) {
1774 outputIndexSet.add(g->first,LocalIndexT(i, OwnerOverlapCopyAttributeSet::owner,
true));
1779 oocomm.communicator().
barrier();
1780 if(oocomm.communicator().
rank()==0)
1781 std::cout<<
" Adding owner indices took "<<
1791 mergeVec(myOwnerVec, myOverlapSet);
1795 myOwnerVec.
swap(myOwnerVec);
1798 oocomm.communicator().
barrier();
1799 if(oocomm.communicator().
rank()==0)
1807 for(
auto g=myOverlapSet.
begin(),
end=myOverlapSet.
end(); g!=
end; ++g, i++) {
1808 outputIndexSet.add(*g,LocalIndexT(i, OwnerOverlapCopyAttributeSet::copy,
true));
1810 myOverlapSet.
clear();
1811 outputIndexSet.endResize();
1813#ifdef DUNE_ISTL_WITH_CHECKING
1815 auto end = outputIndexSet.end();
1817 if (OwnerSet::contains(
index->local().attribute())) {
1821 numOfOwnVtx = oocomm.communicator().
sum(numOfOwnVtx);
1829 [](
const auto& v1,
const auto& v2){ return v1.global() < v2.global();});
1832 oocomm.communicator().
barrier();
1833 if(oocomm.communicator().
rank()==0)
1834 std::cout<<
" Adding overlap indices took "<<
1840 if(color != MPI_UNDEFINED) {
1841 outcomm->remoteIndices().setNeighbours(tneighbors);
1842 outcomm->remoteIndices().template rebuild<true>();
1850 oocomm.communicator().
barrier();
1851 if(oocomm.communicator().
rank()==0)
1859 tSum = t1 + t2 + t3 + t4;
1861 <<mype<<
": WTime for step 1): "<<t1
1869 return color!=MPI_UNDEFINED;
1873 template<
class G,
class P,
class T1,
class T2,
class R>
1874 bool graphRepartition(
const G& graph, P& oocomm,
int nparts,
1879 if(nparts!=oocomm.size())
1880 DUNE_THROW(NotImplemented,
"only available for MPI programs");
1884 template<
class G,
class P,
class T1,
class T2,
class R>
1890 if(nparts!=oocomm.size())
1891 DUNE_THROW(NotImplemented,
"only available for MPI programs");
Provides classes for building the matrix graph.
int globalOwnerVertices
Definition repartition.hh:175
Dune::ParameterTree options
Classes providing communication interfaces for overlapping Schwarz methods.
Matrix & mat
Definition matrixmatrix.hh:347
float real_t
Definition repartition.hh:53
std::size_t idx_t
Definition repartition.hh:63
reference operator[](size_type i)
static constexpr size_type M()
std::ptrdiff_t index() const
void message(const std::string &msg)
virtual void operator()()=0
void repairLocalIndexPointers(std::map< int, SLList< std::pair< typename T::GlobalIndex, typename T::LocalIndex::Attribute >, A > > &globalMap, RemoteIndices< T, A1 > &remoteIndices, const T &indexSet)
const InformationMap & interfaces() const
MPI_Comm communicator() const
const IndexPair * pair(const std::size_t &local) const
void storeGlobalIndicesOfRemoteIndices(std::map< int, SLList< std::pair< typename T::GlobalIndex, typename T::LocalIndex::Attribute >, A > > &globalMap, const RemoteIndices< T, A1 > &remoteIndices)
bool buildCommunication(const G &graph, std::vector< int > &realparts, Dune::OwnerOverlapCopyCommunication< T1, T2 > &oocomm, std::shared_ptr< Dune::OwnerOverlapCopyCommunication< T1, T2 > > &outcomm, RedistributeInterface &redistInf, bool verbose=false)
Definition repartition.hh:1454
void fillIndexSetHoles(const G &graph, Dune::OwnerOverlapCopyCommunication< T1, T2 > &oocomm)
Fills the holes in an index set.
Definition repartition.hh:83
bool commGraphRepartition(const M &mat, Dune::OwnerOverlapCopyCommunication< T1, T2 > &oocomm, Metis::idx_t nparts, std::shared_ptr< Dune::OwnerOverlapCopyCommunication< T1, T2 > > &outcomm, RedistributeInterface &redistInf, bool verbose=false)
Definition repartition.hh:827
void print_carray(S &os, T *array, std::size_t l)
Definition repartition.hh:776
bool isValidGraph(std::size_t noVtx, std::size_t gnoVtx, S noEdges, T *xadj, T *adjncy, bool checkSymmetry)
Definition repartition.hh:783
bool graphRepartition(const G &graph, Dune::OwnerOverlapCopyCommunication< T1, T2 > &oocomm, Metis::idx_t nparts, std::shared_ptr< Dune::OwnerOverlapCopyCommunication< T1, T2 > > &outcomm, RedistributeInterface &redistInf, bool verbose=false)
execute a graph repartition for a giving graph and indexset.
Definition repartition.hh:1233
const_iterator end() const
const_iterator begin() const
double elapsed() const noexcept
@ owner
Definition owneroverlapcopy.hh:61
The (undirected) graph of a matrix.
Definition graph.hh:51
Definition repartition.hh:260
void reserveSpaceForReceiveInterface(int proc, int size)
Definition repartition.hh:284
void buildReceiveInterface(std::vector< std::pair< TG, int > > &indices)
Definition repartition.hh:293
~RedistributeInterface()
Definition repartition.hh:301
void setCommunicator(MPI_Comm comm)
Definition repartition.hh:261
void buildSendInterface(const std::vector< int > &toPart, const IS &idxset)
Definition repartition.hh:266
void addReceiveIndex(int proc, std::size_t idx)
Definition repartition.hh:288