10#ifndef TEUCHOS_MPI_COMM_HPP 
   11#define TEUCHOS_MPI_COMM_HPP 
   21#ifdef HAVE_TEUCHOS_MPI 
   23#include "Teuchos_Comm.hpp" 
   24#include "Teuchos_CommUtilities.hpp" 
   26#include "Teuchos_OpaqueWrapper.hpp" 
   28#include "Teuchos_SerializationTraitsHelpers.hpp" 
   29#include "Teuchos_Workspace.hpp" 
   32#include "Teuchos_Assert.hpp" 
   39#ifdef TEUCHOS_MPI_COMM_DUMP 
   40#  include "Teuchos_VerboseObject.hpp" 
   46TEUCHOSCOMM_LIB_DLL_EXPORT std::string
 
   47mpiErrorCodeToString (
const int err);
 
   63  TEUCHOSCOMM_LIB_DLL_EXPORT 
void safeCommFree (MPI_Comm* comm);
 
   69  TEUCHOSCOMM_LIB_DLL_EXPORT 
int setCommErrhandler (MPI_Comm comm, MPI_Errhandler handler);
 
   73#ifdef TEUCHOS_MPI_COMM_DUMP 
   74template<
typename Ordinal, 
typename T>
 
   76  const std::string &funcName, 
const std::string &buffName
 
   77  ,
const Ordinal bytes, 
const T buff[]
 
   84    << 
"\n" << funcName << 
"::" << buffName << 
":\n";
 
   86  for( Ordinal i = 0; i < bytes; ++i ) {
 
   87    *out << buffName << 
"[" << i << 
"] = '" << buff[i] << 
"'\n";
 
  104template<
class OrdinalType>
 
  105class MpiCommStatus : 
public CommStatus<OrdinalType> {
 
  107  MpiCommStatus (MPI_Status status) : status_ (status) {}
 
  110  virtual ~MpiCommStatus() {}
 
  113  OrdinalType getSourceRank () { 
return status_.MPI_SOURCE; }
 
  116  OrdinalType getTag () { 
return status_.MPI_TAG; }
 
  119  OrdinalType getError () { 
return status_.MPI_ERROR; }
 
  132template<
class OrdinalType>
 
  133inline RCP<MpiCommStatus<OrdinalType> >
 
  134mpiCommStatus (MPI_Status rawMpiStatus)
 
  136  return rcp (
new MpiCommStatus<OrdinalType> (rawMpiStatus));
 
  154template<
class OrdinalType>
 
  155class MpiCommRequestBase : 
public CommRequest<OrdinalType> {
 
  158  MpiCommRequestBase () :
 
  159    rawMpiRequest_ (MPI_REQUEST_NULL)
 
  163  MpiCommRequestBase (MPI_Request rawMpiRequest) :
 
  164    rawMpiRequest_ (rawMpiRequest)
 
  174  MPI_Request releaseRawMpiRequest()
 
  176    MPI_Request tmp_rawMpiRequest = rawMpiRequest_;
 
  177    rawMpiRequest_ = MPI_REQUEST_NULL;
 
  178    return tmp_rawMpiRequest;
 
  182  bool isNull()
 const {
 
  183    return rawMpiRequest_ == MPI_REQUEST_NULL;
 
  187    MPI_Status rawMpiStatus;
 
  190    MPI_Test(&rawMpiRequest_, &flag, &rawMpiStatus);
 
  200  RCP<CommStatus<OrdinalType> > wait () {
 
  201    MPI_Status rawMpiStatus;
 
  204    const int err = MPI_Wait (&rawMpiRequest_, &rawMpiStatus);
 
  206      err != MPI_SUCCESS, std::runtime_error,
 
  207      "Teuchos: MPI_Wait() failed with error \"" 
  208      << mpiErrorCodeToString (err));
 
  210    return mpiCommStatus<OrdinalType> (rawMpiStatus);
 
  217  RCP<CommStatus<OrdinalType> > cancel () {
 
  218    if (rawMpiRequest_ == MPI_REQUEST_NULL) {
 
  222      int err = MPI_Cancel (&rawMpiRequest_);
 
  224        err != MPI_SUCCESS, std::runtime_error,
 
  225        "Teuchos: MPI_Cancel failed with the following error: " 
  226        << mpiErrorCodeToString (err));
 
  233      err = MPI_Wait (&rawMpiRequest_, &status);
 
  235        "Teuchos::MpiCommStatus::cancel: MPI_Wait failed with the following " 
  236        "error: " << mpiErrorCodeToString (err));
 
  237      return mpiCommStatus<OrdinalType> (status);
 
  242  virtual ~MpiCommRequestBase () {
 
  243    if (rawMpiRequest_ != MPI_REQUEST_NULL) {
 
  246      const int err = MPI_Cancel (&rawMpiRequest_);
 
  247      if (err == MPI_SUCCESS) {
 
  264        (void) MPI_Wait (&rawMpiRequest_, MPI_STATUS_IGNORE);
 
  271  MPI_Request rawMpiRequest_;
 
  289template<
class OrdinalType>
 
  290class MpiCommRequest : 
public MpiCommRequestBase<OrdinalType> {
 
  294    MpiCommRequestBase<OrdinalType> (MPI_REQUEST_NULL),
 
  299  MpiCommRequest (MPI_Request rawMpiRequest,
 
  300                  const ArrayView<char>::size_type numBytesInMessage) :
 
  301    MpiCommRequestBase<OrdinalType> (rawMpiRequest),
 
  302    numBytes_ (numBytesInMessage)
 
  310  ArrayView<char>::size_type numBytes ()
 const {
 
  315  virtual ~MpiCommRequest () {}
 
  319  ArrayView<char>::size_type numBytes_;
 
  330template<
class OrdinalType>
 
  331inline RCP<MpiCommRequest<OrdinalType> >
 
  332mpiCommRequest (MPI_Request rawMpiRequest,
 
  335  return rcp (
new MpiCommRequest<OrdinalType> (rawMpiRequest, numBytes));
 
  353template<
typename Ordinal>
 
  354class MpiComm : 
public Comm<Ordinal> {
 
  379  explicit MpiComm (MPI_Comm rawMpiComm);
 
  395  MpiComm (
const RCP<
const OpaqueWrapper<MPI_Comm> >& rawMpiComm);
 
  414  MpiComm (
const RCP<
const OpaqueWrapper<MPI_Comm> >& rawMpiComm,
 
  415           const int defaultTag);
 
  433  MpiComm (
const MpiComm<Ordinal>& other);
 
  436  RCP<const OpaqueWrapper<MPI_Comm> > getRawMpiComm ()
 const {
 
  504  void setErrorHandler (
const RCP<
const OpaqueWrapper<MPI_Errhandler> >& errHandler);
 
  511  virtual int getRank() 
const;
 
  514  virtual int getSize() 
const;
 
  517  virtual void barrier() 
const;
 
  520  virtual void broadcast(
 
  521    const int rootRank, 
const Ordinal bytes, 
char buffer[]
 
  526  gather (
const Ordinal sendBytes, 
const char sendBuffer[],
 
  527          const Ordinal recvBytes, 
char recvBuffer[],
 
  528          const int root) 
const;
 
  530  virtual void gatherAll(
 
  531    const Ordinal sendBytes, 
const char sendBuffer[]
 
  532    ,
const Ordinal recvBytes, 
char recvBuffer[]
 
  535  virtual void reduceAll(
 
  536    const ValueTypeReductionOp<Ordinal,char> &reductOp
 
  537    ,
const Ordinal bytes, 
const char sendBuffer[], 
char globalReducts[]
 
  541    const ValueTypeReductionOp<Ordinal,char> &reductOp
 
  542    ,
const Ordinal bytes, 
const char sendBuffer[], 
char scanReducts[]
 
  546    const Ordinal bytes, 
const char sendBuffer[], 
const int destRank
 
  550  send (
const Ordinal bytes,
 
  551        const char sendBuffer[],
 
  553        const int tag) 
const;
 
  556    const Ordinal bytes, 
const char sendBuffer[], 
const int destRank
 
  560  ssend (
const Ordinal bytes,
 
  561         const char sendBuffer[],
 
  563         const int tag) 
const;
 
  566    const int sourceRank, 
const Ordinal bytes, 
char recvBuffer[]
 
  570    const ArrayView<const char> &sendBuffer,
 
  576             const char sendBuffer[],
 
  578             const int tag) 
const;
 
  580  virtual RCP<CommRequest<Ordinal> > isend(
 
  581    const ArrayView<const char> &sendBuffer,
 
  585  virtual RCP<CommRequest<Ordinal> >
 
  586  isend (
const ArrayView<const char> &sendBuffer,
 
  588         const int tag) 
const;
 
  590  virtual RCP<CommRequest<Ordinal> > 
ireceive(
 
  591    const ArrayView<char> &Buffer,
 
  595  virtual RCP<CommRequest<Ordinal> >
 
  596  ireceive (
const ArrayView<char> &Buffer,
 
  597            const int sourceRank,
 
  598            const int tag) 
const;
 
  600  virtual void waitAll(
 
  601    const ArrayView<RCP<CommRequest<Ordinal> > > &requests
 
  605  waitAll (
const ArrayView<RCP<CommRequest<Ordinal> > >& requests,
 
  606           const ArrayView<RCP<CommStatus<Ordinal> > >& statuses) 
const;
 
  608  virtual RCP<CommStatus<Ordinal> >
 
  609  wait (
const Ptr<RCP<CommRequest<Ordinal> > >& request) 
const;
 
  611  virtual RCP< Comm<Ordinal> > duplicate() 
const;
 
  613  virtual RCP< Comm<Ordinal> > split(
const int color, 
const int key) 
const;
 
  615  virtual RCP< Comm<Ordinal> > createSubcommunicator(
 
  616    const ArrayView<const int>& ranks) 
const;
 
  623  std::string description() 
const;
 
  629  static int const minTag_ = 26000; 
 
  630  static int const maxTag_ = 26099; 
 
  637  int getTag ()
 const { 
return tag_; }
 
  641    if (tag_ == std::numeric_limits<int>::max())
 
  651  void setupMembersFromComm();
 
  652  static int tagCounter_;
 
  661  RCP<const OpaqueWrapper<MPI_Comm> > rawMpiComm_;
 
  679  RCP<const OpaqueWrapper<MPI_Errhandler> > customErrorHandler_;
 
  681  void assertRank(
const int rank, 
const std::string &rankName) 
const;
 
  686#ifdef TEUCHOS_MPI_COMM_DUMP 
  688  static bool show_dump;
 
  707template<
typename Ordinal>
 
  708RCP<MpiComm<Ordinal> >
 
  710  const RCP<
const OpaqueWrapper<MPI_Comm> > &rawMpiComm
 
  727template<
typename Ordinal>
 
  728RCP<MpiComm<Ordinal> >
 
  730              const RCP<
const OpaqueWrapper<MPI_Comm> > &rawMpiComm,
 
  762template<
typename Ordinal>
 
  764getRawMpiComm(
const Comm<Ordinal> &comm);
 
  774template<
typename Ordinal>
 
  775int MpiComm<Ordinal>::tagCounter_ = MpiComm<Ordinal>::minTag_;
 
  781template<
typename Ordinal>
 
  783MpiComm (
const RCP<
const OpaqueWrapper<MPI_Comm> >& rawMpiComm)
 
  786    rawMpiComm.get () == NULL, std::invalid_argument,
 
  787    "Teuchos::MpiComm constructor: The input RCP is null.");
 
  789    *rawMpiComm == MPI_COMM_NULL, std::invalid_argument,
 
  790    "Teuchos::MpiComm constructor: The given MPI_Comm is MPI_COMM_NULL.");
 
  792  rawMpiComm_ = rawMpiComm;
 
  806  setupMembersFromComm ();
 
  810template<
typename Ordinal>
 
  812MpiComm (
const RCP<
const OpaqueWrapper<MPI_Comm> >& rawMpiComm,
 
  813         const int defaultTag)
 
  816    rawMpiComm.get () == NULL, std::invalid_argument,
 
  817    "Teuchos::MpiComm constructor: The input RCP is null.");
 
  819    *rawMpiComm == MPI_COMM_NULL, std::invalid_argument,
 
  820    "Teuchos::MpiComm constructor: The given MPI_Comm is MPI_COMM_NULL.");
 
  822  rawMpiComm_ = rawMpiComm;
 
  824  int err = MPI_Comm_size (*rawMpiComm_, &size_);
 
  826    "Teuchos::MpiComm constructor: MPI_Comm_size failed with " 
  827    "error \"" << mpiErrorCodeToString (err) << 
"\".");
 
  829  err = MPI_Comm_rank (*rawMpiComm_, &rank_);
 
  831    "Teuchos::MpiComm constructor: MPI_Comm_rank failed with " 
  832    "error \"" << mpiErrorCodeToString (err) << 
"\".");
 
  837template<
typename Ordinal>
 
  838MpiComm<Ordinal>::MpiComm (MPI_Comm rawMpiComm)
 
  841    std::invalid_argument, 
"Teuchos::MpiComm constructor: The given MPI_Comm " 
  842    "is MPI_COMM_NULL.");
 
  846  rawMpiComm_ = opaqueWrapper<MPI_Comm> (rawMpiComm);
 
  860  setupMembersFromComm ();
 
  864template<
typename Ordinal>
 
  865MpiComm<Ordinal>::MpiComm (
const MpiComm<Ordinal>& other) :
 
  866  rawMpiComm_ (opaqueWrapper<MPI_Comm> (MPI_COMM_NULL)) 
 
  869  RCP<const OpaqueWrapper<MPI_Comm> > origCommPtr = other.getRawMpiComm ();
 
  871    "Teuchos::MpiComm copy constructor: " 
  872    "The input's getRawMpiComm() method returns null.");
 
  873  MPI_Comm origComm = *origCommPtr;
 
  875    "Teuchos::MpiComm copy constructor: " 
  876    "The input's raw MPI_Comm is MPI_COMM_NULL.");
 
  884    rawMpiComm_ = origCommPtr;
 
  888    const int err = MPI_Comm_dup (origComm, &newComm);
 
  890      "Teuchos::MpiComm copy constructor: MPI_Comm_dup failed with " 
  891      "the following error: " << mpiErrorCodeToString (err));
 
  893    rawMpiComm_ = opaqueWrapper (newComm, details::safeCommFree);
 
  896  setupMembersFromComm ();
 
  900template<
typename Ordinal>
 
  901void MpiComm<Ordinal>::setupMembersFromComm ()
 
  903  int err = MPI_Comm_size (*rawMpiComm_, &size_);
 
  905    "Teuchos::MpiComm constructor: MPI_Comm_size failed with " 
  906    "error \"" << mpiErrorCodeToString (err) << 
"\".");
 
  907  err = MPI_Comm_rank (*rawMpiComm_, &rank_);
 
  909    "Teuchos::MpiComm constructor: MPI_Comm_rank failed with " 
  910    "error \"" << mpiErrorCodeToString (err) << 
"\".");
 
  913  if (tagCounter_ > maxTag_) {
 
  914    tagCounter_ = minTag_;
 
  916  tag_ = tagCounter_++;
 
  926  MPI_Bcast (&tag_, 1, MPI_INT, 0, *rawMpiComm_);
 
  930template<
typename Ordinal>
 
  933setErrorHandler (
const RCP<
const OpaqueWrapper<MPI_Errhandler> >& errHandler)
 
  935  if (! is_null (errHandler)) {
 
  936    const int err = details::setCommErrhandler (*getRawMpiComm (), *errHandler);
 
  938      "Teuchos::MpiComm: Setting the MPI_Comm's error handler failed with " 
  939      "error \"" << mpiErrorCodeToString (err) << 
"\".");
 
  943  customErrorHandler_ = errHandler;
 
  950template<
typename Ordinal>
 
  951int MpiComm<Ordinal>::getRank()
 const 
  957template<
typename Ordinal>
 
  958int MpiComm<Ordinal>::getSize()
 const 
  964template<
typename Ordinal>
 
  965void MpiComm<Ordinal>::barrier()
 const 
  967  TEUCHOS_COMM_TIME_MONITOR(
 
  968    "Teuchos::MpiComm<"<<OrdinalTraits<Ordinal>::name()<<
">::barrier()" 
  970  const int err = MPI_Barrier (*rawMpiComm_);
 
  972    "Teuchos::MpiComm::barrier: MPI_Barrier failed with error \"" 
  973    << mpiErrorCodeToString (err) << 
"\".");
 
  977template<
typename Ordinal>
 
  978void MpiComm<Ordinal>::broadcast(
 
  979  const int rootRank, 
const Ordinal bytes, 
char buffer[]
 
  982  TEUCHOS_COMM_TIME_MONITOR(
 
  983    "Teuchos::MpiComm<"<<OrdinalTraits<Ordinal>::name()<<
">::broadcast(...)" 
  985  const int err = MPI_Bcast (buffer, bytes, MPI_CHAR, rootRank, *rawMpiComm_);
 
  987    "Teuchos::MpiComm::broadcast: MPI_Bcast failed with error \"" 
  988    << mpiErrorCodeToString (err) << 
"\".");
 
  992template<
typename Ordinal>
 
  993void MpiComm<Ordinal>::gatherAll(
 
  994  const Ordinal sendBytes, 
const char sendBuffer[],
 
  995  const Ordinal recvBytes, 
char recvBuffer[]
 
  998  TEUCHOS_COMM_TIME_MONITOR(
 
  999    "Teuchos::MpiComm<"<<OrdinalTraits<Ordinal>::name()<<
">::gatherAll(...)" 
 1003    MPI_Allgather (
const_cast<char *
>(sendBuffer), sendBytes, MPI_CHAR,
 
 1004                   recvBuffer, sendBytes, MPI_CHAR, *rawMpiComm_);
 
 1009    "Teuchos::MpiComm::gatherAll: MPI_Allgather failed with error \"" 
 1010    << mpiErrorCodeToString (err) << 
"\".");
 
 1014template<
typename Ordinal>
 
 1016MpiComm<Ordinal>::gather (
const Ordinal sendBytes,
 
 1017                          const char sendBuffer[],
 
 1018                          const Ordinal recvBytes,
 
 1020                          const int root)
 const 
 1024  TEUCHOS_COMM_TIME_MONITOR(
 
 1025    "Teuchos::MpiComm<"<<OrdinalTraits<Ordinal>::name()<<
">::gather(...)" 
 1028    MPI_Gather (
const_cast<char *
> (sendBuffer), sendBytes, MPI_CHAR,
 
 1029                recvBuffer, sendBytes, MPI_CHAR, root, *rawMpiComm_);
 
 1031    "Teuchos::MpiComm::gather: MPI_Gather failed with error \"" 
 1032    << mpiErrorCodeToString (err) << 
"\".");
 
 1036template<
typename Ordinal>
 
 1039reduceAll (
const ValueTypeReductionOp<Ordinal,char> &reductOp,
 
 1040           const Ordinal bytes,
 
 1041           const char sendBuffer[],
 
 1042           char globalReducts[])
 const 
 1044  TEUCHOS_COMM_TIME_MONITOR( 
"Teuchos::MpiComm::reduceAll(...)" );
 
 1045  int err = MPI_SUCCESS;
 
 1047  if (bytes == 0) 
return;
 
 1049  Details::MpiReductionOp<Ordinal> opWrap (reductOp);
 
 1050  MPI_Op op = Details::setMpiReductionOp (opWrap);
 
 1059  MPI_Datatype char_block;
 
 1060  err = MPI_Type_contiguous (bytes, MPI_CHAR, &char_block);
 
 1062    err != MPI_SUCCESS, std::runtime_error, 
"Teuchos::reduceAll: " 
 1063    "MPI_Type_contiguous failed with error \"" << mpiErrorCodeToString (err)
 
 1065  err = MPI_Type_commit (&char_block);
 
 1067    err != MPI_SUCCESS, std::runtime_error, 
"Teuchos::reduceAll: " 
 1068    "MPI_Type_commit failed with error \"" << mpiErrorCodeToString (err)
 
 1071  if (sendBuffer == globalReducts) {
 
 1075    err = MPI_Allreduce (MPI_IN_PLACE, globalReducts, 1,
 
 1076                         char_block, op, *rawMpiComm_);
 
 1079    err = MPI_Allreduce (
const_cast<char*
> (sendBuffer), globalReducts, 1,
 
 1080                         char_block, op, *rawMpiComm_);
 
 1082  if (err != MPI_SUCCESS) {
 
 1087    (void) MPI_Type_free (&char_block);
 
 1089      true, std::runtime_error, 
"Teuchos::reduceAll (MPI, custom op): " 
 1090      "MPI_Allreduce failed with error \"" << mpiErrorCodeToString (err)
 
 1093  err = MPI_Type_free (&char_block);
 
 1095    err != MPI_SUCCESS, std::runtime_error, 
"Teuchos::reduceAll: " 
 1096    "MPI_Type_free failed with error \"" << mpiErrorCodeToString (err)
 
 1101template<
typename Ordinal>
 
 1102void MpiComm<Ordinal>::scan(
 
 1103  const ValueTypeReductionOp<Ordinal,char> &reductOp
 
 1104  ,
const Ordinal bytes, 
const char sendBuffer[], 
char scanReducts[]
 
 1107  TEUCHOS_COMM_TIME_MONITOR( 
"Teuchos::MpiComm::scan(...)" );
 
 1109  Details::MpiReductionOp<Ordinal> opWrap (reductOp);
 
 1110  MPI_Op op = Details::setMpiReductionOp (opWrap);
 
 1112    MPI_Scan (
const_cast<char*
> (sendBuffer), scanReducts, bytes, MPI_CHAR,
 
 1115    "Teuchos::MpiComm::scan: MPI_Scan() failed with error \"" 
 1116    << mpiErrorCodeToString (err) << 
"\".");
 
 1120template<
typename Ordinal>
 
 1122MpiComm<Ordinal>::send (
const Ordinal bytes,
 
 1123                        const char sendBuffer[],
 
 1124                        const int destRank)
 const 
 1126  TEUCHOS_COMM_TIME_MONITOR( 
"Teuchos::MpiComm::send(...)" );
 
 1128#ifdef TEUCHOS_MPI_COMM_DUMP 
 1130    dumpBuffer<Ordinal,char>(
 
 1131      "Teuchos::MpiComm<Ordinal>::send(...)" 
 1132      ,
"sendBuffer", bytes, sendBuffer
 
 1137  const int err = MPI_Send (
const_cast<char*
>(sendBuffer), bytes, MPI_CHAR,
 
 1138                            destRank, tag_, *rawMpiComm_);
 
 1140    "Teuchos::MpiComm::send: MPI_Send() failed with error \"" 
 1141    << mpiErrorCodeToString (err) << 
"\".");
 
 1145template<
typename Ordinal>
 
 1147MpiComm<Ordinal>::send (
const Ordinal bytes,
 
 1148                        const char sendBuffer[],
 
 1150                        const int tag)
 const 
 1152  TEUCHOS_COMM_TIME_MONITOR( 
"Teuchos::MpiComm::send(...)" );
 
 1153  const int err = MPI_Send (
const_cast<char*
> (sendBuffer), bytes, MPI_CHAR,
 
 1154                            destRank, tag, *rawMpiComm_);
 
 1156    "Teuchos::MpiComm::send: MPI_Send() failed with error \"" 
 1157    << mpiErrorCodeToString (err) << 
"\".");
 
 1161template<
typename Ordinal>
 
 1163MpiComm<Ordinal>::ssend (
const Ordinal bytes,
 
 1164                         const char sendBuffer[],
 
 1165                         const int destRank)
 const 
 1167  TEUCHOS_COMM_TIME_MONITOR( 
"Teuchos::MpiComm::ssend(...)" );
 
 1169#ifdef TEUCHOS_MPI_COMM_DUMP 
 1171    dumpBuffer<Ordinal,char>(
 
 1172      "Teuchos::MpiComm<Ordinal>::send(...)" 
 1173      ,
"sendBuffer", bytes, sendBuffer
 
 1178  const int err = MPI_Ssend (
const_cast<char*
>(sendBuffer), bytes, MPI_CHAR,
 
 1179                             destRank, tag_, *rawMpiComm_);
 
 1181    "Teuchos::MpiComm::send: MPI_Ssend() failed with error \"" 
 1182    << mpiErrorCodeToString (err) << 
"\".");
 
 1185template<
typename Ordinal>
 
 1187MpiComm<Ordinal>::ssend (
const Ordinal bytes,
 
 1188                         const char sendBuffer[],
 
 1190                         const int tag)
 const 
 1192  TEUCHOS_COMM_TIME_MONITOR( 
"Teuchos::MpiComm::ssend(...)" );
 
 1194    MPI_Ssend (
const_cast<char*
>(sendBuffer), bytes, MPI_CHAR,
 
 1195               destRank, tag, *rawMpiComm_);
 
 1197    "Teuchos::MpiComm::send: MPI_Ssend() failed with error \"" 
 1198    << mpiErrorCodeToString (err) << 
"\".");
 
 1201template<
typename Ordinal>
 
 1202void MpiComm<Ordinal>::readySend(
 
 1203  const ArrayView<const char> &sendBuffer,
 
 1207  TEUCHOS_COMM_TIME_MONITOR( 
"Teuchos::MpiComm::readySend" );
 
 1209#ifdef TEUCHOS_MPI_COMM_DUMP 
 1211    dumpBuffer<Ordinal,char>(
 
 1212      "Teuchos::MpiComm<Ordinal>::readySend(...)" 
 1213      ,
"sendBuffer", bytes, sendBuffer
 
 1219    MPI_Rsend (
const_cast<char*
>(sendBuffer.getRawPtr()), 
static_cast<int>(sendBuffer.size()),
 
 1220               MPI_CHAR, destRank, tag_, *rawMpiComm_);
 
 1222    "Teuchos::MpiComm::readySend: MPI_Rsend() failed with error \"" 
 1223    << mpiErrorCodeToString (err) << 
"\".");
 
 1227template<
typename Ordinal>
 
 1228void MpiComm<Ordinal>::
 
 1229readySend (
const Ordinal bytes,
 
 1230           const char sendBuffer[],
 
 1232           const int tag)
 const 
 1234  TEUCHOS_COMM_TIME_MONITOR( 
"Teuchos::MpiComm::readySend" );
 
 1236    MPI_Rsend (
const_cast<char*
> (sendBuffer), bytes,
 
 1237               MPI_CHAR, destRank, tag, *rawMpiComm_);
 
 1239    "Teuchos::MpiComm::readySend: MPI_Rsend() failed with error \"" 
 1240    << mpiErrorCodeToString (err) << 
"\".");
 
 1244template<
typename Ordinal>
 
 1246MpiComm<Ordinal>::receive (
const int sourceRank,
 
 1247                           const Ordinal bytes,
 
 1248                           char recvBuffer[])
 const 
 1250  TEUCHOS_COMM_TIME_MONITOR( 
"Teuchos::MpiComm::receive(...)" );
 
 1255  const int theSrcRank = (sourceRank < 0) ? MPI_ANY_SOURCE : sourceRank;
 
 1258  const int err = MPI_Recv (recvBuffer, bytes, MPI_CHAR, theSrcRank, tag_,
 
 1259                            *rawMpiComm_, &status);
 
 1261    "Teuchos::MpiComm::receive: MPI_Recv() failed with error \"" 
 1262    << mpiErrorCodeToString (err) << 
"\".");
 
 1264#ifdef TEUCHOS_MPI_COMM_DUMP 
 1266    dumpBuffer<Ordinal,char> (
"Teuchos::MpiComm<Ordinal>::receive(...)",
 
 1267                              "recvBuffer", bytes, recvBuffer);
 
 1272  return status.MPI_SOURCE;
 
 1276template<
typename Ordinal>
 
 1277RCP<CommRequest<Ordinal> >
 
 1278MpiComm<Ordinal>::isend (
const ArrayView<const char> &sendBuffer,
 
 1279                         const int destRank)
 const 
 1282  TEUCHOS_COMM_TIME_MONITOR( 
"Teuchos::MpiComm::isend(...)" );
 
 1284  MPI_Request rawMpiRequest = MPI_REQUEST_NULL;
 
 1286    MPI_Isend (
const_cast<char*
> (sendBuffer.getRawPtr ()),
 
 1287               as<Ordinal> (sendBuffer.size ()), MPI_CHAR,
 
 1288               destRank, tag_, *rawMpiComm_, &rawMpiRequest);
 
 1290    "Teuchos::MpiComm::isend: MPI_Isend() failed with error \"" 
 1291    << mpiErrorCodeToString (err) << 
"\".");
 
 1293  return mpiCommRequest<Ordinal> (rawMpiRequest, sendBuffer.size ());
 
 1297template<
typename Ordinal>
 
 1298RCP<CommRequest<Ordinal> >
 
 1300isend (
const ArrayView<const char> &sendBuffer,
 
 1302       const int tag)
 const 
 1305  TEUCHOS_COMM_TIME_MONITOR( 
"Teuchos::MpiComm::isend(...)" );
 
 1307  MPI_Request rawMpiRequest = MPI_REQUEST_NULL;
 
 1309    MPI_Isend (
const_cast<char*
> (sendBuffer.getRawPtr ()),
 
 1310               as<Ordinal> (sendBuffer.size ()), MPI_CHAR,
 
 1311               destRank, tag, *rawMpiComm_, &rawMpiRequest);
 
 1313    "Teuchos::MpiComm::isend: MPI_Isend() failed with error \"" 
 1314    << mpiErrorCodeToString (err) << 
"\".");
 
 1316  return mpiCommRequest<Ordinal> (rawMpiRequest, sendBuffer.size ());
 
 1320template<
typename Ordinal>
 
 1321RCP<CommRequest<Ordinal> >
 
 1322MpiComm<Ordinal>::ireceive (
const ArrayView<char> &recvBuffer,
 
 1323                            const int sourceRank)
 const 
 1325  TEUCHOS_COMM_TIME_MONITOR( 
"Teuchos::MpiComm::ireceive(...)" );
 
 1330  const int theSrcRank = (sourceRank < 0) ? MPI_ANY_SOURCE : sourceRank;
 
 1332  MPI_Request rawMpiRequest = MPI_REQUEST_NULL;
 
 1334    MPI_Irecv (
const_cast<char*
>(recvBuffer.getRawPtr()), recvBuffer.size(),
 
 1335               MPI_CHAR, theSrcRank, tag_, *rawMpiComm_, &rawMpiRequest);
 
 1337    "Teuchos::MpiComm::ireceive: MPI_Irecv() failed with error \"" 
 1338    << mpiErrorCodeToString (err) << 
"\".");
 
 1340  return mpiCommRequest<Ordinal> (rawMpiRequest, recvBuffer.size());
 
 1343template<
typename Ordinal>
 
 1344RCP<CommRequest<Ordinal> >
 
 1345MpiComm<Ordinal>::ireceive (
const ArrayView<char> &recvBuffer,
 
 1346                            const int sourceRank,
 
 1347                            const int tag)
 const 
 1349  TEUCHOS_COMM_TIME_MONITOR( 
"Teuchos::MpiComm::ireceive(...)" );
 
 1354  const int theSrcRank = (sourceRank < 0) ? MPI_ANY_SOURCE : sourceRank;
 
 1356  MPI_Request rawMpiRequest = MPI_REQUEST_NULL;
 
 1358    MPI_Irecv (
const_cast<char*
> (recvBuffer.getRawPtr ()), recvBuffer.size (),
 
 1359               MPI_CHAR, theSrcRank, tag, *rawMpiComm_, &rawMpiRequest);
 
 1361    "Teuchos::MpiComm::ireceive: MPI_Irecv() failed with error \"" 
 1362    << mpiErrorCodeToString (err) << 
"\".");
 
 1364  return mpiCommRequest<Ordinal> (rawMpiRequest, recvBuffer.size ());
 
 1369  template<
typename Ordinal>
 
 1371  waitAllImpl (
const ArrayView<RCP<CommRequest<Ordinal> > >& requests,
 
 1372               const ArrayView<MPI_Status>& rawMpiStatuses)
 
 1374    typedef typename ArrayView<RCP<CommRequest<Ordinal> > >::size_type size_type;
 
 1375    const size_type count = requests.size();
 
 1379      std::logic_error, 
"Teuchos::MpiComm's waitAllImpl: rawMpiStatus.size() = " 
 1380      << rawMpiStatuses.size() << 
" != requests.size() = " << requests.size()
 
 1381      << 
".  Please report this bug to the Tpetra developers.");
 
 1394    bool someNullRequests = 
false;
 
 1395    Array<MPI_Request> rawMpiRequests (count, MPI_REQUEST_NULL);
 
 1396    for (
int i = 0; i < count; ++i) {
 
 1397      RCP<CommRequest<Ordinal> > request = requests[i];
 
 1398      if (! is_null (request)) {
 
 1399        RCP<MpiCommRequestBase<Ordinal> > mpiRequest =
 
 1400          rcp_dynamic_cast<MpiCommRequestBase<Ordinal> > (request);
 
 1408        rawMpiRequests[i] = mpiRequest->releaseRawMpiRequest();
 
 1411        rawMpiRequests[i] = MPI_REQUEST_NULL;
 
 1412        someNullRequests = 
true;
 
 1425    const int err = MPI_Waitall (count, rawMpiRequests.getRawPtr(),
 
 1426                                 rawMpiStatuses.getRawPtr());
 
 1436    if (err != MPI_SUCCESS) {
 
 1437      if (err == MPI_ERR_IN_STATUS) {
 
 1445        Array<std::pair<size_type, int> > errorLocationsAndCodes;
 
 1446        for (size_type k = 0; k < rawMpiStatuses.size(); ++k) {
 
 1447          const int curErr = rawMpiStatuses[k].MPI_ERROR;
 
 1448          if (curErr != MPI_SUCCESS) {
 
 1449            errorLocationsAndCodes.push_back (std::make_pair (k, curErr));
 
 1452        const size_type numErrs = errorLocationsAndCodes.size();
 
 1457          std::ostringstream os;
 
 1458          os << 
"Teuchos::MpiComm::waitAll: MPI_Waitall() failed with error \"" 
 1459             << mpiErrorCodeToString (err) << 
"\".  Of the " << count
 
 1460             << 
" total request" << (count != 1 ? 
"s" : 
"") << 
", " << numErrs
 
 1461             << 
" failed.  Here are the indices of the failed requests, and the " 
 1462            "error codes extracted from their returned MPI_Status objects:" 
 1464          for (size_type k = 0; k < numErrs; ++k) {
 
 1465            const size_type errInd = errorLocationsAndCodes[k].first;
 
 1466            os << 
"Request " << errInd << 
": MPI_ERROR = " 
 1467               << mpiErrorCodeToString (rawMpiStatuses[errInd].MPI_ERROR)
 
 1470          if (someNullRequests) {
 
 1471            os << 
"  On input to MPI_Waitall, there was at least one MPI_" 
 1472              "Request that was MPI_REQUEST_NULL.  MPI_Waitall should not " 
 1473              "normally fail in that case, but we thought we should let you know " 
 1482        std::ostringstream os;
 
 1483        os << 
"Teuchos::MpiComm::waitAll: MPI_Waitall() failed with error \"" 
 1484           << mpiErrorCodeToString (err) << 
"\".";
 
 1485        if (someNullRequests) {
 
 1486          os << 
"  On input to MPI_Waitall, there was at least one MPI_Request " 
 1487            "that was MPI_REQUEST_NULL.  MPI_Waitall should not normally fail in " 
 1488            "that case, but we thought we should let you know regardless.";
 
 1496    std::fill (requests.begin(), requests.end(), null);
 
 1502  template<
typename Ordinal>
 
 1504  waitAllImpl (
const ArrayView<RCP<CommRequest<Ordinal> > >& requests)
 
 1506    typedef typename ArrayView<RCP<CommRequest<Ordinal> > >::size_type size_type;
 
 1507    const size_type count = requests.size ();
 
 1520    bool someNullRequests = 
false;
 
 1521    Array<MPI_Request> rawMpiRequests (count, MPI_REQUEST_NULL);
 
 1522    for (
int i = 0; i < count; ++i) {
 
 1523      RCP<CommRequest<Ordinal> > request = requests[i];
 
 1524      if (! request.is_null ()) {
 
 1525        RCP<MpiCommRequestBase<Ordinal> > mpiRequest =
 
 1526          rcp_dynamic_cast<MpiCommRequestBase<Ordinal> > (request);
 
 1534        rawMpiRequests[i] = mpiRequest->releaseRawMpiRequest ();
 
 1537        rawMpiRequests[i] = MPI_REQUEST_NULL;
 
 1538        someNullRequests = 
true;
 
 1548    const int err = MPI_Waitall (count, rawMpiRequests.getRawPtr(),
 
 1549                                 MPI_STATUSES_IGNORE);
 
 1559    if (err != MPI_SUCCESS) {
 
 1560      std::ostringstream os;
 
 1561      os << 
"Teuchos::MpiComm::waitAll: MPI_Waitall() failed with error \"" 
 1562         << mpiErrorCodeToString (err) << 
"\".";
 
 1563      if (someNullRequests) {
 
 1564        os << std::endl << 
"On input to MPI_Waitall, there was at least one " 
 1565          "MPI_Request that was MPI_REQUEST_NULL.  MPI_Waitall should not " 
 1566          "normally fail in that case, but we thought we should let you know " 
 1577    std::fill (requests.begin(), requests.end(), null);
 
 1584template<
typename Ordinal>
 
 1587waitAll (
const ArrayView<RCP<CommRequest<Ordinal> > >& requests)
 const 
 1589  TEUCHOS_COMM_TIME_MONITOR( 
"Teuchos::MpiComm::waitAll(requests)" );
 
 1592  waitAllImpl<Ordinal> (requests);
 
 1596template<
typename Ordinal>
 
 1599waitAll (
const ArrayView<RCP<CommRequest<Ordinal> > >& requests,
 
 1600         const ArrayView<RCP<CommStatus<Ordinal> > >& statuses)
 const 
 1602  TEUCHOS_COMM_TIME_MONITOR( 
"Teuchos::MpiComm::waitAll(requests, statuses)" );
 
 1604  typedef typename ArrayView<RCP<CommRequest<Ordinal> > >::size_type size_type;
 
 1605  const size_type count = requests.size();
 
 1608    std::invalid_argument, 
"Teuchos::MpiComm::waitAll: requests.size() = " 
 1609    << count << 
" != statuses.size() = " << statuses.size() << 
".");
 
 1611  Array<MPI_Status> rawMpiStatuses (count);
 
 1612  waitAllImpl<Ordinal> (requests, rawMpiStatuses());
 
 1615  for (size_type i = 0; i < count; ++i) {
 
 1616    statuses[i] = mpiCommStatus<Ordinal> (rawMpiStatuses[i]);
 
 1621template<
typename Ordinal>
 
 1622RCP<CommStatus<Ordinal> >
 
 1623MpiComm<Ordinal>::wait (
const Ptr<RCP<CommRequest<Ordinal> > >& request)
 const 
 1625  TEUCHOS_COMM_TIME_MONITOR( 
"Teuchos::MpiComm::wait(...)" );
 
 1627  if (is_null (*request)) {
 
 1631    RCP<CommStatus<Ordinal> > status = (*request)->wait ();
 
 1639template<
typename Ordinal>
 
 1641MpiComm<Ordinal>::duplicate()
 const 
 1643  MPI_Comm origRawComm = *rawMpiComm_;
 
 1644  MPI_Comm newRawComm = MPI_COMM_NULL;
 
 1645  const int err = MPI_Comm_dup (origRawComm, &newRawComm);
 
 1647    "::MpiComm::duplicate: MPI_Comm_dup failed with the following error: " 
 1648    << mpiErrorCodeToString (err));
 
 1653  RCP<OpaqueWrapper<MPI_Comm> > wrapped =
 
 1654    opaqueWrapper<MPI_Comm> (newRawComm, details::safeCommFree);
 
 1658  RCP<MpiComm<Ordinal> > newComm =
 
 1659    rcp (
new MpiComm<Ordinal> (wrapped.getConst (), minTag_));
 
 1660  return rcp_implicit_cast<Comm<Ordinal> > (newComm);
 
 1664template<
typename Ordinal>
 
 1666MpiComm<Ordinal>::split(
const int color, 
const int key)
 const 
 1669  const int splitReturn =
 
 1670    MPI_Comm_split (*rawMpiComm_,
 
 1671                    color < 0 ? MPI_UNDEFINED : color,
 
 1675    splitReturn != MPI_SUCCESS,
 
 1677    "Teuchos::MpiComm::split: Failed to create communicator with color " 
 1678    << color << 
"and key " << key << 
".  MPI_Comm_split failed with error \"" 
 1679    << mpiErrorCodeToString (splitReturn) << 
"\".");
 
 1680  if (newComm == MPI_COMM_NULL) {
 
 1681    return RCP< Comm<Ordinal> >();
 
 1683    RCP<const OpaqueWrapper<MPI_Comm> > wrapped =
 
 1684      opaqueWrapper<MPI_Comm> (newComm, details::safeCommFree);
 
 1689    return rcp (
new MpiComm<Ordinal> (wrapped, minTag_));
 
 1694template<
typename Ordinal>
 
 1696MpiComm<Ordinal>::createSubcommunicator(
const ArrayView<const int> &ranks)
 const 
 1698  int err = MPI_SUCCESS; 
 
 1701  MPI_Group thisGroup;
 
 1702  err = MPI_Comm_group (*rawMpiComm_, &thisGroup);
 
 1704    "Failed to obtain the current communicator's group.  " 
 1705    "MPI_Comm_group failed with error \"" 
 1706    << mpiErrorCodeToString (err) << 
"\".");
 
 1714  err = MPI_Group_incl (thisGroup, ranks.size(),
 
 1715                        const_cast<int*
> (ranks.getRawPtr ()), &newGroup);
 
 1717    "Failed to create subgroup.  MPI_Group_incl failed with error \"" 
 1718    << mpiErrorCodeToString (err) << 
"\".");
 
 1723    err = MPI_Comm_create (*rawMpiComm_, newGroup, &newComm);
 
 1725      "Failed to create subcommunicator.  MPI_Comm_create failed with error \"" 
 1726      << mpiErrorCodeToString (err) << 
"\".");
 
 1733    (void) MPI_Group_free (&newGroup);
 
 1734    (void) MPI_Group_free (&thisGroup);
 
 1739  err = MPI_Group_free (&newGroup);
 
 1741    "Failed to free subgroup.  MPI_Group_free failed with error \"" 
 1742    << mpiErrorCodeToString (err) << 
"\".");
 
 1743  err = MPI_Group_free (&thisGroup);
 
 1745    "Failed to free subgroup.  MPI_Group_free failed with error \"" 
 1746    << mpiErrorCodeToString (err) << 
"\".");
 
 1748  if (newComm == MPI_COMM_NULL) {
 
 1749    return RCP<Comm<Ordinal> > ();
 
 1751    using Teuchos::details::safeCommFree;
 
 1752    typedef OpaqueWrapper<MPI_Comm> ow_type;
 
 1753    RCP<const ow_type> wrapper =
 
 1754      rcp_implicit_cast<const ow_type> (opaqueWrapper (newComm, safeCommFree));
 
 1759    return rcp (
new MpiComm<Ordinal> (wrapper, minTag_));
 
 1767template<
typename Ordinal>
 
 1768std::string MpiComm<Ordinal>::description()
 const 
 1770  std::ostringstream oss;
 
 1776    << 
",rawMpiComm="<<
static_cast<MPI_Comm
>(*rawMpiComm_)
 
 1782#ifdef TEUCHOS_MPI_COMM_DUMP 
 1783template<
typename Ordinal>
 
 1784bool MpiComm<Ordinal>::show_dump = 
false;
 
 1791template<
typename Ordinal>
 
 1792void MpiComm<Ordinal>::assertRank(
const int rank, 
const std::string &rankName)
 const 
 1795    ! ( 0 <= rank && rank < size_ ), std::logic_error
 
 1796    ,
"Error, "<<rankName<<
" = " << rank << 
" is not < 0 or is not" 
 1797    " in the range [0,"<<size_-1<<
"]!" 
 1805template<
typename Ordinal>
 
 1808  const RCP<
const OpaqueWrapper<MPI_Comm> > &rawMpiComm
 
 1811  if( rawMpiComm.get()!=NULL && *rawMpiComm != MPI_COMM_NULL )
 
 1812    return rcp(
new MpiComm<Ordinal>(rawMpiComm));
 
 1813  return Teuchos::null;
 
 1817template<
typename Ordinal>
 
 1820                       const RCP<
const OpaqueWrapper<MPI_Comm> > &rawMpiComm,
 
 1821                       const int defaultTag
 
 1824  if( rawMpiComm.get()!=NULL && *rawMpiComm != MPI_COMM_NULL )
 
 1825    return rcp(
new MpiComm<Ordinal>(rawMpiComm, defaultTag));
 
 1826  return Teuchos::null;
 
 1830template<
typename Ordinal>
 
 1835    dyn_cast<const MpiComm<Ordinal> >(comm).getRawMpiComm()
 
Teuchos header file which uses auto-configuration information to include necessary C++ headers.
 
Implementation detail of Teuchos' MPI wrapper.
 
Defines basic traits for the ordinal field type.
 
Defines basic traits returning the name of a type in a portable and readable way.
 
Definition of Teuchos::as, for conversions between types.
 
Ordinal size_type
Type representing the number of elements in an ArrayRCP or view thereof.
 
Smart reference counting pointer class for automatic garbage collection.
 
static RCP< FancyOStream > getDefaultOStream()
Get the default output stream object.
 
Tabbing class for helping to create formated, indented output for a basic_FancyOStream object.
 
#define TEUCHOS_TEST_FOR_EXCEPTION(throw_exception_test, Exception, msg)
Macro for throwing an exception with breakpointing to ease debugging.
 
#define TEUCHOS_ASSERT_EQUALITY(val1, val2)
This macro is checks that to numbers are equal and if not then throws an exception with a good error ...
 
TypeTo as(const TypeFrom &t)
Convert from one value type to another.
 
std::string typeName(const T &t)
Template function for returning the concrete type name of a passed-in object.
 
The Teuchos namespace contains all of the classes, structs and enums used by Teuchos,...
 
void ssend(const Packet sendBuffer[], const Ordinal count, const int destRank, const int tag, const Comm< Ordinal > &comm)
Variant of ssend() that takes a tag (and restores the correct order of arguments).
 
void readySend(const Packet sendBuffer[], const Ordinal count, const int destRank, const int tag, const Comm< Ordinal > &comm)
Variant of readySend() that accepts a message tag.
 
TEUCHOS_DEPRECATED RCP< T > rcp(T *p, Dealloc_T dealloc, bool owns_mem)
Deprecated.
 
RCP< CommRequest< Ordinal > > ireceive(const ArrayRCP< Packet > &recvBuffer, const int sourceRank, const int tag, const Comm< Ordinal > &comm)
Variant of ireceive that takes a tag argument (and restores the correct order of arguments).
 
void send(const Packet sendBuffer[], const Ordinal count, const int destRank, const int tag, const Comm< Ordinal > &comm)
Variant of send() that takes a tag (and restores the correct order of arguments).
 
Teuchos implementation details.