3#ifndef DUNE_ISTL_REPARTITION_HH
4#define DUNE_ISTL_REPARTITION_HH
49#if HAVE_PARMETIS && defined(REALTYPEWIDTH)
55#if HAVE_PARMETIS && defined(IDXTYPEWIDTH)
56 using idx_t = ::idx_t;
57#elif HAVE_PARMETIS && defined(HAVE_SCOTCH_NUM_TYPE)
58 using idx_t = SCOTCH_Num;
62 using idx_t = std::size_t;
81 template<
class G,
class T1,
class T2>
85 typedef typename IndexSet::LocalIndex::Attribute
Attribute;
91 typedef typename G::ConstVertexIterator VertexIterator;
94 std::size_t sum=0, needed = graph.noVertices()-indexSet.
size();
95 std::vector<std::size_t> neededall(oocomm.communicator().size(), 0);
98 for(
int i=0; i<oocomm.communicator().size(); ++i)
107 typedef typename IndexSet::const_iterator Iterator;
109 end = indexSet.end();
110 for(Iterator it = indexSet.begin(); it != end; ++it)
116 maxgi=oocomm.communicator().max(maxgi);
119 for(
int i=0; i<oocomm.communicator().rank(); ++i)
120 maxgi=maxgi+neededall[i];
123 std::map<int,SLList<std::pair<T1,Attribute> > > globalIndices;
125 indexSet.beginResize();
127 for(VertexIterator
vertex = graph.begin(), vend=graph.end();
vertex != vend; ++
vertex) {
128 const typename IndexSet::IndexPair* pair=lookup.
pair(*
vertex);
131 indexSet.add(maxgi,
typename IndexSet::LocalIndex(*
vertex, OwnerOverlapCopyAttributeSet::owner,
false));
136 indexSet.endResize();
140 oocomm.freeGlobalLookup();
141 oocomm.buildGlobalLookup();
143 std::cout<<
"Holes are filled!"<<std::endl;
144 std::cout<<oocomm.communicator().rank()<<
": "<<oocomm.
indexSet()<<std::endl;
151 class ParmetisDuneIndexMap
154 template<
class Graph,
class OOComm>
155 ParmetisDuneIndexMap(
const Graph& graph,
const OOComm& com);
156 int toParmetis(
int i)
const
158 return duneToParmetis[i];
160 int toLocalParmetis(
int i)
const
162 return duneToParmetis[i]-base_;
164 int operator[](
int i)
const
166 return duneToParmetis[i];
168 int toDune(
int i)
const
170 return parmetisToDune[i];
172 std::vector<int>::size_type numOfOwnVtx()
const
174 return parmetisToDune.size();
176 Metis::idx_t* vtxDist()
180 int globalOwnerVertices;
183 std::vector<int> duneToParmetis;
184 std::vector<int> parmetisToDune;
186 std::vector<Metis::idx_t> vtxDist_;
189 template<
class G,
class OOComm>
190 ParmetisDuneIndexMap::ParmetisDuneIndexMap(
const G& graph,
const OOComm& oocomm)
191 : duneToParmetis(graph.noVertices(), -1), vtxDist_(oocomm.communicator().size()+1)
193 int npes=oocomm.communicator().size(), mype=oocomm.communicator().rank();
195 typedef typename OOComm::ParallelIndexSet::const_iterator Iterator;
196 typedef typename OOComm::OwnerSet OwnerSet;
199 Iterator
end = oocomm.indexSet().end();
200 for(Iterator index = oocomm.indexSet().begin(); index !=
end; ++index) {
201 if (OwnerSet::contains(index->local().attribute())) {
205 parmetisToDune.resize(numOfOwnVtx);
206 std::vector<int> globalNumOfVtx(npes);
208 MPI_Allgather(&numOfOwnVtx, 1, MPI_INT, &(globalNumOfVtx[0]), 1, MPI_INT, oocomm.communicator());
212 for(
int i=0; i<npes; i++) {
214 base += globalNumOfVtx[i];
216 vtxDist_[i+1] = vtxDist_[i] + globalNumOfVtx[i];
218 globalOwnerVertices=vtxDist_[npes];
222 typedef typename G::ConstVertexIterator VertexIterator;
224 std::cout << oocomm.communicator().rank()<<
" vtxDist: ";
225 for(
int i=0; i<= npes; ++i)
226 std::cout << vtxDist_[i]<<
" ";
227 std::cout<<std::endl;
234 VertexIterator vend = graph.end();
236 const typename OOComm::ParallelIndexSet::IndexPair* index=oocomm.globalLookup().pair(*
vertex);
238 if (OwnerSet::contains(index->local().attribute())) {
240 parmetisToDune[base-base_]=index->local();
241 duneToParmetis[index->local()] = base++;
251 std::cout <<oocomm.communicator().rank()<<
": before ";
252 for(std::size_t i=0; i<duneToParmetis.size(); ++i)
253 std::cout<<duneToParmetis[i]<<
" ";
254 std::cout<<std::endl;
256 oocomm.copyOwnerToAll(duneToParmetis,duneToParmetis);
258 std::cout <<oocomm.communicator().rank()<<
": after ";
259 for(std::size_t i=0; i<duneToParmetis.size(); ++i)
260 std::cout<<duneToParmetis[i]<<
" ";
261 std::cout<<std::endl;
266 struct RedistributeInterface
269 void setCommunicator(MPI_Comm comm)
273 template<
class Flags,
class IS>
274 void buildSendInterface(
const std::vector<int>& toPart,
const IS& idxset)
276 std::map<int,int> sizes;
278 typedef typename IS::const_iterator IIter;
279 for(IIter i=idxset.begin(), end=idxset.end(); i!=end; ++i)
280 if(Flags::contains(i->local().attribute()))
281 ++sizes[toPart[i->local()]];
284 typedef std::map<int,int>::const_iterator MIter;
285 for(MIter i=sizes.begin(), end=sizes.end(); i!=end; ++i)
286 interfaces()[i->first].first.reserve(i->second);
289 typedef typename IS::const_iterator IIter;
290 for(IIter i=idxset.begin(), end=idxset.end(); i!=end; ++i)
291 if(Flags::contains(i->local().attribute()))
292 interfaces()[toPart[i->local()]].first.add(i->local());
295 void reserveSpaceForReceiveInterface(
int proc,
int size)
299 void addReceiveIndex(
int proc, std::size_t idx)
303 template<
typename TG>
304 void buildReceiveInterface(std::vector<std::pair<TG,int> >& indices)
306 typedef typename std::vector<std::pair<TG,int> >::const_iterator VIter;
308 for(VIter idx=indices.begin(); idx!= indices.end(); ++idx) {
313 ~RedistributeInterface()
330 void createSendBuf(std::vector<GI>& ownerVec, std::set<GI>& overlapVec, std::set<int>& neighbors,
char *sendBuf,
int buffersize, MPI_Comm comm) {
332 std::size_t s=ownerVec.size();
336 MPI_Pack(&s, 1, MPITraits<std::size_t>::getType(), sendBuf, buffersize, &pos, comm);
337 MPI_Pack(&(ownerVec[0]), s, MPITraits<GI>::getType(), sendBuf, buffersize, &pos, comm);
338 s = overlapVec.size();
339 MPI_Pack(&s, 1, MPITraits<std::size_t>::getType(), sendBuf, buffersize, &pos, comm);
340 typedef typename std::set<GI>::iterator Iter;
341 for(Iter i=overlapVec.begin(), end= overlapVec.end(); i != end; ++i)
342 MPI_Pack(
const_cast<GI*
>(&(*i)), 1, MPITraits<GI>::getType(), sendBuf, buffersize, &pos, comm);
345 MPI_Pack(&s, 1, MPITraits<std::size_t>::getType(), sendBuf, buffersize, &pos, comm);
346 typedef typename std::set<int>::iterator IIter;
348 for(IIter i=neighbors.begin(), end= neighbors.end(); i != end; ++i)
349 MPI_Pack(
const_cast<int*
>(&(*i)), 1, MPI_INT, sendBuf, buffersize, &pos, comm);
360 void saveRecvBuf(
char *recvBuf,
int bufferSize, std::vector<std::pair<GI,int> >& ownerVec,
361 std::set<GI>& overlapVec, std::set<int>& neighbors, RedistributeInterface& inf,
int from, MPI_Comm comm) {
365 MPI_Unpack(recvBuf, bufferSize, &pos, &size, 1, MPITraits<std::size_t>::getType(), comm);
366 inf.reserveSpaceForReceiveInterface(from, size);
367 ownerVec.reserve(ownerVec.size()+size);
368 for(; size!=0; --size) {
370 MPI_Unpack(recvBuf, bufferSize, &pos, &gi, 1, MPITraits<GI>::getType(), comm);
371 ownerVec.push_back(std::make_pair(gi,from));
374 MPI_Unpack(recvBuf, bufferSize, &pos, &size, 1, MPITraits<std::size_t>::getType(), comm);
375 typename std::set<GI>::iterator ipos = overlapVec.begin();
376 Dune::dverb <<
"unpacking "<<size<<
" overlap"<<std::endl;
377 for(; size!=0; --size) {
379 MPI_Unpack(recvBuf, bufferSize, &pos, &gi, 1, MPITraits<GI>::getType(), comm);
380 ipos=overlapVec.insert(ipos, gi);
383 MPI_Unpack(recvBuf, bufferSize, &pos, &size, 1, MPITraits<std::size_t>::getType(), comm);
384 Dune::dverb <<
"unpacking "<<size<<
" neighbors"<<std::endl;
385 typename std::set<int>::iterator npos = neighbors.begin();
386 for(; size!=0; --size) {
388 MPI_Unpack(recvBuf, bufferSize, &pos, &n, 1, MPI_INT, comm);
389 npos=neighbors.insert(npos, n);
407 void getDomain(
const MPI_Comm& comm, T *part,
int numOfOwnVtx,
int nparts,
int *myDomain, std::vector<int> &domainMapping) {
409 MPI_Comm_size(comm, &npes);
410 MPI_Comm_rank(comm, &mype);
417 std::vector<int> domain(nparts, 0);
418 std::vector<int> assigned(npes, 0);
420 domainMapping.assign(domainMapping.size(), -1);
423 for (i=0; i<numOfOwnVtx; i++) {
427 std::vector<int> domainMatrix(npes * nparts, -1);
430 int *buf =
new int[nparts];
431 for (i=0; i<nparts; i++) {
433 domainMatrix[mype*nparts+i] = domain[i];
436 int src = (mype-1+npes)%npes;
437 int dest = (mype+1)%npes;
439 for (i=0; i<npes-1; i++) {
440 MPI_Sendrecv_replace(buf, nparts, MPI_INT, dest, 0, src, 0, comm, &status);
442 pe = ((mype-1-i)+npes)%npes;
443 for(j=0; j<nparts; j++) {
445 domainMatrix[pe*nparts+j] = buf[j];
453 int maxOccurance = 0;
455 std::set<std::size_t> unassigned;
457 for(i=0; i<nparts; i++) {
458 for(j=0; j<npes; j++) {
460 if (assigned[j]==0) {
461 if (maxOccurance < domainMatrix[j*nparts+i]) {
462 maxOccurance = domainMatrix[j*nparts+i];
470 domainMapping[i] = pe;
480 unassigned.insert(i);
485 typename std::vector<int>::iterator next_free = assigned.begin();
487 for(
typename std::set<std::size_t>::iterator domain = unassigned.begin(),
488 end = unassigned.end(); domain != end; ++domain)
490 next_free = std::find_if(next_free, assigned.end(), std::bind(std::less<int>(),
std::placeholders::_1, 1));
491 assert(next_free != assigned.end());
492 domainMapping[*domain] = next_free-assigned.begin();
500 bool operator()(
const T& t1,
const T& t2)
const
518 void mergeVec(std::vector<std::pair<GI, int> >& ownerVec, std::set<GI>& overlapSet) {
520 typedef typename std::vector<std::pair<GI,int> >::const_iterator VIter;
523 if(ownerVec.size()>0)
525 VIter old=ownerVec.begin();
526 for(VIter i=old+1, end=ownerVec.end(); i != end; old=i++)
528 if(i->first==old->first)
530 std::cerr<<
"Value at indes"<<old-ownerVec.begin()<<
" is the same as at index "
531 <<i-ownerVec.begin()<<
" ["<<old->first<<
","<<old->second<<
"]==["
532 <<i->first<<
","<<i->second<<
"]"<<std::endl;
540 typedef typename std::set<GI>::iterator SIter;
541 VIter v=ownerVec.begin(), vend=ownerVec.end();
542 for(SIter s=overlapSet.begin(), send=overlapSet.end(); s!=send;)
544 while(v!=vend && v->first<*s) ++v;
545 if(v!=vend && v->first==*s) {
550 overlapSet.erase(tmp);
570 template<
class OwnerSet,
class Graph,
class IS,
class GI>
571 void getNeighbor(
const Graph& g, std::vector<int>& part,
572 typename Graph::VertexDescriptor vtx,
const IS& indexSet,
573 int toPe, std::set<GI>& neighbor, std::set<int>& neighborProcs) {
574 typedef typename Graph::ConstEdgeIterator Iter;
575 for(Iter edge=g.beginEdges(vtx), end=g.endEdges(vtx); edge!=end; ++edge)
577 const typename IS::IndexPair* pindex = indexSet.pair(edge.target());
579 if(part[pindex->local()]!=toPe || !OwnerSet::contains(pindex->local().attribute()))
582 neighbor.insert(pindex->global());
583 neighborProcs.insert(part[pindex->local()]);
588 template<
class T,
class I>
589 void my_push_back(std::vector<T>& ownerVec,
const I& index,
int proc)
592 ownerVec.push_back(index);
595 template<
class T,
class I>
596 void my_push_back(std::vector<std::pair<T,int> >& ownerVec,
const I& index,
int proc)
598 ownerVec.push_back(std::make_pair(index,proc));
601 void reserve(std::vector<T>&, RedistributeInterface&,
int)
604 void reserve(std::vector<std::pair<T,int> >& ownerVec, RedistributeInterface& redist,
int proc)
606 redist.reserveSpaceForReceiveInterface(proc, ownerVec.size());
627 template<
class OwnerSet,
class G,
class IS,
class T,
class GI>
628 void getOwnerOverlapVec(
const G& graph, std::vector<int>& part, IS& indexSet,
629 int myPe,
int toPe, std::vector<T>& ownerVec, std::set<GI>& overlapSet,
630 RedistributeInterface& redist, std::set<int>& neighborProcs) {
633 typedef typename IS::const_iterator Iterator;
634 for(Iterator index = indexSet.begin(); index != indexSet.end(); ++index) {
636 if(OwnerSet::contains(index->local().attribute()))
638 if(part[index->local()]==toPe)
640 getNeighbor<OwnerSet>(graph, part, index->local(), indexSet,
641 toPe, overlapSet, neighborProcs);
642 my_push_back(ownerVec, index->global(), toPe);
646 reserve(ownerVec, redist, toPe);
657 template<
class F,
class IS>
658 inline bool isOwner(IS& indexSet,
int index) {
660 const typename IS::IndexPair* pindex=indexSet.pair(index);
663 return F::contains(pindex->local().attribute());
667 class BaseEdgeFunctor
670 BaseEdgeFunctor(Metis::idx_t* adj,
const ParmetisDuneIndexMap& data)
671 : i_(), adj_(adj), data_(data)
675 void operator()(
const T& edge)
679 adj_[i_] = data_.toParmetis(edge.target());
690 const ParmetisDuneIndexMap& data_;
695 :
public BaseEdgeFunctor
697 EdgeFunctor(Metis::idx_t* adj,
const ParmetisDuneIndexMap& data, std::size_t)
698 : BaseEdgeFunctor(adj, data)
701 Metis::idx_t* getWeights()
708 template<
class G,
class V,
class E,
class VM,
class EM>
709 class EdgeFunctor<
Dune::Amg::PropertiesGraph<G,V,E,VM,EM> >
710 :
public BaseEdgeFunctor
713 EdgeFunctor(Metis::idx_t* adj,
const ParmetisDuneIndexMap& data, std::size_t s)
714 : BaseEdgeFunctor(adj, data)
716 weight_=
new Metis::idx_t[s];
720 void operator()(
const T& edge)
722 weight_[index()]=edge.properties().depends() ? 3 : 1;
723 BaseEdgeFunctor::operator()(edge);
725 Metis::idx_t* getWeights()
736 Metis::idx_t* weight_;
754 template<
class F,
class G,
class IS,
class EW>
755 void getAdjArrays(G& graph, IS& indexSet, Metis::idx_t *xadj,
761 typedef typename G::ConstVertexIterator VertexIterator;
763 typedef typename IS::const_iterator Iterator;
765 VertexIterator vend = graph.end();
769 if (isOwner<F>(indexSet,*
vertex)) {
771 typedef typename G::ConstEdgeIterator EdgeIterator;
772 EdgeIterator eend =
vertex.end();
773 xadj[j] = ew.index();
775 for(EdgeIterator edge =
vertex.begin(); edge != eend; ++edge) {
780 xadj[j] = ew.index();
784 template<
class G,
class T1,
class T2>
785 bool buildCommunication(
const G& graph, std::vector<int>& realparts,
788 RedistributeInterface& redistInf,
791#ifndef METIS_VER_MAJOR
795 void METIS_PartGraphKway(
int *nvtxs, Metis::idx_t *xadj, Metis::idx_t *adjncy, Metis::idx_t *vwgt,
796 Metis::idx_t *adjwgt,
int *wgtflag,
int *numflag,
int *nparts,
797 int *options,
int *edgecut, Metis::idx_t *part);
799 void METIS_PartGraphRecursive(
int *nvtxs, Metis::idx_t *xadj, Metis::idx_t *adjncy, Metis::idx_t *vwgt,
800 Metis::idx_t *adjwgt,
int *wgtflag,
int *numflag,
int *nparts,
801 int *options,
int *edgecut, Metis::idx_t *part);
806 template<
class S,
class T>
807 inline void print_carray(S& os, T* array, std::size_t l)
809 for(T *cur=array, *end=array+l; cur!=end; ++cur)
813 template<
class S,
class T>
814 inline bool isValidGraph(std::size_t noVtx, std::size_t gnoVtx, S noEdges, T* xadj,
815 T* adjncy,
bool checkSymmetry)
820 for(Metis::idx_t vtx=0; vtx<(Metis::idx_t)noVtx; ++vtx) {
821 if(xadj[vtx]>noEdges || signbit(xadj[vtx])) {
822 std::cerr <<
"Check graph: xadj["<<vtx<<
"]="<<xadj[vtx]<<
" (>"
823 <<noEdges<<
") out of range!"<<std::endl;
826 if(xadj[vtx+1]>noEdges || signbit(xadj[vtx+1])) {
827 std::cerr <<
"Check graph: xadj["<<vtx+1<<
"]="<<xadj[vtx+1]<<
" (>"
828 <<noEdges<<
") out of range!"<<std::endl;
832 for(Metis::idx_t i=xadj[vtx]; i< xadj[vtx+1]; ++i) {
833 if(adjncy[i]<0||((std::size_t)adjncy[i])>gnoVtx) {
834 std::cerr<<
" Edge "<<adjncy[i]<<
" out of range ["<<0<<
","<<noVtx<<
")"
840 for(Metis::idx_t i=xadj[vtx]; i< xadj[vtx+1]; ++i) {
841 Metis::idx_t target=adjncy[i];
844 for(Metis::idx_t j=xadj[target]; j< xadj[target+1]; ++j)
848 std::cerr<<
"Edge ("<<target<<
","<<vtx<<
") "<<i<<
" time"<<std::endl;
857 template<
class M,
class T1,
class T2>
861 RedistributeInterface& redistInf,
864 if(verbose && oocomm.communicator().rank()==0)
865 std::cout<<
"Repartitioning from "<<oocomm.communicator().size()
866 <<
" to "<<nparts<<
" parts"<<std::endl;
868 int rank = oocomm.communicator().rank();
870 int* part =
new int[1];
873 Metis::idx_t* part =
new Metis::idx_t[1];
885 typedef typename RemoteIndices::const_iterator
900 Metis::idx_t *xadj=
new Metis::idx_t[2];
901 Metis::idx_t *vtxdist=
new Metis::idx_t[oocomm.communicator().size()+1];
902 Metis::idx_t *adjncy=
new Metis::idx_t[noNeighbours];
904 Metis::idx_t *vwgt = 0;
905 Metis::idx_t *adjwgt = 0;
909 for(
int i=0; i<oocomm.communicator().size(); ++i)
911 vtxdist[oocomm.communicator().size()]=oocomm.communicator().size();
914 xadj[1]=noNeighbours;
944 typedef typename RemoteIndices::const_iterator NeighbourIterator;
946 Metis::idx_t* adjp=adjncy;
949 vwgt =
new Metis::idx_t[1];
952 adjwgt =
new Metis::idx_t[noNeighbours];
953 Metis::idx_t* adjwp=adjwgt;
958 if(n->first != rank) {
966 assert(isValidGraph(vtxdist[rank+1]-vtxdist[rank],
967 vtxdist[oocomm.communicator().size()],
968 noNeighbours, xadj, adjncy,
false));
971 Metis::idx_t numflag=0;
972 Metis::idx_t edgecut;
976 Metis::real_t *tpwgts =
new Metis::real_t[nparts];
977 for(
int i=0; i<nparts; ++i)
978 tpwgts[i]=1.0/nparts;
979 MPI_Comm comm=oocomm.communicator();
982 print_carray(
Dune::dinfo, vtxdist, oocomm.communicator().size()+1);
995 oocomm.communicator().barrier();
996 if(verbose && oocomm.communicator().rank()==0)
997 std::cout<<
"Creating comm graph took "<<time.elapsed()<<std::endl;
1000#ifdef PARALLEL_PARTITION
1001 Metis::real_t ubvec = 1.15;
1003 int options[5] ={ 0,1,15,0,0};
1008 ParMETIS_V3_PartKway(vtxdist, xadj, adjncy,
1009 vwgt, adjwgt, &wgtflag,
1010 &numflag, &ncon, &nparts, tpwgts, &ubvec, options, &edgecut, part,
1012 if(verbose && oocomm.communicator().rank()==0)
1013 std::cout<<
"ParMETIS took "<<time.elapsed()<<std::endl;
1017 std::size_t gnoedges=0;
1019 noedges =
new int[oocomm.communicator().size()];
1020 Dune::dverb<<
"noNeighbours: "<<noNeighbours<<std::endl;
1022 MPI_Allgather(&noNeighbours,1,MPI_INT,noedges,1, MPI_INT,oocomm.communicator());
1024 if(verbose && oocomm.communicator().rank()==0)
1025 std::cout<<
"Gathering noedges took "<<time1.elapsed()<<std::endl;
1028 Metis::idx_t noVertices = vtxdist[oocomm.communicator().size()];
1029 Metis::idx_t *gxadj = 0;
1030 Metis::idx_t *gvwgt = 0;
1031 Metis::idx_t *gadjncy = 0;
1032 Metis::idx_t *gadjwgt = 0;
1033 Metis::idx_t *gpart = 0;
1040 std::size_t localNoVtx=vtxdist[rank+1]-vtxdist[rank];
1042 std::size_t gxadjlen = vtxdist[oocomm.communicator().size()]-vtxdist[0]+oocomm.communicator().size();
1046 print_carray(
Dune::dinfo, noedges, oocomm.communicator().size());
1048 displ =
new int[oocomm.communicator().size()];
1049 xdispl =
new int[oocomm.communicator().size()];
1050 noxs =
new int[oocomm.communicator().size()];
1051 vdispl =
new int[oocomm.communicator().size()];
1052 novs =
new int[oocomm.communicator().size()];
1054 for(
int i=0; i < oocomm.communicator().size(); ++i) {
1055 noxs[i]=vtxdist[i+1]-vtxdist[i]+1;
1056 novs[i]=vtxdist[i+1]-vtxdist[i];
1059 Metis::idx_t *so= vtxdist;
1061 for(
int *xcurr = xdispl, *vcurr = vdispl, *end=vdispl+oocomm.communicator().size();
1062 vcurr!=end; ++vcurr, ++xcurr, ++so, ++offset) {
1064 *xcurr = offset + *so;
1070 for(
int *curr=noedges, *end=noedges+oocomm.communicator().size()-1;
1071 curr!=end; ++curr) {
1077 print_carray(
Dune::dinfo, displ, oocomm.communicator().size());
1082 for(
int *curr=noedges, *end=noedges+oocomm.communicator().size();
1087 Dune::dinfo<<
"gxadjlen: "<<gxadjlen<<
" noVertices: "<<noVertices
1088 <<
" gnoedges: "<<gnoedges<<std::endl;
1089 gxadj =
new Metis::idx_t[gxadjlen];
1090 gpart =
new Metis::idx_t[noVertices];
1092 gvwgt =
new Metis::idx_t[noVertices];
1093 gadjwgt =
new Metis::idx_t[gnoedges];
1095 gadjncy =
new Metis::idx_t[gnoedges];
1098 if(verbose && oocomm.communicator().rank()==0)
1099 std::cout<<
"Preparing global graph took "<<time1.elapsed()<<std::endl;
1103 MPI_Allgatherv(xadj,2,MPITraits<Metis::idx_t>::getType(),
1104 gxadj,noxs,xdispl,MPITraits<Metis::idx_t>::getType(),
1106 MPI_Allgatherv(adjncy,noNeighbours,MPITraits<Metis::idx_t>::getType(),
1107 gadjncy,noedges,displ,MPITraits<Metis::idx_t>::getType(),
1110 MPI_Allgatherv(adjwgt,noNeighbours,MPITraits<Metis::idx_t>::getType(),
1111 gadjwgt,noedges,displ,MPITraits<Metis::idx_t>::getType(),
1113 MPI_Allgatherv(vwgt,localNoVtx,MPITraits<Metis::idx_t>::getType(),
1114 gvwgt,novs,vdispl,MPITraits<Metis::idx_t>::getType(),
1117 if(verbose && oocomm.communicator().rank()==0)
1118 std::cout<<
"Gathering global graph data took "<<time1.elapsed()<<std::endl;
1128 Metis::idx_t increment = vtxdist[1];
1129 Metis::idx_t *start=gxadj+1;
1130 for(
int i=1; i<oocomm.communicator().size(); ++i) {
1132 int lprev = vtxdist[i]-vtxdist[i-1];
1133 int l = vtxdist[i+1]-vtxdist[i];
1135 assert((start+l+offset)-gxadj<=
static_cast<Metis::idx_t
>(gxadjlen));
1136 increment = *(start-1);
1137 std::transform(start+offset, start+l+offset, start, std::bind(std::plus<Metis::idx_t>(),
std::placeholders::_1, increment));
1151 if(verbose && oocomm.communicator().rank()==0)
1152 std::cout<<
"Postprocesing global graph data took "<<time1.elapsed()<<std::endl;
1155 assert(isValidGraph(noVertices, noVertices, gnoedges,
1156 gxadj, gadjncy,
true));
1159 if(verbose && oocomm.communicator().rank()==0)
1160 std::cout<<
"Creating grah one 1 process took "<<time.elapsed()<<std::endl;
1162#if METIS_VER_MAJOR >= 5
1163 Metis::idx_t ncon = 1;
1164 Metis::idx_t moptions[METIS_NOPTIONS];
1165 METIS_SetDefaultOptions(moptions);
1166 moptions[METIS_OPTION_NUMBERING] = numflag;
1167 METIS_PartGraphRecursive(&noVertices, &ncon, gxadj, gadjncy, gvwgt, NULL, gadjwgt,
1168 &nparts, NULL, NULL, moptions, &edgecut, gpart);
1170 int options[5] = {0, 1, 1, 3, 3};
1172 METIS_PartGraphRecursive(&noVertices, gxadj, gadjncy, gvwgt, gadjwgt, &wgtflag,
1173 &numflag, &nparts, options, &edgecut, gpart);
1176 if(verbose && oocomm.communicator().rank()==0)
1177 std::cout<<
"METIS took "<<time.elapsed()<<std::endl;
1191 MPI_Scatter(gpart, 1, MPITraits<Metis::idx_t>::getType(), part, 1,
1192 MPITraits<Metis::idx_t>::getType(), 0, comm);
1216 Dune::dinfo<<
" repart "<<rank <<
" -> "<< part[0]<<std::endl;
1218 std::vector<int> realpart(mat.
N(), part[0]);
1223 if(verbose && oocomm.communicator().rank()==0)
1224 std::cout<<
"Scattering repartitioning took "<<time.elapsed()<<std::endl;
1228 oocomm.buildGlobalLookup(mat.
N());
1231 if(verbose && oocomm.communicator().rank()==0)
1232 std::cout<<
"Filling index set took "<<time.elapsed()<<std::endl;
1237 noNeighbours = oocomm.communicator().sum(noNeighbours)
1238 / oocomm.communicator().size();
1239 if(oocomm.communicator().rank()==0)
1240 std::cout<<
"Average no neighbours was "<<noNeighbours<<std::endl;
1242 bool ret = buildCommunication(graph, realpart, oocomm, outcomm, redistInf,
1244 if(verbose && oocomm.communicator().rank()==0)
1245 std::cout<<
"Building index sets took "<<time.elapsed()<<std::endl;
1267 template<
class G,
class T1,
class T2>
1270 RedistributeInterface& redistInf,
1275 MPI_Comm comm=oocomm.communicator();
1276 oocomm.buildGlobalLookup(graph.noVertices());
1279 if(verbose && oocomm.communicator().rank()==0)
1280 std::cout<<
"Filling holes took "<<time.
elapsed()<<std::endl;
1287 double t1=0.0, t2=0.0, t3=0.0, t4=0.0, tSum=0.0;
1292 int mype = oocomm.communicator().rank();
1294 assert(nparts<=
static_cast<Metis::idx_t
>(oocomm.communicator().size()));
1315 typedef typename OOComm::OwnerSet OwnerSet;
1320 ParmetisDuneIndexMap indexMap(graph,oocomm);
1321 Metis::idx_t *part =
new Metis::idx_t[indexMap.numOfOwnVtx()];
1322 for(std::size_t i=0; i < indexMap.numOfOwnVtx(); ++i)
1326 if(oocomm.communicator().rank()==0 && nparts>1)
1327 std::cerr<<
"ParMETIS not activated. Will repartition to 1 domain instead of requested "
1328 <<nparts<<
" domains."<<std::endl;
1335 Metis::idx_t *xadj =
new Metis::idx_t[indexMap.numOfOwnVtx()+1];
1336 Metis::idx_t *adjncy =
new Metis::idx_t[graph.noEdges()];
1337 EdgeFunctor<G> ef(adjncy, indexMap, graph.noEdges());
1338 getAdjArrays<OwnerSet>(graph, oocomm.globalLookup(), xadj, ef);
1344 Metis::idx_t numflag=0, wgtflag=0, options[3], edgecut=0, ncon=1;
1346 Metis::real_t *tpwgts =
new Metis::real_t[nparts];
1347 for(
int i=0; i<nparts; ++i)
1348 tpwgts[i]=1.0/nparts;
1349 Metis::real_t ubvec[1];
1357 wgtflag = (ef.getWeights()!=NULL) ? 1 : 0;
1365 std::cout<<std::endl;
1366 std::cout<<
"Testing ParMETIS_V3_PartKway with options[1-2] = {"
1367 <<options[1]<<
" "<<options[2]<<
"}, Ncon: "
1368 <<ncon<<
", Nparts: "<<nparts<<std::endl;
1379 oocomm.communicator().barrier();
1380 if(oocomm.communicator().rank()==0)
1381 std::cout<<
"Preparing for parmetis took "<<time.
elapsed()<<std::endl;
1388 ParMETIS_V3_PartKway(indexMap.vtxDist(), xadj, adjncy,
1389 NULL, ef.getWeights(), &wgtflag,
1390 &numflag, &ncon, &nparts, tpwgts, ubvec, options, &edgecut, part, &
const_cast<MPI_Comm&
>(comm));
1401 std::cout<<std::endl;
1402 std::cout<<
"ParMETIS_V3_PartKway reported a cut of "<<edgecut<<std::endl;
1403 std::cout<<std::endl;
1405 std::cout<<mype<<
": PARMETIS-Result: ";
1406 for(
int i=0; i < indexMap.vtxDist()[mype+1]-indexMap.vtxDist()[mype]; ++i) {
1407 std::cout<<part[i]<<
" ";
1409 std::cout<<std::endl;
1410 std::cout<<
"Testing ParMETIS_V3_PartKway with options[1-2] = {"
1411 <<options[1]<<
" "<<options[2]<<
"}, Ncon: "
1412 <<ncon<<
", Nparts: "<<nparts<<std::endl;
1423 oocomm.communicator().barrier();
1424 if(oocomm.communicator().rank()==0)
1425 std::cout<<
"Parmetis took "<<time.
elapsed()<<std::endl;
1432 for(std::size_t i=0; i<indexMap.numOfOwnVtx(); ++i)
1442 std::vector<int> domainMapping(nparts);
1444 getDomain(comm, part, indexMap.numOfOwnVtx(), nparts, &myDomain, domainMapping);
1449 std::cout<<mype<<
": myDomain: "<<myDomain<<std::endl;
1450 std::cout<<mype<<
": DomainMapping: ";
1451 for(
auto j : range(nparts)) {
1452 std::cout<<
" do: "<<j<<
" pe: "<<domainMapping[j]<<
" ";
1454 std::cout<<std::endl;
1461 std::vector<int> setPartition(oocomm.
indexSet().
size(), -1);
1463 typedef typename OOComm::ParallelIndexSet::const_iterator Iterator;
1466 if(OwnerSet::contains(index->local().attribute())) {
1467 setPartition[index->local()]=domainMapping[part[i++]];
1477 bool ret = buildCommunication(graph, setPartition, oocomm, outcomm, redistInf,
1480 oocomm.communicator().barrier();
1481 if(oocomm.communicator().rank()==0)
1482 std::cout<<
"Creating indexsets took "<<time.
elapsed()<<std::endl;
1489 template<
class G,
class T1,
class T2>
1490 bool buildCommunication(
const G& graph,
1493 RedistributeInterface& redistInf,
1497 typedef typename OOComm::OwnerSet OwnerSet;
1502 redistInf.buildSendInterface<OwnerSet>(setPartition, oocomm.
indexSet());
1528 int npes = oocomm.communicator().size();
1531 std::set<int> recvFrom;
1537 typedef typename std::vector<int>::const_iterator VIter;
1538 int mype = oocomm.communicator().rank();
1541 std::set<int> tsendTo;
1542 for(VIter i=setPartition.begin(), iend = setPartition.end(); i!=iend; ++i)
1545 noSendTo = tsendTo.size();
1546 sendTo =
new int[noSendTo];
1547 typedef std::set<int>::const_iterator iterator;
1549 for(iterator i=tsendTo.begin(); i != tsendTo.end(); ++i, ++idx)
1554 int* gnoSend=
new int[oocomm.communicator().size()];
1555 int* gsendToDispl =
new int[oocomm.communicator().size()+1];
1557 MPI_Allgather(&noSendTo, 1, MPI_INT, gnoSend, 1,
1558 MPI_INT, oocomm.communicator());
1561 int totalNoRecv = 0;
1562 for(
int i=0; i<npes; ++i)
1563 totalNoRecv += gnoSend[i];
1565 int *gsendTo =
new int[totalNoRecv];
1569 for(
int i=0; i<npes; ++i)
1570 gsendToDispl[i+1]=gsendToDispl[i]+gnoSend[i];
1573 MPI_Allgatherv(sendTo, noSendTo, MPI_INT, gsendTo, gnoSend, gsendToDispl,
1574 MPI_INT, oocomm.communicator());
1577 for(
int proc=0; proc < npes; ++proc)
1578 for(
int i=gsendToDispl[proc]; i < gsendToDispl[proc+1]; ++i)
1579 if(gsendTo[i]==mype)
1580 recvFrom.insert(proc);
1582 bool existentOnNextLevel = recvFrom.size()>0;
1586 delete[] gsendToDispl;
1591 if(recvFrom.size()) {
1592 std::cout<<mype<<
": recvFrom: ";
1593 typedef typename std::set<int>::const_iterator siter;
1594 for(siter i=recvFrom.begin(); i!= recvFrom.end(); ++i) {
1599 std::cout<<std::endl<<std::endl;
1600 std::cout<<mype<<
": sendTo: ";
1601 for(
int i=0; i<noSendTo; i++) {
1602 std::cout<<sendTo[i]<<
" ";
1604 std::cout<<std::endl<<std::endl;
1608 if(oocomm.communicator().rank()==0)
1609 std::cout<<
" Communicating the receive information took "<<
1610 time.elapsed()<<std::endl;
1624 typedef typename OOComm::ParallelIndexSet::GlobalIndex GI;
1625 typedef std::vector<GI> GlobalVector;
1626 std::vector<std::pair<GI,int> > myOwnerVec;
1627 std::set<GI> myOverlapSet;
1628 GlobalVector sendOwnerVec;
1629 std::set<GI> sendOverlapSet;
1630 std::set<int> myNeighbors;
1635 char **sendBuffers=
new char*[noSendTo];
1636 MPI_Request *requests =
new MPI_Request[noSendTo];
1639 for(
int i=0; i < noSendTo; ++i) {
1641 sendOwnerVec.clear();
1642 sendOverlapSet.clear();
1645 std::set<int> neighbors;
1646 getOwnerOverlapVec<OwnerSet>(graph, setPartition, oocomm.globalLookup(),
1647 mype, sendTo[i], sendOwnerVec, sendOverlapSet, redistInf,
1653 MPI_Pack_size(1, MPITraits<std::size_t>::getType(), oocomm.communicator(), &buffersize);
1654 MPI_Pack_size(sendOwnerVec.size(), MPITraits<GI>::getType(), oocomm.communicator(), &tsize);
1656 MPI_Pack_size(1, MPITraits<std::size_t>::getType(), oocomm.communicator(), &tsize);
1658 MPI_Pack_size(sendOverlapSet.size(), MPITraits<GI>::getType(), oocomm.communicator(), &tsize);
1659 buffersize += tsize;
1660 MPI_Pack_size(1, MPITraits<std::size_t>::getType(), oocomm.communicator(), &tsize);
1661 buffersize += tsize;
1662 MPI_Pack_size(neighbors.size(), MPI_INT, oocomm.communicator(), &tsize);
1663 buffersize += tsize;
1665 sendBuffers[i] =
new char[buffersize];
1668 std::cout<<mype<<
" sending "<<sendOwnerVec.size()<<
" owner and "<<
1669 sendOverlapSet.size()<<
" overlap to "<<sendTo[i]<<
" buffersize="<<buffersize<<std::endl;
1671 createSendBuf(sendOwnerVec, sendOverlapSet, neighbors, sendBuffers[i], buffersize, oocomm.communicator());
1672 MPI_Issend(sendBuffers[i], buffersize, MPI_PACKED, sendTo[i], 99, oocomm.communicator(), requests+i);
1676 oocomm.communicator().barrier();
1677 if(oocomm.communicator().rank()==0)
1678 std::cout<<
" Creating sends took "<<
1679 time.elapsed()<<std::endl;
1684 int noRecv = recvFrom.size();
1685 int oldbuffersize=0;
1690 MPI_Probe(MPI_ANY_SOURCE, 99, oocomm.communicator(), &stat);
1692 MPI_Get_count(&stat, MPI_PACKED, &buffersize);
1694 if(oldbuffersize<buffersize) {
1697 recvBuf =
new char[buffersize];
1698 oldbuffersize = buffersize;
1700 MPI_Recv(recvBuf, buffersize, MPI_PACKED, stat.MPI_SOURCE, 99, oocomm.communicator(), &stat);
1701 saveRecvBuf(recvBuf, buffersize, myOwnerVec, myOverlapSet, myNeighbors, redistInf,
1702 stat.MPI_SOURCE, oocomm.communicator());
1711 MPI_Status *statuses =
new MPI_Status[noSendTo];
1712 int send = MPI_Waitall(noSendTo, requests, statuses);
1715 if(send==MPI_ERR_IN_STATUS) {
1716 std::cerr<<mype<<
": Error in sending :"<<std::endl;
1718 for(
int i=0; i< noSendTo; i++)
1719 if(statuses[i].MPI_ERROR!=MPI_SUCCESS) {
1722 MPI_Error_string(statuses[i].MPI_ERROR, message, &messageLength);
1723 std::cerr<<
" source="<<statuses[i].MPI_SOURCE<<
" message: ";
1724 for(
int j = 0; j < messageLength; j++)
1725 std::cout<<message[j];
1727 std::cerr<<std::endl;
1731 oocomm.communicator().barrier();
1732 if(oocomm.communicator().rank()==0)
1733 std::cout<<
" Receiving and saving took "<<
1734 time.elapsed()<<std::endl;
1738 for(
int i=0; i < noSendTo; ++i)
1739 delete[] sendBuffers[i];
1741 delete[] sendBuffers;
1745 redistInf.setCommunicator(oocomm.communicator());
1756 if (!existentOnNextLevel) {
1758 color= MPI_UNDEFINED;
1760 MPI_Comm outputComm;
1762 MPI_Comm_split(oocomm.communicator(), color, oocomm.communicator().rank(), &outputComm);
1766 int newrank=outcomm->communicator().rank();
1767 int *newranks=
new int[oocomm.communicator().size()];
1768 std::vector<int> tneighbors;
1769 tneighbors.reserve(myNeighbors.size());
1771 typename OOComm::ParallelIndexSet& outputIndexSet = outcomm->indexSet();
1773 MPI_Allgather(&newrank, 1, MPI_INT, newranks, 1,
1774 MPI_INT, oocomm.communicator());
1775 typedef typename std::set<int>::const_iterator IIter;
1778 std::cout<<oocomm.communicator().rank()<<
" ";
1779 for(IIter i=myNeighbors.begin(), end=myNeighbors.end();
1781 assert(newranks[*i]>=0);
1782 std::cout<<*i<<
"->"<<newranks[*i]<<
" ";
1783 tneighbors.push_back(newranks[*i]);
1785 std::cout<<std::endl;
1787 for(IIter i=myNeighbors.begin(), end=myNeighbors.end();
1789 tneighbors.push_back(newranks[*i]);
1793 myNeighbors.clear();
1796 oocomm.communicator().barrier();
1797 if(oocomm.communicator().rank()==0)
1798 std::cout<<
" Calculating new neighbours ("<<tneighbors.size()<<
") took "<<
1799 time.elapsed()<<std::endl;
1804 outputIndexSet.beginResize();
1807 std::sort(myOwnerVec.begin(), myOwnerVec.end(), SortFirst());
1811 typedef typename OOComm::ParallelIndexSet::LocalIndex LocalIndex;
1812 typedef typename std::vector<std::pair<GI,int> >::const_iterator VPIter;
1814 for(VPIter g=myOwnerVec.begin(), end =myOwnerVec.end(); g!=end; ++g, ++i ) {
1815 outputIndexSet.add(g->first,LocalIndex(i, OwnerOverlapCopyAttributeSet::owner,
true));
1816 redistInf.addReceiveIndex(g->second, i);
1820 oocomm.communicator().barrier();
1821 if(oocomm.communicator().rank()==0)
1822 std::cout<<
" Adding owner indices took "<<
1823 time.elapsed()<<std::endl;
1832 mergeVec(myOwnerVec, myOverlapSet);
1836 myOwnerVec.swap(myOwnerVec);
1839 oocomm.communicator().barrier();
1840 if(oocomm.communicator().rank()==0)
1841 std::cout<<
" Merging indices took "<<
1842 time.elapsed()<<std::endl;
1848 typedef typename std::set<GI>::const_iterator SIter;
1849 for(SIter g=myOverlapSet.begin(), end=myOverlapSet.end(); g!=end; ++g, i++) {
1850 outputIndexSet.add(*g,LocalIndex(i, OwnerOverlapCopyAttributeSet::copy,
true));
1852 myOverlapSet.clear();
1853 outputIndexSet.endResize();
1855#ifdef DUNE_ISTL_WITH_CHECKING
1857 typedef typename OOComm::ParallelIndexSet::const_iterator Iterator;
1858 Iterator end = outputIndexSet.end();
1859 for(Iterator index = outputIndexSet.begin(); index != end; ++index) {
1860 if (OwnerSet::contains(index->local().attribute())) {
1864 numOfOwnVtx = oocomm.communicator().sum(numOfOwnVtx);
1871 Iterator index=outputIndexSet.begin();
1874 for(Iterator old = outputIndexSet.begin(); index != end; old=index++) {
1875 if(old->global()>index->global())
1876 DUNE_THROW(ISTLError,
"Index set's globalindex not sorted correctly");
1881 oocomm.communicator().barrier();
1882 if(oocomm.communicator().rank()==0)
1883 std::cout<<
" Adding overlap indices took "<<
1884 time.elapsed()<<std::endl;
1889 if(color != MPI_UNDEFINED) {
1890 outcomm->remoteIndices().setNeighbours(tneighbors);
1891 outcomm->remoteIndices().template rebuild<true>();
1899 oocomm.communicator().barrier();
1900 if(oocomm.communicator().rank()==0)
1901 std::cout<<
" Storing indexsets took "<<
1902 time.elapsed()<<std::endl;
1908 tSum = t1 + t2 + t3 + t4;
1909 std::cout<<std::endl
1910 <<mype<<
": WTime for step 1): "<<t1
1918 return color!=MPI_UNDEFINED;
1922 template<
class G,
class P,
class T1,
class T2,
class R>
1924 std::shared_ptr<P>& outcomm,
1928 if(nparts!=oocomm.size())
1929 DUNE_THROW(NotImplemented,
"only available for MPI programs");
1933 template<
class G,
class P,
class T1,
class T2,
class R>
1934 bool commGraphRepartition(
const G& graph, P& oocomm,
int nparts,
1935 std::shared_ptr<P>& outcomm,
1939 if(nparts!=oocomm.size())
1940 DUNE_THROW(NotImplemented,
"only available for MPI programs");
The (undirected) graph of a matrix.
Definition: graph.hh:49
Index Set Interface base class.
Definition: indexidset.hh:76
IndexType size(GeometryType type) const
Return total number of entities of given geometry type in entity set .
Definition: indexidset.hh:220
MPI_Comm communicator_
The MPI communicator we use.
Definition: interface.hh:314
size_type N() const
Return the number of rows.
Definition: matrix.hh:691
A class setting up standard communication for a two-valued attribute set with owner/overlap/copy sema...
Definition: owneroverlapcopy.hh:172
const ParallelIndexSet & indexSet() const
Get the underlying parallel index set.
Definition: owneroverlapcopy.hh:472
void copyCopyToAll(const T &source, T &dest) const
Communicate values from copy data points to all other data points.
Definition: owneroverlapcopy.hh:340
void copyOwnerToAll(const T &source, T &dest) const
Communicate values from owner data points to all other data points.
Definition: owneroverlapcopy.hh:323
const RemoteIndices & remoteIndices() const
Get the underlying remote indices.
Definition: owneroverlapcopy.hh:481
LocalIndex::Attribute Attribute
The type of the attribute.
Definition: remoteindices.hh:224
const_iterator end() const
Get an iterator over all remote index lists.
Definition: remoteindices.hh:1535
int neighbours() const
Get the number of processors we share indices with.
Definition: remoteindices.hh:1452
const_iterator begin() const
Get an iterator over all remote index lists.
Definition: remoteindices.hh:1528
A simple stop watch.
Definition: timer.hh:41
void reset() noexcept
Reset timer while keeping the running/stopped state.
Definition: timer.hh:55
double elapsed() const noexcept
Get elapsed user-time from last reset until now/last stop in seconds.
Definition: timer.hh:75
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:490
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:422
const IndexPair * pair(const std::size_t &local) const
Get the index pair corresponding to a local index.
void storeGlobalIndicesOfRemoteIndices(std::map< int, SLList< std::pair< typename T::GlobalIndex, typename T::LocalIndex::Attribute >, A > > &globalMap, const RemoteIndices< T, A1 > &remoteIndices)
Stores the corresponding global indices of the remote index information.
Definition: indicessyncer.hh:461
constexpr index_constant< 1 > _1
Compile time index with value 1.
Definition: indices.hh:54
typename FieldTraits< Type >::real_type real_t
Convenient access to FieldTraits<Type>::real_type.
Definition: typetraits.hh:382
#define DUNE_UNUSED
A macro for marking variables that the compiler mistakenly flags as unused, which sometimes happens d...
Definition: unused.hh:16
#define DUNE_UNUSED_PARAMETER(parm)
A macro to mark intentionally unused function parameters with.
Definition: unused.hh:25
#define DUNE_THROW(E, m)
Definition: exceptions.hh:216
constexpr GeometryType vertex
GeometryType representing a vertex.
Definition: type.hh:797
auto max(ADLTag< 0 >, const V &v1, const V &v2)
implements binary Simd::max()
Definition: defaults.hh:79
DInfoType dinfo(std::cout)
Stream for informative output.
Definition: stdstreams.hh:138
DVerbType dverb(std::cout)
Singleton of verbose debug stream.
Definition: stdstreams.hh:114
Provides a map between global and local indices.
Class for adding missing indices of a distributed index set in a local communication.
Traits classes for mapping types onto MPI_Datatype.
Dune namespace.
Definition: alignedallocator.hh:14
void fillIndexSetHoles(const G &graph, Dune::OwnerOverlapCopyCommunication< T1, T2 > &oocomm)
Fills the holes in an index set.
Definition: repartition.hh:82
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:1268
Classes providing communication interfaces for overlapping Schwarz methods.
Utilities for reduction like operations on ranges.
Classes describing a distributed indexset.
Standard Dune debug streams.
A traits class describing the mapping of types onto MPI_Datatypes.
Definition: mpitraits.hh:38
@ nonoverlapping
Category for non-overlapping solvers.
Definition: solvercategory.hh:25
static Category category(const OP &op, decltype(op.category()) *=nullptr)
Helperfunction to extract the solver category either from an enum, or from the newly introduced virtu...
Definition: solvercategory.hh:32
Definition of the DUNE_UNUSED macro for the case that config.h is not available.