|
Teuchos - Trilinos Tools Package 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 #include "Teuchos_GlobalMPISession.hpp" 00030 #include "Teuchos_TestForException.hpp" 00031 00032 namespace Teuchos { 00033 00034 bool GlobalMPISession::haveMPIState_ = false; 00035 bool GlobalMPISession::mpiIsFinalized_ = false; 00036 int GlobalMPISession::rank_ = 0 ; 00037 int GlobalMPISession::nProc_ = 1 ; 00038 00039 GlobalMPISession::GlobalMPISession( int* argc, char*** argv, std::ostream *out ) 00040 { 00041 std::ostringstream oss; 00042 00043 // Above is used to create all output before sending to *out to avoid 00044 // jumbled parallel output between processors 00045 00046 #ifdef HAVE_MPI 00047 // initialize MPI 00048 int mpiHasBeenStarted = 0, mpierr = 0; 00049 MPI_Initialized(&mpiHasBeenStarted); 00050 TEST_FOR_EXCEPTION_PRINT( 00051 mpiHasBeenStarted, std::runtime_error 00052 ,"Error, you can only call this constructor once!" 00053 ,out 00054 ); 00055 00056 mpierr = ::MPI_Init (argc, (char ***) argv); 00057 TEST_FOR_EXCEPTION_PRINT( 00058 mpierr != 0, std::runtime_error 00059 ,"Error code=" << mpierr << " detected in GlobalMPISession::GlobalMPISession(argc,argv)" 00060 ,out 00061 ); 00062 00063 initialize(out); // Get NProc_ and rank_ 00064 00065 int nameLen; 00066 char procName[MPI_MAX_PROCESSOR_NAME]; 00067 mpierr = ::MPI_Get_processor_name(procName,&nameLen); 00068 TEST_FOR_EXCEPTION_PRINT( 00069 mpierr != 0, std::runtime_error 00070 ,"Error code=" << mpierr << " detected in MPI_Get_processor_name()" 00071 ,out 00072 ); 00073 00074 oss << "Teuchos::GlobalMPISession::GlobalMPISession(): started processor with name " 00075 << procName << " and rank " << rank_ << "!" << std::endl; 00076 00077 #else 00078 oss << "Teuchos::GlobalMPISession::GlobalMPISession(): started serial run" << std::endl; 00079 #endif 00080 #ifndef TEUCHOS_SUPPRESS_PROC_STARTUP_BANNER 00081 // See if we should suppress the startup banner 00082 bool printStartupBanner = true; 00083 const std::string suppress_option("--teuchos-suppress-startup-banner"); 00084 for( int opt_i = 0; opt_i < *argc; ++opt_i ) { 00085 if( suppress_option == (*argv)[opt_i] ) { 00086 // We are suppressing the output! 00087 printStartupBanner = false; 00088 // Remove this option! 00089 // Note that (*argv)[*argc]==0 but convention so we copy it too! 00090 for( int i = opt_i; i < *argc; ++i ) 00091 (*argv)[i] = (*argv)[i+1]; 00092 --*argc; 00093 } 00094 } 00095 if( out && printStartupBanner ) 00096 *out << oss.str() << std::flush; 00097 #endif 00098 } 00099 00100 GlobalMPISession::~GlobalMPISession() 00101 { 00102 haveMPIState_ = false; 00103 mpiIsFinalized_ = true; 00104 #ifdef HAVE_MPI 00105 int mpierr = ::MPI_Finalize(); 00106 TEST_FOR_EXCEPTION_PRINT( 00107 mpierr != 0, std::runtime_error 00108 ,"Error code=" << mpierr << " detected in MPI_Finalize()" 00109 ,&std::cerr 00110 ); 00111 #endif 00112 } 00113 00114 bool GlobalMPISession::mpiIsInitialized() { 00115 if(!haveMPIState_) 00116 initialize(&std::cerr); 00117 return haveMPIState_; 00118 } 00119 00120 bool GlobalMPISession::mpiIsFinalized() 00121 { 00122 return mpiIsFinalized_; 00123 } 00124 00125 int GlobalMPISession::getRank() 00126 { 00127 if(!haveMPIState_) 00128 initialize(&std::cerr); 00129 return rank_; 00130 } 00131 00132 int GlobalMPISession::getNProc() { 00133 if(!haveMPIState_) 00134 initialize(&std::cerr); 00135 return nProc_; 00136 } 00137 00138 // private 00139 00140 void GlobalMPISession::initialize( std::ostream *out ) 00141 { 00142 #ifdef HAVE_MPI 00143 00144 if(mpiIsFinalized_) { 00145 // MPI has aleady been finalized so we have a serial machine again! 00146 rank_ = 0; 00147 nProc_ = 1; 00148 return; 00149 } 00150 00151 if(haveMPIState_) 00152 return; // We already have what we need! 00153 00154 // We don't have the state of MPI so the constructor for this class must not 00155 // have been called. However, if MPI has been called in another way we 00156 // can still get the state of MPI_COMM_WORLD here. 00157 00158 int mpiHasBeenStarted = 0, mpierr = 0; 00159 MPI_Initialized(&mpiHasBeenStarted); 00160 00161 if(!mpiHasBeenStarted) 00162 return; // We have to give up and just leave NProc_ and rank_ at the default values. 00163 00164 // Get the state of MPI 00165 00166 mpierr = ::MPI_Comm_rank( MPI_COMM_WORLD, &rank_ ); 00167 TEST_FOR_EXCEPTION_PRINT( 00168 mpierr != 0, std::runtime_error 00169 ,"Error code=" << mpierr << " detected in MPI_Comm_rank()" 00170 ,out 00171 ); 00172 00173 mpierr = ::MPI_Comm_size( MPI_COMM_WORLD, &nProc_ ); 00174 TEST_FOR_EXCEPTION_PRINT( 00175 mpierr != 0, std::runtime_error 00176 ,"Error code=" << mpierr << " detected in MPI_Comm_size()" 00177 ,out 00178 ); 00179 00180 haveMPIState_ = true; 00181 mpiIsFinalized_ = false; 00182 00183 #endif // HAVE_MPI 00184 00185 } 00186 00187 } // namespace Teuchos
1.7.4