Teuchos_GlobalMPISession.cpp

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

Generated on Wed May 12 21:24:40 2010 for Teuchos - Trilinos Tools Package by  doxygen 1.4.7