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

Generated on Tue Oct 20 12:48:33 2009 for Belos by doxygen 1.4.7