Teuchos_DefaultMpiComm.hpp

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   // These should be private but the PGI compiler requires them be public
00220 
00221   static int const minTag_ = 26000; // These came from Teuchos::MpiComm???
00222   static int const maxTag_ = 26099; // ""
00223 
00224 private:
00225 
00226   static int tagCounter_;
00227 
00228   RCP<const OpaqueWrapper<MPI_Comm> > rawMpiComm_;
00229   int rank_;
00230   int size_;
00231   int tag_;
00232 
00233   void assertRank(const int rank, const std::string &rankName) const;
00234 
00235   // Not defined and not to be called!
00236   MpiComm();
00237 
00238 #ifdef TEUCHOS_MPI_COMM_DUMP
00239 public:
00240   static bool show_dump;
00241 #endif // TEUCHOS_MPI_COMM_DUMP
00242   
00243 };
00244 
00245 
00259 template<typename Ordinal>
00260 RCP<MpiComm<Ordinal> >
00261 createMpiComm(
00262   const RCP<const OpaqueWrapper<MPI_Comm> > &rawMpiComm
00263   );
00264 
00265 
00266 // ////////////////////////
00267 // Implementations
00268 
00269 
00270 // Static members
00271 
00272 
00273 template<typename Ordinal>
00274 int MpiComm<Ordinal>::tagCounter_ = MpiComm<Ordinal>::minTag_;
00275 
00276 
00277 // Constructors
00278 
00279 
00280 template<typename Ordinal>
00281 MpiComm<Ordinal>::MpiComm(
00282   const RCP<const OpaqueWrapper<MPI_Comm> > &rawMpiComm
00283   )
00284 {
00285   TEST_FOR_EXCEPT( rawMpiComm.get()==NULL );
00286   TEST_FOR_EXCEPT( *rawMpiComm == MPI_COMM_NULL );
00287   rawMpiComm_ = rawMpiComm;
00288   MPI_Comm_size(*rawMpiComm_,&size_);
00289   MPI_Comm_rank(*rawMpiComm_,&rank_);
00290   if(tagCounter_ > maxTag_)
00291     tagCounter_ = minTag_;
00292   tag_ = tagCounter_++;
00293 }
00294 
00295 
00296 // Overridden from Comm
00297 
00298   
00299 template<typename Ordinal>
00300 int MpiComm<Ordinal>::getRank() const
00301 {
00302   return rank_;
00303 }
00304 
00305   
00306 template<typename Ordinal>
00307 int MpiComm<Ordinal>::getSize() const
00308 {
00309   return size_;
00310 }
00311 
00312   
00313 template<typename Ordinal>
00314 void MpiComm<Ordinal>::barrier() const
00315 {
00316   TEUCHOS_COMM_TIME_MONITOR(
00317     "Teuchos::MpiComm<"<<OrdinalTraits<Ordinal>::name()<<">::barrier()"
00318     );
00319   MPI_Barrier(*rawMpiComm_);
00320 }
00321 
00322   
00323 template<typename Ordinal>
00324 void MpiComm<Ordinal>::broadcast(
00325   const int rootRank, const Ordinal bytes, char buffer[]
00326   ) const
00327 {
00328   TEUCHOS_COMM_TIME_MONITOR(
00329     "Teuchos::MpiComm<"<<OrdinalTraits<Ordinal>::name()<<">::broadcast(...)"
00330     );
00331   MPI_Bcast(buffer,bytes,MPI_CHAR,rootRank,*rawMpiComm_);
00332 }
00333 
00334   
00335 template<typename Ordinal>
00336 void MpiComm<Ordinal>::gatherAll(
00337     const Ordinal sendBytes, const char sendBuffer[]
00338     ,const Ordinal recvBytes, char recvBuffer[]
00339   ) const
00340 {
00341   TEUCHOS_COMM_TIME_MONITOR(
00342     "Teuchos::MpiComm<"<<OrdinalTraits<Ordinal>::name()<<">::gatherAll(...)"
00343     );
00344   TEST_FOR_EXCEPT(!(sendBytes*size_==recvBytes));
00345   MPI_Allgather(
00346     const_cast<char *>(sendBuffer),sendBytes,MPI_CHAR
00347     ,recvBuffer,sendBytes,MPI_CHAR
00348     ,*rawMpiComm_
00349     );
00350 }
00351 
00352   
00353 template<typename Ordinal>
00354 void MpiComm<Ordinal>::reduceAll(
00355   const ValueTypeReductionOp<Ordinal,char> &reductOp
00356   ,const Ordinal bytes, const char sendBuffer[], char globalReducts[]
00357   ) const
00358 {
00359   TEUCHOS_COMM_TIME_MONITOR(
00360     "Teuchos::MpiComm<"<<OrdinalTraits<Ordinal>::name()<<">::reduceAll(...)"
00361     );
00362   MpiReductionOpSetter op(mpiReductionOp(rcp(&reductOp,false)));
00363   MPI_Allreduce(
00364     const_cast<char*>(sendBuffer),globalReducts,bytes,MPI_CHAR,op.mpi_op()
00365     ,*rawMpiComm_
00366     );
00367 }
00368 
00369 
00370 template<typename Ordinal>
00371 void MpiComm<Ordinal>::reduceAllAndScatter(
00372   const ValueTypeReductionOp<Ordinal,char> &reductOp
00373   ,const Ordinal sendBytes, const char sendBuffer[]
00374   ,const Ordinal recvCounts[], char myGlobalReducts[]
00375   ) const
00376 {
00377 
00378   (void)sendBytes; // Ignore if not in debug mode
00379 
00380   TEUCHOS_COMM_TIME_MONITOR(
00381     "Teuchos::MpiComm<"<<OrdinalTraits<Ordinal>::name()<<">::reduceAllAndScatter(...)"
00382     );
00383 
00384 #ifdef TEUCHOS_DEBUG
00385   Ordinal sumRecvBytes = 0;
00386   for( Ordinal i = 0; i < size_; ++i ) {
00387     sumRecvBytes += recvCounts[i];
00388   }
00389   TEST_FOR_EXCEPT(!(sumRecvBytes==sendBytes));
00390 #endif // TEUCHOS_DEBUG
00391 
00392 #ifdef TEUCHOS_MPI_COMM_DUMP
00393   if(show_dump) {
00394     dumpBuffer<Ordinal,char>(
00395       "Teuchos::MpiComm<Ordinal>::reduceAllAndScatter(...)",
00396       "sendBuffer", sendBytes, sendBuffer );
00397     dumpBuffer<Ordinal,Ordinal>(
00398       "Teuchos::MpiComm<Ordinal>::reduceAllAndScatter(...)",
00399       "recvCounts", as<Ordinal>(size_), recvCounts );
00400     dumpBuffer<Ordinal,char>(
00401       "Teuchos::MpiComm<Ordinal>::reduceAllAndScatter(...)",
00402       "myGlobalReducts", as<char>(recvCounts[rank_]), myGlobalReducts );
00403   }
00404 #endif // TEUCHOS_MPI_COMM_DUMP
00405 
00406   // Create a new recvCount[] if Ordinal!=int
00407   WorkspaceStore* wss = get_default_workspace_store().get();
00408   const bool Ordinal_is_int = typeid(int)==typeid(Ordinal);
00409   Workspace<int> ws_int_recvCounts(wss,Ordinal_is_int?0:size_);
00410   const int *int_recvCounts = 0;
00411   if(Ordinal_is_int) {
00412     int_recvCounts = reinterpret_cast<const int*>(recvCounts);
00413     // Note: We must do an reinterpet cast since this must
00414     // compile even if it is not executed.  I could implement
00415     // code that would not need to do this using template
00416     // conditionals but I don't want to bother.
00417   }
00418   else {
00419     std::copy(recvCounts, recvCounts+size_, &ws_int_recvCounts[0]);
00420     int_recvCounts = &ws_int_recvCounts[0];
00421   }
00422 
00423   // Perform the operation
00424   MpiReductionOpSetter op(mpiReductionOp(rcp(&reductOp, false)));
00425   MPI_Reduce_scatter(
00426     const_cast<char*>(sendBuffer), myGlobalReducts,
00427     const_cast<int*>(int_recvCounts),
00428     MPI_CHAR,
00429     op.mpi_op(),
00430     *rawMpiComm_
00431     );
00432 
00433 }
00434 
00435 
00436 template<typename Ordinal>
00437 void MpiComm<Ordinal>::scan(
00438   const ValueTypeReductionOp<Ordinal,char> &reductOp
00439   ,const Ordinal bytes, const char sendBuffer[], char scanReducts[]
00440   ) const
00441 {
00442   TEUCHOS_COMM_TIME_MONITOR(
00443     "Teuchos::MpiComm<"<<OrdinalTraits<Ordinal>::name()<<">::scan(...)"
00444     );
00445   MpiReductionOpSetter op(mpiReductionOp(rcp(&reductOp,false)));
00446   MPI_Scan(
00447     const_cast<char*>(sendBuffer),scanReducts,bytes,MPI_CHAR,op.mpi_op()
00448     ,*rawMpiComm_
00449     );
00450 }
00451 
00452 
00453 template<typename Ordinal>
00454 void MpiComm<Ordinal>::send(
00455   const Ordinal bytes, const char sendBuffer[], const int destRank
00456   ) const
00457 {
00458   TEUCHOS_COMM_TIME_MONITOR(
00459     "Teuchos::MpiComm<"<<OrdinalTraits<Ordinal>::name()<<">::send(...)"
00460     );
00461 #ifdef TEUCHOS_DEBUG
00462   TEST_FOR_EXCEPTION(
00463     ! ( 0 <= destRank && destRank < size_ ), std::logic_error
00464     ,"Error, destRank = " << destRank << " is not < 0 or is not"
00465     " in the range [0,"<<size_-1<<"]!"
00466     );
00467 #endif // TEUCHOS_DEBUG
00468 #ifdef TEUCHOS_MPI_COMM_DUMP
00469   if(show_dump) {
00470     dumpBuffer<Ordinal,char>(
00471       "Teuchos::MpiComm<Ordinal>::send(...)"
00472       ,"sendBuffer", bytes, sendBuffer
00473       );
00474   }
00475 #endif // TEUCHOS_MPI_COMM_DUMP
00476   MPI_Send(
00477     const_cast<char*>(sendBuffer),bytes,MPI_CHAR,destRank,tag_,*rawMpiComm_
00478     );
00479   // ToDo: What about error handling???
00480 }
00481 
00482 
00483 template<typename Ordinal>
00484 void MpiComm<Ordinal>::readySend(
00485   const ArrayView<const char> &sendBuffer,
00486   const int destRank
00487   ) const
00488 {
00489   TEUCHOS_COMM_TIME_MONITOR(
00490     "Teuchos::MpiComm<"<<OrdinalTraits<Ordinal>::name()<<">::readySend(...)"
00491     );
00492 #ifdef TEUCHOS_DEBUG
00493   TEST_FOR_EXCEPTION(
00494     ! ( 0 <= destRank && destRank < size_ ), std::logic_error
00495     ,"Error, destRank = " << destRank << " is not < 0 or is not"
00496     " in the range [0,"<<size_-1<<"]!"
00497     );
00498 #endif // TEUCHOS_DEBUG
00499 #ifdef TEUCHOS_MPI_COMM_DUMP
00500   if(show_dump) {
00501     dumpBuffer<Ordinal,char>(
00502       "Teuchos::MpiComm<Ordinal>::readySend(...)"
00503       ,"sendBuffer", bytes, sendBuffer
00504       );
00505   }
00506 #endif // TEUCHOS_MPI_COMM_DUMP
00507   MPI_Rsend(
00508     const_cast<char*>(sendBuffer.getRawPtr()),sendBuffer.size(),MPI_CHAR,destRank,tag_,*rawMpiComm_
00509     );
00510   // ToDo: What about error handling???
00511 }
00512 
00513 
00514 template<typename Ordinal>
00515 int MpiComm<Ordinal>::receive(
00516     const int sourceRank, const Ordinal bytes, char recvBuffer[]
00517   ) const
00518 {
00519   TEUCHOS_COMM_TIME_MONITOR(
00520     "Teuchos::MpiComm<"<<OrdinalTraits<Ordinal>::name()<<">::receive(...)"
00521     );
00522 #ifdef TEUCHOS_DEBUG
00523   TEST_FOR_EXCEPTION(
00524     sourceRank >=0 && !(sourceRank < size_), std::logic_error
00525     ,"Error, sourceRank = " << sourceRank << " is not < 0 or is not"
00526     " in the range [0,"<<(size_-1)<<"]!"
00527     );
00528 #endif // TEUCHOS_DEBUG
00529   MPI_Status status;
00530   MPI_Recv(
00531     recvBuffer,bytes,MPI_CHAR
00532     ,sourceRank >= 0 ? sourceRank : MPI_ANY_SOURCE
00533     ,tag_,*rawMpiComm_
00534     ,&status
00535     );
00536 #ifdef TEUCHOS_MPI_COMM_DUMP
00537   if(show_dump) {
00538     dumpBuffer<Ordinal,char>(
00539       "Teuchos::MpiComm<Ordinal>::receive(...)"
00540       ,"recvBuffer", bytes, recvBuffer
00541       );
00542   }
00543 #endif // TEUCHOS_MPI_COMM_DUMP
00544   return status.MPI_SOURCE;
00545   // ToDo: What about error handling???
00546 }
00547 
00548 
00549 template<typename Ordinal>
00550 RCP<CommRequest> MpiComm<Ordinal>::isend(
00551   const ArrayView<const char> &sendBuffer,
00552   const int destRank
00553   ) const
00554 {
00555   TEUCHOS_COMM_TIME_MONITOR(
00556     "Teuchos::MpiComm<"<<OrdinalTraits<Ordinal>::name()<<">::isend(...)"
00557     );
00558 #ifdef TEUCHOS_DEBUG
00559   assertRank(destRank, "destRank");
00560 #endif // TEUCHOS_DEBUG
00561   MPI_Request rawMpiRequest = MPI_REQUEST_NULL;
00562   MPI_Isend(
00563     const_cast<char*>(sendBuffer.getRawPtr()), sendBuffer.size(), MPI_CHAR, destRank,
00564     tag_, *rawMpiComm_, &rawMpiRequest );
00565   return mpiCommRequest(rawMpiRequest);
00566   // ToDo: What about MPI error handling???
00567 }
00568 
00569 
00570 template<typename Ordinal>
00571 RCP<CommRequest> MpiComm<Ordinal>::ireceive(
00572   const ArrayView<char> &recvBuffer,
00573   const int sourceRank
00574   ) const
00575 {
00576   TEUCHOS_COMM_TIME_MONITOR(
00577     "Teuchos::MpiComm<"<<OrdinalTraits<Ordinal>::name()<<">::ireceive(...)"
00578     );
00579 #ifdef TEUCHOS_DEBUG
00580   assertRank(sourceRank, "sourceRank");
00581 #endif // TEUCHOS_DEBUG
00582   MPI_Request rawMpiRequest = MPI_REQUEST_NULL;
00583   MPI_Irecv(
00584     const_cast<char*>(recvBuffer.getRawPtr()), recvBuffer.size(), MPI_CHAR, sourceRank,
00585     tag_, *rawMpiComm_, &rawMpiRequest );
00586   return mpiCommRequest(rawMpiRequest);
00587   // ToDo: What about MPI error handling???
00588 }
00589 
00590 
00591 template<typename Ordinal>
00592 void MpiComm<Ordinal>::waitAll(
00593   const ArrayView<RCP<CommRequest> > &requests
00594   ) const
00595 {
00596   TEUCHOS_COMM_TIME_MONITOR(
00597     "Teuchos::MpiComm<"<<OrdinalTraits<Ordinal>::name()<<">::waitAll(...)"
00598     );
00599   const int count = requests.size();
00600 #ifdef TEUCHOS_DEBUG
00601   TEST_FOR_EXCEPT( requests.size() == 0 );
00602 #endif
00603   
00604   Array<MPI_Request> rawMpiRequests(count, MPI_REQUEST_NULL);
00605   for (int i = 0; i < count; ++i) {
00606     RCP<CommRequest> &request = requests[i];
00607     if (!is_null(request)) {
00608       const RCP<MpiCommRequest> mpiCommRequest =
00609         rcp_dynamic_cast<MpiCommRequest>(request);
00610       rawMpiRequests[i] = mpiCommRequest->releaseRawMpiRequest();
00611     }
00612     // else already null
00613     request = null;
00614   }
00615 
00616   Array<MPI_Status> rawMpiStatuses(count);
00617   MPI_Waitall( count, rawMpiRequests.getRawPtr(), rawMpiStatuses.getRawPtr() );
00618   // ToDo: We really should check the status?
00619 
00620 }
00621 
00622 
00623 template<typename Ordinal>
00624 void MpiComm<Ordinal>::wait(
00625   const Ptr<RCP<CommRequest> > &request
00626   ) const
00627 {
00628   TEUCHOS_COMM_TIME_MONITOR(
00629     "Teuchos::MpiComm<"<<OrdinalTraits<Ordinal>::name()<<">::wait(...)"
00630     );
00631   if (is_null(*request)) {
00632     return; // Nothing to wait on ...
00633   }
00634   const RCP<MpiCommRequest> mpiCommRequest =
00635     rcp_dynamic_cast<MpiCommRequest>(*request);
00636   MPI_Request rawMpiRequest = mpiCommRequest->releaseRawMpiRequest();
00637   MPI_Status status;
00638   MPI_Wait( &rawMpiRequest, &status );
00639   // ToDo: We really should check the status?
00640   *request = null;
00641 }
00642 
00643 
00644 // Overridden from Describable
00645 
00646 
00647 template<typename Ordinal>
00648 std::string MpiComm<Ordinal>::description() const
00649 {
00650   std::ostringstream oss;
00651   oss
00652     << typeName(*this)
00653     << "{"
00654     << "size="<<size_
00655     << ",rank="<<rank_
00656     << ",rawMpiComm="<<static_cast<MPI_Comm>(*rawMpiComm_)
00657     <<"}";
00658   return oss.str();
00659 }
00660 
00661 
00662 #ifdef TEUCHOS_MPI_COMM_DUMP
00663 template<typename Ordinal>
00664 bool MpiComm<Ordinal>::show_dump = false;
00665 #endif
00666 
00667 
00668 // private
00669 
00670 
00671 template<typename Ordinal>
00672 void MpiComm<Ordinal>::assertRank(const int rank, const std::string &rankName) const
00673 {
00674   TEST_FOR_EXCEPTION(
00675     ! ( 0 <= rank && rank < size_ ), std::logic_error
00676     ,"Error, "<<rankName<<" = " << rank << " is not < 0 or is not"
00677     " in the range [0,"<<size_-1<<"]!"
00678     );
00679 }
00680 
00681 
00682 } // namespace Teuchos
00683 
00684 
00685 template<typename Ordinal>
00686 Teuchos::RCP<Teuchos::MpiComm<Ordinal> >
00687 Teuchos::createMpiComm(
00688   const RCP<const OpaqueWrapper<MPI_Comm> > &rawMpiComm
00689   )
00690 {
00691   if( rawMpiComm.get()!=NULL && *rawMpiComm != MPI_COMM_NULL )
00692     return rcp(new MpiComm<Ordinal>(rawMpiComm));
00693   return Teuchos::null;
00694 }
00695 
00696 
00697 #endif // TEUCHOS_MPI_COMM_HPP

Generated on Tue Jul 13 09:22:59 2010 for Teuchos - Trilinos Tools Package by  doxygen 1.4.7