Zoltan 2 Version 0.5
Zoltan2_Environment.hpp
Go to the documentation of this file.
00001 // @HEADER
00002 //
00003 // ***********************************************************************
00004 //
00005 //   Zoltan2: A package of combinatorial algorithms for scientific computing
00006 //                  Copyright 2012 Sandia Corporation
00007 //
00008 // Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
00009 // the U.S. Government retains certain rights in this software.
00010 //
00011 // Redistribution and use in source and binary forms, with or without
00012 // modification, are permitted provided that the following conditions are
00013 // met:
00014 //
00015 // 1. Redistributions of source code must retain the above copyright
00016 // notice, this list of conditions and the following disclaimer.
00017 //
00018 // 2. Redistributions in binary form must reproduce the above copyright
00019 // notice, this list of conditions and the following disclaimer in the
00020 // documentation and/or other materials provided with the distribution.
00021 //
00022 // 3. Neither the name of the Corporation nor the names of the
00023 // contributors may be used to endorse or promote products derived from
00024 // this software without specific prior written permission.
00025 //
00026 // THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
00027 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00028 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
00029 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
00030 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
00031 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
00032 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
00033 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
00034 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
00035 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
00036 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00037 //
00038 // Questions? Contact Karen Devine      (kddevin@sandia.gov)
00039 //                    Erik Boman        (egboman@sandia.gov)
00040 //                    Siva Rajamanickam (srajama@sandia.gov)
00041 //
00042 // ***********************************************************************
00043 //
00044 // @HEADER
00045 
00050 #ifndef _ZOLTAN2_ENVIRONMENT_HPP_
00051 #define _ZOLTAN2_ENVIRONMENT_HPP_
00052 
00053 #include <Zoltan2_config.h>
00054 #include <Zoltan2_Util.hpp>
00055 #include <Zoltan2_IO.hpp>
00056 #include <Zoltan2_Parameters.hpp>
00057 #include <Zoltan2_DebugManager.hpp>
00058 #include <Zoltan2_TimerManager.hpp>
00059 #include <Zoltan2_MetricOutputManager.hpp>
00060 
00061 #include <Teuchos_RCP.hpp>
00062 #include <Teuchos_ParameterList.hpp>
00063 #include <Teuchos_Comm.hpp>
00064 #include <Teuchos_DefaultComm.hpp>
00065 #include <Teuchos_CommHelpers.hpp>
00066 
00067 namespace Zoltan2 {
00068 
00082 class Environment{
00083 
00084 public:
00085 
00086   typedef long   memory_t;     
00088   typedef Teuchos::RCP<const Teuchos::Comm<int> > Comm_t;
00089   typedef Teuchos::RCP<DebugManager>     DebugManager_t;
00090   typedef Teuchos::RCP<MetricOutputManager<memory_t> > MemoryProfilerManager_t;
00091   typedef Teuchos::RCP<TimerManager> Timer_t;
00092 
00093   int  myRank_;   
00095   int  numProcs_; 
00097   Comm_t comm_;   
00099   AssertionLevel errorCheckLevel_; 
00109   Environment(Teuchos::ParameterList &problemParams,
00110     const Teuchos::RCP<const Teuchos::Comm<int> > &comm );
00111 
00118   Environment();
00119 
00122   ~Environment();
00123 
00130   void setTimer(RCP<TimerManager> &timer) { timerOut_=timer; timingOn_=true;}
00131 
00132 #ifdef Z2_OMIT_ALL_ERROR_CHECKING
00133 
00134   void localInputAssertion(const char *file, int lineNum,
00135     const char *msg, bool ok, AssertionLevel level) const {}
00136 
00137   void globalInputAssertion(const char *file, int lineNum,
00138     const char *msg, bool ok, AssertionLevel level, 
00139     const Comm_t &comm=comm_) const {}
00140 
00141   void localBugAssertion(const char *file, int lineNum,
00142     const char *msg, bool ok, AssertionLevel level) const {}
00143 
00144   void globalBugAssertion(const char *file, int lineNum,
00145     const char *msg, bool ok, AssertionLevel level, 
00146     const Comm_t &comm=comm_) const {}
00147 
00148   void localMemoryAssertion(const char *file, int lineNum,
00149     size_t nobj, bool ok) const {}
00150 
00151   void globalMemoryAssertion(const char *file, int lineNum,
00152     size_t nobj, bool ok, const Comm_t &comm=comm_) const {}
00153 
00154 #else
00155 
00169   void localInputAssertion(const char *file, int lineNum,
00170     const char *msg, bool ok, AssertionLevel level) const {
00171 
00172     if (level <= errorCheckLevel_ && !ok){
00173       std::ostringstream emsg;
00174       emsg << myRank_<< ": " << file << "," << lineNum<< std::endl;
00175       if (msg)
00176         emsg << myRank_ << ": error: " << msg << std::endl;
00177       throw std::runtime_error(emsg.str()); 
00178     }
00179   }
00196   void globalInputAssertion(const char *file, int lineNum,
00197     const char *msg, bool ok, AssertionLevel level, 
00198     const Comm_t &comm) const {
00199 
00200     if (level <= errorCheckLevel_){
00201       int anyFail=0, fail = (!ok ? 1 : 0); 
00202       Teuchos::reduceAll<int,int>(*comm, Teuchos::REDUCE_MAX, 1, &fail, 
00203         &anyFail); 
00204       if (anyFail > 0){
00205         std::ostringstream emsg;
00206         emsg << myRank_<< ": " << file << "," << lineNum<< std::endl;
00207         if (msg && !ok)
00208           emsg << myRank_ << ": error: " << msg << std::endl;
00209         else
00210           emsg << myRank_ << ": exiting" << std::endl;
00211   
00212         throw std::runtime_error(emsg.str()); 
00213       }
00214     }
00215   }
00216 
00236   void localBugAssertion(const char *file, int lineNum,
00237     const char *msg, bool ok, AssertionLevel level) const {
00238 
00239     if (level <= errorCheckLevel_ && !ok){
00240       std::ostringstream emsg;
00241       emsg << myRank_<< ": " << file << "," << lineNum<< std::endl;
00242       if (msg)
00243         emsg << myRank_ << ": bug: " << msg << std::endl;
00244       throw std::logic_error(emsg.str()); 
00245     }
00246   }
00247 
00269   void globalBugAssertion(const char *file, int lineNum,
00270     const char *msg, bool ok, AssertionLevel level, 
00271    const Comm_t &comm) const {
00272 
00273     if (level <= errorCheckLevel_){
00274       int anyFail=0, fail = (!ok ? 1 : 0); 
00275       Teuchos::reduceAll<int,int>(*comm, Teuchos::REDUCE_MAX, 1, &fail, 
00276         &anyFail); 
00277       if (anyFail > 0){
00278 
00279         std::ostringstream emsg;
00280         emsg << myRank_<< ": " << file << "," << lineNum<< std::endl;
00281         if (msg && !ok)
00282           emsg << myRank_ << ": bug: " << msg << std::endl;
00283         else
00284           emsg << myRank_ << ": exiting" << std::endl;
00285   
00286         throw std::logic_error(emsg.str()); 
00287       }
00288     }
00289   }
00290 
00304   void localMemoryAssertion(const char *file, int lineNum, size_t nobj, 
00305     bool ok) const {
00306 
00307    if (!ok){ 
00308      std::cerr << myRank_ << ": " << file << ", " << lineNum<< std::endl;
00309      std::cerr << myRank_ << ": " << nobj << " objects" << std::endl;
00310      throw std::bad_alloc();
00311     } 
00312   }
00313 
00329   void globalMemoryAssertion(const char *file, int lineNum,
00330     size_t nobj, bool ok, const Comm_t &comm) const {
00331 
00332     int anyFail=0, fail = (!ok ? 1 : 0); 
00333     Teuchos::reduceAll<int,int>(*comm, Teuchos::REDUCE_MAX, 1, &fail, &anyFail); 
00334     if (anyFail > 0){
00335       std::cerr << myRank_ << ": " << file << ", " << lineNum<< std::endl;
00336       if (!ok)
00337         std::cerr << myRank_ << ": " << nobj << " objects" << std::endl;
00338       else
00339         std::cerr << myRank_ << ": exiting" << std::endl;
00340 
00341       throw std::bad_alloc();
00342     }
00343   }
00344 #endif
00345 
00346   // For debugging and profiling output, we define "char *" versions
00347   // as well as "string" versions to avoid runtime conversion of "char *"
00348   // to "string".
00349 
00361 #ifdef Z2_OMIT_ALL_STATUS_MESSAGES
00362   void debug(MessageOutputLevel level, const char *msg) const{ return;}
00363   void debug(MessageOutputLevel level, const std::string msg) const{ return;}
00364 #else
00365   void debug(MessageOutputLevel level, const char *msg) const{ 
00366     debugOut_->print(level, msg);}
00367   void debug(MessageOutputLevel level, const std::string &msg) const{ 
00368     debugOut_->print(level, msg);}
00369 #endif
00370 
00371 #ifdef Z2_OMIT_ALL_PROFILING
00372 
00373   void timerStart(TimerType tt, const char * timerName) const  {return;}
00374   void timerStart(TimerType tt, const string &timerName) const  {return;}
00375   void timerStart(TimerType tt, const char * timerName, int, 
00376     int fieldWidth=0) const  {return;}
00377   void timerStart(TimerType tt, const string &timerName, int, 
00378     int fieldWidth=0) const  {return;}
00379 
00380   void timerStop(TimerType tt, const char * timerName) const {return;}
00381   void timerStop(TimerType tt, const string &timerName) const {return;}
00382   void timerStop(TimerType tt, const char * timerName, int, 
00383     int fieldWidth=0) const {return;}
00384   void timerStop(TimerType tt, const string &timerName, int, 
00385     int fieldWidth=0) const {return;}
00386 
00387 #else
00388 
00391   void timerStart(TimerType tt, const char *timerName) const  {
00392     if (timingOn_) timerOut_->start(tt, timerName); }
00393 
00394   void timerStart(TimerType tt, const string &timerName) const  {
00395     if (timingOn_) timerOut_->start(tt, timerName); }
00396 
00399   void timerStart(TimerType tt, const char *timerName, int num, 
00400     int fieldWidth=0) const  {
00401     if (timingOn_){
00402       ostringstream oss;
00403       oss << timerName << " ";
00404       if (fieldWidth > 0){
00405         oss.width(fieldWidth);
00406         oss.fill('0');
00407       }
00408       oss << num;
00409       timerOut_->start(tt, oss.str()); 
00410     }
00411   }
00412 
00413   void timerStart(TimerType tt, const string &timerName, int num, 
00414     int fieldWidth=0) const  {
00415     if (timingOn_){
00416       ostringstream oss;
00417       oss << timerName << " ";
00418       if (fieldWidth > 0){
00419         oss.width(fieldWidth);
00420         oss.fill('0');
00421       }
00422       oss << num;
00423       timerOut_->start(tt, oss.str()); 
00424     }
00425   }
00426 
00430   void timerStop(TimerType tt, const char *timerName) const {
00431     if (timingOn_) timerOut_->stop(tt, timerName); }
00432 
00433   void timerStop(TimerType tt, const string &timerName) const {
00434     if (timingOn_) timerOut_->stop(tt, timerName); }
00435 
00439   void timerStop(TimerType tt, const char *timerName, int num, 
00440     int fieldWidth=0) const {
00441     if (timingOn_){
00442       ostringstream oss;
00443       oss << timerName << " ";
00444       if (fieldWidth > 0){
00445         oss.width(fieldWidth);
00446         oss.fill('0');
00447       }
00448       oss << num;
00449       timerOut_->stop(tt, oss.str()); 
00450     }
00451   }
00452 
00453   void timerStop(TimerType tt, const string &timerName, int num, 
00454     int fieldWidth=0) const {
00455     if (timingOn_){
00456       ostringstream oss;
00457       oss << timerName << " ";
00458       if (fieldWidth > 0){
00459         oss.width(fieldWidth);
00460         oss.fill('0');
00461       }
00462       oss << num;
00463       timerOut_->stop(tt, oss.str()); 
00464     }
00465   }
00466   
00467 #endif
00468 
00484 #ifdef Z2_OMIT_ALL_PROFILING
00485   void memory(const char *msg) const {return;}
00486 
00487   void memory(const std::string &msg) const {return; }
00488 #else
00489   void memory(const char *msg) const
00490     {if (memoryOn_)
00491        memoryOut_->print(msg, getProcessKilobytes());}
00492 
00493   void memory(const std::string &msg) const
00494     {if (memoryOn_)
00495       memoryOut_->print(msg, getProcessKilobytes());}
00496 #endif
00497 
00502   const Teuchos::ParameterList &getParameters() const { return params_; }
00503 
00508   Teuchos::ParameterList &getParametersNonConst() { return params_; }
00509 
00513   bool doTiming() const { return timingOn_; }
00514 
00518 #ifdef Z2_OMIT_ALL_STATUS_MESSAGES
00519   bool doStatus() const { return false;}
00520   MessageOutputLevel getDebugLevel() const {return NO_STATUS;}
00521 #else
00522   bool doStatus() const { return debugOut_->getDebugLevel() > NO_STATUS;}
00523 
00524   MessageOutputLevel getDebugLevel() const {return debugOut_->getDebugLevel(); }
00525 #endif
00526 
00530   bool doMemoryProfiling() const { return memoryOn_;}
00531 
00543   const Teuchos::ParameterList &getUnvalidatedParameters() const { 
00544     return unvalidatedParams_; }
00545 
00559   static void convertStringToInt(Teuchos::ParameterList &params);
00560 
00561 private:
00562 
00565   void commitParameters();
00566 
00571   Teuchos::ParameterList unvalidatedParams_;
00572 
00581   Teuchos::ParameterList params_;
00582 
00583   DebugManager_t debugOut_;    
00585   Timer_t timerOut_;             
00586   bool timingOn_;
00587 
00588   MemoryProfilerManager_t memoryOut_;  
00589   bool memoryOn_;
00590   RCP<std::ofstream> memoryOutputFile_;
00591 };
00592 
00596 #define Z2_UNSET_STRING std::string("notSet")
00597 
00599 // Templated namespace definitions used by the class
00600 
00613 template<typename metric_t>
00614   void makeMetricOutputManager(int rank, bool iPrint, 
00615     std::string fname, int ost,
00616     Teuchos::RCP<MetricOutputManager<metric_t> > &mgr,
00617     std::string units, int fieldWidth,
00618     RCP<std::ofstream> &fptr)
00619 {
00620   typedef MetricOutputManager<metric_t> manager_t;
00621 
00622   OSType os = static_cast<OSType>(ost);
00623 
00624   bool haveFname = (fname != Z2_UNSET_STRING);
00625   bool haveStreamName = (os != NUM_OUTPUT_STREAMS);
00626 
00627   if (!haveFname && !haveStreamName){
00628     mgr = Teuchos::rcp(new manager_t(rank, iPrint, std::cout, true,
00629       units, fieldWidth));
00630     return;
00631   }
00632 
00633   if (haveFname){
00634     std::ofstream *oFile = NULL;
00635     if (iPrint){
00636       oFile = new std::ofstream;
00637       std::string newFname;
00638       addNumberToFileName(rank, fname, newFname);
00639       try{
00640         oFile->open(newFname.c_str(), std::ios::out|std::ios::trunc);
00641       }
00642       catch(std::exception &e){
00643         throw std::runtime_error(e.what());
00644       }
00645       fptr = rcp(oFile);
00646     }
00647     mgr = Teuchos::rcp(new manager_t(rank, iPrint, *oFile, true,
00648       units, fieldWidth));
00649     return;
00650   }
00651 
00652   if (os == COUT_STREAM)
00653     mgr = Teuchos::rcp(new manager_t(rank, iPrint, std::cout, true,
00654       units, fieldWidth));
00655   else if (os == CERR_STREAM)
00656     mgr = Teuchos::rcp(new manager_t(rank, iPrint, std::cerr, true,
00657       units, fieldWidth));
00658   else if (os == NULL_STREAM)
00659     mgr = Teuchos::rcp(new manager_t(rank, false, std::cout, true,
00660       units, fieldWidth));
00661   else
00662     throw std::logic_error("invalid metric output stream was not caught");
00663 }
00664 
00665 }  // namespace Zoltan2
00666 
00667 #endif