Teuchos - Trilinos Tools Package Version of the Day
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 // 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 // The header file does not at all depend on MPI routines or types,
00046 // so we can defer inclusion of mpi.h to here.  This also fixes Bug
00047 // 5631:  https://software.sandia.gov/bugzilla/show_bug.cgi?id=5631
00048 #ifdef HAVE_MPI
00049 #include "mpi.h"
00050 #endif
00051 
00052 
00053 namespace Teuchos {
00054 
00055 bool GlobalMPISession::haveMPIState_ = false;
00056 bool GlobalMPISession::mpiIsFinalized_ = false;
00057 int GlobalMPISession::rank_ = 0 ;
00058 int GlobalMPISession::nProc_ = 1 ;
00059 
00060 GlobalMPISession::GlobalMPISession( int* argc, char*** argv, std::ostream *out )
00061 {
00062   std::ostringstream oss;
00063 
00064   // Above is used to create all output before sending to *out to avoid
00065   // jumbled parallel output between processors
00066 
00067 #ifdef HAVE_MPI
00068   // initialize MPI
00069         int mpiHasBeenStarted = 0, mpierr = 0;
00070         MPI_Initialized(&mpiHasBeenStarted);
00071         TEUCHOS_TEST_FOR_EXCEPTION_PRINT(
00072     mpiHasBeenStarted, std::runtime_error
00073     ,"Error, you can only call this constructor once!"
00074     ,out
00075     );
00076 
00077   mpierr = ::MPI_Init (argc, (char ***) argv);
00078   TEUCHOS_TEST_FOR_EXCEPTION_PRINT(
00079     mpierr != 0, std::runtime_error
00080     ,"Error code=" << mpierr << " detected in GlobalMPISession::GlobalMPISession(argc,argv)"
00081     ,out
00082     );
00083 
00084   initialize(out); // Get NProc_ and rank_
00085 
00086   int nameLen;
00087         char procName[MPI_MAX_PROCESSOR_NAME];
00088   mpierr = ::MPI_Get_processor_name(procName,&nameLen);
00089   TEUCHOS_TEST_FOR_EXCEPTION_PRINT(
00090     mpierr != 0, std::runtime_error
00091     ,"Error code=" << mpierr << " detected in MPI_Get_processor_name()"
00092     ,out
00093     );
00094 
00095   oss << "Teuchos::GlobalMPISession::GlobalMPISession(): started processor with name "
00096       << procName << " and rank " << rank_ << "!" << std::endl;
00097 
00098 #else
00099   oss << "Teuchos::GlobalMPISession::GlobalMPISession(): started serial run" << std::endl;
00100 #endif
00101 #ifndef TEUCHOS_SUPPRESS_PROC_STARTUP_BANNER
00102   // See if we should suppress the startup banner
00103   bool printStartupBanner = true;
00104   const std::string suppress_option("--teuchos-suppress-startup-banner");
00105   for( int opt_i = 0; opt_i < *argc; ++opt_i ) {
00106     if( suppress_option == (*argv)[opt_i] ) {
00107       // We are suppressing the output!
00108       printStartupBanner = false;
00109       // Remove this option!
00110       // Note that (*argv)[*argc]==0 but convention so we copy it too!
00111       for( int i = opt_i; i < *argc; ++i )
00112         (*argv)[i] = (*argv)[i+1];
00113       --*argc;
00114     }
00115   }
00116   if( out && printStartupBanner )
00117     *out << oss.str() << std::flush;
00118 #endif
00119 }
00120 
00121 GlobalMPISession::~GlobalMPISession()
00122 {
00123   haveMPIState_ = false;
00124   mpiIsFinalized_ = true;
00125 #ifdef HAVE_MPI
00126   int mpierr = ::MPI_Finalize();
00127   TEUCHOS_TEST_FOR_EXCEPTION_PRINT(
00128     mpierr != 0, std::runtime_error
00129     ,"Error code=" << mpierr << " detected in MPI_Finalize()"
00130     ,&std::cerr
00131     );
00132 #endif
00133 }
00134 
00135 bool GlobalMPISession::mpiIsInitialized() {
00136   if(!haveMPIState_)
00137     initialize(&std::cerr);
00138   return haveMPIState_;
00139 }
00140 
00141 bool GlobalMPISession::mpiIsFinalized()
00142 {
00143   return mpiIsFinalized_;
00144 }
00145 
00146 int GlobalMPISession::getRank()
00147 {
00148   if(!haveMPIState_)
00149     initialize(&std::cerr);
00150   return rank_;
00151 }
00152 
00153 int GlobalMPISession::getNProc() {
00154   if(!haveMPIState_)
00155     initialize(&std::cerr);
00156   return nProc_;
00157 }
00158 
00159 // private
00160 
00161 void GlobalMPISession::initialize( std::ostream *out )
00162 {
00163 #ifdef HAVE_MPI
00164 
00165   if(mpiIsFinalized_) {
00166     // MPI has aleady been finalized so we have a serial machine again!
00167     rank_ = 0;
00168     nProc_ = 1;
00169     return;
00170   }
00171 
00172   if(haveMPIState_)
00173     return; // We already have what we need!
00174 
00175   // We don't have the state of MPI so the constructor for this class must not
00176   // have been called.  However, if MPI has been called in another way we
00177   // can still get the state of MPI_COMM_WORLD here.
00178 
00179   int mpiHasBeenStarted = 0, mpierr = 0;
00180   MPI_Initialized(&mpiHasBeenStarted);
00181 
00182   if(!mpiHasBeenStarted)
00183     return;  // We have to give up and just leave NProc_ and rank_ at the default values.
00184 
00185   // Get the state of MPI
00186 
00187   mpierr = ::MPI_Comm_rank( MPI_COMM_WORLD, &rank_ );
00188   TEUCHOS_TEST_FOR_EXCEPTION_PRINT(
00189     mpierr != 0, std::runtime_error
00190     ,"Error code=" << mpierr << " detected in MPI_Comm_rank()"
00191     ,out
00192     );
00193 
00194   mpierr = ::MPI_Comm_size( MPI_COMM_WORLD, &nProc_ );
00195   TEUCHOS_TEST_FOR_EXCEPTION_PRINT(
00196     mpierr != 0, std::runtime_error
00197     ,"Error code=" << mpierr << " detected in MPI_Comm_size()"
00198     ,out
00199     );
00200 
00201   haveMPIState_ = true;
00202   mpiIsFinalized_ = false;
00203 
00204 #endif // HAVE_MPI
00205 
00206 }
00207 
00208 } // namespace Teuchos
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines