|
Teuchos Package Browser (Single Doxygen Collection) Version of the Day
|
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
1.7.4