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