Teuchos_DefaultMpiComm.hpp

Go to the documentation of this file.
00001 // @HEADER
00002 // ***********************************************************************
00003 // 
00004 //                    Teuchos: Common Tools Package
00005 //                 Copyright (2004) Sandia Corporation
00006 // 
00007 // Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive
00008 // license for use of this work by or on behalf of the U.S. Government.
00009 // 
00010 // This library is free software; you can redistribute it and/or modify
00011 // it under the terms of the GNU Lesser General Public License as
00012 // published by the Free Software Foundation; either version 2.1 of the
00013 // License, or (at your option) any later version.
00014 //  
00015 // This library is distributed in the hope that it will be useful, but
00016 // WITHOUT ANY WARRANTY; without even the implied warranty of
00017 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00018 // Lesser General Public License for more details.
00019 //  
00020 // You should have received a copy of the GNU Lesser General Public
00021 // License along with this library; if not, write to the Free Software
00022 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
00023 // USA
00024 // Questions? Contact Michael A. Heroux (maherou@sandia.gov) 
00025 // 
00026 // ***********************************************************************
00027 // @HEADER
00028 
00029 #ifndef TEUCHOS_MPI_COMM_HPP
00030 #define TEUCHOS_MPI_COMM_HPP
00031 
00032 
00033 #include "Teuchos_Comm.hpp"
00034 #include "Teuchos_CommUtilities.hpp"
00035 #include "Teuchos_OrdinalTraits.hpp"
00036 #include "Teuchos_OpaqueWrapper.hpp"
00037 #include "Teuchos_MpiReductionOpSetter.hpp"
00038 #include "Teuchos_SerializationTraitsHelpers.hpp"
00039 #include "Teuchos_Workspace.hpp"
00040 #include "Teuchos_TypeNameTraits.hpp"
00041 #include "Teuchos_as.hpp"
00042 #include "mpi.h"
00043 
00044 
00045 // This must be defined globally for the whole program!
00046 //#define TEUCHOS_MPI_COMM_DUMP
00047 
00048 
00049 #ifdef TEUCHOS_MPI_COMM_DUMP
00050 #  include "Teuchos_VerboseObject.hpp"
00051 #endif
00052 
00053 
00054 namespace Teuchos {
00055 
00056 
00057 #ifdef TEUCHOS_MPI_COMM_DUMP
00058 template<typename Ordinal, typename T>
00059 void dumpBuffer(
00060   const std::string &funcName, const std::string &buffName
00061   ,const Ordinal bytes, const T buff[]
00062   )
00063 {
00064   Teuchos::RCP<Teuchos::FancyOStream>
00065     out = Teuchos::VerboseObjectBase::getDefaultOStream();
00066   Teuchos::OSTab tab(out);
00067   *out
00068     << "\n" << funcName << "::" << buffName << ":\n";
00069   tab.incrTab();
00070   for( Ordinal i = 0; i < bytes; ++i ) {
00071     *out << buffName << "[" << i << "] = '" << buff[i] << "'\n";
00072   }
00073   *out << "\n";
00074 }
00075 #endif // TEUCHOS_MPI_COMM_DUMP
00076 
00077 
00079 class MpiCommRequest : public CommRequest {
00080 public:
00082   MpiCommRequest( MPI_Request rawMpiRequest )
00083     :rawMpiRequest_(rawMpiRequest)
00084     {}
00086   MPI_Request releaseRawMpiRequest()
00087     {
00088       MPI_Request tmp_rawMpiRequest = rawMpiRequest_;
00089       rawMpiRequest_ = MPI_REQUEST_NULL;
00090       return tmp_rawMpiRequest;
00091     }
00092 private:
00093   MPI_Request rawMpiRequest_;
00094   MpiCommRequest(); // Not defined
00095 };
00096 
00097 
00102 inline
00103 const RCP<MpiCommRequest>
00104 mpiCommRequest( MPI_Request rawMpiRequest  )
00105 {
00106   return Teuchos::rcp(new MpiCommRequest(rawMpiRequest));
00107 }
00108 
00109 
00120 template<typename Ordinal>
00121 class MpiComm : public Comm<Ordinal> {
00122 public:
00123 
00125 
00126 
00133   MpiComm(
00134     const RCP<const OpaqueWrapper<MPI_Comm> > &rawMpiComm
00135     );
00136 
00138   RCP<const OpaqueWrapper<MPI_Comm> > getRawMpiComm() const
00139   {return rawMpiComm_;}
00140 
00142 
00144 
00145 
00147   virtual int getRank() const;
00149   virtual int getSize() const;
00151   virtual void barrier() const;
00153   virtual void broadcast(
00154     const int rootRank, const Ordinal bytes, char buffer[]
00155     ) const;
00157   virtual void gatherAll(
00158     const Ordinal sendBytes, const char sendBuffer[]
00159     ,const Ordinal recvBytes, char recvBuffer[]
00160     ) const;
00162   virtual void reduceAll(
00163     const ValueTypeReductionOp<Ordinal,char> &reductOp
00164     ,const Ordinal bytes, const char sendBuffer[], char globalReducts[]
00165     ) const;
00167   virtual void reduceAllAndScatter(
00168     const ValueTypeReductionOp<Ordinal,char> &reductOp
00169     ,const Ordinal sendBytes, const char sendBuffer[]
00170     ,const Ordinal recvCounts[], char myGlobalReducts[]
00171     ) const;
00173   virtual void scan(
00174     const ValueTypeReductionOp<Ordinal,char> &reductOp
00175     ,const Ordinal bytes, const char sendBuffer[], char scanReducts[]
00176     ) const;
00178   virtual void send(
00179     const Ordinal bytes, const char sendBuffer[], const int destRank
00180     ) const;
00182   virtual int receive(
00183     const int sourceRank, const Ordinal bytes, char recvBuffer[]
00184     ) const;
00186   virtual void readySend(
00187     const ArrayView<const char> &sendBuffer,
00188     const int destRank
00189     ) const;
00191   virtual RCP<CommRequest> isend(
00192     const ArrayView<const char> &sendBuffer,
00193     const int destRank
00194     ) const;
00196   virtual RCP<CommRequest> ireceive(
00197     const ArrayView<char> &Buffer,
00198     const int sourceRank
00199     ) const;
00201   virtual void waitAll(
00202     const ArrayView<RCP<CommRequest> > &requests
00203     ) const;
00205   virtual void wait(
00206     const Ptr<RCP<CommRequest> > &request
00207     ) const;
00208 
00210 
00212 
00213 
00215   std::string description() const;
00216 
00218 
00219 private:
00220 
00221   static int const minTag_ = 26000; // These came from Teuchos::MpiComm???
00222   static int const maxTag_ = 26099; // ""
00223   static int tagCounter_;
00224 
00225   RCP<const OpaqueWrapper<MPI_Comm> > rawMpiComm_;
00226   int rank_;
00227   int size_;
00228   int tag_;
00229 
00230   void assertRank(const int rank, const std::string &rankName) const;
00231 
00232   // Not defined and not to be called!
00233   MpiComm();
00234 
00235 #ifdef TEUCHOS_MPI_COMM_DUMP
00236 public:
00237   static bool show_dump;
00238 #endif // TEUCHOS_MPI_COMM_DUMP
00239   
00240 };
00241 
00242 
00256 template<typename Ordinal>
00257 RCP<MpiComm<Ordinal> >
00258 createMpiComm(
00259   const RCP<const OpaqueWrapper<MPI_Comm> > &rawMpiComm
00260   );
00261 
00262 
00263 // ////////////////////////
00264 // Implementations
00265 
00266 
00267 // Static members
00268 
00269 
00270 template<typename Ordinal>
00271 int MpiComm<Ordinal>::tagCounter_ = MpiComm<Ordinal>::minTag_;
00272 
00273 
00274 // Constructors
00275 
00276 
00277 template<typename Ordinal>
00278 MpiComm<Ordinal>::MpiComm(
00279   const RCP<const OpaqueWrapper<MPI_Comm> > &rawMpiComm
00280   )
00281 {
00282   TEST_FOR_EXCEPT( rawMpiComm.get()==NULL );
00283   TEST_FOR_EXCEPT( *rawMpiComm == MPI_COMM_NULL );
00284   rawMpiComm_ = rawMpiComm;
00285   MPI_Comm_size(*rawMpiComm_,&size_);
00286   MPI_Comm_rank(*rawMpiComm_,&rank_);
00287   if(tagCounter_ > maxTag_)
00288     tagCounter_ = minTag_;
00289   tag_ = tagCounter_++;
00290 }
00291 
00292 
00293 // Overridden from Comm
00294 
00295   
00296 template<typename Ordinal>
00297 int MpiComm<Ordinal>::getRank() const
00298 {
00299   return rank_;
00300 }
00301 
00302   
00303 template<typename Ordinal>
00304 int MpiComm<Ordinal>::getSize() const
00305 {
00306   return size_;
00307 }
00308 
00309   
00310 template<typename Ordinal>
00311 void MpiComm<Ordinal>::barrier() const
00312 {
00313   TEUCHOS_COMM_TIME_MONITOR(
00314     "Teuchos::MpiComm<"<<OrdinalTraits<Ordinal>::name()<<">::barrier()"
00315     );
00316   MPI_Barrier(*rawMpiComm_);
00317 }
00318 
00319   
00320 template<typename Ordinal>
00321 void MpiComm<Ordinal>::broadcast(
00322   const int rootRank, const Ordinal bytes, char buffer[]
00323   ) const
00324 {
00325   TEUCHOS_COMM_TIME_MONITOR(
00326     "Teuchos::MpiComm<"<<OrdinalTraits<Ordinal>::name()<<">::broadcast(...)"
00327     );
00328   MPI_Bcast(buffer,bytes,MPI_CHAR,rootRank,*rawMpiComm_);
00329 }
00330 
00331   
00332 template<typename Ordinal>
00333 void MpiComm<Ordinal>::gatherAll(
00334     const Ordinal sendBytes, const char sendBuffer[]
00335     ,const Ordinal recvBytes, char recvBuffer[]
00336   ) const
00337 {
00338   TEUCHOS_COMM_TIME_MONITOR(
00339     "Teuchos::MpiComm<"<<OrdinalTraits<Ordinal>::name()<<">::gatherAll(...)"
00340     );
00341   TEST_FOR_EXCEPT(!(sendBytes*size_==recvBytes));
00342   MPI_Allgather(
00343     const_cast<char *>(sendBuffer),sendBytes,MPI_CHAR
00344     ,recvBuffer,sendBytes,MPI_CHAR
00345     ,*rawMpiComm_
00346     );
00347 }
00348 
00349   
00350 template<typename Ordinal>
00351 void MpiComm<Ordinal>::reduceAll(
00352   const ValueTypeReductionOp<Ordinal,char> &reductOp
00353   ,const Ordinal bytes, const char sendBuffer[], char globalReducts[]
00354   ) const
00355 {
00356   TEUCHOS_COMM_TIME_MONITOR(
00357     "Teuchos::MpiComm<"<<OrdinalTraits<Ordinal>::name()<<">::reduceAll(...)"
00358     );
00359   MpiReductionOpSetter op(mpiReductionOp(rcp(&reductOp,false)));
00360   MPI_Allreduce(
00361     const_cast<char*>(sendBuffer),globalReducts,bytes,MPI_CHAR,op.mpi_op()
00362     ,*rawMpiComm_
00363     );
00364 }
00365 
00366 
00367 template<typename Ordinal>
00368 void MpiComm<Ordinal>::reduceAllAndScatter(
00369   const ValueTypeReductionOp<Ordinal,char> &reductOp
00370   ,const Ordinal sendBytes, const char sendBuffer[]
00371   ,const Ordinal recvCounts[], char myGlobalReducts[]
00372   ) const
00373 {
00374 
00375   (void)sendBytes; // Ignore if not in debug mode
00376 
00377   TEUCHOS_COMM_TIME_MONITOR(
00378     "Teuchos::MpiComm<"<<OrdinalTraits<Ordinal>::name()<<">::reduceAllAndScatter(...)"
00379     );
00380 
00381 #ifdef TEUCHOS_DEBUG
00382   Ordinal sumRecvBytes = 0;
00383   for( Ordinal i = 0; i < size_; ++i ) {
00384     sumRecvBytes += recvCounts[i];
00385   }
00386   TEST_FOR_EXCEPT(!(sumRecvBytes==sendBytes));
00387 #endif // TEUCHOS_DEBUG
00388 
00389 #ifdef TEUCHOS_MPI_COMM_DUMP
00390   if(show_dump) {
00391     dumpBuffer<Ordinal,char>(
00392       "Teuchos::MpiComm<Ordinal>::reduceAllAndScatter(...)",
00393       "sendBuffer", sendBytes, sendBuffer );
00394     dumpBuffer<Ordinal,Ordinal>(
00395       "Teuchos::MpiComm<Ordinal>::reduceAllAndScatter(...)",
00396       "recvCounts", as<Ordinal>(size_), recvCounts );
00397     dumpBuffer<Ordinal,char>(
00398       "Teuchos::MpiComm<Ordinal>::reduceAllAndScatter(...)",
00399       "myGlobalReducts", as<char>(recvCounts[rank_]), myGlobalReducts );
00400   }
00401 #endif // TEUCHOS_MPI_COMM_DUMP
00402 
00403   // Create a new recvCount[] if Ordinal!=int
00404   WorkspaceStore* wss = get_default_workspace_store().get();
00405   const bool Ordinal_is_int = typeid(int)==typeid(Ordinal);
00406   Workspace<int> ws_int_recvCounts(wss,Ordinal_is_int?0:size_);
00407   const int *int_recvCounts = 0;
00408   if(Ordinal_is_int) {
00409     int_recvCounts = reinterpret_cast<const int*>(recvCounts);
00410     // Note: We must do an reinterpet cast since this must
00411     // compile even if it is not executed.  I could implement
00412     // code that would not need to do this using template
00413     // conditionals but I don't want to bother.
00414   }
00415   else {
00416     std::copy(recvCounts, recvCounts+size_, &ws_int_recvCounts[0]);
00417     int_recvCounts = &ws_int_recvCounts[0];
00418   }
00419 
00420   // Perform the operation
00421   MpiReductionOpSetter op(mpiReductionOp(rcp(&reductOp, false)));
00422   MPI_Reduce_scatter(
00423     const_cast<char*>(sendBuffer), myGlobalReducts,
00424     const_cast<int*>(int_recvCounts),
00425     MPI_CHAR,
00426     op.mpi_op(),
00427     *rawMpiComm_
00428     );
00429 
00430 }
00431 
00432 
00433 template<typename Ordinal>
00434 void MpiComm<Ordinal>::scan(
00435   const ValueTypeReductionOp<Ordinal,char> &reductOp
00436   ,const Ordinal bytes, const char sendBuffer[], char scanReducts[]
00437   ) const
00438 {
00439   TEUCHOS_COMM_TIME_MONITOR(
00440     "Teuchos::MpiComm<"<<OrdinalTraits<Ordinal>::name()<<">::scan(...)"
00441     );
00442   MpiReductionOpSetter op(mpiReductionOp(rcp(&reductOp,false)));
00443   MPI_Scan(
00444     const_cast<char*>(sendBuffer),scanReducts,bytes,MPI_CHAR,op.mpi_op()
00445     ,*rawMpiComm_
00446     );
00447 }
00448 
00449 
00450 template<typename Ordinal>
00451 void MpiComm<Ordinal>::send(
00452   const Ordinal bytes, const char sendBuffer[], const int destRank
00453   ) const
00454 {
00455   TEUCHOS_COMM_TIME_MONITOR(
00456     "Teuchos::MpiComm<"<<OrdinalTraits<Ordinal>::name()<<">::send(...)"
00457     );
00458 #ifdef TEUCHOS_DEBUG
00459   TEST_FOR_EXCEPTION(
00460     ! ( 0 <= destRank && destRank < size_ ), std::logic_error
00461     ,"Error, destRank = " << destRank << " is not < 0 or is not"
00462     " in the range [0,"<<size_-1<<"]!"
00463     );
00464 #endif // TEUCHOS_DEBUG
00465 #ifdef TEUCHOS_MPI_COMM_DUMP
00466   if(show_dump) {
00467     dumpBuffer<Ordinal,char>(
00468       "Teuchos::MpiComm<Ordinal>::send(...)"
00469       ,"sendBuffer", bytes, sendBuffer
00470       );
00471   }
00472 #endif // TEUCHOS_MPI_COMM_DUMP
00473   MPI_Send(
00474     const_cast<char*>(sendBuffer),bytes,MPI_CHAR,destRank,tag_,*rawMpiComm_
00475     );
00476   // ToDo: What about error handling???
00477 }
00478 
00479 
00480 template<typename Ordinal>
00481 void MpiComm<Ordinal>::readySend(
00482   const ArrayView<const char> &sendBuffer,
00483   const int destRank
00484   ) const
00485 {
00486   TEUCHOS_COMM_TIME_MONITOR(
00487     "Teuchos::MpiComm<"<<OrdinalTraits<Ordinal>::name()<<">::readySend(...)"
00488     );
00489 #ifdef TEUCHOS_DEBUG
00490   TEST_FOR_EXCEPTION(
00491     ! ( 0 <= destRank && destRank < size_ ), std::logic_error
00492     ,"Error, destRank = " << destRank << " is not < 0 or is not"
00493     " in the range [0,"<<size_-1<<"]!"
00494     );
00495 #endif // TEUCHOS_DEBUG
00496 #ifdef TEUCHOS_MPI_COMM_DUMP
00497   if(show_dump) {
00498     dumpBuffer<Ordinal,char>(
00499       "Teuchos::MpiComm<Ordinal>::readySend(...)"
00500       ,"sendBuffer", bytes, sendBuffer
00501       );
00502   }
00503 #endif // TEUCHOS_MPI_COMM_DUMP
00504   MPI_Rsend(
00505     const_cast<char*>(sendBuffer.getRawPtr()),sendBuffer.size(),MPI_CHAR,destRank,tag_,*rawMpiComm_
00506     );
00507   // ToDo: What about error handling???
00508 }
00509 
00510 
00511 template<typename Ordinal>
00512 int MpiComm<Ordinal>::receive(
00513     const int sourceRank, const Ordinal bytes, char recvBuffer[]
00514   ) const
00515 {
00516   TEUCHOS_COMM_TIME_MONITOR(
00517     "Teuchos::MpiComm<"<<OrdinalTraits<Ordinal>::name()<<">::receive(...)"
00518     );
00519 #ifdef TEUCHOS_DEBUG
00520   TEST_FOR_EXCEPTION(
00521     sourceRank >=0 && !(sourceRank < size_), std::logic_error
00522     ,"Error, sourceRank = " << sourceRank << " is not < 0 or is not"
00523     " in the range [0,"<<(size_-1)<<"]!"
00524     );
00525 #endif // TEUCHOS_DEBUG
00526   MPI_Status status;
00527   MPI_Recv(
00528     recvBuffer,bytes,MPI_CHAR
00529     ,sourceRank >= 0 ? sourceRank : MPI_ANY_SOURCE
00530     ,tag_,*rawMpiComm_
00531     ,&status
00532     );
00533 #ifdef TEUCHOS_MPI_COMM_DUMP
00534   if(show_dump) {
00535     dumpBuffer<Ordinal,char>(
00536       "Teuchos::MpiComm<Ordinal>::receive(...)"
00537       ,"recvBuffer", bytes, recvBuffer
00538       );
00539   }
00540 #endif // TEUCHOS_MPI_COMM_DUMP
00541   return status.MPI_SOURCE;
00542   // ToDo: What about error handling???
00543 }
00544 
00545 
00546 template<typename Ordinal>
00547 RCP<CommRequest> MpiComm<Ordinal>::isend(
00548   const ArrayView<const char> &sendBuffer,
00549   const int destRank
00550   ) const
00551 {
00552   TEUCHOS_COMM_TIME_MONITOR(
00553     "Teuchos::MpiComm<"<<OrdinalTraits<Ordinal>::name()<<">::isend(...)"
00554     );
00555 #ifdef TEUCHOS_DEBUG
00556   assertRank(destRank, "destRank");
00557 #endif // TEUCHOS_DEBUG
00558   MPI_Request rawMpiRequest = MPI_REQUEST_NULL;
00559   MPI_Isend(
00560     const_cast<char*>(sendBuffer.getRawPtr()), sendBuffer.size(), MPI_CHAR, destRank,
00561     tag_, *rawMpiComm_, &rawMpiRequest );
00562   return mpiCommRequest(rawMpiRequest);
00563   // ToDo: What about MPI error handling???
00564 }
00565 
00566 
00567 template<typename Ordinal>
00568 RCP<CommRequest> MpiComm<Ordinal>::ireceive(
00569   const ArrayView<char> &recvBuffer,
00570   const int sourceRank
00571   ) const
00572 {
00573   TEUCHOS_COMM_TIME_MONITOR(
00574     "Teuchos::MpiComm<"<<OrdinalTraits<Ordinal>::name()<<">::ireceive(...)"
00575     );
00576 #ifdef TEUCHOS_DEBUG
00577   assertRank(sourceRank, "sourceRank");
00578 #endif // TEUCHOS_DEBUG
00579   MPI_Request rawMpiRequest = MPI_REQUEST_NULL;
00580   MPI_Irecv(
00581     const_cast<char*>(recvBuffer.getRawPtr()), recvBuffer.size(), MPI_CHAR, sourceRank,
00582     tag_, *rawMpiComm_, &rawMpiRequest );
00583   return mpiCommRequest(rawMpiRequest);
00584   // ToDo: What about MPI error handling???
00585 }
00586 
00587 
00588 template<typename Ordinal>
00589 void MpiComm<Ordinal>::waitAll(
00590   const ArrayView<RCP<CommRequest> > &requests
00591   ) const
00592 {
00593   TEUCHOS_COMM_TIME_MONITOR(
00594     "Teuchos::MpiComm<"<<OrdinalTraits<Ordinal>::name()<<">::waitAll(...)"
00595     );
00596   const int count = requests.size();
00597 #ifdef TEUCHOS_DEBUG
00598   TEST_FOR_EXCEPT( requests.size() == 0 );
00599 #endif
00600   
00601   Array<MPI_Request> rawMpiRequests(count, MPI_REQUEST_NULL);
00602   for (int i = 0; i < count; ++i) {
00603     RCP<CommRequest> &request = requests[i];
00604     if (!is_null(request)) {
00605       const RCP<MpiCommRequest> mpiCommRequest =
00606         rcp_dynamic_cast<MpiCommRequest>(request);
00607       rawMpiRequests[i] = mpiCommRequest->releaseRawMpiRequest();
00608     }
00609     // else already null
00610     request = null;
00611   }
00612 
00613   Array<MPI_Status> rawMpiStatuses(count);
00614   MPI_Waitall( count, rawMpiRequests.getRawPtr(), rawMpiStatuses.getRawPtr() );
00615   // ToDo: We really should check the status?
00616 
00617 }
00618 
00619 
00620 template<typename Ordinal>
00621 void MpiComm<Ordinal>::wait(
00622   const Ptr<RCP<CommRequest> > &request
00623   ) const
00624 {
00625   TEUCHOS_COMM_TIME_MONITOR(
00626     "Teuchos::MpiComm<"<<OrdinalTraits<Ordinal>::name()<<">::wait(...)"
00627     );
00628   if (is_null(*request)) {
00629     return; // Nothing to wait on ...
00630   }
00631   const RCP<MpiCommRequest> mpiCommRequest =
00632     rcp_dynamic_cast<MpiCommRequest>(*request);
00633   MPI_Request rawMpiRequest = mpiCommRequest->releaseRawMpiRequest();
00634   MPI_Status status;
00635   MPI_Wait( &rawMpiRequest, &status );
00636   // ToDo: We really should check the status?
00637   *request = null;
00638 }
00639 
00640 
00641 // Overridden from Describable
00642 
00643 
00644 template<typename Ordinal>
00645 std::string MpiComm<Ordinal>::description() const
00646 {
00647   std::ostringstream oss;
00648   oss
00649     << typeName(*this)
00650     << "{"
00651     << "size="<<size_
00652     << ",rank="<<rank_
00653     << ",rawMpiComm="<<static_cast<MPI_Comm>(*rawMpiComm_)
00654     <<"}";
00655   return oss.str();
00656 }
00657 
00658 
00659 #ifdef TEUCHOS_MPI_COMM_DUMP
00660 template<typename Ordinal>
00661 bool MpiComm<Ordinal>::show_dump = false;
00662 #endif
00663 
00664 
00665 // private
00666 
00667 
00668 template<typename Ordinal>
00669 void MpiComm<Ordinal>::assertRank(const int rank, const std::string &rankName) const
00670 {
00671   TEST_FOR_EXCEPTION(
00672     ! ( 0 <= rank && rank < size_ ), std::logic_error
00673     ,"Error, "<<rankName<<" = " << rank << " is not < 0 or is not"
00674     " in the range [0,"<<size_-1<<"]!"
00675     );
00676 }
00677 
00678 
00679 } // namespace Teuchos
00680 
00681 
00682 template<typename Ordinal>
00683 Teuchos::RCP<Teuchos::MpiComm<Ordinal> >
00684 Teuchos::createMpiComm(
00685   const RCP<const OpaqueWrapper<MPI_Comm> > &rawMpiComm
00686   )
00687 {
00688   if( rawMpiComm.get()!=NULL && *rawMpiComm != MPI_COMM_NULL )
00689     return rcp(new MpiComm<Ordinal>(rawMpiComm));
00690   return Teuchos::null;
00691 }
00692 
00693 
00694 #endif // TEUCHOS_MPI_COMM_HPP
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines

Generated on Tue Oct 20 10:13:59 2009 for Teuchos Package Browser (Single Doxygen Collection) by  doxygen 1.6.1