Zoltan2 Version of the Day
Zoltan2_Problem.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_PROBLEM_HPP_
00051 #define _ZOLTAN2_PROBLEM_HPP_
00052 
00053 #include <Zoltan2_Standards.hpp>
00054 #include <Zoltan2_GraphModel.hpp>
00055 #include <Zoltan2_IdentifierModel.hpp>
00056 #include <Zoltan2_CoordinateModel.hpp>
00057 #include <Zoltan2_TimerManager.hpp>
00058 
00059 using std::cout;
00060 using std::endl;
00061 
00062 namespace Zoltan2{
00063 
00067      
00068 template<typename Adapter>
00069 class Problem {
00070 public:
00071   
00072 #ifdef HAVE_ZOLTAN2_MPI
00073 
00075   Problem(Adapter *, ParameterList *params, MPI_Comm comm);
00076 #endif
00077 
00080   Problem(Adapter *, ParameterList *params);
00081 
00084   virtual ~Problem() {};
00085 
00088   void resetParameters(ParameterList *params);
00089 
00092   virtual void solve(bool updateInputData) = 0;
00093 
00107 #ifdef Z2_OMIT_ALL_ERROR_CHECKING
00108   void printTimers() const {return;}
00109 #else
00110   void printTimers() const
00111   {
00112     if (!timer_.is_null())
00113       timer_->printAndResetToZero();
00114   }
00115 #endif
00116 
00117 
00118 protected:
00119 
00120   // The Problem is templated on the input adapter.  We interact
00121   // with the input adapter through the base class interface.  
00122   // The Model objects are also templated on the input adapter and 
00123   // are explicitly instantiated for each base input type (vector, 
00124   // graph, matrix, mesh, identifier list, and coordinate list).
00125 
00126   typedef typename Adapter::base_adapter_t base_adapter_t;
00127 
00128   Adapter* inputAdapter_;
00129   base_adapter_t *baseInputAdapter_;
00130 
00131   RCP<GraphModel<base_adapter_t> > graphModel_;  
00132   RCP<IdentifierModel<base_adapter_t> > identifierModel_;  
00133   RCP<CoordinateModel<base_adapter_t> > coordinateModel_;  
00134 
00135   // Algorithms are passed a base model class, and query
00136   // the model through the base class interface (graph, hypergraph,
00137   // identifiers, or coordinates).
00138 
00139   RCP<const Model<base_adapter_t> > baseModel_;  
00140 
00141   RCP<ParameterList> params_;
00142   RCP<const Comm<int> > comm_;
00143 
00144   // The Problem has a non const Environment object.  This is because
00145   //   the Problem creates the Environment and may update it before
00146   //   finally calling the algorithm.
00147 
00148   RCP<Environment> env_;
00149 
00150   // The Problem needs a const version of the Environment.  No other
00151   //    methods are permitted to change the Environment.
00152 
00153   RCP<const Environment> envConst_;
00154 
00155   // If the user requested timing, this is the TimerManager.
00156 
00157   RCP<TimerManager> timer_;
00158 
00159 private:
00160   void setupProblemEnvironment(ParameterList *pl);
00161 
00162 };
00163 
00164 #ifdef HAVE_ZOLTAN2_MPI
00165 
00166 template <typename Adapter>
00167   Problem<Adapter>::Problem( Adapter *input, ParameterList *params,
00168     MPI_Comm comm) : inputAdapter_(input), baseInputAdapter_(),
00169       graphModel_(), identifierModel_(), baseModel_(),
00170       params_(), comm_(), env_(), envConst_(), timer_()
00171 {
00172   HELLO;
00173   RCP<Teuchos::OpaqueWrapper<MPI_Comm> > wrapper = 
00174     Teuchos::opaqueWrapper(comm);
00175   comm_ = rcp<const Comm<int> >(new Teuchos::MpiComm<int>(wrapper));
00176   setupProblemEnvironment(params);
00177 }
00178 #endif
00179 
00180 template <typename Adapter>
00181   Problem<Adapter>::Problem( Adapter *input, ParameterList *params):
00182     inputAdapter_(input), 
00183     baseInputAdapter_(dynamic_cast<base_adapter_t *>(input)),
00184     graphModel_(), identifierModel_(), baseModel_(),
00185     params_(), comm_(), env_(), envConst_(), timer_()
00186 {
00187   HELLO;
00188   comm_ = DefaultComm<int>::getComm();
00189   setupProblemEnvironment(params);
00190 }
00191 
00192 template <typename Adapter>
00193   void Problem<Adapter>::setupProblemEnvironment(ParameterList *params)
00194 {
00195   baseInputAdapter_ = dynamic_cast<base_adapter_t *>(inputAdapter_);
00196 
00197   try{
00198     env_ = rcp(new Environment(*params, Teuchos::DefaultComm<int>::getComm()));
00199   }
00200   Z2_FORWARD_EXCEPTIONS
00201 
00202   envConst_ = rcp_const_cast<const Environment>(env_);
00203 
00204   ParameterList &processedParameters = env_->getParametersNonConst();
00205   params_ = rcp<ParameterList>(&processedParameters, false);
00206 
00207 #ifndef Z2_OMIT_ALL_PROFILING
00208   ParameterList pl = *params_;
00209 
00210   // Give a timer to the Environment if requested.
00211   bool haveType=false, haveStream=false, haveFile=false;
00212   int choice = MACRO_TIMERS;   // default timer type
00213 
00214   const Teuchos::ParameterEntry *pe = pl.getEntryPtr("timer_type");
00215 
00216   if (pe){
00217     choice = pe->getValue<int>(&choice);
00218     haveType = true;
00219   }
00220 
00221   TimerType tt = static_cast<TimerType>(choice);
00222 
00223   string fname;
00224   pe = pl.getEntryPtr("timer_output_file");
00225   if (pe){
00226     haveFile = true;
00227     fname = pe->getValue<string>(&fname);
00228     std::ofstream *dbgFile = new std::ofstream;
00229     if (comm_->getRank()==0){
00230       // Using Teuchos::TimeMonitor, node 0 prints global timing info.
00231       try{
00232         dbgFile->open(fname.c_str(), std::ios::out|std::ios::trunc);
00233       }
00234       catch(std::exception &e){
00235         throw std::runtime_error(e.what());
00236       }
00237     }
00238     timer_ = rcp(new TimerManager(comm_, dbgFile, tt));
00239   }
00240   else{
00241     choice = COUT_STREAM;  // default output stream
00242     pe = pl.getEntryPtr("timer_output_stream");
00243     if (pe){
00244       choice = pe->getValue<int>(&choice);
00245       haveStream = true;
00246     }
00247 
00248     OSType outputStream = static_cast<OSType>(choice);
00249 
00250     if (haveStream || haveType){
00251       if (outputStream == COUT_STREAM)
00252         timer_ = rcp(new TimerManager(comm_, &cout, tt));
00253       else if (outputStream == CERR_STREAM)
00254         timer_ = rcp(new TimerManager(comm_, &cerr, tt));
00255       else if (outputStream == NULL_STREAM){
00256         std::ofstream *of = NULL;
00257         timer_ = rcp(new TimerManager(comm_, of, tt));
00258       }
00259     }
00260   }
00261 
00262   if (haveType || haveStream || haveFile)
00263     env_->setTimer(timer_);
00264   
00265 #endif
00266 
00267 }
00268 
00269 template <typename Adapter>
00270   void Problem<Adapter>::resetParameters(ParameterList *params)
00271 {
00272   env_ = rcp(new Environment(*params, Teuchos::DefaultComm<int>::getComm()));
00273   envConst_ = rcp_const_cast<const Environment>(env_);
00274 
00275   ParameterList &processedParameters = env_->getParametersNonConst();
00276   params_ = rcp<ParameterList>(&processedParameters, false);
00277 
00278   // We assume the timing output parameters have not changed,
00279   // and carry on with the same timer.
00280 
00281   if (!timer_.is_null())
00282     env_->setTimer(timer_);
00283 }
00284 
00285 } // namespace Zoltan2
00286 
00287 #endif