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 "BelosStatusTestOutputFactory.hpp"
00051 #include "BelosOutputManager.hpp"
00052 #include "Teuchos_BLAS.hpp"
00053 #include "Teuchos_LAPACK.hpp"
00054 #include "Teuchos_TimeMonitor.hpp"
00055 
00072 namespace Belos {
00073   
00075 
00076   
00083   class BlockCGSolMgrLinearProblemFailure : public BelosError {public:
00084     BlockCGSolMgrLinearProblemFailure(const std::string& what_arg) : BelosError(what_arg)
00085     {}};
00086   
00093   class BlockCGSolMgrOrthoFailure : public BelosError {public:
00094     BlockCGSolMgrOrthoFailure(const std::string& what_arg) : BelosError(what_arg)
00095     {}};
00096   
00097   template<class ScalarType, class MV, class OP>
00098   class BlockCGSolMgr : public SolverManager<ScalarType,MV,OP> {
00099     
00100   private:
00101     typedef MultiVecTraits<ScalarType,MV> MVT;
00102     typedef OperatorTraits<ScalarType,MV,OP> OPT;
00103     typedef Teuchos::ScalarTraits<ScalarType> SCT;
00104     typedef typename Teuchos::ScalarTraits<ScalarType>::magnitudeType MagnitudeType;
00105     typedef Teuchos::ScalarTraits<MagnitudeType> MT;
00106     
00107   public:
00108     
00110 
00111 
00117      BlockCGSolMgr();
00118 
00147     BlockCGSolMgr( const Teuchos::RCP<LinearProblem<ScalarType,MV,OP> > &problem,
00148        const Teuchos::RCP<Teuchos::ParameterList> &pl );
00149     
00151     virtual ~BlockCGSolMgr() {};
00153     
00155 
00156     
00157     const LinearProblem<ScalarType,MV,OP>& getProblem() const {
00158       return *problem_;
00159     }
00160 
00163     Teuchos::RCP<const Teuchos::ParameterList> getValidParameters() const;
00164     
00167     Teuchos::RCP<const Teuchos::ParameterList> getCurrentParameters() const { return params_; }
00168     
00174     Teuchos::Array<Teuchos::RCP<Teuchos::Time> > getTimers() const {
00175       return tuple(timerSolve_);
00176     }
00177 
00179     int getNumIters() const {
00180       return numIters_;
00181     }
00182 
00185     bool isLOADetected() const { return false; }
00186  
00188     
00190 
00191    
00193     void setProblem( const Teuchos::RCP<LinearProblem<ScalarType,MV,OP> > &problem ) { problem_ = problem; }
00194    
00196     void setParameters( const Teuchos::RCP<Teuchos::ParameterList> &params );
00197     
00199    
00201 
00202 
00206     void reset( const ResetType type ) { if ((type & Belos::Problem) && !Teuchos::is_null(problem_)) problem_->setProblem(); }
00208  
00210 
00211     
00229     ReturnType solve();
00230     
00232     
00235     
00237     std::string description() const;
00238     
00240     
00241   private:
00242 
00243     // Linear problem.
00244     Teuchos::RCP<LinearProblem<ScalarType,MV,OP> > problem_;
00245     
00246     // Output manager.
00247     Teuchos::RCP<OutputManager<ScalarType> > printer_;
00248     Teuchos::RCP<std::ostream> outputStream_;
00249 
00250     // Status test.
00251     Teuchos::RCP<StatusTest<ScalarType,MV,OP> > sTest_;
00252     Teuchos::RCP<StatusTestMaxIters<ScalarType,MV,OP> > maxIterTest_;
00253     Teuchos::RCP<StatusTestGenResNorm<ScalarType,MV,OP> > convTest_;
00254     Teuchos::RCP<StatusTestOutput<ScalarType,MV,OP> > outputTest_;
00255 
00256     // Orthogonalization manager.
00257     Teuchos::RCP<MatOrthoManager<ScalarType,MV,OP> > ortho_; 
00258     
00259     // Current parameter list.
00260     Teuchos::RCP<ParameterList> params_;
00261     
00262     // Default solver values.
00263     static const MagnitudeType convtol_default_;
00264     static const MagnitudeType orthoKappa_default_;
00265     static const int maxIters_default_;
00266     static const bool adaptiveBlockSize_default_;
00267     static const bool showMaxResNormOnly_default_;
00268     static const int blockSize_default_;
00269     static const int verbosity_default_;
00270     static const int outputStyle_default_;
00271     static const int outputFreq_default_;
00272     static const std::string label_default_;
00273     static const std::string orthoType_default_;
00274     static const Teuchos::RCP<std::ostream> outputStream_default_;
00275 
00276     // Current solver values.
00277     MagnitudeType convtol_, orthoKappa_;
00278     int maxIters_, numIters_;
00279     int blockSize_, verbosity_, outputStyle_, outputFreq_;
00280     bool adaptiveBlockSize_, showMaxResNormOnly_;
00281     std::string orthoType_; 
00282     
00283     // Timers.
00284     std::string label_;
00285     Teuchos::RCP<Teuchos::Time> timerSolve_;
00286 
00287     // Internal state variables.
00288     bool isSet_;
00289   };
00290 
00291 
00292 // Default solver values.
00293 template<class ScalarType, class MV, class OP>
00294 const typename BlockCGSolMgr<ScalarType,MV,OP>::MagnitudeType BlockCGSolMgr<ScalarType,MV,OP>::convtol_default_ = 1e-8;
00295 
00296 template<class ScalarType, class MV, class OP>
00297 const typename BlockCGSolMgr<ScalarType,MV,OP>::MagnitudeType BlockCGSolMgr<ScalarType,MV,OP>::orthoKappa_default_ = -1.0;
00298 
00299 template<class ScalarType, class MV, class OP>
00300 const int BlockCGSolMgr<ScalarType,MV,OP>::maxIters_default_ = 1000;
00301 
00302 template<class ScalarType, class MV, class OP>
00303 const bool BlockCGSolMgr<ScalarType,MV,OP>::adaptiveBlockSize_default_ = true;
00304 
00305 template<class ScalarType, class MV, class OP>
00306 const bool BlockCGSolMgr<ScalarType,MV,OP>::showMaxResNormOnly_default_ = false;
00307 
00308 template<class ScalarType, class MV, class OP>
00309 const int BlockCGSolMgr<ScalarType,MV,OP>::blockSize_default_ = 1;
00310 
00311 template<class ScalarType, class MV, class OP>
00312 const int BlockCGSolMgr<ScalarType,MV,OP>::verbosity_default_ = Belos::Errors;
00313 
00314 template<class ScalarType, class MV, class OP>
00315 const int BlockCGSolMgr<ScalarType,MV,OP>::outputStyle_default_ = Belos::General;
00316 
00317 template<class ScalarType, class MV, class OP>
00318 const int BlockCGSolMgr<ScalarType,MV,OP>::outputFreq_default_ = -1;
00319 
00320 template<class ScalarType, class MV, class OP>
00321 const std::string BlockCGSolMgr<ScalarType,MV,OP>::label_default_ = "Belos";
00322 
00323 template<class ScalarType, class MV, class OP>
00324 const std::string BlockCGSolMgr<ScalarType,MV,OP>::orthoType_default_ = "DGKS";
00325 
00326 template<class ScalarType, class MV, class OP>
00327 const Teuchos::RCP<std::ostream> BlockCGSolMgr<ScalarType,MV,OP>::outputStream_default_ = Teuchos::rcp(&std::cout,false);
00328 
00329 
00330 // Empty Constructor
00331 template<class ScalarType, class MV, class OP>
00332 BlockCGSolMgr<ScalarType,MV,OP>::BlockCGSolMgr() :
00333   outputStream_(outputStream_default_),
00334   convtol_(convtol_default_),
00335   orthoKappa_(orthoKappa_default_),
00336   maxIters_(maxIters_default_),
00337   blockSize_(blockSize_default_),
00338   verbosity_(verbosity_default_),
00339   outputStyle_(outputStyle_default_),
00340   outputFreq_(outputFreq_default_),
00341   adaptiveBlockSize_(adaptiveBlockSize_default_),
00342   showMaxResNormOnly_(showMaxResNormOnly_default_),
00343   orthoType_(orthoType_default_),
00344   label_(label_default_),
00345   isSet_(false)
00346 {}
00347 
00348 
00349 // Basic Constructor
00350 template<class ScalarType, class MV, class OP>
00351 BlockCGSolMgr<ScalarType,MV,OP>::BlockCGSolMgr( 
00352                  const Teuchos::RCP<LinearProblem<ScalarType,MV,OP> > &problem,
00353                  const Teuchos::RCP<Teuchos::ParameterList> &pl ) : 
00354   problem_(problem),
00355   outputStream_(outputStream_default_),
00356   convtol_(convtol_default_),
00357   orthoKappa_(orthoKappa_default_),
00358   maxIters_(maxIters_default_),
00359   blockSize_(blockSize_default_),
00360   verbosity_(verbosity_default_),
00361   outputStyle_(outputStyle_default_),
00362   outputFreq_(outputFreq_default_),
00363   adaptiveBlockSize_(adaptiveBlockSize_default_),
00364   showMaxResNormOnly_(showMaxResNormOnly_default_),
00365   orthoType_(orthoType_default_),
00366   label_(label_default_),
00367   isSet_(false)
00368 {
00369   TEST_FOR_EXCEPTION(problem_ == Teuchos::null, std::invalid_argument, "Problem not given to solver manager.");
00370 
00371   // If the parameter list pointer is null, then set the current parameters to the default parameter list.
00372   if ( !is_null(pl) ) {
00373     setParameters( pl );  
00374   }
00375 }
00376 
00377 template<class ScalarType, class MV, class OP>
00378 void BlockCGSolMgr<ScalarType,MV,OP>::setParameters( const Teuchos::RCP<Teuchos::ParameterList> &params )
00379 {
00380   // Create the internal parameter list if ones doesn't already exist.
00381   if (params_ == Teuchos::null) {
00382     params_ = Teuchos::rcp( new Teuchos::ParameterList(*getValidParameters()) );
00383   }
00384   else {
00385     params->validateParameters(*getValidParameters());
00386   }
00387 
00388   // Check for maximum number of iterations
00389   if (params->isParameter("Maximum Iterations")) {
00390     maxIters_ = params->get("Maximum Iterations",maxIters_default_);
00391 
00392     // Update parameter in our list and in status test.
00393     params_->set("Maximum Iterations", maxIters_);
00394     if (maxIterTest_!=Teuchos::null)
00395       maxIterTest_->setMaxIters( maxIters_ );
00396   }
00397 
00398   // Check for blocksize
00399   if (params->isParameter("Block Size")) {
00400     blockSize_ = params->get("Block Size",blockSize_default_);    
00401     TEST_FOR_EXCEPTION(blockSize_ <= 0, std::invalid_argument,
00402            "Belos::BlockCGSolMgr: \"Block Size\" must be strictly positive.");
00403 
00404     // Update parameter in our list.
00405     params_->set("Block Size", blockSize_);
00406   }
00407 
00408   // Check if the blocksize should be adaptive
00409   if (params->isParameter("Adaptive Block Size")) {
00410     adaptiveBlockSize_ = params->get("Adaptive Block Size",adaptiveBlockSize_default_);
00411     
00412     // Update parameter in our list.
00413     params_->set("Adaptive Block Size", adaptiveBlockSize_);
00414   }
00415 
00416   // Check to see if the timer label changed.
00417   if (params->isParameter("Timer Label")) {
00418     std::string tempLabel = params->get("Timer Label", label_default_);
00419 
00420     // Update parameter in our list and solver timer
00421     if (tempLabel != label_) {
00422       label_ = tempLabel;
00423       params_->set("Timer Label", label_);
00424       std::string solveLabel = label_ + ": BlockCGSolMgr total solve time";
00425       timerSolve_ = Teuchos::TimeMonitor::getNewTimer(solveLabel);
00426     }
00427   }
00428 
00429   // Check if the orthogonalization changed.
00430   if (params->isParameter("Orthogonalization")) {
00431     std::string tempOrthoType = params->get("Orthogonalization",orthoType_default_);
00432     TEST_FOR_EXCEPTION( tempOrthoType != "DGKS" && tempOrthoType != "ICGS" && tempOrthoType != "IMGS", 
00433                         std::invalid_argument,
00434       "Belos::BlockCGSolMgr: \"Orthogonalization\" must be either \"DGKS\", \"ICGS\", or \"IMGS\".");
00435     if (tempOrthoType != orthoType_) {
00436       orthoType_ = tempOrthoType;
00437       // Create orthogonalization manager
00438       if (orthoType_=="DGKS") {
00439   if (orthoKappa_ <= 0) {
00440     ortho_ = Teuchos::rcp( new DGKSOrthoManager<ScalarType,MV,OP>( label_ ) );
00441   }
00442   else {
00443     ortho_ = Teuchos::rcp( new DGKSOrthoManager<ScalarType,MV,OP>( label_ ) );
00444     Teuchos::rcp_dynamic_cast<DGKSOrthoManager<ScalarType,MV,OP> >(ortho_)->setDepTol( orthoKappa_ );
00445   }
00446       }
00447       else if (orthoType_=="ICGS") {
00448   ortho_ = Teuchos::rcp( new ICGSOrthoManager<ScalarType,MV,OP>( label_ ) );
00449       } 
00450       else if (orthoType_=="IMGS") {
00451   ortho_ = Teuchos::rcp( new IMGSOrthoManager<ScalarType,MV,OP>( label_ ) );
00452       } 
00453     }  
00454   }
00455 
00456   // Check which orthogonalization constant to use.
00457   if (params->isParameter("Orthogonalization Constant")) {
00458     orthoKappa_ = params->get("Orthogonalization Constant",orthoKappa_default_);
00459 
00460     // Update parameter in our list.
00461     params_->set("Orthogonalization Constant",orthoKappa_);
00462     if (orthoType_=="DGKS") {
00463       if (orthoKappa_ > 0 && ortho_ != Teuchos::null) {
00464   Teuchos::rcp_dynamic_cast<DGKSOrthoManager<ScalarType,MV,OP> >(ortho_)->setDepTol( orthoKappa_ );
00465       }
00466     } 
00467   }
00468 
00469   // Check for a change in verbosity level
00470   if (params->isParameter("Verbosity")) {
00471     if (Teuchos::isParameterType<int>(*params,"Verbosity")) {
00472       verbosity_ = params->get("Verbosity", verbosity_default_);
00473     } else {
00474       verbosity_ = (int)Teuchos::getParameter<Belos::MsgType>(*params,"Verbosity");
00475     }
00476 
00477     // Update parameter in our list.
00478     params_->set("Verbosity", verbosity_);
00479     if (printer_ != Teuchos::null)
00480       printer_->setVerbosity(verbosity_);
00481   }
00482 
00483   // Check for a change in output style
00484   if (params->isParameter("Output Style")) {
00485     if (Teuchos::isParameterType<int>(*params,"Output Style")) {
00486       outputStyle_ = params->get("Output Style", outputStyle_default_);
00487     } else {
00488       outputStyle_ = (int)Teuchos::getParameter<Belos::OutputType>(*params,"Output Style");
00489     }
00490 
00491     // Update parameter in our list.
00492     params_->set("Output Style", outputStyle_);
00493     outputTest_ == Teuchos::null;
00494   }
00495 
00496   // output stream
00497   if (params->isParameter("Output Stream")) {
00498     outputStream_ = Teuchos::getParameter<Teuchos::RCP<std::ostream> >(*params,"Output Stream");
00499 
00500     // Update parameter in our list.
00501     params_->set("Output Stream", outputStream_);
00502     if (printer_ != Teuchos::null)
00503       printer_->setOStream( outputStream_ );
00504   }
00505 
00506   // frequency level
00507   if (verbosity_ & Belos::StatusTestDetails) {
00508     if (params->isParameter("Output Frequency")) {
00509       outputFreq_ = params->get("Output Frequency", outputFreq_default_);
00510     }
00511 
00512     // Update parameter in out list and output status test.
00513     params_->set("Output Frequency", outputFreq_);
00514     if (outputTest_ != Teuchos::null)
00515       outputTest_->setOutputFrequency( outputFreq_ );
00516   }
00517 
00518   // Create output manager if we need to.
00519   if (printer_ == Teuchos::null) {
00520     printer_ = Teuchos::rcp( new OutputManager<ScalarType>(verbosity_, outputStream_) );
00521   }  
00522   
00523   // Convergence
00524   typedef Belos::StatusTestCombo<ScalarType,MV,OP>  StatusTestCombo_t;
00525   typedef Belos::StatusTestGenResNorm<ScalarType,MV,OP>  StatusTestResNorm_t;
00526 
00527   // Check for convergence tolerance
00528   if (params->isParameter("Convergence Tolerance")) {
00529     convtol_ = params->get("Convergence Tolerance",convtol_default_);
00530 
00531     // Update parameter in our list and residual tests.
00532     params_->set("Convergence Tolerance", convtol_);
00533     if (convTest_ != Teuchos::null)
00534       convTest_->setTolerance( convtol_ );
00535   }
00536   
00537   if (params->isParameter("Show Maximum Residual Norm Only")) {
00538     showMaxResNormOnly_ = Teuchos::getParameter<bool>(*params,"Show Maximum Residual Norm Only");
00539 
00540     // Update parameter in our list and residual tests
00541     params_->set("Show Maximum Residual Norm Only", showMaxResNormOnly_);
00542     if (convTest_ != Teuchos::null)
00543       convTest_->setShowMaxResNormOnly( showMaxResNormOnly_ );
00544   }
00545 
00546   // Create status tests if we need to.
00547 
00548   // Basic test checks maximum iterations and native residual.
00549   if (maxIterTest_ == Teuchos::null)
00550     maxIterTest_ = Teuchos::rcp( new StatusTestMaxIters<ScalarType,MV,OP>( maxIters_ ) );
00551   
00552   // Implicit residual test, using the native residual to determine if convergence was achieved.
00553   if (convTest_ == Teuchos::null)
00554     convTest_ = Teuchos::rcp( new StatusTestResNorm_t( convtol_, 1 ) );
00555   
00556   if (sTest_ == Teuchos::null)
00557     sTest_ = Teuchos::rcp( new StatusTestCombo_t( StatusTestCombo_t::OR, maxIterTest_, convTest_ ) );
00558   
00559   if (outputTest_ == Teuchos::null) {
00560 
00561     // Create the status test output class.
00562     // This class manages and formats the output from the status test.
00563     StatusTestOutputFactory<ScalarType,MV,OP> stoFactory( outputStyle_ );
00564     outputTest_ = stoFactory.create( printer_, sTest_, outputFreq_, Passed+Failed+Undefined );
00565 
00566     // Set the solver string for the output test
00567     std::string solverDesc = " Block CG ";
00568     outputTest_->setSolverDesc( solverDesc );
00569 
00570   }
00571 
00572   // Create orthogonalization manager if we need to.
00573   if (ortho_ == Teuchos::null) {
00574     if (orthoType_=="DGKS") {
00575       if (orthoKappa_ <= 0) {
00576   ortho_ = Teuchos::rcp( new DGKSOrthoManager<ScalarType,MV,OP>( label_ ) );
00577       }
00578       else {
00579   ortho_ = Teuchos::rcp( new DGKSOrthoManager<ScalarType,MV,OP>( label_ ) );
00580   Teuchos::rcp_dynamic_cast<DGKSOrthoManager<ScalarType,MV,OP> >(ortho_)->setDepTol( orthoKappa_ );
00581       }
00582     }
00583     else if (orthoType_=="ICGS") {
00584       ortho_ = Teuchos::rcp( new ICGSOrthoManager<ScalarType,MV,OP>( label_ ) );
00585     } 
00586     else if (orthoType_=="IMGS") {
00587       ortho_ = Teuchos::rcp( new IMGSOrthoManager<ScalarType,MV,OP>( label_ ) );
00588     } 
00589     else {
00590       TEST_FOR_EXCEPTION(orthoType_!="ICGS"&&orthoType_!="DGKS"&&orthoType_!="IMGS",std::logic_error,
00591        "Belos::BlockCGSolMgr(): Invalid orthogonalization type.");
00592     }  
00593   }
00594 
00595   // Create the timer if we need to.
00596   if (timerSolve_ == Teuchos::null) {
00597     std::string solveLabel = label_ + ": BlockCGSolMgr total solve time";
00598     timerSolve_ = Teuchos::TimeMonitor::getNewTimer(solveLabel);
00599   }
00600 
00601   // Inform the solver manager that the current parameters were set.
00602   isSet_ = true;
00603 }
00604 
00605     
00606 template<class ScalarType, class MV, class OP>
00607 Teuchos::RCP<const Teuchos::ParameterList> 
00608 BlockCGSolMgr<ScalarType,MV,OP>::getValidParameters() const
00609 {
00610   static Teuchos::RCP<const Teuchos::ParameterList> validPL;
00611   
00612   // Set all the valid parameters and their default values.
00613   if(is_null(validPL)) {
00614     Teuchos::RCP<Teuchos::ParameterList> pl = Teuchos::parameterList();
00615     pl->set("Convergence Tolerance", convtol_default_,
00616       "The relative residual tolerance that needs to be achieved by the\n"
00617       "iterative solver in order for the linear system to be declared converged.");
00618     pl->set("Maximum Iterations", maxIters_default_,
00619       "The maximum number of block iterations allowed for each\n"
00620       "set of RHS solved.");
00621     pl->set("Block Size", blockSize_default_,
00622       "The number of vectors in each block.");
00623     pl->set("Adaptive Block Size", adaptiveBlockSize_default_,
00624       "Whether the solver manager should adapt to the block size\n"
00625       "based on the number of RHS to solve.");
00626     pl->set("Verbosity", verbosity_default_,
00627       "What type(s) of solver information should be outputted\n"
00628       "to the output stream.");
00629     pl->set("Output Style", outputStyle_default_,
00630       "What style is used for the solver information outputted\n"
00631       "to the output stream.");
00632     pl->set("Output Frequency", outputFreq_default_,
00633       "How often convergence information should be outputted\n"
00634       "to the output stream.");  
00635     pl->set("Output Stream", outputStream_default_,
00636       "A reference-counted pointer to the output stream where all\n"
00637       "solver output is sent.");
00638     pl->set("Show Maximum Residual Norm Only", showMaxResNormOnly_default_,
00639       "When convergence information is printed, only show the maximum\n"
00640       "relative residual norm when the block size is greater than one.");
00641     pl->set("Timer Label", label_default_,
00642       "The string to use as a prefix for the timer labels.");
00643     //  pl->set("Restart Timers", restartTimers_);
00644     pl->set("Orthogonalization", orthoType_default_,
00645       "The type of orthogonalization to use: DGKS, ICGS, or IMGS.");
00646     pl->set("Orthogonalization Constant",orthoKappa_default_,
00647       "The constant used by DGKS orthogonalization to determine\n"
00648       "whether another step of classical Gram-Schmidt is necessary.");
00649     validPL = pl;
00650   }
00651   return validPL;
00652 }
00653 
00654   
00655 // solve()
00656 template<class ScalarType, class MV, class OP>
00657 ReturnType BlockCGSolMgr<ScalarType,MV,OP>::solve() {
00658 
00659   // Set the current parameters if they were not set before.
00660   // NOTE:  This may occur if the user generated the solver manager with the default constructor and 
00661   // then didn't set any parameters using setParameters().
00662   if (!isSet_) {
00663     setParameters(Teuchos::parameterList(*getValidParameters()));
00664   }
00665 
00666   Teuchos::BLAS<int,ScalarType> blas;
00667   Teuchos::LAPACK<int,ScalarType> lapack;
00668   
00669   TEST_FOR_EXCEPTION(!problem_->isProblemSet(),BlockCGSolMgrLinearProblemFailure,
00670                      "Belos::BlockCGSolMgr::solve(): Linear problem is not ready, setProblem() has not been called.");
00671 
00672   // Create indices for the linear systems to be solved.
00673   int startPtr = 0;
00674   int numRHS2Solve = MVT::GetNumberVecs( *(problem_->getRHS()) );
00675   int numCurrRHS = ( numRHS2Solve < blockSize_) ? numRHS2Solve : blockSize_;
00676 
00677   std::vector<int> currIdx, currIdx2;
00678   //  If an adaptive block size is allowed then only the linear systems that need to be solved are solved.
00679   //  Otherwise, the index set is generated that informs the linear problem that some linear systems are augmented.
00680   if ( adaptiveBlockSize_ ) {
00681     blockSize_ = numCurrRHS;
00682     currIdx.resize( numCurrRHS  );
00683     currIdx2.resize( numCurrRHS  );
00684     for (int i=0; i<numCurrRHS; ++i) 
00685       { currIdx[i] = startPtr+i; currIdx2[i]=i; }
00686     
00687   }
00688   else {
00689     currIdx.resize( blockSize_ );
00690     currIdx2.resize( blockSize_ );
00691     for (int i=0; i<numCurrRHS; ++i) 
00692       { currIdx[i] = startPtr+i; currIdx2[i]=i; }
00693     for (int i=numCurrRHS; i<blockSize_; ++i) 
00694       { currIdx[i] = -1; currIdx2[i] = i; }
00695   }
00696 
00697   // Inform the linear problem of the current linear system to solve.
00698   problem_->setLSIndex( currIdx );
00699 
00701   // Parameter list
00702   Teuchos::ParameterList plist;
00703   plist.set("Block Size",blockSize_);
00704   
00705   // Reset the status test.  
00706   outputTest_->reset();
00707 
00708   // Assume convergence is achieved, then let any failed convergence set this to false.
00709   bool isConverged = true;  
00710 
00712   // BlockCG solver
00713 
00714   Teuchos::RCP<CGIteration<ScalarType,MV,OP> > block_cg_iter;
00715   if (blockSize_ == 1)
00716     block_cg_iter = Teuchos::rcp( new CGIter<ScalarType,MV,OP>(problem_,printer_,outputTest_,plist) );
00717   else
00718     block_cg_iter = Teuchos::rcp( new BlockCGIter<ScalarType,MV,OP>(problem_,printer_,outputTest_,ortho_,plist) );
00719   
00720 
00721   // Enter solve() iterations
00722   {
00723     Teuchos::TimeMonitor slvtimer(*timerSolve_);
00724 
00725     while ( numRHS2Solve > 0 ) {
00726       //
00727       // Reset the active / converged vectors from this block
00728       std::vector<int> convRHSIdx;
00729       std::vector<int> currRHSIdx( currIdx );
00730       currRHSIdx.resize(numCurrRHS);
00731 
00732       // Reset the number of iterations.
00733       block_cg_iter->resetNumIters();
00734 
00735       // Reset the number of calls that the status test output knows about.
00736       outputTest_->resetNumCalls();
00737 
00738       // Get the current residual for this block of linear systems.
00739       Teuchos::RCP<MV> R_0 = MVT::CloneViewNonConst( *(Teuchos::rcp_const_cast<MV>(problem_->getInitResVec())), currIdx );
00740 
00741       // Set the new state and initialize the solver.
00742       CGIterationState<ScalarType,MV> newstate;
00743       newstate.R = R_0;
00744       block_cg_iter->initializeCG(newstate);
00745 
00746       while(1) {
00747   
00748   // tell block_cg_iter to iterate
00749   try {
00750     block_cg_iter->iterate();
00751     
00753     //
00754     // check convergence first
00755     //
00757     if ( convTest_->getStatus() == Passed ) {
00758       // We have convergence of at least one linear system.
00759 
00760       // Figure out which linear systems converged.
00761       std::vector<int> convIdx = Teuchos::rcp_dynamic_cast<StatusTestGenResNorm<ScalarType,MV,OP> >(convTest_)->convIndices();
00762 
00763       // If the number of converged linear systems is equal to the
00764             // number of current linear systems, then we are done with this block.
00765       if (convIdx.size() == currRHSIdx.size())
00766         break;  // break from while(1){block_cg_iter->iterate()}
00767 
00768       // Inform the linear problem that we are finished with this current linear system.
00769       problem_->setCurrLS();
00770 
00771       // Reset currRHSIdx to have the right-hand sides that are left to converge for this block.
00772       int have = 0;
00773             std::vector<int> unconvIdx(currRHSIdx.size());
00774       for (unsigned int i=0; i<currRHSIdx.size(); ++i) {
00775         bool found = false;
00776         for (unsigned int j=0; j<convIdx.size(); ++j) {
00777     if (currRHSIdx[i] == convIdx[j]) {
00778       found = true;
00779       break;
00780     }
00781         }
00782         if (!found) {
00783                 currIdx2[have] = currIdx2[i];
00784     currRHSIdx[have++] = currRHSIdx[i];
00785         }
00786               else {
00787               } 
00788       }
00789       currRHSIdx.resize(have);
00790       currIdx2.resize(have);
00791 
00792       // Set the remaining indices after deflation.
00793       problem_->setLSIndex( currRHSIdx );
00794 
00795       // Get the current residual vector.
00796       std::vector<MagnitudeType> norms;
00797             R_0 = MVT::CloneCopy( *(block_cg_iter->getNativeResiduals(&norms)),currIdx2 );
00798       for (int i=0; i<have; ++i) { currIdx2[i] = i; }
00799 
00800       // Set the new blocksize for the solver.
00801       block_cg_iter->setBlockSize( have );
00802 
00803       // Set the new state and initialize the solver.
00804       CGIterationState<ScalarType,MV> defstate;
00805       defstate.R = R_0;
00806       block_cg_iter->initializeCG(defstate);
00807     }
00809     //
00810     // check for maximum iterations
00811     //
00813     else if ( maxIterTest_->getStatus() == Passed ) {
00814       // we don't have convergence
00815       isConverged = false;
00816       break;  // break from while(1){block_cg_iter->iterate()}
00817     }
00818 
00820     //
00821     // we returned from iterate(), but none of our status tests Passed.
00822     // something is wrong, and it is probably our fault.
00823     //
00825 
00826     else {
00827       TEST_FOR_EXCEPTION(true,std::logic_error,
00828              "Belos::BlockCGSolMgr::solve(): Invalid return from CGIteration::iterate().");
00829     }
00830   }
00831   catch (const std::exception &e) {
00832     printer_->stream(Errors) << "Error! Caught std::exception in CGIteration::iterate() at iteration " 
00833            << block_cg_iter->getNumIters() << std::endl 
00834            << e.what() << std::endl;
00835     throw;
00836   }
00837       }
00838       
00839       // Inform the linear problem that we are finished with this block linear system.
00840       problem_->setCurrLS();
00841       
00842       // Update indices for the linear systems to be solved.
00843       startPtr += numCurrRHS;
00844       numRHS2Solve -= numCurrRHS;
00845       if ( numRHS2Solve > 0 ) {
00846   numCurrRHS = ( numRHS2Solve < blockSize_) ? numRHS2Solve : blockSize_;
00847 
00848   if ( adaptiveBlockSize_ ) {
00849           blockSize_ = numCurrRHS;
00850     currIdx.resize( numCurrRHS  );
00851     currIdx2.resize( numCurrRHS  );
00852     for (int i=0; i<numCurrRHS; ++i) 
00853       { currIdx[i] = startPtr+i; currIdx2[i] = i; }   
00854   }
00855   else {
00856     currIdx.resize( blockSize_ );
00857     currIdx2.resize( blockSize_ );
00858     for (int i=0; i<numCurrRHS; ++i) 
00859       { currIdx[i] = startPtr+i; currIdx2[i] = i; }
00860     for (int i=numCurrRHS; i<blockSize_; ++i) 
00861       { currIdx[i] = -1; currIdx2[i] = i; }
00862   }
00863   // Set the next indices.
00864   problem_->setLSIndex( currIdx );
00865 
00866   // Set the new blocksize for the solver.
00867   block_cg_iter->setBlockSize( blockSize_ );  
00868       }
00869       else {
00870         currIdx.resize( numRHS2Solve );
00871       }
00872       
00873     }// while ( numRHS2Solve > 0 )
00874     
00875   }
00876 
00877   // print final summary
00878   sTest_->print( printer_->stream(FinalSummary) );
00879  
00880   // print timing information
00881   Teuchos::TimeMonitor::summarize( printer_->stream(TimingDetails) );
00882  
00883   // get iteration information for this solve
00884   numIters_ = maxIterTest_->getNumIters();
00885  
00886   if (!isConverged) {
00887     return Unconverged; // return from BlockCGSolMgr::solve() 
00888   }
00889   return Converged; // return from BlockCGSolMgr::solve() 
00890 }
00891 
00892 //  This method requires the solver manager to return a std::string that describes itself.
00893 template<class ScalarType, class MV, class OP>
00894 std::string BlockCGSolMgr<ScalarType,MV,OP>::description() const
00895 {
00896   std::ostringstream oss;
00897   oss << "Belos::BlockCGSolMgr<...,"<<Teuchos::ScalarTraits<ScalarType>::name()<<">";
00898   oss << "{";
00899   oss << "Ortho Type='"<<orthoType_<<"\', Block Size=" << blockSize_;
00900   oss << "}";
00901   return oss.str();
00902 }
00903   
00904 } // end Belos namespace
00905 
00906 #endif /* BELOS_BLOCK_CG_SOLMGR_HPP */
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines
Generated on Wed Apr 13 10:05:05 2011 for Belos by  doxygen 1.6.3