BelosBlockCGSolMgr.hpp

Go to the documentation of this file.
00001 // @HEADER
00002 // ***********************************************************************
00003 //
00004 //                 Belos: Block Linear Solvers Package
00005 //                 Copyright (2004) Sandia Corporation
00006 //
00007 // Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive
00008 // license for use of this work by or on behalf of the U.S. Government.
00009 //
00010 // This library is free software; you can redistribute it and/or modify
00011 // it under the terms of the GNU Lesser General Public License as
00012 // published by the Free Software Foundation; either version 2.1 of the
00013 // License, or (at your option) any later version.
00014 //
00015 // This library is distributed in the hope that it will be useful, but
00016 // WITHOUT ANY WARRANTY; without even the implied warranty of
00017 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00018 // Lesser General Public License for more details.
00019 //
00020 // You should have received a copy of the GNU Lesser General Public
00021 // License along with this library; if not, write to the Free Software
00022 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
00023 // USA
00024 // Questions? Contact Michael A. Heroux (maherou@sandia.gov)
00025 //
00026 // ***********************************************************************
00027 // @HEADER
00028 
00029 #ifndef BELOS_BLOCK_CG_SOLMGR_HPP
00030 #define BELOS_BLOCK_CG_SOLMGR_HPP
00031 
00036 #include "BelosConfigDefs.hpp"
00037 #include "BelosTypes.hpp"
00038 
00039 #include "BelosLinearProblem.hpp"
00040 #include "BelosSolverManager.hpp"
00041 
00042 #include "BelosCGIter.hpp"
00043 #include "BelosBlockCGIter.hpp"
00044 #include "BelosDGKSOrthoManager.hpp"
00045 #include "BelosICGSOrthoManager.hpp"
00046 #include "BelosIMGSOrthoManager.hpp"
00047 #include "BelosStatusTestMaxIters.hpp"
00048 #include "BelosStatusTestGenResNorm.hpp"
00049 #include "BelosStatusTestCombo.hpp"
00050 #include "BelosStatusTestOutput.hpp"
00051 #include "BelosOutputManager.hpp"
00052 #include "Teuchos_BLAS.hpp"
00053 #include "Teuchos_LAPACK.hpp"
00054 #include "Teuchos_TimeMonitor.hpp"
00055 
00069 namespace Belos {
00070   
00072 
00073   
00080   class BlockCGSolMgrLinearProblemFailure : public BelosError {public:
00081     BlockCGSolMgrLinearProblemFailure(const std::string& what_arg) : BelosError(what_arg)
00082     {}};
00083   
00090   class BlockCGSolMgrOrthoFailure : public BelosError {public:
00091     BlockCGSolMgrOrthoFailure(const std::string& what_arg) : BelosError(what_arg)
00092     {}};
00093   
00094   template<class ScalarType, class MV, class OP>
00095   class BlockCGSolMgr : public SolverManager<ScalarType,MV,OP> {
00096     
00097   private:
00098     typedef MultiVecTraits<ScalarType,MV> MVT;
00099     typedef OperatorTraits<ScalarType,MV,OP> OPT;
00100     typedef Teuchos::ScalarTraits<ScalarType> SCT;
00101     typedef typename Teuchos::ScalarTraits<ScalarType>::magnitudeType MagnitudeType;
00102     typedef Teuchos::ScalarTraits<MagnitudeType> MT;
00103     
00104   public:
00105     
00107 
00108 
00114      BlockCGSolMgr();
00115 
00143     BlockCGSolMgr( const Teuchos::RCP<LinearProblem<ScalarType,MV,OP> > &problem,
00144        const Teuchos::RCP<Teuchos::ParameterList> &pl );
00145     
00147     virtual ~BlockCGSolMgr() {};
00149     
00151 
00152     
00153     const LinearProblem<ScalarType,MV,OP>& getProblem() const {
00154       return *problem_;
00155     }
00156 
00159     Teuchos::RCP<const Teuchos::ParameterList> getValidParameters() const;
00160     
00163     Teuchos::RCP<const Teuchos::ParameterList> getCurrentParameters() const { return params_; }
00164     
00170     Teuchos::Array<Teuchos::RCP<Teuchos::Time> > getTimers() const {
00171       return tuple(timerSolve_);
00172     }
00173 
00175     int getNumIters() const {
00176       return numIters_;
00177     }
00178 
00181     bool isLOADetected() const { return false; }
00182  
00184     
00186 
00187    
00189     void setProblem( const Teuchos::RCP<LinearProblem<ScalarType,MV,OP> > &problem ) { problem_ = problem; }
00190    
00192     void setParameters( const Teuchos::RCP<Teuchos::ParameterList> &params );
00193     
00195    
00197 
00198 
00202     void reset( const ResetType type ) { if ((type & Belos::Problem) && !Teuchos::is_null(problem_)) problem_->setProblem(); }
00204  
00206 
00207     
00225     ReturnType solve();
00226     
00228     
00231     
00233     std::string description() const;
00234     
00236     
00237   private:
00238 
00239     // Linear problem.
00240     Teuchos::RCP<LinearProblem<ScalarType,MV,OP> > problem_;
00241     
00242     // Output manager.
00243     Teuchos::RCP<OutputManager<ScalarType> > printer_;
00244     Teuchos::RCP<std::ostream> outputStream_;
00245 
00246     // Status test.
00247     Teuchos::RCP<StatusTest<ScalarType,MV,OP> > sTest_;
00248     Teuchos::RCP<StatusTestMaxIters<ScalarType,MV,OP> > maxIterTest_;
00249     Teuchos::RCP<StatusTestGenResNorm<ScalarType,MV,OP> > convTest_;
00250     Teuchos::RCP<StatusTestOutput<ScalarType,MV,OP> > outputTest_;
00251 
00252     // Orthogonalization manager.
00253     Teuchos::RCP<MatOrthoManager<ScalarType,MV,OP> > ortho_; 
00254     
00255     // Current parameter list.
00256     Teuchos::RCP<ParameterList> params_;
00257     
00258     // Default solver values.
00259     static const MagnitudeType convtol_default_;
00260     static const MagnitudeType orthoKappa_default_;
00261     static const int maxIters_default_;
00262     static const bool adaptiveBlockSize_default_;
00263     static const bool showMaxResNormOnly_default_;
00264     static const int blockSize_default_;
00265     static const int verbosity_default_;
00266     static const int outputFreq_default_;
00267     static const std::string label_default_;
00268     static const std::string orthoType_default_;
00269     static const Teuchos::RCP<std::ostream> outputStream_default_;
00270 
00271     // Current solver values.
00272     MagnitudeType convtol_, orthoKappa_;
00273     int maxIters_, numIters_;
00274     int blockSize_, verbosity_, outputFreq_;
00275     bool adaptiveBlockSize_, showMaxResNormOnly_;
00276     std::string orthoType_; 
00277     
00278     // Timers.
00279     std::string label_;
00280     Teuchos::RCP<Teuchos::Time> timerSolve_;
00281 
00282     // Internal state variables.
00283     bool isSet_;
00284   };
00285 
00286 
00287 // Default solver values.
00288 template<class ScalarType, class MV, class OP>
00289 const typename Teuchos::ScalarTraits<ScalarType>::magnitudeType BlockCGSolMgr<ScalarType,MV,OP>::convtol_default_ = 1e-8;
00290 
00291 template<class ScalarType, class MV, class OP>
00292 const typename Teuchos::ScalarTraits<ScalarType>::magnitudeType BlockCGSolMgr<ScalarType,MV,OP>::orthoKappa_default_ = -1.0;
00293 
00294 template<class ScalarType, class MV, class OP>
00295 const int BlockCGSolMgr<ScalarType,MV,OP>::maxIters_default_ = 1000;
00296 
00297 template<class ScalarType, class MV, class OP>
00298 const bool BlockCGSolMgr<ScalarType,MV,OP>::adaptiveBlockSize_default_ = true;
00299 
00300 template<class ScalarType, class MV, class OP>
00301 const bool BlockCGSolMgr<ScalarType,MV,OP>::showMaxResNormOnly_default_ = false;
00302 
00303 template<class ScalarType, class MV, class OP>
00304 const int BlockCGSolMgr<ScalarType,MV,OP>::blockSize_default_ = 1;
00305 
00306 template<class ScalarType, class MV, class OP>
00307 const int BlockCGSolMgr<ScalarType,MV,OP>::verbosity_default_ = Belos::Errors;
00308 
00309 template<class ScalarType, class MV, class OP>
00310 const int BlockCGSolMgr<ScalarType,MV,OP>::outputFreq_default_ = -1;
00311 
00312 template<class ScalarType, class MV, class OP>
00313 const std::string BlockCGSolMgr<ScalarType,MV,OP>::label_default_ = "Belos";
00314 
00315 template<class ScalarType, class MV, class OP>
00316 const std::string BlockCGSolMgr<ScalarType,MV,OP>::orthoType_default_ = "DGKS";
00317 
00318 template<class ScalarType, class MV, class OP>
00319 const Teuchos::RCP<std::ostream> BlockCGSolMgr<ScalarType,MV,OP>::outputStream_default_ = Teuchos::rcp(&std::cout,false);
00320 
00321 
00322 // Empty Constructor
00323 template<class ScalarType, class MV, class OP>
00324 BlockCGSolMgr<ScalarType,MV,OP>::BlockCGSolMgr() :
00325   outputStream_(outputStream_default_),
00326   convtol_(convtol_default_),
00327   orthoKappa_(orthoKappa_default_),
00328   maxIters_(maxIters_default_),
00329   blockSize_(blockSize_default_),
00330   verbosity_(verbosity_default_),
00331   outputFreq_(outputFreq_default_),
00332   adaptiveBlockSize_(adaptiveBlockSize_default_),
00333   showMaxResNormOnly_(showMaxResNormOnly_default_),
00334   orthoType_(orthoType_default_),
00335   label_(label_default_),
00336   isSet_(false)
00337 {}
00338 
00339 
00340 // Basic Constructor
00341 template<class ScalarType, class MV, class OP>
00342 BlockCGSolMgr<ScalarType,MV,OP>::BlockCGSolMgr( 
00343                  const Teuchos::RCP<LinearProblem<ScalarType,MV,OP> > &problem,
00344                  const Teuchos::RCP<Teuchos::ParameterList> &pl ) : 
00345   problem_(problem),
00346   outputStream_(outputStream_default_),
00347   convtol_(convtol_default_),
00348   orthoKappa_(orthoKappa_default_),
00349   maxIters_(maxIters_default_),
00350   blockSize_(blockSize_default_),
00351   verbosity_(verbosity_default_),
00352   outputFreq_(outputFreq_default_),
00353   adaptiveBlockSize_(adaptiveBlockSize_default_),
00354   showMaxResNormOnly_(showMaxResNormOnly_default_),
00355   orthoType_(orthoType_default_),
00356   label_(label_default_),
00357   isSet_(false)
00358 {
00359   TEST_FOR_EXCEPTION(problem_ == Teuchos::null, std::invalid_argument, "Problem not given to solver manager.");
00360 
00361   // If the parameter list pointer is null, then set the current parameters to the default parameter list.
00362   if ( !is_null(pl) ) {
00363     setParameters( pl );  
00364   }
00365 }
00366 
00367 template<class ScalarType, class MV, class OP>
00368 void BlockCGSolMgr<ScalarType,MV,OP>::setParameters( const Teuchos::RCP<Teuchos::ParameterList> &params )
00369 {
00370   // Create the internal parameter list if ones doesn't already exist.
00371   if (params_ == Teuchos::null) {
00372     params_ = Teuchos::rcp( new Teuchos::ParameterList(*getValidParameters()) );
00373   }
00374   else {
00375     params->validateParameters(*getValidParameters());
00376   }
00377 
00378   // Check for maximum number of iterations
00379   if (params->isParameter("Maximum Iterations")) {
00380     maxIters_ = params->get("Maximum Iterations",maxIters_default_);
00381 
00382     // Update parameter in our list and in status test.
00383     params_->set("Maximum Iterations", maxIters_);
00384     if (maxIterTest_!=Teuchos::null)
00385       maxIterTest_->setMaxIters( maxIters_ );
00386   }
00387 
00388   // Check for blocksize
00389   if (params->isParameter("Block Size")) {
00390     blockSize_ = params->get("Block Size",blockSize_default_);    
00391     TEST_FOR_EXCEPTION(blockSize_ <= 0, std::invalid_argument,
00392            "Belos::BlockCGSolMgr: \"Block Size\" must be strictly positive.");
00393 
00394     // Update parameter in our list.
00395     params_->set("Block Size", blockSize_);
00396   }
00397 
00398   // Check if the blocksize should be adaptive
00399   if (params->isParameter("Adapative Block Size")) {
00400     adaptiveBlockSize_ = params->get("Adaptive Block Size",adaptiveBlockSize_default_);
00401     
00402     // Update parameter in our list.
00403     params_->set("Adaptive Block Size", adaptiveBlockSize_);
00404   }
00405 
00406   // Check to see if the timer label changed.
00407   if (params->isParameter("Timer Label")) {
00408     std::string tempLabel = params->get("Timer Label", label_default_);
00409 
00410     // Update parameter in our list and solver timer
00411     if (tempLabel != label_) {
00412       label_ = tempLabel;
00413       params_->set("Timer Label", label_);
00414       std::string solveLabel = label_ + ": BlockCGSolMgr total solve time";
00415       timerSolve_ = Teuchos::TimeMonitor::getNewTimer(solveLabel);
00416     }
00417   }
00418 
00419   // Check if the orthogonalization changed.
00420   if (params->isParameter("Orthogonalization")) {
00421     std::string tempOrthoType = params->get("Orthogonalization",orthoType_default_);
00422     TEST_FOR_EXCEPTION( tempOrthoType != "DGKS" && tempOrthoType != "ICGS" && tempOrthoType != "IMGS", 
00423                         std::invalid_argument,
00424       "Belos::BlockCGSolMgr: \"Orthogonalization\" must be either \"DGKS\", \"ICGS\", or \"IMGS\".");
00425     if (tempOrthoType != orthoType_) {
00426       orthoType_ = tempOrthoType;
00427       // Create orthogonalization manager
00428       if (orthoType_=="DGKS") {
00429   if (orthoKappa_ <= 0) {
00430     ortho_ = Teuchos::rcp( new DGKSOrthoManager<ScalarType,MV,OP>( label_ ) );
00431   }
00432   else {
00433     ortho_ = Teuchos::rcp( new DGKSOrthoManager<ScalarType,MV,OP>( label_ ) );
00434     Teuchos::rcp_dynamic_cast<DGKSOrthoManager<ScalarType,MV,OP> >(ortho_)->setDepTol( orthoKappa_ );
00435   }
00436       }
00437       else if (orthoType_=="ICGS") {
00438   ortho_ = Teuchos::rcp( new ICGSOrthoManager<ScalarType,MV,OP>( label_ ) );
00439       } 
00440       else if (orthoType_=="IMGS") {
00441   ortho_ = Teuchos::rcp( new IMGSOrthoManager<ScalarType,MV,OP>( label_ ) );
00442       } 
00443     }  
00444   }
00445 
00446   // Check which orthogonalization constant to use.
00447   if (params->isParameter("Orthogonalization Constant")) {
00448     orthoKappa_ = params->get("Orthogonalization Constant",orthoKappa_default_);
00449 
00450     // Update parameter in our list.
00451     params_->set("Orthogonalization Constant",orthoKappa_);
00452     if (orthoType_=="DGKS") {
00453       if (orthoKappa_ > 0 && ortho_ != Teuchos::null) {
00454   Teuchos::rcp_dynamic_cast<DGKSOrthoManager<ScalarType,MV,OP> >(ortho_)->setDepTol( orthoKappa_ );
00455       }
00456     } 
00457   }
00458 
00459   // Check for a change in verbosity level
00460   if (params->isParameter("Verbosity")) {
00461     if (Teuchos::isParameterType<int>(*params,"Verbosity")) {
00462       verbosity_ = params->get("Verbosity", verbosity_default_);
00463     } else {
00464       verbosity_ = (int)Teuchos::getParameter<Belos::MsgType>(*params,"Verbosity");
00465     }
00466 
00467     // Update parameter in our list.
00468     params_->set("Verbosity", verbosity_);
00469     if (printer_ != Teuchos::null)
00470       printer_->setVerbosity(verbosity_);
00471   }
00472 
00473   // output stream
00474   if (params->isParameter("Output Stream")) {
00475     outputStream_ = Teuchos::getParameter<Teuchos::RCP<std::ostream> >(*params,"Output Stream");
00476 
00477     // Update parameter in our list.
00478     params_->set("Output Stream", outputStream_);
00479     if (printer_ != Teuchos::null)
00480       printer_->setOStream( outputStream_ );
00481   }
00482 
00483   // frequency level
00484   if (verbosity_ & Belos::StatusTestDetails) {
00485     if (params->isParameter("Output Frequency")) {
00486       outputFreq_ = params->get("Output Frequency", outputFreq_default_);
00487     }
00488 
00489     // Update parameter in out list and output status test.
00490     params_->set("Output Frequency", outputFreq_);
00491     if (outputTest_ != Teuchos::null)
00492       outputTest_->setOutputFrequency( outputFreq_ );
00493   }
00494 
00495   // Create output manager if we need to.
00496   if (printer_ == Teuchos::null) {
00497     printer_ = Teuchos::rcp( new OutputManager<ScalarType>(verbosity_, outputStream_) );
00498   }  
00499   
00500   // Convergence
00501   typedef Belos::StatusTestCombo<ScalarType,MV,OP>  StatusTestCombo_t;
00502   typedef Belos::StatusTestGenResNorm<ScalarType,MV,OP>  StatusTestResNorm_t;
00503 
00504   // Check for convergence tolerance
00505   if (params->isParameter("Convergence Tolerance")) {
00506     convtol_ = params->get("Convergence Tolerance",convtol_default_);
00507 
00508     // Update parameter in our list and residual tests.
00509     params_->set("Convergence Tolerance", convtol_);
00510     if (convTest_ != Teuchos::null)
00511       convTest_->setTolerance( convtol_ );
00512   }
00513   
00514   if (params->isParameter("Show Maximum Residual Norm Only")) {
00515     showMaxResNormOnly_ = Teuchos::getParameter<bool>(*params,"Show Maximum Residual Norm Only");
00516 
00517     // Update parameter in our list and residual tests
00518     params_->set("Show Maximum Residual Norm Only", showMaxResNormOnly_);
00519     if (convTest_ != Teuchos::null)
00520       convTest_->setShowMaxResNormOnly( showMaxResNormOnly_ );
00521   }
00522 
00523   // Create status tests if we need to.
00524 
00525   // Basic test checks maximum iterations and native residual.
00526   if (maxIterTest_ == Teuchos::null)
00527     maxIterTest_ = Teuchos::rcp( new StatusTestMaxIters<ScalarType,MV,OP>( maxIters_ ) );
00528   
00529   // Implicit residual test, using the native residual to determine if convergence was achieved.
00530   if (convTest_ == Teuchos::null)
00531     convTest_ = Teuchos::rcp( new StatusTestResNorm_t( convtol_, 1 ) );
00532   
00533   if (sTest_ == Teuchos::null)
00534     sTest_ = Teuchos::rcp( new StatusTestCombo_t( StatusTestCombo_t::OR, maxIterTest_, convTest_ ) );
00535   
00536   if (outputTest_ == Teuchos::null) {
00537     if (outputFreq_ > 0) {
00538       outputTest_ = Teuchos::rcp( new StatusTestOutput<ScalarType,MV,OP>( printer_, 
00539                     sTest_, 
00540                     outputFreq_, 
00541                     Passed+Failed+Undefined ) ); 
00542     }
00543     else {
00544       outputTest_ = Teuchos::rcp( new StatusTestOutput<ScalarType,MV,OP>( printer_, 
00545                     sTest_, 1 ) );
00546     }
00547   }
00548 
00549   // Create orthogonalization manager if we need to.
00550   if (ortho_ == Teuchos::null) {
00551     if (orthoType_=="DGKS") {
00552       if (orthoKappa_ <= 0) {
00553   ortho_ = Teuchos::rcp( new DGKSOrthoManager<ScalarType,MV,OP>( label_ ) );
00554       }
00555       else {
00556   ortho_ = Teuchos::rcp( new DGKSOrthoManager<ScalarType,MV,OP>( label_ ) );
00557   Teuchos::rcp_dynamic_cast<DGKSOrthoManager<ScalarType,MV,OP> >(ortho_)->setDepTol( orthoKappa_ );
00558       }
00559     }
00560     else if (orthoType_=="ICGS") {
00561       ortho_ = Teuchos::rcp( new ICGSOrthoManager<ScalarType,MV,OP>( label_ ) );
00562     } 
00563     else if (orthoType_=="IMGS") {
00564       ortho_ = Teuchos::rcp( new IMGSOrthoManager<ScalarType,MV,OP>( label_ ) );
00565     } 
00566     else {
00567       TEST_FOR_EXCEPTION(orthoType_!="ICGS"&&orthoType_!="DGKS"&&orthoType_!="IMGS",std::logic_error,
00568        "Belos::BlockCGSolMgr(): Invalid orthogonalization type.");
00569     }  
00570   }
00571 
00572   // Create the timer if we need to.
00573   if (timerSolve_ == Teuchos::null) {
00574     std::string solveLabel = label_ + ": BlockCGSolMgr total solve time";
00575     timerSolve_ = Teuchos::TimeMonitor::getNewTimer(solveLabel);
00576   }
00577 
00578   // Inform the solver manager that the current parameters were set.
00579   isSet_ = true;
00580 }
00581 
00582     
00583 template<class ScalarType, class MV, class OP>
00584 Teuchos::RCP<const Teuchos::ParameterList> 
00585 BlockCGSolMgr<ScalarType,MV,OP>::getValidParameters() const
00586 {
00587   static Teuchos::RCP<const Teuchos::ParameterList> validPL;
00588   
00589   // Set all the valid parameters and their default values.
00590   if(is_null(validPL)) {
00591     Teuchos::RCP<Teuchos::ParameterList> pl = Teuchos::parameterList();
00592     pl->set("Convergence Tolerance", convtol_default_,
00593       "The relative residual tolerance that needs to be achieved by the\n"
00594       "iterative solver in order for the linear system to be declared converged.");
00595     pl->set("Maximum Iterations", maxIters_default_,
00596       "The maximum number of block iterations allowed for each\n"
00597       "set of RHS solved.");
00598     pl->set("Block Size", blockSize_default_,
00599       "The number of vectors in each block.");
00600     pl->set("Adaptive Block Size", adaptiveBlockSize_default_,
00601       "Whether the solver manager should adapt to the block size\n"
00602       "based on the number of RHS to solve.");
00603     pl->set("Verbosity", verbosity_default_,
00604       "What type(s) of solver information should be outputted\n"
00605       "to the output stream.");
00606     pl->set("Output Frequency", outputFreq_default_,
00607       "How often convergence information should be outputted\n"
00608       "to the output stream.");  
00609     pl->set("Output Stream", outputStream_default_,
00610       "A reference-counted pointer to the output stream where all\n"
00611       "solver output is sent.");
00612     pl->set("Show Maximum Residual Norm Only", showMaxResNormOnly_default_,
00613       "When convergence information is printed, only show the maximum\n"
00614       "relative residual norm when the block size is greater than one.");
00615     pl->set("Timer Label", label_default_,
00616       "The string to use as a prefix for the timer labels.");
00617     //  pl->set("Restart Timers", restartTimers_);
00618     pl->set("Orthogonalization", orthoType_default_,
00619       "The type of orthogonalization to use: DGKS, ICGS, or IMGS.");
00620     pl->set("Orthogonalization Constant",orthoKappa_default_,
00621       "The constant used by DGKS orthogonalization to determine\n"
00622       "whether another step of classical Gram-Schmidt is necessary.");
00623     validPL = pl;
00624   }
00625   return validPL;
00626 }
00627 
00628   
00629 // solve()
00630 template<class ScalarType, class MV, class OP>
00631 ReturnType BlockCGSolMgr<ScalarType,MV,OP>::solve() {
00632 
00633   // Set the current parameters if they were not set before.
00634   // NOTE:  This may occur if the user generated the solver manager with the default constructor and 
00635   // then didn't set any parameters using setParameters().
00636   if (!isSet_) {
00637     setParameters(Teuchos::parameterList(*getValidParameters()));
00638   }
00639 
00640   Teuchos::BLAS<int,ScalarType> blas;
00641   Teuchos::LAPACK<int,ScalarType> lapack;
00642   
00643   TEST_FOR_EXCEPTION(!problem_->isProblemSet(),BlockCGSolMgrLinearProblemFailure,
00644                      "Belos::BlockCGSolMgr::solve(): Linear problem is not ready, setProblem() has not been called.");
00645 
00646   // Create indices for the linear systems to be solved.
00647   int startPtr = 0;
00648   int numRHS2Solve = MVT::GetNumberVecs( *(problem_->getRHS()) );
00649   int numCurrRHS = ( numRHS2Solve < blockSize_) ? numRHS2Solve : blockSize_;
00650 
00651   std::vector<int> currIdx, currIdx2;
00652   //  If an adaptive block size is allowed then only the linear systems that need to be solved are solved.
00653   //  Otherwise, the index set is generated that informs the linear problem that some linear systems are augmented.
00654   if ( adaptiveBlockSize_ ) {
00655     blockSize_ = numCurrRHS;
00656     currIdx.resize( numCurrRHS  );
00657     currIdx2.resize( numCurrRHS  );
00658     for (int i=0; i<numCurrRHS; ++i) 
00659       { currIdx[i] = startPtr+i; currIdx2[i]=i; }
00660     
00661   }
00662   else {
00663     currIdx.resize( blockSize_ );
00664     currIdx2.resize( blockSize_ );
00665     for (int i=0; i<numCurrRHS; ++i) 
00666       { currIdx[i] = startPtr+i; currIdx2[i]=i; }
00667     for (int i=numCurrRHS; i<blockSize_; ++i) 
00668       { currIdx[i] = -1; currIdx2[i] = i; }
00669   }
00670 
00671   // Inform the linear problem of the current linear system to solve.
00672   problem_->setLSIndex( currIdx );
00673 
00675   // Parameter list
00676   Teuchos::ParameterList plist;
00677   plist.set("Block Size",blockSize_);
00678   
00679   // Reset the status test.  
00680   outputTest_->reset();
00681 
00682   // Assume convergence is achieved, then let any failed convergence set this to false.
00683   bool isConverged = true;  
00684 
00686   // BlockCG solver
00687 
00688   Teuchos::RCP<CGIteration<ScalarType,MV,OP> > block_cg_iter;
00689   if (blockSize_ == 1)
00690     block_cg_iter = Teuchos::rcp( new CGIter<ScalarType,MV,OP>(problem_,printer_,outputTest_,plist) );
00691   else
00692     block_cg_iter = Teuchos::rcp( new BlockCGIter<ScalarType,MV,OP>(problem_,printer_,outputTest_,ortho_,plist) );
00693   
00694 
00695   // Enter solve() iterations
00696   {
00697     Teuchos::TimeMonitor slvtimer(*timerSolve_);
00698 
00699     while ( numRHS2Solve > 0 ) {
00700       //
00701       // Reset the active / converged vectors from this block
00702       std::vector<int> convRHSIdx;
00703       std::vector<int> currRHSIdx( currIdx );
00704       currRHSIdx.resize(numCurrRHS);
00705 
00706       // Reset the number of iterations.
00707       block_cg_iter->resetNumIters();
00708 
00709       // Reset the number of calls that the status test output knows about.
00710       outputTest_->resetNumCalls();
00711 
00712       // Get the current residual for this block of linear systems.
00713       Teuchos::RCP<MV> R_0 = MVT::CloneView( *(Teuchos::rcp_const_cast<MV>(problem_->getInitResVec())), currIdx );
00714 
00715       // Set the new state and initialize the solver.
00716       CGIterationState<ScalarType,MV> newstate;
00717       newstate.R = R_0;
00718       block_cg_iter->initializeCG(newstate);
00719 
00720       while(1) {
00721   
00722   // tell block_cg_iter to iterate
00723   try {
00724     block_cg_iter->iterate();
00725     
00727     //
00728     // check convergence first
00729     //
00731     if ( convTest_->getStatus() == Passed ) {
00732       // We have convergence of at least one linear system.
00733 
00734       // Figure out which linear systems converged.
00735       std::vector<int> convIdx = Teuchos::rcp_dynamic_cast<StatusTestGenResNorm<ScalarType,MV,OP> >(convTest_)->convIndices();
00736 
00737       // If the number of converged linear systems is equal to the
00738             // number of current linear systems, then we are done with this block.
00739       if (convIdx.size() == currRHSIdx.size())
00740         break;  // break from while(1){block_cg_iter->iterate()}
00741 
00742       // Inform the linear problem that we are finished with this current linear system.
00743       problem_->setCurrLS();
00744 
00745       // Reset currRHSIdx to have the right-hand sides that are left to converge for this block.
00746       int have = 0;
00747             std::vector<int> unconvIdx(currRHSIdx.size());
00748       for (unsigned int i=0; i<currRHSIdx.size(); ++i) {
00749         bool found = false;
00750         for (unsigned int j=0; j<convIdx.size(); ++j) {
00751     if (currRHSIdx[i] == convIdx[j]) {
00752       found = true;
00753       break;
00754     }
00755         }
00756         if (!found) {
00757                 currIdx2[have] = currIdx2[i];
00758     currRHSIdx[have++] = currRHSIdx[i];
00759         }
00760               else {
00761               } 
00762       }
00763       currRHSIdx.resize(have);
00764       currIdx2.resize(have);
00765 
00766       // Set the remaining indices after deflation.
00767       problem_->setLSIndex( currRHSIdx );
00768 
00769       // Get the current residual vector.
00770       std::vector<MagnitudeType> norms;
00771             R_0 = MVT::CloneCopy( *(block_cg_iter->getNativeResiduals(&norms)),currIdx2 );
00772       for (int i=0; i<have; ++i) { currIdx2[i] = i; }
00773 
00774       // Set the new blocksize for the solver.
00775       block_cg_iter->setBlockSize( have );
00776 
00777       // Set the new state and initialize the solver.
00778       CGIterationState<ScalarType,MV> defstate;
00779       defstate.R = R_0;
00780       block_cg_iter->initializeCG(defstate);
00781     }
00783     //
00784     // check for maximum iterations
00785     //
00787     else if ( maxIterTest_->getStatus() == Passed ) {
00788       // we don't have convergence
00789       isConverged = false;
00790       break;  // break from while(1){block_cg_iter->iterate()}
00791     }
00792 
00794     //
00795     // we returned from iterate(), but none of our status tests Passed.
00796     // something is wrong, and it is probably our fault.
00797     //
00799 
00800     else {
00801       TEST_FOR_EXCEPTION(true,std::logic_error,
00802              "Belos::BlockCGSolMgr::solve(): Invalid return from CGIteration::iterate().");
00803     }
00804   }
00805   catch (const std::exception &e) {
00806     printer_->stream(Errors) << "Error! Caught std::exception in CGIteration::iterate() at iteration " 
00807            << block_cg_iter->getNumIters() << std::endl 
00808            << e.what() << std::endl;
00809     throw;
00810   }
00811       }
00812       
00813       // Inform the linear problem that we are finished with this block linear system.
00814       problem_->setCurrLS();
00815       
00816       // Update indices for the linear systems to be solved.
00817       startPtr += numCurrRHS;
00818       numRHS2Solve -= numCurrRHS;
00819       if ( numRHS2Solve > 0 ) {
00820   numCurrRHS = ( numRHS2Solve < blockSize_) ? numRHS2Solve : blockSize_;
00821 
00822   if ( adaptiveBlockSize_ ) {
00823           blockSize_ = numCurrRHS;
00824     currIdx.resize( numCurrRHS  );
00825     currIdx2.resize( numCurrRHS  );
00826     for (int i=0; i<numCurrRHS; ++i) 
00827       { currIdx[i] = startPtr+i; currIdx2[i] = i; }   
00828   }
00829   else {
00830     currIdx.resize( blockSize_ );
00831     currIdx2.resize( blockSize_ );
00832     for (int i=0; i<numCurrRHS; ++i) 
00833       { currIdx[i] = startPtr+i; currIdx2[i] = i; }
00834     for (int i=numCurrRHS; i<blockSize_; ++i) 
00835       { currIdx[i] = -1; currIdx2[i] = i; }
00836   }
00837   // Set the next indices.
00838   problem_->setLSIndex( currIdx );
00839 
00840   // Set the new blocksize for the solver.
00841   block_cg_iter->setBlockSize( blockSize_ );  
00842       }
00843       else {
00844         currIdx.resize( numRHS2Solve );
00845       }
00846       
00847     }// while ( numRHS2Solve > 0 )
00848     
00849   }
00850 
00851   // print final summary
00852   sTest_->print( printer_->stream(FinalSummary) );
00853  
00854   // print timing information
00855   Teuchos::TimeMonitor::summarize( printer_->stream(TimingDetails) );
00856  
00857   // get iteration information for this solve
00858   numIters_ = maxIterTest_->getNumIters();
00859  
00860   if (!isConverged) {
00861     return Unconverged; // return from BlockCGSolMgr::solve() 
00862   }
00863   return Converged; // return from BlockCGSolMgr::solve() 
00864 }
00865 
00866 //  This method requires the solver manager to return a std::string that describes itself.
00867 template<class ScalarType, class MV, class OP>
00868 std::string BlockCGSolMgr<ScalarType,MV,OP>::description() const
00869 {
00870   std::ostringstream oss;
00871   oss << "Belos::BlockCGSolMgr<...,"<<Teuchos::ScalarTraits<ScalarType>::name()<<">";
00872   oss << "{";
00873   oss << "Ortho Type='"<<orthoType_<<"\', Block Size=" << blockSize_;
00874   oss << "}";
00875   return oss.str();
00876 }
00877   
00878 } // end Belos namespace
00879 
00880 #endif /* BELOS_BLOCK_CG_SOLMGR_HPP */

Generated on Wed May 12 21:30:08 2010 for Belos by  doxygen 1.4.7