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