35 void **
GetBufPtr() {
return(_buf ? &_buf : NULL); };
40 virtual int Pack(
void **inbuf = NULL);
41 virtual int UnPack(
const void *outbuf = NULL);
45 delete [] (
char*)_buf;
84 int RenewCommunicator(MPI_Comm &inComm);
87 return(RenewCommunicator(inComm));
90 MPI_Datatype IntegerTypeID;
100 int WaitRecv(
int recvid);
104 void ClearRequests();
105 int NOpenRequests() {
return(_send_requests.size() + _recv_requests.size()); };
107 int Initialize(
int* narg = NULL,
char*** args = NULL);
108 bool Good() {
return(_initd); };
109 int SetExit(
int errin){
return(_error = errin);};
110 int SetErr(
int errin){
return(_error = errin);};
119 int CartNeighbors(std::vector<int> &neighborRanks);
122 MPI_Comm
Comm(){
return(_comm);};
126 int ComputeCartesianDims(
int numNodes,
int numDims);
127 int InitializeCartesianTopology(
int numNodes,
int numDims,std::vector<int> &dimDir,
128 const std::vector<int> &isPeriodic,
bool reOrder,
131 int StartSend(
unsigned int rid);
133 int StartRecv(
unsigned int rid);
135 int BroadCast(std::string &sval,
int root_rank = 0);
137 int _ASend(
void *buf,
int sendsize,
unsigned int remote_rank,
int tag = 0);
138 int _SetSend(
void *buf,
int sendsize,
unsigned int remote_rank,
int tag = 0);
139 int _ARecv(
void *buf,
int recvsize,
unsigned int remote_rank,
int tag = 0);
140 int _SetRecv(
void *buf,
int recvsize,
unsigned int remote_rank,
int tag = 0);
141 int _AllGatherv(
void *sendbuf,
int mysendcnt,
int datasize,
void *recvbuf);
142 int _Send(
void *buf,
int sendsize,
unsigned int remote_rank,
int tag = 0);
143 int _Recv(
void *buf,
int recvsize,
unsigned int remote_rank,
int tag = 0);
145 int _BroadCastMOV(std::vector<MobileObject *> &mos,
int root_rank=0);
146 int _GatherMO(
MobileObject *sPtr,std::vector<MobileObject *> &rVec,
int sndcnt,
int root = 0);
147 int _GatherMOV(std::vector<MobileObject *> &sVec,std::vector<MobileObject *> &rVec,
148 std::vector<int> &nsend_all,
int root = 0);
149 int _AllGatherMO(
MobileObject *sPtr,std::vector<MobileObject *> &rVec,
int sndcnt=1);
150 int _AllGatherMOV(std::vector<MobileObject *> &sVec,std::vector<MobileObject *> &rVec,
151 std::vector<int> &nsend_all);
154 template<
typename DataType>
155 int ASendBuf(DataType *sendBuf,
size_t nVal,
unsigned int remote_rank,
158 int sizeofdata =
sizeof(DataType);
159 return(_ASend(sendBuf,sizeofdata*nVal,remote_rank,tag));
162 template<
typename DataType>
163 int ARecvBuf(DataType *recvbuf,
size_t nVal,
unsigned int remote_rank,
166 int sizeofdata =
sizeof(DataType);
167 return(_ARecv(recvbuf,sizeofdata*nVal,remote_rank,tag));
170 template<
typename DataType>
171 int ASend(std::vector<DataType> &sendbuf,
unsigned int remote_rank,
174 int sizeofdata =
sizeof(DataType);
175 int sendcnt = sendbuf.size();
176 return (_ASend(&sendbuf[0],sizeofdata*sendcnt,remote_rank,tag));
179 template<
typename DataType>
180 int ASend(std::vector<DataType> &sendbuf,
unsigned int startIndex,
181 unsigned int sendSize,
unsigned int remote_rank,
184 int sizeofdata =
sizeof(DataType);
185 return (_ASend(&sendbuf[startIndex],sizeofdata*sendSize,remote_rank,tag));
188 template<
typename DataType>
189 int SetSend(std::vector<DataType> &sendbuf,
unsigned int remote_rank,
192 int sizeofdata =
sizeof(DataType);
193 int sendcnt = sendbuf.size();
194 return(_SetSend(&sendbuf[0],sendcnt*sizeofdata,remote_rank,tag));
197 template<
typename DataType>
198 int SetRecv(std::vector<DataType> &recvbuf,
unsigned int remote_rank,
201 int sizeofdata =
sizeof(DataType);
202 int recvcnt = recvbuf.size();
203 return(_SetRecv(&recvbuf[0],recvcnt*sizeofdata,remote_rank,tag));
206 template<
typename DataType>
207 int ARecv(std::vector<DataType> &recvbuf,
unsigned int remote_rank,
210 int sizeofdata =
sizeof(DataType);
211 int recvcnt = recvbuf.size();
212 return(_ARecv(&recvbuf[0],sizeofdata*recvcnt,remote_rank,tag));
215 template<
typename DataType>
216 int ARecv(std::vector<DataType> &recvbuf,
unsigned int startIndex,
217 unsigned int numRecv,
unsigned int remote_rank,
220 int sizeofdata =
sizeof(DataType);
221 return(_ARecv(&recvbuf[startIndex],sizeofdata*numRecv,remote_rank,tag));
224 template<
typename DataType>
228 if(_rank == root_rank){
229 std::ostringstream Ostr;
231 std::string sendString(Ostr.str());
232 numBytes = sendString.size();
233 _rc = MPI_Bcast(&numBytes,1,MPI_INT,root_rank,_comm);
234 if(_rc == MPI_SUCCESS){
235 const char *sendData = sendString.c_str();
236 _rc = MPI_Bcast((
void *)sendData,numBytes,MPI_CHAR,root_rank,_comm);
239 _rc = MPI_Bcast(&numBytes,1,MPI_INT,root_rank,_comm);
240 if(_rc == MPI_SUCCESS){
241 char *recvData =
new char [numBytes+1];
242 _rc = MPI_Bcast(recvData,numBytes,MPI_CHAR,root_rank,_comm);
243 recvData[numBytes] =
'\0';
244 std::istringstream Istr(recvData);
252 template<
typename DataType>
255 int sizeofdata =
sizeof(DataType);
256 return((_rc = MPI_Bcast(&buf,sizeofdata,MPI_CHAR,root_rank,_comm)));
259 template<
typename DataType>
262 int sizeofdata =
sizeof(DataType);
263 int bufsize = buf.size();
264 _rc = MPI_Bcast(&bufsize,1,MPI_INT,root_rank,_comm);
265 if(_rank != root_rank)
267 _rc = MPI_Bcast(&buf[0],buf.size()*sizeofdata,MPI_CHAR,root_rank,_comm);
272 template<
typename DataType>
273 int Reduce(DataType &send,DataType &recv,
276 _rc = MPI_Reduce(&send,&recv,1,ResolveDataType(dt),
277 ResolveOp(op),root,_comm);
283 template<
typename DataType>
284 int Reduce(std::vector<DataType> &send,std::vector<DataType> &recv,
287 int count = send.size();
294 _rc = MPI_Reduce(&send[0],&recv[0],count,ResolveDataType(dt),
295 ResolveOp(op),root,_comm);
301 template<
typename DataType>
302 int AllReduce(std::vector<DataType> &send,std::vector<DataType> &recv,
305 int count = send.size();
307 _rc = MPI_Allreduce(&send[0],&recv[0],count,ResolveDataType(dt),
308 ResolveOp(op),_comm);
315 template<
typename DataType>
319 _rc = MPI_Allreduce(&send,&recv,1,ResolveDataType(dt),
320 ResolveOp(op),_comm);
325 template<
typename DataType>
326 int AllGather(std::vector<DataType> &sendvec,std::vector<DataType> &recvvec,
327 int sndcnt=0,
int recvcnt=0)
329 size_t datasize =
sizeof(DataType);
331 sndcnt = sendvec.size();
334 std::cout <<
"Sendcount = " << sndcnt <<
" ReceiveCount = " << recvcnt << std::endl;
335 _rc = MPI_Allgather((
void *)(&(sendvec[0])),sndcnt*datasize,MPI_CHAR,
336 (
void *)(&(recvvec[0])),recvcnt*datasize,MPI_CHAR,_comm);
354 template<
typename DataType>
355 int AllGather(DataType &sendval,std::vector<DataType> &recvvec)
357 size_t messagesize =
sizeof(DataType);
358 recvvec.resize(_nproc);
359 _rc = MPI_Allgather((
void *)&sendval,messagesize,MPI_CHAR,
360 (
void *)&recvvec[0],messagesize,MPI_CHAR,_comm);
365 template<
typename DataType>
366 int AllGatherv(std::vector<DataType> &sendvec,std::vector<DataType> &recvvec,std::vector<int> &nsend_all)
368 int datasize =
sizeof(DataType);
369 int mysendcnt = sendvec.size();
371 if(nsend_all.empty()){
372 nsend_all.resize(_nproc,0);
373 this->AllGather(mysendcnt,nsend_all);
375 this->AllReduce(mysendcnt,totalcnt,
DTINT,
SUMOP);
376 recvvec.resize(totalcnt);
377 return(_AllGatherv(&sendvec[0],mysendcnt,datasize,&recvvec[0]));
380 template<
typename DataType>
381 int AllGatherv(std::vector<DataType> &sendvec,std::vector<DataType> &recvvec)
383 int datasize =
sizeof(DataType);
384 int mysendcnt = sendvec.size();
386 std::vector<int> nsend_all;
387 nsend_all.resize(_nproc,0);
388 this->AllGather(mysendcnt,nsend_all);
389 this->AllReduce(mysendcnt,totalcnt,
DTINT,
SUMOP);
390 recvvec.resize(totalcnt);
391 return(_AllGatherv(&sendvec[0],mysendcnt,datasize,&recvvec[0]));
394 template<
typename DataType>
395 int Gather(DataType &sendval,std::vector<DataType> &recvvec,
int root=0)
397 size_t messagesize =
sizeof(DataType);
398 if(this->Rank() == root){
399 recvvec.resize(this->Size());
401 _rc = MPI_Gather((
void *)&sendval,messagesize,MPI_CHAR,
402 (
void *)&recvvec[0],messagesize,MPI_CHAR,
408 template<
typename DataType>
409 int StreamGather(DataType &sendval,std::vector<DataType> &recvvec,
int root=0)
411 std::ostringstream outStream;
412 outStream << sendval;
413 std::string sendVal(outStream.str());
414 const char *sendData = sendVal.c_str();
415 int messageSize = sendVal.size();
416 std::vector<int> allSizes(_nproc,0);
417 std::vector<int> allDisps(_nproc,0);
418 allSizes[_rank] = messageSize;
419 this->Gather(messageSize,allSizes,root);
421 for(
int iRank = 0;iRank < _nproc;iRank++){
422 allDisps[iRank] = totalSize;
423 totalSize += allSizes[iRank];
425 char *recvData =
new char [totalSize];
426 _rc = MPI_Gatherv(const_cast<void *>(static_cast<const void *>(sendData)),
427 allSizes[_rank],MPI_CHAR,
428 (
void *)(&(recvData[0])),&allSizes[0],
429 &allDisps[0],MPI_CHAR,root,_comm);
432 for(
int iRank = 0;iRank < _nproc;iRank++){
433 std::string rankString(&recvData[allDisps[iRank]],allSizes[iRank]);
434 recvvec.push_back(rankString);
441 template<
typename DataType>
442 int Gather(std::vector<DataType> &sendvec,std::vector<DataType> &recvvec,
443 int sndcnt=0,
int recvcnt=0,
int root=0)
445 size_t datasize =
sizeof(DataType);
447 sndcnt = sendvec.size();
451 recvvec.resize(recvcnt*_nproc);
452 _rc = MPI_Gather((
void *)(&(sendvec[0])),sndcnt*datasize,MPI_CHAR,
453 (
void *)(&(recvvec[0])),recvcnt*datasize,MPI_CHAR,
459 template<
typename DataType>
460 int Gatherv(std::vector<DataType> &sendvec,std::vector<DataType> &recvvec,
461 std::vector<int> &nsend_all,
int nsend = 0,
int root=0)
463 int datasize =
sizeof(DataType);
465 nsend = sendvec.size();
467 if(nsend_all.empty()){
468 nsend_all.resize(_nproc);
469 nsend_all[_rank] = nsend;
470 this->Gather(nsend,nsend_all,root);
472 for(
int i = 0;i < _nproc;i++)
473 nrecv += nsend_all[i];
474 std::vector<int> allsizes(_nproc,0);
475 std::vector<int> disps(_nproc,0);
477 recvvec.resize(nrecv);
478 for(
int i = 0; i < _nproc;i++){
479 allsizes[i] = nsend_all[i] * datasize;
481 disps[i] = disps[i-1]+allsizes[i-1];
484 _rc = MPI_Gatherv((
void *)(&(sendvec[0])),allsizes[_rank],MPI_CHAR,
485 (
void *)(&(recvvec[0])),&allsizes[0],&disps[0],MPI_CHAR,
495 template<
typename MOType>
498 return(this->BroadCast(dynamic_cast<MobileObject *>(&mo),root_rank));
501 template<
typename MOType>
504 return(this->BroadCast(dynamic_cast<MobileObject *>(&mo),root_rank));
507 template<
typename MOType>
510 std::vector<MobileObject *> moc;
511 moc.resize(mov.size());
512 std::vector<MobileObject *>::iterator moci = moc.begin();
513 typename std::vector<MOType>::iterator oi = mov.begin();
514 while(moci != moc.end())
515 *moci++ = dynamic_cast<MobileObject *>(&(*oi++));
516 return(_BroadCastMOV(moc,root_rank));
519 template<
typename MOType>
522 int nobjs = mov.size();
526 if((_rc = MPI_Bcast(&nobjs,1,MPI_INT,root_rank,_comm)))
528 if(_rank != root_rank)
530 std::vector<MobileObject *> moc;
531 moc.resize(mov.size());
532 std::vector<MobileObject *>::iterator moci = moc.begin();
533 typename std::vector<MOType>::iterator oi = mov.begin();
534 while(moci != moc.end())
535 *moci++ = dynamic_cast<MobileObject *>(&(*oi++));
536 return(_BroadCastMOV(moc,root_rank));
543 template<
typename MOType>
544 int GatherMO(MOType &sendval,std::vector<MOType> &recvvec,
int root = 0)
548 std::vector<MobileObject *> recv_v;
551 recvvec.resize(_nproc);
552 recv_v.resize(_nproc,NULL);
553 std::vector<MobileObject *>::iterator moci = recv_v.begin();
554 typename std::vector<MOType>::iterator oi = recvvec.begin();
555 while(moci != recv_v.end())
556 *moci++ = dynamic_cast<MobileObject *>(&(*oi++));
558 _rc = this->_GatherMO(sendPtr,recv_v,1,root);
563 template<
typename MOType>
564 int GatherMO(std::vector<MOType> &sendvec,std::vector<MOType> &recvvec,
565 std::vector<int> &nsend_all,
int root = 0)
567 int nsend = sendvec.size();
568 if(nsend_all.empty()){
569 nsend_all.resize(_nproc,0);
570 nsend_all[_rank] = nsend;
571 this->Gather(nsend,nsend_all,root);
575 std::vector<int>::iterator nsi = nsend_all.begin();
576 while(nsi != nsend_all.end())
578 recvvec.resize(nrecv);
580 std::vector<MobileObject *> send_v(nsend,NULL);
581 std::vector<MobileObject *> recv_v(nrecv,NULL);
582 std::vector<MobileObject *>::iterator moci = recv_v.begin();
583 typename std::vector<MOType>::iterator oi = recvvec.begin();
584 while(moci != recv_v.end())
585 *moci++ = dynamic_cast<MobileObject *>(&(*oi++));
586 moci = send_v.begin();
587 oi = sendvec.begin();
588 while(moci != send_v.end())
589 *moci++ = dynamic_cast<MobileObject *>(&(*oi++));
590 _rc = this->_GatherMOV(send_v,recv_v,nsend_all,root);
595 template<
typename MOType>
598 recvvec.resize(_nproc);
600 std::vector<MobileObject *> recv_v(_nproc,NULL);
601 std::vector<MobileObject *>::iterator moci = recv_v.begin();
602 typename std::vector<MOType>::iterator oi = recvvec.begin();
603 while(moci != recv_v.end())
604 *moci++ = dynamic_cast<MobileObject *>(&(*oi++));
605 _rc = this->_AllGatherMO(sendPtr,recv_v);
610 template<
typename MOType>
611 int AllGatherMO(std::vector<MOType> &sendvec,std::vector<MOType> &recvvec,
612 std::vector<int> &nsend_all,
int root = 0)
614 int nsend = sendvec.size();
615 if(nsend_all.empty()){
616 nsend_all.resize(_nproc,0);
617 nsend_all[_rank] = nsend;
618 this->Gather(nsend,nsend_all,root);
622 std::vector<int>::iterator nsi = nsend_all.begin();
623 while(nsi != nsend_all.end())
625 recvvec.resize(nrecv);
627 std::vector<MobileObject *> send_v(nsend,NULL);
628 std::vector<MobileObject *> recv_v(nrecv,NULL);
629 std::vector<MobileObject *>::iterator moci = recv_v.begin();
630 typename std::vector<MOType>::iterator oi = recvvec.begin();
631 while(moci != recv_v.end())
632 *moci++ = dynamic_cast<MobileObject *>(&(*oi++));
633 moci = send_v.begin();
634 oi = sendvec.begin();
635 while(moci != send_v.end())
636 *moci++ = dynamic_cast<MobileObject *>(&(*oi++));
637 _rc = this->_GatherMOV(send_v,recv_v,nsend_all,root);
642 template<
typename MOType>
643 int GatherMOV(std::vector<MOType> &sendvec,std::vector<MOType> &recvvec,
644 std::vector<int> &nsend_all,
int root = 0)
646 int nsend = sendvec.size();
647 if(nsend_all.empty()){
648 nsend_all.resize(_nproc,0);
649 nsend_all[_rank] = nsend;
650 this->Gather(nsend,nsend_all,root);
654 std::vector<int>::iterator nsi = nsend_all.begin();
655 while(nsi != nsend_all.end())
657 recvvec.resize(nrecv);
659 std::vector<MobileObject *> send_v(nsend,NULL);
660 std::vector<MobileObject *> recv_v(nrecv,NULL);
661 std::vector<MobileObject *>::iterator moci = recv_v.begin();
662 typename std::vector<MOType>::iterator oi = recvvec.begin();
663 while(moci != recv_v.end())
664 *moci++ = dynamic_cast<MobileObject *>(&(*oi++));
665 moci = send_v.begin();
666 oi = sendvec.begin();
667 while(moci != send_v.end())
668 *moci++ = dynamic_cast<MobileObject *>(&(*oi++));
669 _rc = this->_GatherMOV(send_v,recv_v,nsend_all,root);
674 template<
typename MOType>
675 int AllGatherMOV(std::vector<MOType> &sendvec,std::vector<MOType> &recvvec,
676 std::vector<int> &nsend_all,
int root = 0)
678 int nsend = sendvec.size();
679 if(nsend_all.empty()){
680 nsend_all.resize(_nproc,0);
681 nsend_all[_rank] = nsend;
682 this->Gather(nsend,nsend_all,root);
686 std::vector<int>::iterator nsi = nsend_all.begin();
687 while(nsi != nsend_all.end())
689 recvvec.resize(nrecv);
691 std::vector<MobileObject *> send_v(nsend,NULL);
692 std::vector<MobileObject *> recv_v(nrecv,NULL);
693 std::vector<MobileObject *>::iterator moci = recv_v.begin();
694 typename std::vector<MOType>::iterator oi = recvvec.begin();
695 while(moci != recv_v.end())
696 *moci++ = dynamic_cast<MobileObject *>(&(*oi++));
697 moci = send_v.begin();
698 oi = sendvec.begin();
699 while(moci != send_v.end())
700 *moci++ = dynamic_cast<MobileObject *>(&(*oi++));
701 _rc = this->_AllGatherMOV(send_v,recv_v,nsend_all);
706 template <
typename T >
707 int Union(std::vector< T > &input_data,std::vector< T > &output_data)
709 std::vector< T > all_items;
710 int err = AllGatherv< T >(input_data,all_items);
711 std::sort(all_items.begin(),all_items.end());
712 typename std::vector< T >::iterator ui = std::unique(all_items.begin(),all_items.end());
713 output_data.resize(ui - all_items.begin());
714 std::copy(all_items.begin(),ui,output_data.begin());
int SetCommunicator(MPI_Comm &inComm)
int AllGatherv(std::vector< DataType > &sendvec, std::vector< DataType > &recvvec)
Utility class for creating derived objects that are parallel.
const void * GetBuffer() const
int GatherMO(MOType &sendval, std::vector< MOType > &recvvec, int root=0)
int ARecvBuf(DataType *recvbuf, size_t nVal, unsigned int remote_rank, int tag=0)
ParallelObject(CommunicatorObject &incomm)
int BroadCastMO(MOType &mo, int root_rank=0)
int AllGatherMO(MOType &sendval, std::vector< MOType > &recvvec)
provides communication for complex objects.
std::vector< int > _cart_periodic
DataTypes
Supported data types.
std::vector< int > _cart_dims
std::vector< MPI_Request > _recv_requests
int BroadCastMobileObject(MOType &mo, int root_rank=0)
int ARecv(std::vector< DataType > &recvbuf, unsigned int remote_rank, int tag=0)
Defines MPI-specific parallel global and program classes.
int ASend(std::vector< DataType > &sendbuf, unsigned int remote_rank, int tag=0)
int SetRecv(std::vector< DataType > &recvbuf, unsigned int remote_rank, int tag=0)
int AllGather(DataType &sendval, std::vector< DataType > &recvvec)
int Union(std::vector< T > &input_data, std::vector< T > &output_data)
int AllReduce(std::vector< DataType > &send, std::vector< DataType > &recv, const comm::DataTypes &dt, const comm::Ops &op)
std::vector< int > _cart_coords
int ASendBuf(DataType *sendBuf, size_t nVal, unsigned int remote_rank, int tag=-1)
int AllReduce(DataType &send, DataType &recv, const comm::DataTypes &dt, const comm::Ops &op)
int SetSend(std::vector< DataType > &sendbuf, unsigned int remote_rank, int tag=0)
int AllGatherMO(std::vector< MOType > &sendvec, std::vector< MOType > &recvvec, std::vector< int > &nsend_all, int root=0)
MPI_Comm GetCommunicator() const
std::vector< int > _send_tags
int ASend(std::vector< DataType > &sendbuf, unsigned int startIndex, unsigned int sendSize, unsigned int remote_rank, int tag=0)
int BroadCast(std::vector< DataType > &buf, int root_rank)
virtual int Pack(void **inbuf=NULL)
virtual void DestroyBuffer()
Main encapsulation of MPI.
int AllGatherMOV(std::vector< MOType > &sendvec, std::vector< MOType > &recvvec, std::vector< int > &nsend_all, int root=0)
int Initialize(CommunicatorObject &incomm)
int AllGather(std::vector< DataType > &sendvec, std::vector< DataType > &recvvec, int sndcnt=0, int recvcnt=0)
int Gather(DataType &sendval, std::vector< DataType > &recvvec, int root=0)
int AllGatherv(std::vector< DataType > &sendvec, std::vector< DataType > &recvvec, std::vector< int > &nsend_all)
const std::string Hostname(bool longname=false)
int StreamGather(DataType &sendval, std::vector< DataType > &recvvec, int root=0)
int ARecv(std::vector< DataType > &recvbuf, unsigned int startIndex, unsigned int numRecv, unsigned int remote_rank, int tag=0)
int BroadCastMO(std::vector< MOType > &mov, int root_rank=0)
int Gather(std::vector< DataType > &sendvec, std::vector< DataType > &recvvec, int sndcnt=0, int recvcnt=0, int root=0)
virtual CommunicatorObject & Communicator()
std::vector< MPI_Status > _status
virtual int PrepareBuffer(size_t bsize)
virtual int UnPack(const void *outbuf=NULL)
int BroadCastMOVector(std::vector< MOType > &mov, int root_rank=0)
Ops
Operations for collectives.
int Initialize(base &stencilSet, int interiorOrder)
Initialize the sbp::base stencilset with the SBP operator of given order.
int GatherMOV(std::vector< MOType > &sendvec, std::vector< MOType > &recvvec, std::vector< int > &nsend_all, int root=0)
std::vector< MPI_Request > _send_requests
virtual ~ParallelObject()
int Reduce(DataType &send, DataType &recv, const comm::DataTypes &dt, const comm::Ops &op, int root)
int Reduce(std::vector< DataType > &send, std::vector< DataType > &recv, const comm::DataTypes &dt, const comm::Ops &op, int root)
int StreamBroadCast(DataType &inData, int root_rank=0)
std::vector< int > & CartDimensions()
CommunicatorObject _communicator
int BroadCast(DataType &buf, int root_rank)
int Gatherv(std::vector< DataType > &sendvec, std::vector< DataType > &recvvec, std::vector< int > &nsend_all, int nsend=0, int root=0)
std::vector< int > & CartCoordinates()
int GatherMO(std::vector< MOType > &sendvec, std::vector< MOType > &recvvec, std::vector< int > &nsend_all, int root=0)
std::vector< int > _recv_tags