Zoltan2
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   inline void debug(MessageOutputLevel level, const char *msg) const{ return;}
00363   inline void debug(MessageOutputLevel level, const std::string& msg) const{
00364       return;
00365   }
00366   inline void debug(int level, const char *msg) const{ return;}
00367   inline void debug(int level, const std::string& msg) const{ return;}
00368 #else
00369   inline void debug(MessageOutputLevel level, const char *msg) const{
00370       debugOut_->print(level, msg);
00371   }
00372 
00373   inline void debug(MessageOutputLevel level, const std::string& msg) const{
00374       debugOut_->print(level, msg);
00375   }
00376 
00377   inline void debug(int level, const char *msg) const{
00378       MessageOutputLevel msg_enum = static_cast<MessageOutputLevel>(level);
00379       debugOut_->print(msg_enum, msg);
00380   }
00381 
00382   inline void debug(int level, const std::string& msg) const{
00383       MessageOutputLevel msg_enum = static_cast<MessageOutputLevel>(level);
00384       debugOut_->print(msg_enum, msg);
00385   }
00386 #endif
00387 
00388 #ifdef Z2_OMIT_ALL_PROFILING
00389 
00390   void timerStart(TimerType tt, const char * timerName) const  {return;}
00391   void timerStart(TimerType tt, const std::string &timerName) const  {return;}
00392   void timerStart(TimerType tt, const char * timerName, int, 
00393     int fieldWidth=0) const  {return;}
00394   void timerStart(TimerType tt, const std::string &timerName, int, 
00395     int fieldWidth=0) const  {return;}
00396 
00397   void timerStop(TimerType tt, const char * timerName) const {return;}
00398   void timerStop(TimerType tt, const std::string &timerName) const {return;}
00399   void timerStop(TimerType tt, const char * timerName, int, 
00400     int fieldWidth=0) const {return;}
00401   void timerStop(TimerType tt, const std::string &timerName, int, 
00402     int fieldWidth=0) const {return;}
00403 
00404 #else
00405 
00408   void timerStart(TimerType tt, const char *timerName) const  {
00409     if (timingOn_) timerOut_->start(tt, timerName); }
00410 
00411   void timerStart(TimerType tt, const std::string &timerName) const  {
00412     if (timingOn_) timerOut_->start(tt, timerName); }
00413 
00416   void timerStart(TimerType tt, const char *timerName, int num, 
00417     int fieldWidth=0) const  {
00418     if (timingOn_){
00419       std::ostringstream oss;
00420       oss << timerName << " ";
00421       if (fieldWidth > 0){
00422         oss.width(fieldWidth);
00423         oss.fill('0');
00424       }
00425       oss << num;
00426       timerOut_->start(tt, oss.str()); 
00427     }
00428   }
00429 
00430   void timerStart(TimerType tt, const std::string &timerName, int num, 
00431     int fieldWidth=0) const  {
00432     if (timingOn_){
00433       std::ostringstream oss;
00434       oss << timerName << " ";
00435       if (fieldWidth > 0){
00436         oss.width(fieldWidth);
00437         oss.fill('0');
00438       }
00439       oss << num;
00440       timerOut_->start(tt, oss.str()); 
00441     }
00442   }
00443 
00447   void timerStop(TimerType tt, const char *timerName) const {
00448     if (timingOn_) timerOut_->stop(tt, timerName); }
00449 
00450   void timerStop(TimerType tt, const std::string &timerName) const {
00451     if (timingOn_) timerOut_->stop(tt, timerName); }
00452 
00456   void timerStop(TimerType tt, const char *timerName, int num, 
00457     int fieldWidth=0) const {
00458     if (timingOn_){
00459       std::ostringstream oss;
00460       oss << timerName << " ";
00461       if (fieldWidth > 0){
00462         oss.width(fieldWidth);
00463         oss.fill('0');
00464       }
00465       oss << num;
00466       timerOut_->stop(tt, oss.str()); 
00467     }
00468   }
00469 
00470   void timerStop(TimerType tt, const std::string &timerName, int num, 
00471     int fieldWidth=0) const {
00472     if (timingOn_){
00473       std::ostringstream oss;
00474       oss << timerName << " ";
00475       if (fieldWidth > 0){
00476         oss.width(fieldWidth);
00477         oss.fill('0');
00478       }
00479       oss << num;
00480       timerOut_->stop(tt, oss.str()); 
00481     }
00482   }
00483   
00484 #endif
00485 
00501 #ifdef Z2_OMIT_ALL_PROFILING
00502   void memory(const char *msg) const {return;}
00503 
00504   void memory(const std::string &msg) const {return; }
00505 #else
00506   void memory(const char *msg) const
00507     {if (memoryOn_)
00508        memoryOut_->print(msg, getProcessKilobytes());}
00509 
00510   void memory(const std::string &msg) const
00511     {if (memoryOn_)
00512       memoryOut_->print(msg, getProcessKilobytes());}
00513 #endif
00514 
00519   const Teuchos::ParameterList &getParameters() const { return params_; }
00520 
00525   Teuchos::ParameterList &getParametersNonConst() { return params_; }
00526 
00530   bool doTiming() const { return timingOn_; }
00531 
00535 #ifdef Z2_OMIT_ALL_STATUS_MESSAGES
00536   bool doStatus() const { return false;}
00537   MessageOutputLevel getDebugLevel() const {return NO_STATUS;}
00538 #else
00539   bool doStatus() const { return debugOut_->getDebugLevel() > NO_STATUS;}
00540 
00541   MessageOutputLevel getDebugLevel() const {return debugOut_->getDebugLevel(); }
00542 #endif
00543 
00547   bool doMemoryProfiling() const { return memoryOn_;}
00548 
00560   const Teuchos::ParameterList &getUnvalidatedParameters() const { 
00561     return unvalidatedParams_; }
00562 
00576   static void convertStringToInt(Teuchos::ParameterList &params);
00577 
00578 private:
00579 
00582   void commitParameters();
00583 
00588   Teuchos::ParameterList unvalidatedParams_;
00589 
00598   Teuchos::ParameterList params_;
00599 
00600   DebugManager_t debugOut_;    
00602   Timer_t timerOut_;             
00603   bool timingOn_;
00604 
00605   MemoryProfilerManager_t memoryOut_;  
00606   bool memoryOn_;
00607   RCP<std::ofstream> memoryOutputFile_;
00608 };
00609 
00613 #define Z2_UNSET_STRING std::string("notSet")
00614 
00616 // Templated namespace definitions used by the class
00617 
00630 template<typename metric_t>
00631   void makeMetricOutputManager(int rank, bool iPrint, 
00632     std::string fname, int ost,
00633     Teuchos::RCP<MetricOutputManager<metric_t> > &mgr,
00634     std::string units, int fieldWidth,
00635     RCP<std::ofstream> &fptr)
00636 {
00637   typedef MetricOutputManager<metric_t> manager_t;
00638 
00639   OSType os = static_cast<OSType>(ost);
00640 
00641   bool haveFname = (fname != Z2_UNSET_STRING);
00642   bool haveStreamName = (os != NUM_OUTPUT_STREAMS);
00643 
00644   if (!haveFname && !haveStreamName){
00645     mgr = Teuchos::rcp(new manager_t(rank, iPrint, std::cout, true,
00646       units, fieldWidth));
00647     return;
00648   }
00649 
00650   if (haveFname){
00651     std::ofstream *oFile = NULL;
00652     if (iPrint){
00653       oFile = new std::ofstream;
00654       std::string newFname;
00655       addNumberToFileName(rank, fname, newFname);
00656       try{
00657         oFile->open(newFname.c_str(), std::ios::out|std::ios::trunc);
00658       }
00659       catch(std::exception &e){
00660         throw std::runtime_error(e.what());
00661       }
00662       fptr = rcp(oFile);
00663     }
00664     mgr = Teuchos::rcp(new manager_t(rank, iPrint, *oFile, true,
00665       units, fieldWidth));
00666     return;
00667   }
00668 
00669   if (os == COUT_STREAM)
00670     mgr = Teuchos::rcp(new manager_t(rank, iPrint, std::cout, true,
00671       units, fieldWidth));
00672   else if (os == CERR_STREAM)
00673     mgr = Teuchos::rcp(new manager_t(rank, iPrint, std::cerr, true,
00674       units, fieldWidth));
00675   else if (os == NULL_STREAM)
00676     mgr = Teuchos::rcp(new manager_t(rank, false, std::cout, true,
00677       units, fieldWidth));
00678   else
00679     throw std::logic_error("invalid metric output stream was not caught");
00680 }
00681 
00682 }  // namespace Zoltan2
00683 
00684 #endif