Teuchos Package Browser (Single Doxygen Collection) Version of the Day
Teuchos_GlobalMPISession.cpp
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 // Redistribution and use in source and binary forms, with or without
00011 // modification, are permitted provided that the following conditions are
00012 // met:
00013 //
00014 // 1. Redistributions of source code must retain the above copyright
00015 // notice, this list of conditions and the following disclaimer.
00016 //
00017 // 2. Redistributions in binary form must reproduce the above copyright
00018 // notice, this list of conditions and the following disclaimer in the
00019 // documentation and/or other materials provided with the distribution.
00020 //
00021 // 3. Neither the name of the Corporation nor the names of the
00022 // contributors may be used to endorse or promote products derived from
00023 // this software without specific prior written permission.
00024 //
00025 // THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
00026 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00027 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
00028 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
00029 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
00030 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
00031 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
00032 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
00033 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
00034 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
00035 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00036 //
00037 // Questions? Contact Michael A. Heroux (maherou@sandia.gov)
00038 //
00039 // ***********************************************************************
00040 // @HEADER
00041 
00042 #include "Teuchos_GlobalMPISession.hpp"
00043 #include "Teuchos_Assert.hpp"
00044 
00045 namespace Teuchos {
00046 
00047 bool GlobalMPISession::haveMPIState_ = false;
00048 bool GlobalMPISession::mpiIsFinalized_ = false;
00049 int GlobalMPISession::rank_ = 0 ;
00050 int GlobalMPISession::nProc_ = 1 ;
00051 
00052 GlobalMPISession::GlobalMPISession( int* argc, char*** argv, std::ostream *out )
00053 {
00054   std::ostringstream oss;
00055 
00056   // Above is used to create all output before sending to *out to avoid
00057   // jumbled parallel output between processors
00058 
00059 #ifdef HAVE_MPI
00060   // initialize MPI
00061   int mpiHasBeenStarted = 0, mpierr = 0;
00062   MPI_Initialized(&mpiHasBeenStarted);
00063   TEUCHOS_TEST_FOR_EXCEPTION_PRINT(
00064     mpiHasBeenStarted, std::runtime_error
00065     ,"Error, you can only call this constructor once!"
00066     ,out
00067     );
00068 
00069   mpierr = ::MPI_Init (argc, (char ***) argv);
00070   TEUCHOS_TEST_FOR_EXCEPTION_PRINT(
00071     mpierr != 0, std::runtime_error
00072     ,"Error code=" << mpierr << " detected in GlobalMPISession::GlobalMPISession(argc,argv)"
00073     ,out
00074     );
00075 
00076   initialize(out); // Get NProc_ and rank_
00077   
00078   int nameLen;
00079   char procName[MPI_MAX_PROCESSOR_NAME];
00080   mpierr = ::MPI_Get_processor_name(procName,&nameLen);
00081   TEUCHOS_TEST_FOR_EXCEPTION_PRINT(
00082     mpierr != 0, std::runtime_error
00083     ,"Error code=" << mpierr << " detected in MPI_Get_processor_name()"
00084     ,out
00085     );
00086 
00087   oss << "Teuchos::GlobalMPISession::GlobalMPISession(): started processor with name "
00088       << procName << " and rank " << rank_ << "!" << std::endl;
00089 
00090 #else
00091   oss << "Teuchos::GlobalMPISession::GlobalMPISession(): started serial run" << std::endl;
00092 #endif
00093 #ifndef TEUCHOS_SUPPRESS_PROC_STARTUP_BANNER
00094   // See if we should suppress the startup banner
00095   bool printStartupBanner = true;
00096   const std::string suppress_option("--teuchos-suppress-startup-banner");
00097   for( int opt_i = 0; opt_i < *argc; ++opt_i ) { 
00098     if( suppress_option == (*argv)[opt_i] ) {
00099       // We are suppressing the output!
00100       printStartupBanner = false;
00101       // Remove this option!
00102       // Note that (*argv)[*argc]==0 but convention so we copy it too!
00103       for( int i = opt_i; i < *argc; ++i )
00104         (*argv)[i] = (*argv)[i+1];
00105       --*argc;
00106     }
00107   }
00108   if( out && printStartupBanner )
00109     *out << oss.str() << std::flush;
00110 #endif
00111 }
00112 
00113 GlobalMPISession::~GlobalMPISession()
00114 {
00115   haveMPIState_ = false;
00116   mpiIsFinalized_ = true;
00117 #ifdef HAVE_MPI
00118   int mpierr = ::MPI_Finalize();
00119   TEUCHOS_TEST_FOR_EXCEPTION_PRINT(
00120     mpierr != 0, std::runtime_error
00121     ,"Error code=" << mpierr << " detected in MPI_Finalize()"
00122     ,&std::cerr
00123     );
00124 #endif
00125 }
00126 
00127 bool GlobalMPISession::mpiIsInitialized() {
00128   if(!haveMPIState_)
00129     initialize(&std::cerr);
00130   return haveMPIState_;
00131 }
00132 
00133 bool GlobalMPISession::mpiIsFinalized()
00134 {
00135   return mpiIsFinalized_;
00136 }
00137   
00138 int GlobalMPISession::getRank()
00139 {
00140   if(!haveMPIState_)
00141     initialize(&std::cerr);
00142   return rank_;
00143 }
00144 
00145 int GlobalMPISession::getNProc() {
00146   if(!haveMPIState_)
00147     initialize(&std::cerr);
00148   return nProc_;
00149 }
00150 
00151 // private
00152 
00153 void GlobalMPISession::initialize( std::ostream *out )
00154 {
00155 #ifdef HAVE_MPI
00156 
00157   if(mpiIsFinalized_) {
00158     // MPI has aleady been finalized so we have a serial machine again!
00159     rank_ = 0;
00160     nProc_ = 1;
00161     return;
00162   }
00163 
00164   if(haveMPIState_)
00165     return; // We already have what we need!
00166 
00167   // We don't have the state of MPI so the constructor for this class must not
00168   // have been called.  However, if MPI has been called in another way we
00169   // can still get the state of MPI_COMM_WORLD here.
00170 
00171   int mpiHasBeenStarted = 0, mpierr = 0;
00172   MPI_Initialized(&mpiHasBeenStarted);
00173   
00174   if(!mpiHasBeenStarted)
00175     return;  // We have to give up and just leave NProc_ and rank_ at the default values.
00176   
00177   // Get the state of MPI
00178   
00179   mpierr = ::MPI_Comm_rank( MPI_COMM_WORLD, &rank_ );
00180   TEUCHOS_TEST_FOR_EXCEPTION_PRINT(
00181     mpierr != 0, std::runtime_error
00182     ,"Error code=" << mpierr << " detected in MPI_Comm_rank()"
00183     ,out
00184     );
00185   
00186   mpierr = ::MPI_Comm_size( MPI_COMM_WORLD, &nProc_ );
00187   TEUCHOS_TEST_FOR_EXCEPTION_PRINT(
00188     mpierr != 0, std::runtime_error
00189     ,"Error code=" << mpierr << " detected in MPI_Comm_size()"
00190     ,out
00191     );
00192 
00193   haveMPIState_ = true;
00194   mpiIsFinalized_ = false;
00195 
00196 #endif // HAVE_MPI
00197   
00198 }
00199 
00200 } // namespace Teuchos
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines