3#ifndef DUNE_REPARTITION_HH
4#define DUNE_REPARTITION_HH
57 template<
class G,
class T1,
class T2>
61 typedef typename IndexSet::LocalIndex::Attribute
Attribute;
67 typedef typename G::ConstVertexIterator VertexIterator;
70 std::size_t sum=0, needed = graph.noVertices()-indexSet.
size();
71 std::vector<std::size_t> neededall(oocomm.communicator().
size(), 0);
74 for(
int i=0; i<oocomm.communicator().size(); ++i)
83 typedef typename IndexSet::const_iterator Iterator;
86 for(Iterator it = indexSet.begin(); it != end; ++it)
87 maxgi=std::max(maxgi,it->global());
92 maxgi=oocomm.communicator().
max(maxgi);
95 for(
int i=0; i<oocomm.communicator().rank(); ++i)
96 maxgi=maxgi+neededall[i];
99 std::map<int,SLList<std::pair<T1,Attribute> > > globalIndices;
101 indexSet.beginResize();
103 for(VertexIterator vertex = graph.begin(), vend=graph.end(); vertex != vend; ++vertex) {
104 const typename IndexSet::IndexPair* pair=lookup.
pair(*vertex);
107 indexSet.add(maxgi,
typename IndexSet::LocalIndex(*vertex, OwnerOverlapCopyAttributeSet::owner,
false));
112 indexSet.endResize();
116 oocomm.freeGlobalLookup();
117 oocomm.buildGlobalLookup();
119 std::cout<<
"Holes are filled!"<<std::endl;
120 std::cout<<oocomm.communicator().
rank()<<
": "<<oocomm.
indexSet()<<std::endl;
127 class ParmetisDuneIndexMap
130 template<
class Graph,
class OOComm>
131 ParmetisDuneIndexMap(
const Graph& graph,
const OOComm& com);
132 int toParmetis(
int i)
const
134 return duneToParmetis[i];
136 int toLocalParmetis(
int i)
const
138 return duneToParmetis[i]-base_;
140 int operator[](
int i)
const
142 return duneToParmetis[i];
144 int toDune(
int i)
const
146 return parmetisToDune[i];
148 std::vector<int>::size_type numOfOwnVtx()
const
150 return parmetisToDune.size();
156 int globalOwnerVertices;
159 std::vector<int> duneToParmetis;
160 std::vector<int> parmetisToDune;
162 std::vector<int> vtxDist_;
165 template<
class G,
class OOComm>
166 ParmetisDuneIndexMap::ParmetisDuneIndexMap(
const G& graph,
const OOComm& oocomm)
167 : duneToParmetis(graph.noVertices(), -1), vtxDist_(oocomm.communicator().size()+1)
169 int npes=oocomm.communicator().size(), mype=oocomm.communicator().rank();
171 typedef typename OOComm::ParallelIndexSet::const_iterator Iterator;
172 typedef typename OOComm::OwnerSet OwnerSet;
175 Iterator
end = oocomm.indexSet().end();
176 for(Iterator index = oocomm.indexSet().begin(); index !=
end; ++index) {
177 if (OwnerSet::contains(index->local().attribute())) {
181 parmetisToDune.resize(numOfOwnVtx);
182 std::vector<int> globalNumOfVtx(npes);
184 MPI_Allgather(&numOfOwnVtx, 1, MPI_INT, &(globalNumOfVtx[0]), 1, MPI_INT, oocomm.communicator());
188 for(
int i=0; i<npes; i++) {
190 base += globalNumOfVtx[i];
192 vtxDist_[i+1] = vtxDist_[i] + globalNumOfVtx[i];
194 globalOwnerVertices=vtxDist_[npes];
198 typedef typename G::ConstVertexIterator VertexIterator;
200 std::cout << oocomm.communicator().rank()<<
" vtxDist: ";
201 for(
int i=0; i<= npes; ++i)
202 std::cout << vtxDist_[i]<<
" ";
203 std::cout<<std::endl;
210 VertexIterator vend = graph.end();
211 for(VertexIterator vertex = graph.begin(); vertex != vend; ++vertex) {
212 const typename OOComm::ParallelIndexSet::IndexPair* index=oocomm.globalLookup().pair(*vertex);
214 if (OwnerSet::contains(index->local().attribute())) {
216 parmetisToDune[base-base_]=index->local();
217 duneToParmetis[index->local()] = base++;
227 std::cout <<oocomm.communicator().rank()<<
": before ";
228 for(std::size_t i=0; i<duneToParmetis.size(); ++i)
229 std::cout<<duneToParmetis[i]<<
" ";
230 std::cout<<std::endl;
232 oocomm.copyOwnerToAll(duneToParmetis,duneToParmetis);
234 std::cout <<oocomm.communicator().rank()<<
": after ";
235 for(std::size_t i=0; i<duneToParmetis.size(); ++i)
236 std::cout<<duneToParmetis[i]<<
" ";
237 std::cout<<std::endl;
242 struct RedistributeInterface
245 void setCommunicator(MPI_Comm comm)
249 template<
class Flags,
class IS>
250 void buildSendInterface(
const std::vector<int>& toPart,
const IS& idxset)
252 std::map<int,int> sizes;
254 typedef typename IS::const_iterator IIter;
255 for(IIter i=idxset.begin(), end=idxset.end(); i!=end; ++i)
256 if(Flags::contains(i->local().attribute()))
257 ++sizes[toPart[i->local()]];
260 typedef std::map<int,int>::const_iterator MIter;
261 for(MIter i=sizes.begin(), end=sizes.end(); i!=end; ++i)
262 interfaces()[i->first].first.reserve(i->second);
265 typedef typename IS::const_iterator IIter;
266 for(IIter i=idxset.begin(), end=idxset.end(); i!=end; ++i)
267 if(Flags::contains(i->local().attribute()))
268 interfaces()[toPart[i->local()]].first.add(i->local());
271 void reserveSpaceForReceiveInterface(
int proc,
int size)
275 void addReceiveIndex(
int proc, std::size_t idx)
279 template<
typename TG>
280 void buildReceiveInterface(std::vector<std::pair<TG,int> >& indices)
282 typedef typename std::vector<std::pair<TG,int> >::const_iterator VIter;
284 for(VIter idx=indices.begin(); idx!= indices.end(); ++idx) {
289 ~RedistributeInterface()
306 void createSendBuf(std::vector<GI>& ownerVec, std::set<GI>& overlapVec, std::set<int>& neighbors,
char *sendBuf,
int buffersize, MPI_Comm comm) {
308 std::size_t s=ownerVec.size();
312 MPI_Pack(&s, 1, MPITraits<std::size_t>::getType(), sendBuf, buffersize, &pos, comm);
313 MPI_Pack(&(ownerVec[0]), s, MPITraits<GI>::getType(), sendBuf, buffersize, &pos, comm);
314 s = overlapVec.size();
315 MPI_Pack(&s, 1, MPITraits<std::size_t>::getType(), sendBuf, buffersize, &pos, comm);
316 typedef typename std::set<GI>::iterator Iter;
317 for(Iter i=overlapVec.begin(), end= overlapVec.end(); i != end; ++i)
318 MPI_Pack(
const_cast<GI*
>(&(*i)), 1, MPITraits<GI>::getType(), sendBuf, buffersize, &pos, comm);
321 MPI_Pack(&s, 1, MPITraits<std::size_t>::getType(), sendBuf, buffersize, &pos, comm);
322 typedef typename std::set<int>::iterator IIter;
324 for(IIter i=neighbors.begin(), end= neighbors.end(); i != end; ++i)
325 MPI_Pack(
const_cast<int*
>(&(*i)), 1, MPI_INT, sendBuf, buffersize, &pos, comm);
336 void saveRecvBuf(
char *recvBuf,
int bufferSize, std::vector<std::pair<GI,int> >& ownerVec,
337 std::set<GI>& overlapVec, std::set<int>& neighbors, RedistributeInterface& inf,
int from, MPI_Comm comm) {
341 MPI_Unpack(recvBuf, bufferSize, &pos, &size, 1, MPITraits<std::size_t>::getType(), comm);
342 inf.reserveSpaceForReceiveInterface(from, size);
343 ownerVec.reserve(ownerVec.size()+size);
344 for(; size!=0; --size) {
346 MPI_Unpack(recvBuf, bufferSize, &pos, &gi, 1, MPITraits<GI>::getType(), comm);
347 ownerVec.push_back(std::make_pair(gi,from));
350 MPI_Unpack(recvBuf, bufferSize, &pos, &size, 1, MPITraits<std::size_t>::getType(), comm);
351 typename std::set<GI>::iterator ipos = overlapVec.begin();
352 Dune::dverb <<
"unpacking "<<size<<
" overlap"<<std::endl;
353 for(; size!=0; --size) {
355 MPI_Unpack(recvBuf, bufferSize, &pos, &gi, 1, MPITraits<GI>::getType(), comm);
356 ipos=overlapVec.insert(ipos, gi);
359 MPI_Unpack(recvBuf, bufferSize, &pos, &size, 1, MPITraits<std::size_t>::getType(), comm);
360 Dune::dverb <<
"unpacking "<<size<<
" neighbors"<<std::endl;
361 typename std::set<int>::iterator npos = neighbors.begin();
362 for(; size!=0; --size) {
364 MPI_Unpack(recvBuf, bufferSize, &pos, &n, 1, MPI_INT, comm);
365 npos=neighbors.insert(npos, n);
383 void getDomain(
const MPI_Comm& comm, T *part,
int numOfOwnVtx,
int nparts,
int *myDomain, std::vector<int> &domainMapping) {
385 MPI_Comm_size(comm, &npes);
386 MPI_Comm_rank(comm, &mype);
393 std::vector<int> domain(nparts);
394 std::vector<int> assigned(npes);
396 for (i=0; i<nparts; i++) {
397 domainMapping[i] = -1;
400 for (i=0; i<npes; i++) {
404 for (i=0; i<numOfOwnVtx; i++) {
408 int *domainMatrix =
new int[npes * nparts];
410 for(i=0; i<npes*nparts; i++) {
415 int *buf =
new int[nparts];
416 for (i=0; i<nparts; i++) {
418 domainMatrix[mype*nparts+i] = domain[i];
421 int src = (mype-1+npes)%npes;
422 int dest = (mype+1)%npes;
424 for (i=0; i<npes-1; i++) {
425 MPI_Sendrecv_replace(buf, nparts, MPI_INT, dest, 0, src, 0, comm, &status);
427 pe = ((mype-1-i)+npes)%npes;
428 for(j=0; j<nparts; j++) {
430 domainMatrix[pe*nparts+j] = buf[j];
438 int maxOccurance = 0;
440 for(i=0; i<nparts; i++) {
441 for(j=0; j<npes; j++) {
443 if (assigned[j]==0) {
444 if (maxOccurance < domainMatrix[j*nparts+i]) {
445 maxOccurance = domainMatrix[j*nparts+i];
453 domainMapping[i] = pe;
464 delete[] domainMatrix;
471 bool operator()(
const T& t1,
const T& t2)
const
489 void mergeVec(std::vector<std::pair<GI, int> >& ownerVec, std::set<GI>& overlapSet) {
491 typedef typename std::vector<std::pair<GI,int> >::const_iterator VIter;
494 if(ownerVec.size()>0)
496 VIter old=ownerVec.begin();
497 for(VIter i=old+1, end=ownerVec.end(); i != end; old=i++)
499 if(i->first==old->first)
501 std::cerr<<
"Value at indes"<<old-ownerVec.begin()<<
" is the same as at index "
502 <<i-ownerVec.begin()<<
" ["<<old->first<<
","<<old->second<<
"]==["
503 <<i->first<<
","<<i->second<<
"]"<<std::endl;
511 typedef typename std::set<GI>::iterator SIter;
512 VIter v=ownerVec.begin(), vend=ownerVec.end();
513 for(SIter s=overlapSet.begin(), send=overlapSet.end(); s!=send;)
515 while(v!=vend && v->first<*s) ++v;
516 if(v!=vend && v->first==*s) {
521 overlapSet.erase(tmp);
541 template<
class OwnerSet,
class Graph,
class IS,
class GI>
542 void getNeighbor(
const Graph& g, std::vector<int>& part,
543 typename Graph::VertexDescriptor vtx,
const IS& indexSet,
544 int toPe, std::set<GI>& neighbor, std::set<int>& neighborProcs) {
545 typedef typename Graph::ConstEdgeIterator Iter;
546 for(Iter edge=g.beginEdges(vtx), end=g.endEdges(vtx); edge!=end; ++edge)
548 const typename IS::IndexPair* pindex = indexSet.pair(edge.target());
550 if(part[pindex->local()]!=toPe || !OwnerSet::contains(pindex->local().attribute()))
553 neighbor.insert(pindex->global());
554 neighborProcs.insert(part[pindex->local()]);
559 template<
class T,
class I>
560 void my_push_back(std::vector<T>& ownerVec,
const I& index,
int proc)
563 ownerVec.push_back(index);
566 template<
class T,
class I>
567 void my_push_back(std::vector<std::pair<T,int> >& ownerVec,
const I& index,
int proc)
569 ownerVec.push_back(std::make_pair(index,proc));
572 void reserve(std::vector<T>&, RedistributeInterface&,
int)
575 void reserve(std::vector<std::pair<T,int> >& ownerVec, RedistributeInterface& redist,
int proc)
577 redist.reserveSpaceForReceiveInterface(proc, ownerVec.size());
598 template<
class OwnerSet,
class G,
class IS,
class T,
class GI>
599 void getOwnerOverlapVec(
const G& graph, std::vector<int>& part, IS& indexSet,
600 int myPe,
int toPe, std::vector<T>& ownerVec, std::set<GI>& overlapSet,
601 RedistributeInterface& redist, std::set<int>& neighborProcs) {
604 typedef typename IS::const_iterator Iterator;
605 for(Iterator index = indexSet.begin(); index != indexSet.end(); ++index) {
607 if(OwnerSet::contains(index->local().attribute()))
609 if(part[index->local()]==toPe)
611 getNeighbor<OwnerSet>(graph, part, index->local(), indexSet,
612 toPe, overlapSet, neighborProcs);
613 my_push_back(ownerVec, index->global(), toPe);
617 reserve(ownerVec, redist, toPe);
628 template<
class F,
class IS>
629 inline bool isOwner(IS& indexSet,
int index) {
631 const typename IS::IndexPair* pindex=indexSet.pair(index);
634 return F::contains(pindex->local().attribute());
638 class BaseEdgeFunctor
641 BaseEdgeFunctor(
int* adj,
const ParmetisDuneIndexMap& data)
642 : i_(), adj_(adj), data_(data)
646 void operator()(
const T& edge)
650 adj_[i_] = data_.toParmetis(edge.target());
661 const ParmetisDuneIndexMap& data_;
666 :
public BaseEdgeFunctor
668 EdgeFunctor(
int* adj,
const ParmetisDuneIndexMap& data, std::size_t s)
669 : BaseEdgeFunctor(adj, data)
679 template<
class G,
class V,
class E,
class VM,
class EM>
680 class EdgeFunctor<
Dune::Amg::PropertiesGraph<G,V,E,VM,EM> >
681 :
public BaseEdgeFunctor
684 EdgeFunctor(
int* adj,
const ParmetisDuneIndexMap& data, std::size_t s)
685 : BaseEdgeFunctor(adj, data)
691 void operator()(
const T& edge)
693 weight_[index()]=edge.properties().depends() ? 3 : 1;
694 BaseEdgeFunctor::operator()(edge);
725 template<
class F,
class G,
class IS,
class EW>
726 void getAdjArrays(G& graph, IS& indexSet,
int *xadj,
732 typedef typename G::ConstVertexIterator VertexIterator;
734 typedef typename IS::const_iterator Iterator;
736 VertexIterator vend = graph.end();
739 for(VertexIterator vertex = graph.begin(); vertex != vend; ++vertex) {
740 if (isOwner<F>(indexSet,*vertex)) {
742 typedef typename G::ConstEdgeIterator EdgeIterator;
743 EdgeIterator eend = vertex.end();
744 xadj[j] = ew.index();
746 for(EdgeIterator edge = vertex.begin(); edge != eend; ++edge) {
751 xadj[j] = ew.index();
755 template<
class G,
class T1,
class T2>
756 bool buildCommunication(
const G& graph, std::vector<int>& realparts,
759 RedistributeInterface& redistInf,
762#if PARMETIS_MAJOR_VERSION > 3
763 typedef idx_t idxtype;
764#elif defined(METISNAMEL)
767 typedef std::size_t idxtype;
773 void METIS_PartGraphKway(
int *nvtxs, idxtype *xadj, idxtype *adjncy, idxtype *vwgt,
774 idxtype *adjwgt,
int *wgtflag,
int *numflag,
int *nparts,
775 int *options,
int *edgecut, idxtype *part);
777 void METIS_PartGraphRecursive(
int *nvtxs, idxtype *xadj, idxtype *adjncy, idxtype *vwgt,
778 idxtype *adjwgt,
int *wgtflag,
int *numflag,
int *nparts,
779 int *options,
int *edgecut, idxtype *part);
782 typedef std::size_t idxtype;
785 template<
class S,
class T>
786 inline void print_carray(S& os, T* array, std::size_t l)
788 for(T *cur=array, *end=array+l; cur!=end; ++cur)
792 inline bool isValidGraph(std::size_t noVtx, std::size_t gnoVtx, idxtype noEdges, idxtype* xadj,
793 idxtype* adjncy,
bool checkSymmetry)
797 for(idxtype vtx=0; vtx<(idxtype)noVtx; ++vtx) {
798 if(xadj[vtx]>noEdges||xadj[vtx]<0) {
799 std::cerr <<
"Check graph: xadj["<<vtx<<
"]="<<xadj[vtx]<<
" (>"
800 <<noEdges<<
") out of range!"<<std::endl;
803 if(xadj[vtx+1]>noEdges||xadj[vtx+1]<0) {
804 std::cerr <<
"Check graph: xadj["<<vtx+1<<
"]="<<xadj[vtx+1]<<
" (>"
805 <<noEdges<<
") out of range!"<<std::endl;
809 for(idxtype i=xadj[vtx]; i< xadj[vtx+1]; ++i) {
810 if(adjncy[i]<0||((std::size_t)adjncy[i])>gnoVtx) {
811 std::cerr<<
" Edge "<<adjncy[i]<<
" out of range ["<<0<<
","<<noVtx<<
")"
817 for(idxtype i=xadj[vtx]; i< xadj[vtx+1]; ++i) {
818 idxtype target=adjncy[i];
821 for(idxtype j=xadj[target]; j< xadj[target+1]; ++j)
825 std::cerr<<
"Edge ("<<target<<
","<<vtx<<
") "<<i<<
" time"<<std::endl;
834 template<
class M,
class T1,
class T2>
837 RedistributeInterface& redistInf,
840 if(verbose && oocomm.communicator().
rank()==0)
841 std::cout<<
"Repartitioning from "<<oocomm.communicator().
size()
842 <<
" to "<<nparts<<
" parts"<<std::endl;
844 int rank = oocomm.communicator().
rank();
846 int* part =
new int[1];
849 idxtype* part =
new idxtype[1];
861 typedef typename RemoteIndices::const_iterator
876 idxtype *xadj=
new idxtype[2];
877 idxtype *vtxdist=
new idxtype[oocomm.communicator().
size()+1];
878 idxtype *adjncy=
new idxtype[noNeighbours];
885 for(
int i=0; i<oocomm.communicator().size(); ++i)
887 vtxdist[oocomm.communicator().
size()]=oocomm.communicator().
size();
890 xadj[1]=noNeighbours;
920 typedef typename RemoteIndices::const_iterator NeighbourIterator;
922 idxtype* adjp=adjncy;
925 vwgt =
new idxtype[1];
928 adjwgt =
new idxtype[noNeighbours];
929 idxtype* adjwp=adjwgt;
934 if(n->first != rank) {
942 assert(isValidGraph(vtxdist[rank+1]-vtxdist[rank],
943 vtxdist[oocomm.communicator().
size()],
944 noNeighbours, xadj, adjncy,
false));
946 int wgtflag=0, numflag=0, edgecut;
950 float *tpwgts =
new float[nparts];
951 for(
int i=0; i<nparts; ++i)
952 tpwgts[i]=1.0/nparts;
953 int options[5] ={ 0,1,15,0,0};
954 MPI_Comm comm=oocomm.communicator();
970 oocomm.communicator().
barrier();
971 if(verbose && oocomm.communicator().
rank()==0)
972 std::cout<<
"Creating comm graph took "<<time.elapsed()<<std::endl;
975#ifdef PARALLEL_PARTITION
982 ParMETIS_V3_PartKway(vtxdist, xadj, adjncy,
983 vwgt, adjwgt, &wgtflag,
984 &numflag, &ncon, &nparts, tpwgts, &ubvec, options, &edgecut, part,
986 if(verbose && oocomm.communicator().
rank()==0)
987 std::cout<<
"ParMETIS took "<<time.elapsed()<<std::endl;
991 std::size_t gnoedges=0;
993 noedges =
new int[oocomm.communicator().
size()];
994 Dune::dverb<<
"noNeighbours: "<<noNeighbours<<std::endl;
996 MPI_Allgather(&noNeighbours,1,MPI_INT,noedges,1, MPI_INT,oocomm.communicator());
998 if(verbose && oocomm.communicator().
rank()==0)
999 std::cout<<
"Gathering noedges took "<<time1.elapsed()<<std::endl;
1002 int noVertices = vtxdist[oocomm.communicator().
size()];
1005 idxtype *gadjncy = 0;
1006 idxtype *gadjwgt = 0;
1014 std::size_t localNoVtx=vtxdist[rank+1]-vtxdist[rank];
1016 std::size_t gxadjlen = vtxdist[oocomm.communicator().
size()]-vtxdist[0]+oocomm.communicator().
size();
1022 displ =
new int[oocomm.communicator().
size()];
1023 xdispl =
new int[oocomm.communicator().
size()];
1024 noxs =
new int[oocomm.communicator().
size()];
1025 vdispl =
new int[oocomm.communicator().
size()];
1026 novs =
new int[oocomm.communicator().
size()];
1028 for(
int i=0; i < oocomm.communicator().size(); ++i) {
1029 noxs[i]=vtxdist[i+1]-vtxdist[i]+1;
1030 novs[i]=vtxdist[i+1]-vtxdist[i];
1033 idxtype *so= vtxdist;
1035 for(
int *xcurr = xdispl, *vcurr = vdispl, *end=vdispl+oocomm.communicator().
size();
1036 vcurr!=end; ++vcurr, ++xcurr, ++so, ++offset) {
1038 *xcurr = offset + *so;
1044 for(
int *curr=noedges, *end=noedges+oocomm.communicator().
size()-1;
1045 curr!=end; ++curr) {
1056 for(
int *curr=noedges, *end=noedges+oocomm.communicator().
size();
1061 Dune::dinfo<<
"gxadjlen: "<<gxadjlen<<
" noVertices: "<<noVertices
1062 <<
" gnoedges: "<<gnoedges<<std::endl;
1063 gxadj =
new idxtype[gxadjlen];
1064 gpart =
new idxtype[noVertices];
1066 gvwgt =
new idxtype[noVertices];
1067 gadjwgt =
new idxtype[gnoedges];
1069 gadjncy =
new idxtype[gnoedges];
1072 if(verbose && oocomm.communicator().
rank()==0)
1073 std::cout<<
"Preparing global graph took "<<time1.elapsed()<<std::endl;
1077 MPI_Allgatherv(xadj,2,MPITraits<idxtype>::getType(),
1078 gxadj,noxs,xdispl,MPITraits<idxtype>::getType(),
1080 MPI_Allgatherv(adjncy,noNeighbours,MPITraits<idxtype>::getType(),
1081 gadjncy,noedges,displ,MPITraits<idxtype>::getType(),
1084 MPI_Allgatherv(adjwgt,noNeighbours,MPITraits<idxtype>::getType(),
1085 gadjwgt,noedges,displ,MPITraits<idxtype>::getType(),
1087 MPI_Allgatherv(vwgt,localNoVtx,MPITraits<idxtype>::getType(),
1088 gvwgt,novs,vdispl,MPITraits<idxtype>::getType(),
1091 if(verbose && oocomm.communicator().
rank()==0)
1092 std::cout<<
"Gathering global graph data took "<<time1.elapsed()<<std::endl;
1102 idxtype increment = vtxdist[1];
1103 idxtype *start=gxadj+1;
1104 for(
int i=1; i<oocomm.communicator().size(); ++i) {
1106 int lprev = vtxdist[i]-vtxdist[i-1];
1107 int l = vtxdist[i+1]-vtxdist[i];
1109 assert((start+l+offset)-gxadj<=
static_cast<idxtype
>(gxadjlen));
1110 increment = *(start-1);
1111 std::transform(start+offset, start+l+offset, start, std::bind2nd(std::plus<idxtype>(), increment));
1125 if(verbose && oocomm.communicator().
rank()==0)
1126 std::cout<<
"Postprocesing global graph data took "<<time1.elapsed()<<std::endl;
1129 assert(isValidGraph(noVertices, noVertices, gnoedges,
1130 gxadj, gadjncy,
true));
1133 if(verbose && oocomm.communicator().
rank()==0)
1134 std::cout<<
"Creating grah one 1 process took "<<time.elapsed()<<std::endl;
1136 options[0]=0; options[1]=1; options[2]=1; options[3]=3; options[4]=3;
1138 METIS_PartGraphRecursive(&noVertices, gxadj, gadjncy, gvwgt, gadjwgt, &wgtflag,
1139 &numflag, &nparts, options, &edgecut, gpart);
1141 if(verbose && oocomm.communicator().
rank()==0)
1142 std::cout<<
"METIS took "<<time.elapsed()<<std::endl;
1156 MPI_Scatter(gpart, 1, MPITraits<idxtype>::getType(), part, 1,
1157 MPITraits<idxtype>::getType(), 0, comm);
1181 Dune::dinfo<<
" repart "<<rank <<
" -> "<< part[0]<<std::endl;
1183 std::vector<int> realpart(mat.
N(), part[0]);
1188 if(verbose && oocomm.communicator().
rank()==0)
1189 std::cout<<
"Scattering repartitioning took "<<time.elapsed()<<std::endl;
1193 oocomm.buildGlobalLookup(mat.
N());
1196 if(verbose && oocomm.communicator().
rank()==0)
1197 std::cout<<
"Filling index set took "<<time.elapsed()<<std::endl;
1202 noNeighbours = oocomm.communicator().
sum(noNeighbours)
1203 / oocomm.communicator().
size();
1204 if(oocomm.communicator().
rank()==0)
1205 std::cout<<
"Average no neighbours was "<<noNeighbours<<std::endl;
1207 bool ret = buildCommunication(graph, realpart, oocomm, outcomm, redistInf,
1209 if(verbose && oocomm.communicator().
rank()==0)
1210 std::cout<<
"Building index sets took "<<time.elapsed()<<std::endl;
1232 template<
class G,
class T1,
class T2>
1235 RedistributeInterface& redistInf,
1240 MPI_Comm comm=oocomm.communicator();
1241 oocomm.buildGlobalLookup(graph.noVertices());
1244 if(verbose && oocomm.communicator().
rank()==0)
1245 std::cout<<
"Filling holes took "<<time.
elapsed()<<std::endl;
1252 double t1=0.0, t2=0.0, t3=0.0, t4=0.0, tSum=0.0;
1257 int mype = oocomm.communicator().
rank();
1259 assert(nparts<=oocomm.communicator().
size());
1280 typedef typename OOComm::OwnerSet OwnerSet;
1285 ParmetisDuneIndexMap indexMap(graph,oocomm);
1287 idxtype *part =
new idxtype[indexMap.numOfOwnVtx()];
1289 std::size_t *part =
new std::size_t[indexMap.numOfOwnVtx()];
1291 for(std::size_t i=0; i < indexMap.numOfOwnVtx(); ++i)
1295 if(oocomm.communicator().
rank()==0 && nparts>1)
1296 std::cerr<<
"ParMETIS not activated. Will repartition to 1 domain instead of requested "
1297 <<nparts<<
" domains."<<std::endl;
1304 idxtype *xadj =
new idxtype[indexMap.numOfOwnVtx()+1];
1305 idxtype *adjncy =
new idxtype[graph.noEdges()];
1306 EdgeFunctor<G> ef(adjncy, indexMap, graph.noEdges());
1307 getAdjArrays<OwnerSet>(graph, oocomm.globalLookup(), xadj, ef);
1313 int numflag=0, wgtflag=0, options[3], edgecut=0, ncon=1;
1315 float *tpwgts =
new float[nparts];
1316 for(
int i=0; i<nparts; ++i)
1317 tpwgts[i]=1.0/nparts;
1326 wgtflag = (ef.getWeights()!=NULL) ? 1 : 0;
1334 std::cout<<std::endl;
1335 std::cout<<
"Testing ParMETIS_V3_PartKway with options[1-2] = {"
1336 <<options[1]<<
" "<<options[2]<<
"}, Ncon: "
1337 <<ncon<<
", Nparts: "<<nparts<<std::endl;
1348 oocomm.communicator().
barrier();
1349 if(oocomm.communicator().
rank()==0)
1350 std::cout<<
"Preparing for parmetis took "<<time.
elapsed()<<std::endl;
1357 ParMETIS_V3_PartKway(indexMap.vtxDist(), xadj, adjncy,
1358 NULL, ef.getWeights(), &wgtflag,
1359 &numflag, &ncon, &nparts, tpwgts, ubvec, options, &edgecut, part, &
const_cast<MPI_Comm&
>(comm));
1370 std::cout<<std::endl;
1371 std::cout<<
"ParMETIS_V3_PartKway reported a cut of "<<edgecut<<std::endl;
1372 std::cout<<std::endl;
1374 std::cout<<mype<<
": PARMETIS-Result: ";
1375 for(
int i=0; i < indexMap.vtxDist()[mype+1]-indexMap.vtxDist()[mype]; ++i) {
1376 std::cout<<part[i]<<
" ";
1378 std::cout<<std::endl;
1379 std::cout<<
"Testing ParMETIS_V3_PartKway with options[1-2] = {"
1380 <<options[1]<<
" "<<options[2]<<
"}, Ncon: "
1381 <<ncon<<
", Nparts: "<<nparts<<std::endl;
1392 oocomm.communicator().
barrier();
1393 if(oocomm.communicator().
rank()==0)
1394 std::cout<<
"Parmetis took "<<time.
elapsed()<<std::endl;
1401 for(std::size_t i=0; i<indexMap.numOfOwnVtx(); ++i)
1411 std::vector<int> domainMapping(nparts);
1413 getDomain(comm, part, indexMap.numOfOwnVtx(), nparts, &myDomain, domainMapping);
1418 std::cout<<mype<<
": myDomain: "<<myDomain<<std::endl;
1419 std::cout<<mype<<
": DomainMapping: ";
1420 for(
int j=0; j<nparts; j++) {
1421 std::cout<<
" do: "<<j<<
" pe: "<<domainMapping[j]<<
" ";
1423 std::cout<<std::endl;
1430 std::vector<int> setPartition(oocomm.
indexSet().
size(), -1);
1432 typedef typename OOComm::ParallelIndexSet::const_iterator Iterator;
1435 if(OwnerSet::contains(index->local().attribute())) {
1436 setPartition[index->local()]=domainMapping[part[i++]];
1446 bool ret = buildCommunication(graph, setPartition, oocomm, outcomm, redistInf,
1449 oocomm.communicator().
barrier();
1450 if(oocomm.communicator().
rank()==0)
1451 std::cout<<
"Creating indexsets took "<<time.
elapsed()<<std::endl;
1458 template<
class G,
class T1,
class T2>
1459 bool buildCommunication(
const G& graph,
1462 RedistributeInterface& redistInf,
1466 typedef typename OOComm::OwnerSet OwnerSet;
1471 redistInf.buildSendInterface<OwnerSet>(setPartition, oocomm.
indexSet());
1497 int npes = oocomm.communicator().
size();
1500 std::set<int> recvFrom;
1506 typedef typename std::vector<int>::const_iterator VIter;
1507 int mype = oocomm.communicator().
rank();
1510 std::set<int> tsendTo;
1511 for(VIter i=setPartition.begin(), iend = setPartition.end(); i!=iend; ++i)
1514 noSendTo = tsendTo.size();
1515 sendTo =
new int[noSendTo];
1516 typedef std::set<int>::const_iterator iterator;
1518 for(iterator i=tsendTo.begin(); i != tsendTo.end(); ++i, ++idx)
1523 int* gnoSend=
new int[oocomm.communicator().
size()];
1524 int* gsendToDispl =
new int[oocomm.communicator().
size()+1];
1526 MPI_Allgather(&noSendTo, 1, MPI_INT, gnoSend, 1,
1527 MPI_INT, oocomm.communicator());
1530 int totalNoRecv = 0;
1531 for(
int i=0; i<npes; ++i)
1532 totalNoRecv += gnoSend[i];
1534 int *gsendTo =
new int[totalNoRecv];
1538 for(
int i=0; i<npes; ++i)
1539 gsendToDispl[i+1]=gsendToDispl[i]+gnoSend[i];
1542 MPI_Allgatherv(sendTo, noSendTo, MPI_INT, gsendTo, gnoSend, gsendToDispl,
1543 MPI_INT, oocomm.communicator());
1546 for(
int proc=0; proc < npes; ++proc)
1547 for(
int i=gsendToDispl[proc]; i < gsendToDispl[proc+1]; ++i)
1548 if(gsendTo[i]==mype)
1549 recvFrom.insert(proc);
1551 bool existentOnNextLevel = recvFrom.size()>0;
1555 delete[] gsendToDispl;
1560 if(recvFrom.size()) {
1561 std::cout<<mype<<
": recvFrom: ";
1562 typedef typename std::set<int>::const_iterator siter;
1563 for(siter i=recvFrom.begin(); i!= recvFrom.end(); ++i) {
1568 std::cout<<std::endl<<std::endl;
1569 std::cout<<mype<<
": sendTo: ";
1570 for(
int i=0; i<noSendTo; i++) {
1571 std::cout<<sendTo[i]<<
" ";
1573 std::cout<<std::endl<<std::endl;
1577 if(oocomm.communicator().
rank()==0)
1578 std::cout<<
" Communicating the receive information took "<<
1579 time.elapsed()<<std::endl;
1593 typedef typename OOComm::ParallelIndexSet::GlobalIndex GI;
1594 typedef std::vector<GI> GlobalVector;
1595 std::vector<std::pair<GI,int> > myOwnerVec;
1596 std::set<GI> myOverlapSet;
1597 GlobalVector sendOwnerVec;
1598 std::set<GI> sendOverlapSet;
1599 std::set<int> myNeighbors;
1604 char **sendBuffers=
new char*[noSendTo];
1605 MPI_Request *requests =
new MPI_Request[noSendTo];
1608 for(
int i=0; i < noSendTo; ++i) {
1610 sendOwnerVec.clear();
1611 sendOverlapSet.clear();
1614 std::set<int> neighbors;
1615 getOwnerOverlapVec<OwnerSet>(graph, setPartition, oocomm.globalLookup(),
1616 mype, sendTo[i], sendOwnerVec, sendOverlapSet, redistInf,
1622 MPI_Pack_size(1, MPITraits<std::size_t>::getType(), oocomm.communicator(), &buffersize);
1623 MPI_Pack_size(sendOwnerVec.size(), MPITraits<GI>::getType(), oocomm.communicator(), &tsize);
1625 MPI_Pack_size(1, MPITraits<std::size_t>::getType(), oocomm.communicator(), &tsize);
1627 MPI_Pack_size(sendOverlapSet.size(), MPITraits<GI>::getType(), oocomm.communicator(), &tsize);
1628 buffersize += tsize;
1629 MPI_Pack_size(1, MPITraits<std::size_t>::getType(), oocomm.communicator(), &tsize);
1630 buffersize += tsize;
1631 MPI_Pack_size(neighbors.size(), MPI_INT, oocomm.communicator(), &tsize);
1632 buffersize += tsize;
1634 sendBuffers[i] =
new char[buffersize];
1637 std::cout<<mype<<
" sending "<<sendOwnerVec.size()<<
" owner and "<<
1638 sendOverlapSet.size()<<
" overlap to "<<sendTo[i]<<
" buffersize="<<buffersize<<std::endl;
1640 createSendBuf(sendOwnerVec, sendOverlapSet, neighbors, sendBuffers[i], buffersize, oocomm.communicator());
1641 MPI_Issend(sendBuffers[i], buffersize, MPI_PACKED, sendTo[i], 99, oocomm.communicator(), requests+i);
1645 oocomm.communicator().
barrier();
1646 if(oocomm.communicator().
rank()==0)
1647 std::cout<<
" Creating sends took "<<
1648 time.elapsed()<<std::endl;
1653 int noRecv = recvFrom.size();
1654 int oldbuffersize=0;
1659 MPI_Probe(MPI_ANY_SOURCE, 99, oocomm.communicator(), &stat);
1661 MPI_Get_count(&stat, MPI_PACKED, &buffersize);
1663 if(oldbuffersize<buffersize) {
1666 recvBuf =
new char[buffersize];
1667 oldbuffersize = buffersize;
1669 MPI_Recv(recvBuf, buffersize, MPI_PACKED, stat.MPI_SOURCE, 99, oocomm.communicator(), &stat);
1670 saveRecvBuf(recvBuf, buffersize, myOwnerVec, myOverlapSet, myNeighbors, redistInf,
1671 stat.MPI_SOURCE, oocomm.communicator());
1680 MPI_Status *statuses =
new MPI_Status[noSendTo];
1681 int send = MPI_Waitall(noSendTo, requests, statuses);
1684 if(send==MPI_ERR_IN_STATUS) {
1685 std::cerr<<mype<<
": Error in sending :"<<std::endl;
1687 for(
int i=0; i< noSendTo; i++)
1688 if(statuses[i].MPI_ERROR!=MPI_SUCCESS) {
1691 MPI_Error_string(statuses[i].MPI_ERROR, message, &messageLength);
1692 std::cerr<<
" source="<<statuses[i].MPI_SOURCE<<
" message: ";
1693 for(
int i=0; i< messageLength; i++)
1694 std::cout<<message[i];
1696 std::cerr<<std::endl;
1700 oocomm.communicator().
barrier();
1701 if(oocomm.communicator().
rank()==0)
1702 std::cout<<
" Receiving and saving took "<<
1703 time.elapsed()<<std::endl;
1707 for(
int i=0; i < noSendTo; ++i)
1708 delete[] sendBuffers[i];
1710 delete[] sendBuffers;
1714 redistInf.setCommunicator(oocomm.communicator());
1725 if (!existentOnNextLevel) {
1727 color= MPI_UNDEFINED;
1729 MPI_Comm outputComm;
1731 MPI_Comm_split(oocomm.communicator(), color, oocomm.communicator().
rank(), &outputComm);
1735 int newrank=outcomm->communicator().
rank();
1736 int *newranks=
new int[oocomm.communicator().
size()];
1737 std::vector<int> tneighbors;
1738 tneighbors.reserve(myNeighbors.size());
1740 typename OOComm::ParallelIndexSet& outputIndexSet = outcomm->
indexSet();
1742 MPI_Allgather(&newrank, 1, MPI_INT, newranks, 1,
1743 MPI_INT, oocomm.communicator());
1744 typedef typename std::set<int>::const_iterator IIter;
1747 std::cout<<oocomm.communicator().
rank()<<
" ";
1748 for(IIter i=myNeighbors.begin(), end=myNeighbors.end();
1750 assert(newranks[*i]>=0);
1751 std::cout<<*i<<
"->"<<newranks[*i]<<
" ";
1752 tneighbors.push_back(newranks[*i]);
1754 std::cout<<std::endl;
1756 for(IIter i=myNeighbors.begin(), end=myNeighbors.end();
1758 tneighbors.push_back(newranks[*i]);
1762 myNeighbors.clear();
1765 oocomm.communicator().
barrier();
1766 if(oocomm.communicator().
rank()==0)
1767 std::cout<<
" Calculating new neighbours ("<<tneighbors.size()<<
") took "<<
1768 time.elapsed()<<std::endl;
1773 outputIndexSet.beginResize();
1776 std::sort(myOwnerVec.begin(), myOwnerVec.end(), SortFirst());
1780 typedef typename OOComm::ParallelIndexSet::LocalIndex LocalIndex;
1781 typedef typename std::vector<std::pair<GI,int> >::const_iterator VPIter;
1783 for(VPIter g=myOwnerVec.begin(), end =myOwnerVec.end(); g!=end; ++g, ++i ) {
1784 outputIndexSet.add(g->first,LocalIndex(i, OwnerOverlapCopyAttributeSet::owner,
true));
1785 redistInf.addReceiveIndex(g->second, i);
1789 oocomm.communicator().
barrier();
1790 if(oocomm.communicator().
rank()==0)
1791 std::cout<<
" Adding owner indices took "<<
1792 time.elapsed()<<std::endl;
1801 mergeVec(myOwnerVec, myOverlapSet);
1805 myOwnerVec.swap(myOwnerVec);
1808 oocomm.communicator().
barrier();
1809 if(oocomm.communicator().
rank()==0)
1810 std::cout<<
" Merging indices took "<<
1811 time.elapsed()<<std::endl;
1817 typedef typename std::set<GI>::const_iterator SIter;
1818 for(SIter g=myOverlapSet.begin(), end=myOverlapSet.end(); g!=end; ++g, i++) {
1819 outputIndexSet.add(*g,LocalIndex(i, OwnerOverlapCopyAttributeSet::copy,
true));
1821 myOverlapSet.clear();
1822 outputIndexSet.endResize();
1824#ifdef DUNE_ISTL_WITH_CHECKING
1826 typedef typename OOComm::ParallelIndexSet::const_iterator Iterator;
1827 Iterator end = outputIndexSet.end();
1828 for(Iterator index = outputIndexSet.begin(); index != end; ++index) {
1829 if (OwnerSet::contains(index->local().attribute())) {
1833 numOfOwnVtx = oocomm.communicator().
sum(numOfOwnVtx);
1840 Iterator index=outputIndexSet.begin();
1843 for(Iterator old = outputIndexSet.begin(); index != end; old=index++) {
1844 if(old->global()>index->global())
1845 DUNE_THROW(ISTLError,
"Index set's globalindex not sorted correctly");
1850 oocomm.communicator().
barrier();
1851 if(oocomm.communicator().
rank()==0)
1852 std::cout<<
" Adding overlap indices took "<<
1853 time.elapsed()<<std::endl;
1858 if(color != MPI_UNDEFINED) {
1868 oocomm.communicator().
barrier();
1869 if(oocomm.communicator().
rank()==0)
1870 std::cout<<
" Storing indexsets took "<<
1871 time.elapsed()<<std::endl;
1877 tSum = t1 + t2 + t3 + t4;
1878 std::cout<<std::endl
1879 <<mype<<
": WTime for step 1): "<<t1
1887 return color!=MPI_UNDEFINED;
1891 template<
class G,
class P,
class T1,
class T2,
class R>
1897 if(nparts!=oocomm.size())
1898 DUNE_THROW(NotImplemented,
"only available for MPI programs");
1902 template<
class G,
class P,
class T1,
class T2,
class R>
1903 bool commGraphRepartition(
const G& graph, P& oocomm,
int nparts,
1908 if(nparts!=oocomm.size())
1909 DUNE_THROW(NotImplemented,
"only available for MPI programs");
The (undirected) graph of a matrix.
Definition: graph.hh:50
int rank() const
Return rank, is between 0 and size()-1.
Definition: mpicollectivecommunication.hh:162
T max(T &in) const
Compute the maximum of the argument over all processes and return the result in every process....
Definition: mpicollectivecommunication.hh:224
int size() const
Number of processes in set, is greater than 0.
Definition: mpicollectivecommunication.hh:168
int barrier() const
Wait until all processes have arrived at this point in the program.
Definition: mpicollectivecommunication.hh:239
T sum(T &in) const
Compute the sum of the argument over all processes and return the result in every process....
Definition: mpicollectivecommunication.hh:175
Index Set Interface base class.
Definition: indexidset.hh:78
IndexType size(GeometryType type) const
Return total number of entities of given geometry type in entity set .
Definition: indexidset.hh:204
MPI_Comm communicator_
The MPI communicator we use.
Definition: interface.hh:315
size_type N() const
Return the number of rows.
Definition: matrix.hh:160
A class setting up standard communication for a two-valued attribute set with owner/overlap/copy sema...
Definition: owneroverlapcopy.hh:173
const ParallelIndexSet & indexSet() const
Get the underlying parallel index set.
Definition: owneroverlapcopy.hh:466
const SolverCategory::Category getSolverCategory() const
Set Solver Category.
Definition: owneroverlapcopy.hh:302
void copyCopyToAll(const T &source, T &dest) const
Communicate values from copy data points to all other data points.
Definition: owneroverlapcopy.hh:335
void copyOwnerToAll(const T &source, T &dest) const
Communicate values from owner data points to all other data points.
Definition: owneroverlapcopy.hh:318
const RemoteIndices & remoteIndices() const
Get the underlying remote indices.
Definition: owneroverlapcopy.hh:475
LocalIndex::Attribute Attribute
The type of the attribute.
Definition: remoteindices.hh:220
const_iterator end() const
Get an iterator over all remote index lists.
Definition: remoteindices.hh:1525
int neighbours() const
Get the number of processors we share indices with.
Definition: remoteindices.hh:1442
const_iterator begin() const
Get an iterator over all remote index lists.
Definition: remoteindices.hh:1518
A simple stop watch.
Definition: timer.hh:52
void reset()
Reset timer while keeping the running/stopped state.
Definition: timer.hh:66
double elapsed() const
Get elapsed user-time from last reset until now/last stop in seconds.
Definition: timer.hh:86
Provides utility classes for syncing distributed data via MPI communication.
Classes for building sets out of enumeration values.
Provides classes for building the matrix graph.
size_t size() const
Get the total number (public and nonpublic) indices.
void repairLocalIndexPointers(std::map< int, SLList< std::pair< typename T::GlobalIndex, typename T::LocalIndex::Attribute >, A > > &globalMap, RemoteIndices< T, A1 > &remoteIndices, const T &indexSet)
Repair the pointers to the local indices in the remote indices.
Definition: indicessyncer.hh:492
void storeGlobalIndicesOfRemoteIndices(std::map< int, SLList< std::pair< typename T::GlobalIndex, typename T::LocalIndex::Attribute >, A > > &globalMap, const RemoteIndices< T, A1 > &remoteIndices, const T &indexSet)
Stores the corresponding global indices of the remote index information.
Definition: indicessyncer.hh:462
iterator begin()
Get an iterator over the indices positioned at the first index.
iterator end()
Get an iterator over the indices positioned after the last index.
const InformationMap & interfaces() const
Get information about the interfaces.
Definition: interface.hh:423
const IndexPair * pair(const std::size_t &local) const
Get the index pair corresponding to a local index.
#define DUNE_THROW(E, m)
Definition: exceptions.hh:244
DInfoType dinfo(std::cout)
Stream for informative output.
Definition: stdstreams.hh:139
DVerbType dverb(std::cout)
Singleton of verbose debug stream.
Definition: stdstreams.hh:115
Provides a map between global and local indices.
Class for adding missing indices of a distributed index set in a local communication.
Dune namespace.
Definition: alignment.hh:14
void fillIndexSetHoles(const G &graph, Dune::OwnerOverlapCopyCommunication< T1, T2 > &oocomm)
Fills the holes in an index set.
Definition: repartition.hh:58
bool graphRepartition(const G &graph, Dune::OwnerOverlapCopyCommunication< T1, T2 > &oocomm, int nparts, Dune::OwnerOverlapCopyCommunication< T1, T2 > *&outcomm, RedistributeInterface &redistInf, bool verbose=false)
execute a graph repartition for a giving graph and indexset.
Definition: repartition.hh:1233
Classes providing communication interfaces for overlapping Schwarz methods.
Traits classes for mapping types onto MPI_Datatype.
Classes describing a distributed indexset.
Standard Dune debug streams.
A traits class describing the mapping of types onto MPI_Datatypes.
Definition: mpitraits.hh:37
@ nonoverlapping
Category for on overlapping solvers.
Definition: solvercategory.hh:24
Definition of the DUNE_UNUSED macro for the case that config.h is not available.
#define DUNE_UNUSED_PARAMETER(parm)
A macro to mark intentional unused function parameters with.
Definition: unused.hh:18