Belos Version of the Day
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 the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
00008 // the U.S. Government retains certain rights in this software.
00009 //
00010 // Redistribution and use in source and binary forms, with or without
00011 // modification, are permitted provided that the following conditions are
00012 // met:
00013 //
00014 // 1. Redistributions of source code must retain the above copyright
00015 // notice, this list of conditions and the following disclaimer.
00016 //
00017 // 2. Redistributions in binary form must reproduce the above copyright
00018 // notice, this list of conditions and the following disclaimer in the
00019 // documentation and/or other materials provided with the distribution.
00020 //
00021 // 3. Neither the name of the Corporation nor the names of the
00022 // contributors may be used to endorse or promote products derived from
00023 // this software without specific prior written permission.
00024 //
00025 // THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
00026 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00027 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
00028 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
00029 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
00030 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
00031 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
00032 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
00033 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
00034 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
00035 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00036 //
00037 // Questions? Contact Michael A. Heroux (maherou@sandia.gov)
00038 //
00039 // ************************************************************************
00040 //@HEADER
00041 
00042 #ifndef BELOS_BLOCK_CG_SOLMGR_HPP
00043 #define BELOS_BLOCK_CG_SOLMGR_HPP
00044 
00049 #include "BelosConfigDefs.hpp"
00050 #include "BelosTypes.hpp"
00051 
00052 #include "BelosLinearProblem.hpp"
00053 #include "BelosSolverManager.hpp"
00054 
00055 #include "BelosCGIter.hpp"
00056 #include "BelosBlockCGIter.hpp"
00057 #include "BelosDGKSOrthoManager.hpp"
00058 #include "BelosICGSOrthoManager.hpp"
00059 #include "BelosIMGSOrthoManager.hpp"
00060 #include "BelosStatusTestMaxIters.hpp"
00061 #include "BelosStatusTestGenResNorm.hpp"
00062 #include "BelosStatusTestCombo.hpp"
00063 #include "BelosStatusTestOutputFactory.hpp"
00064 #include "BelosOutputManager.hpp"
00065 #include "Teuchos_BLAS.hpp"
00066 #include "Teuchos_LAPACK.hpp"
00067 #ifdef BELOS_TEUCHOS_TIME_MONITOR
00068 #include "Teuchos_TimeMonitor.hpp"
00069 #endif
00070 
00087 namespace Belos {
00088   
00090 
00091   
00098   class BlockCGSolMgrLinearProblemFailure : public BelosError {public:
00099     BlockCGSolMgrLinearProblemFailure(const std::string& what_arg) : BelosError(what_arg)
00100     {}};
00101   
00108   class BlockCGSolMgrOrthoFailure : public BelosError {public:
00109     BlockCGSolMgrOrthoFailure(const std::string& what_arg) : BelosError(what_arg)
00110     {}};
00111   
00112   template<class ScalarType, class MV, class OP>
00113   class BlockCGSolMgr : public SolverManager<ScalarType,MV,OP> {
00114     
00115   private:
00116     typedef MultiVecTraits<ScalarType,MV> MVT;
00117     typedef OperatorTraits<ScalarType,MV,OP> OPT;
00118     typedef Teuchos::ScalarTraits<ScalarType> SCT;
00119     typedef typename Teuchos::ScalarTraits<ScalarType>::magnitudeType MagnitudeType;
00120     typedef Teuchos::ScalarTraits<MagnitudeType> MT;
00121     
00122   public:
00123     
00125 
00126 
00132      BlockCGSolMgr();
00133 
00162     BlockCGSolMgr( const Teuchos::RCP<LinearProblem<ScalarType,MV,OP> > &problem,
00163        const Teuchos::RCP<Teuchos::ParameterList> &pl );
00164     
00166     virtual ~BlockCGSolMgr() {};
00168     
00170 
00171     
00172     const LinearProblem<ScalarType,MV,OP>& getProblem() const {
00173       return *problem_;
00174     }
00175 
00178     Teuchos::RCP<const Teuchos::ParameterList> getValidParameters() const;
00179     
00182     Teuchos::RCP<const Teuchos::ParameterList> getCurrentParameters() const { return params_; }
00183     
00189     Teuchos::Array<Teuchos::RCP<Teuchos::Time> > getTimers() const {
00190       return Teuchos::tuple(timerSolve_);
00191     }
00192 
00194     int getNumIters() const {
00195       return numIters_;
00196     }
00197 
00200     bool isLOADetected() const { return false; }
00201  
00203     
00205 
00206    
00208     void setProblem( const Teuchos::RCP<LinearProblem<ScalarType,MV,OP> > &problem ) { problem_ = problem; }
00209    
00211     void setParameters( const Teuchos::RCP<Teuchos::ParameterList> &params );
00212     
00214    
00216 
00217 
00221     void reset( const ResetType type ) { if ((type & Belos::Problem) && !Teuchos::is_null(problem_)) problem_->setProblem(); }
00223  
00225 
00226     
00244     ReturnType solve();
00245     
00247     
00250     
00252     std::string description() const;
00253     
00255     
00256   private:
00257 
00258     // Linear problem.
00259     Teuchos::RCP<LinearProblem<ScalarType,MV,OP> > problem_;
00260     
00261     // Output manager.
00262     Teuchos::RCP<OutputManager<ScalarType> > printer_;
00263     Teuchos::RCP<std::ostream> outputStream_;
00264 
00265     // Status test.
00266     Teuchos::RCP<StatusTest<ScalarType,MV,OP> > sTest_;
00267     Teuchos::RCP<StatusTestMaxIters<ScalarType,MV,OP> > maxIterTest_;
00268     Teuchos::RCP<StatusTestGenResNorm<ScalarType,MV,OP> > convTest_;
00269     Teuchos::RCP<StatusTestOutput<ScalarType,MV,OP> > outputTest_;
00270 
00271     // Orthogonalization manager.
00272     Teuchos::RCP<MatOrthoManager<ScalarType,MV,OP> > ortho_; 
00273     
00274     // Current parameter list.
00275     Teuchos::RCP<Teuchos::ParameterList> params_;
00276     
00277     // Default solver values.
00278     static const MagnitudeType convtol_default_;
00279     static const MagnitudeType orthoKappa_default_;
00280     static const int maxIters_default_;
00281     static const bool adaptiveBlockSize_default_;
00282     static const bool showMaxResNormOnly_default_;
00283     static const int blockSize_default_;
00284     static const int verbosity_default_;
00285     static const int outputStyle_default_;
00286     static const int outputFreq_default_;
00287     static const std::string label_default_;
00288     static const std::string orthoType_default_;
00289     static const Teuchos::RCP<std::ostream> outputStream_default_;
00290 
00291     // Current solver values.
00292     MagnitudeType convtol_, orthoKappa_;
00293     int maxIters_, numIters_;
00294     int blockSize_, verbosity_, outputStyle_, outputFreq_;
00295     bool adaptiveBlockSize_, showMaxResNormOnly_;
00296     std::string orthoType_; 
00297     
00298     // Timers.
00299     std::string label_;
00300     Teuchos::RCP<Teuchos::Time> timerSolve_;
00301 
00302     // Internal state variables.
00303     bool isSet_;
00304   };
00305 
00306 
00307 // Default solver values.
00308 template<class ScalarType, class MV, class OP>
00309 const typename BlockCGSolMgr<ScalarType,MV,OP>::MagnitudeType BlockCGSolMgr<ScalarType,MV,OP>::convtol_default_ = 1e-8;
00310 
00311 template<class ScalarType, class MV, class OP>
00312 const typename BlockCGSolMgr<ScalarType,MV,OP>::MagnitudeType BlockCGSolMgr<ScalarType,MV,OP>::orthoKappa_default_ = -1.0;
00313 
00314 template<class ScalarType, class MV, class OP>
00315 const int BlockCGSolMgr<ScalarType,MV,OP>::maxIters_default_ = 1000;
00316 
00317 template<class ScalarType, class MV, class OP>
00318 const bool BlockCGSolMgr<ScalarType,MV,OP>::adaptiveBlockSize_default_ = true;
00319 
00320 template<class ScalarType, class MV, class OP>
00321 const bool BlockCGSolMgr<ScalarType,MV,OP>::showMaxResNormOnly_default_ = false;
00322 
00323 template<class ScalarType, class MV, class OP>
00324 const int BlockCGSolMgr<ScalarType,MV,OP>::blockSize_default_ = 1;
00325 
00326 template<class ScalarType, class MV, class OP>
00327 const int BlockCGSolMgr<ScalarType,MV,OP>::verbosity_default_ = Belos::Errors;
00328 
00329 template<class ScalarType, class MV, class OP>
00330 const int BlockCGSolMgr<ScalarType,MV,OP>::outputStyle_default_ = Belos::General;
00331 
00332 template<class ScalarType, class MV, class OP>
00333 const int BlockCGSolMgr<ScalarType,MV,OP>::outputFreq_default_ = -1;
00334 
00335 template<class ScalarType, class MV, class OP>
00336 const std::string BlockCGSolMgr<ScalarType,MV,OP>::label_default_ = "Belos";
00337 
00338 template<class ScalarType, class MV, class OP>
00339 const std::string BlockCGSolMgr<ScalarType,MV,OP>::orthoType_default_ = "DGKS";
00340 
00341 template<class ScalarType, class MV, class OP>
00342 const Teuchos::RCP<std::ostream> BlockCGSolMgr<ScalarType,MV,OP>::outputStream_default_ = Teuchos::rcp(&std::cout,false);
00343 
00344 
00345 // Empty Constructor
00346 template<class ScalarType, class MV, class OP>
00347 BlockCGSolMgr<ScalarType,MV,OP>::BlockCGSolMgr() :
00348   outputStream_(outputStream_default_),
00349   convtol_(convtol_default_),
00350   orthoKappa_(orthoKappa_default_),
00351   maxIters_(maxIters_default_),
00352   blockSize_(blockSize_default_),
00353   verbosity_(verbosity_default_),
00354   outputStyle_(outputStyle_default_),
00355   outputFreq_(outputFreq_default_),
00356   adaptiveBlockSize_(adaptiveBlockSize_default_),
00357   showMaxResNormOnly_(showMaxResNormOnly_default_),
00358   orthoType_(orthoType_default_),
00359   label_(label_default_),
00360   isSet_(false)
00361 {}
00362 
00363 
00364 // Basic Constructor
00365 template<class ScalarType, class MV, class OP>
00366 BlockCGSolMgr<ScalarType,MV,OP>::BlockCGSolMgr( 
00367                  const Teuchos::RCP<LinearProblem<ScalarType,MV,OP> > &problem,
00368                  const Teuchos::RCP<Teuchos::ParameterList> &pl ) : 
00369   problem_(problem),
00370   outputStream_(outputStream_default_),
00371   convtol_(convtol_default_),
00372   orthoKappa_(orthoKappa_default_),
00373   maxIters_(maxIters_default_),
00374   blockSize_(blockSize_default_),
00375   verbosity_(verbosity_default_),
00376   outputStyle_(outputStyle_default_),
00377   outputFreq_(outputFreq_default_),
00378   adaptiveBlockSize_(adaptiveBlockSize_default_),
00379   showMaxResNormOnly_(showMaxResNormOnly_default_),
00380   orthoType_(orthoType_default_),
00381   label_(label_default_),
00382   isSet_(false)
00383 {
00384   TEST_FOR_EXCEPTION(problem_ == Teuchos::null, std::invalid_argument, "Problem not given to solver manager.");
00385 
00386   // If the parameter list pointer is null, then set the current parameters to the default parameter list.
00387   if ( !is_null(pl) ) {
00388     setParameters( pl );  
00389   }
00390 }
00391 
00392 template<class ScalarType, class MV, class OP>
00393 void BlockCGSolMgr<ScalarType,MV,OP>::setParameters( const Teuchos::RCP<Teuchos::ParameterList> &params )
00394 {
00395   // Create the internal parameter list if ones doesn't already exist.
00396   if (params_ == Teuchos::null) {
00397     params_ = Teuchos::rcp( new Teuchos::ParameterList(*getValidParameters()) );
00398   }
00399   else {
00400     params->validateParameters(*getValidParameters());
00401   }
00402 
00403   // Check for maximum number of iterations
00404   if (params->isParameter("Maximum Iterations")) {
00405     maxIters_ = params->get("Maximum Iterations",maxIters_default_);
00406 
00407     // Update parameter in our list and in status test.
00408     params_->set("Maximum Iterations", maxIters_);
00409     if (maxIterTest_!=Teuchos::null)
00410       maxIterTest_->setMaxIters( maxIters_ );
00411   }
00412 
00413   // Check for blocksize
00414   if (params->isParameter("Block Size")) {
00415     blockSize_ = params->get("Block Size",blockSize_default_);    
00416     TEST_FOR_EXCEPTION(blockSize_ <= 0, std::invalid_argument,
00417            "Belos::BlockCGSolMgr: \"Block Size\" must be strictly positive.");
00418 
00419     // Update parameter in our list.
00420     params_->set("Block Size", blockSize_);
00421   }
00422 
00423   // Check if the blocksize should be adaptive
00424   if (params->isParameter("Adaptive Block Size")) {
00425     adaptiveBlockSize_ = params->get("Adaptive Block Size",adaptiveBlockSize_default_);
00426     
00427     // Update parameter in our list.
00428     params_->set("Adaptive Block Size", adaptiveBlockSize_);
00429   }
00430 
00431   // Check to see if the timer label changed.
00432   if (params->isParameter("Timer Label")) {
00433     std::string tempLabel = params->get("Timer Label", label_default_);
00434 
00435     // Update parameter in our list and solver timer
00436     if (tempLabel != label_) {
00437       label_ = tempLabel;
00438       params_->set("Timer Label", label_);
00439       std::string solveLabel = label_ + ": BlockCGSolMgr total solve time";
00440 #ifdef BELOS_TEUCHOS_TIME_MONITOR
00441       timerSolve_ = Teuchos::TimeMonitor::getNewTimer(solveLabel);
00442 #endif
00443     }
00444   }
00445 
00446   // Check if the orthogonalization changed.
00447   if (params->isParameter("Orthogonalization")) {
00448     std::string tempOrthoType = params->get("Orthogonalization",orthoType_default_);
00449     TEST_FOR_EXCEPTION( tempOrthoType != "DGKS" && tempOrthoType != "ICGS" && tempOrthoType != "IMGS", 
00450                         std::invalid_argument,
00451       "Belos::BlockCGSolMgr: \"Orthogonalization\" must be either \"DGKS\", \"ICGS\", or \"IMGS\".");
00452     if (tempOrthoType != orthoType_) {
00453       orthoType_ = tempOrthoType;
00454       // Create orthogonalization manager
00455       if (orthoType_=="DGKS") {
00456   if (orthoKappa_ <= 0) {
00457     ortho_ = Teuchos::rcp( new DGKSOrthoManager<ScalarType,MV,OP>( label_ ) );
00458   }
00459   else {
00460     ortho_ = Teuchos::rcp( new DGKSOrthoManager<ScalarType,MV,OP>( label_ ) );
00461     Teuchos::rcp_dynamic_cast<DGKSOrthoManager<ScalarType,MV,OP> >(ortho_)->setDepTol( orthoKappa_ );
00462   }
00463       }
00464       else if (orthoType_=="ICGS") {
00465   ortho_ = Teuchos::rcp( new ICGSOrthoManager<ScalarType,MV,OP>( label_ ) );
00466       } 
00467       else if (orthoType_=="IMGS") {
00468   ortho_ = Teuchos::rcp( new IMGSOrthoManager<ScalarType,MV,OP>( label_ ) );
00469       } 
00470     }  
00471   }
00472 
00473   // Check which orthogonalization constant to use.
00474   if (params->isParameter("Orthogonalization Constant")) {
00475     orthoKappa_ = params->get("Orthogonalization Constant",orthoKappa_default_);
00476 
00477     // Update parameter in our list.
00478     params_->set("Orthogonalization Constant",orthoKappa_);
00479     if (orthoType_=="DGKS") {
00480       if (orthoKappa_ > 0 && ortho_ != Teuchos::null) {
00481   Teuchos::rcp_dynamic_cast<DGKSOrthoManager<ScalarType,MV,OP> >(ortho_)->setDepTol( orthoKappa_ );
00482       }
00483     } 
00484   }
00485 
00486   // Check for a change in verbosity level
00487   if (params->isParameter("Verbosity")) {
00488     if (Teuchos::isParameterType<int>(*params,"Verbosity")) {
00489       verbosity_ = params->get("Verbosity", verbosity_default_);
00490     } else {
00491       verbosity_ = (int)Teuchos::getParameter<Belos::MsgType>(*params,"Verbosity");
00492     }
00493 
00494     // Update parameter in our list.
00495     params_->set("Verbosity", verbosity_);
00496     if (printer_ != Teuchos::null)
00497       printer_->setVerbosity(verbosity_);
00498   }
00499 
00500   // Check for a change in output style
00501   if (params->isParameter("Output Style")) {
00502     if (Teuchos::isParameterType<int>(*params,"Output Style")) {
00503       outputStyle_ = params->get("Output Style", outputStyle_default_);
00504     } else {
00505       outputStyle_ = (int)Teuchos::getParameter<Belos::OutputType>(*params,"Output Style");
00506     }
00507 
00508     // Update parameter in our list.
00509     params_->set("Output Style", outputStyle_);
00510     outputTest_ = Teuchos::null;
00511   }
00512 
00513   // output stream
00514   if (params->isParameter("Output Stream")) {
00515     outputStream_ = Teuchos::getParameter<Teuchos::RCP<std::ostream> >(*params,"Output Stream");
00516 
00517     // Update parameter in our list.
00518     params_->set("Output Stream", outputStream_);
00519     if (printer_ != Teuchos::null)
00520       printer_->setOStream( outputStream_ );
00521   }
00522 
00523   // frequency level
00524   if (verbosity_ & Belos::StatusTestDetails) {
00525     if (params->isParameter("Output Frequency")) {
00526       outputFreq_ = params->get("Output Frequency", outputFreq_default_);
00527     }
00528 
00529     // Update parameter in out list and output status test.
00530     params_->set("Output Frequency", outputFreq_);
00531     if (outputTest_ != Teuchos::null)
00532       outputTest_->setOutputFrequency( outputFreq_ );
00533   }
00534 
00535   // Create output manager if we need to.
00536   if (printer_ == Teuchos::null) {
00537     printer_ = Teuchos::rcp( new OutputManager<ScalarType>(verbosity_, outputStream_) );
00538   }  
00539   
00540   // Convergence
00541   typedef Belos::StatusTestCombo<ScalarType,MV,OP>  StatusTestCombo_t;
00542   typedef Belos::StatusTestGenResNorm<ScalarType,MV,OP>  StatusTestResNorm_t;
00543 
00544   // Check for convergence tolerance
00545   if (params->isParameter("Convergence Tolerance")) {
00546     convtol_ = params->get("Convergence Tolerance",convtol_default_);
00547 
00548     // Update parameter in our list and residual tests.
00549     params_->set("Convergence Tolerance", convtol_);
00550     if (convTest_ != Teuchos::null)
00551       convTest_->setTolerance( convtol_ );
00552   }
00553   
00554   if (params->isParameter("Show Maximum Residual Norm Only")) {
00555     showMaxResNormOnly_ = Teuchos::getParameter<bool>(*params,"Show Maximum Residual Norm Only");
00556 
00557     // Update parameter in our list and residual tests
00558     params_->set("Show Maximum Residual Norm Only", showMaxResNormOnly_);
00559     if (convTest_ != Teuchos::null)
00560       convTest_->setShowMaxResNormOnly( showMaxResNormOnly_ );
00561   }
00562 
00563   // Create status tests if we need to.
00564 
00565   // Basic test checks maximum iterations and native residual.
00566   if (maxIterTest_ == Teuchos::null)
00567     maxIterTest_ = Teuchos::rcp( new StatusTestMaxIters<ScalarType,MV,OP>( maxIters_ ) );
00568   
00569   // Implicit residual test, using the native residual to determine if convergence was achieved.
00570   if (convTest_ == Teuchos::null)
00571     convTest_ = Teuchos::rcp( new StatusTestResNorm_t( convtol_, 1 ) );
00572   
00573   if (sTest_ == Teuchos::null)
00574     sTest_ = Teuchos::rcp( new StatusTestCombo_t( StatusTestCombo_t::OR, maxIterTest_, convTest_ ) );
00575   
00576   if (outputTest_ == Teuchos::null) {
00577 
00578     // Create the status test output class.
00579     // This class manages and formats the output from the status test.
00580     StatusTestOutputFactory<ScalarType,MV,OP> stoFactory( outputStyle_ );
00581     outputTest_ = stoFactory.create( printer_, sTest_, outputFreq_, Passed+Failed+Undefined );
00582 
00583     // Set the solver string for the output test
00584     std::string solverDesc = " Block CG ";
00585     outputTest_->setSolverDesc( solverDesc );
00586 
00587   }
00588 
00589   // Create orthogonalization manager if we need to.
00590   if (ortho_ == Teuchos::null) {
00591     if (orthoType_=="DGKS") {
00592       if (orthoKappa_ <= 0) {
00593   ortho_ = Teuchos::rcp( new DGKSOrthoManager<ScalarType,MV,OP>( label_ ) );
00594       }
00595       else {
00596   ortho_ = Teuchos::rcp( new DGKSOrthoManager<ScalarType,MV,OP>( label_ ) );
00597   Teuchos::rcp_dynamic_cast<DGKSOrthoManager<ScalarType,MV,OP> >(ortho_)->setDepTol( orthoKappa_ );
00598       }
00599     }
00600     else if (orthoType_=="ICGS") {
00601       ortho_ = Teuchos::rcp( new ICGSOrthoManager<ScalarType,MV,OP>( label_ ) );
00602     } 
00603     else if (orthoType_=="IMGS") {
00604       ortho_ = Teuchos::rcp( new IMGSOrthoManager<ScalarType,MV,OP>( label_ ) );
00605     } 
00606     else {
00607       TEST_FOR_EXCEPTION(orthoType_!="ICGS"&&orthoType_!="DGKS"&&orthoType_!="IMGS",std::logic_error,
00608        "Belos::BlockCGSolMgr(): Invalid orthogonalization type.");
00609     }  
00610   }
00611 
00612   // Create the timer if we need to.
00613   if (timerSolve_ == Teuchos::null) {
00614     std::string solveLabel = label_ + ": BlockCGSolMgr total solve time";
00615 #ifdef BELOS_TEUCHOS_TIME_MONITOR
00616     timerSolve_ = Teuchos::TimeMonitor::getNewTimer(solveLabel);
00617 #endif
00618   }
00619 
00620   // Inform the solver manager that the current parameters were set.
00621   isSet_ = true;
00622 }
00623 
00624     
00625 template<class ScalarType, class MV, class OP>
00626 Teuchos::RCP<const Teuchos::ParameterList> 
00627 BlockCGSolMgr<ScalarType,MV,OP>::getValidParameters() const
00628 {
00629   static Teuchos::RCP<const Teuchos::ParameterList> validPL;
00630   
00631   // Set all the valid parameters and their default values.
00632   if(is_null(validPL)) {
00633     Teuchos::RCP<Teuchos::ParameterList> pl = Teuchos::parameterList();
00634     pl->set("Convergence Tolerance", convtol_default_,
00635       "The relative residual tolerance that needs to be achieved by the\n"
00636       "iterative solver in order for the linear system to be declared converged.");
00637     pl->set("Maximum Iterations", maxIters_default_,
00638       "The maximum number of block iterations allowed for each\n"
00639       "set of RHS solved.");
00640     pl->set("Block Size", blockSize_default_,
00641       "The number of vectors in each block.");
00642     pl->set("Adaptive Block Size", adaptiveBlockSize_default_,
00643       "Whether the solver manager should adapt to the block size\n"
00644       "based on the number of RHS to solve.");
00645     pl->set("Verbosity", verbosity_default_,
00646       "What type(s) of solver information should be outputted\n"
00647       "to the output stream.");
00648     pl->set("Output Style", outputStyle_default_,
00649       "What style is used for the solver information outputted\n"
00650       "to the output stream.");
00651     pl->set("Output Frequency", outputFreq_default_,
00652       "How often convergence information should be outputted\n"
00653       "to the output stream.");  
00654     pl->set("Output Stream", outputStream_default_,
00655       "A reference-counted pointer to the output stream where all\n"
00656       "solver output is sent.");
00657     pl->set("Show Maximum Residual Norm Only", showMaxResNormOnly_default_,
00658       "When convergence information is printed, only show the maximum\n"
00659       "relative residual norm when the block size is greater than one.");
00660     pl->set("Timer Label", label_default_,
00661       "The string to use as a prefix for the timer labels.");
00662     //  pl->set("Restart Timers", restartTimers_);
00663     pl->set("Orthogonalization", orthoType_default_,
00664       "The type of orthogonalization to use: DGKS, ICGS, or IMGS.");
00665     pl->set("Orthogonalization Constant",orthoKappa_default_,
00666       "The constant used by DGKS orthogonalization to determine\n"
00667       "whether another step of classical Gram-Schmidt is necessary.");
00668     validPL = pl;
00669   }
00670   return validPL;
00671 }
00672 
00673   
00674 // solve()
00675 template<class ScalarType, class MV, class OP>
00676 ReturnType BlockCGSolMgr<ScalarType,MV,OP>::solve() {
00677 
00678   // Set the current parameters if they were not set before.
00679   // NOTE:  This may occur if the user generated the solver manager with the default constructor and 
00680   // then didn't set any parameters using setParameters().
00681   if (!isSet_) {
00682     setParameters(Teuchos::parameterList(*getValidParameters()));
00683   }
00684 
00685   Teuchos::BLAS<int,ScalarType> blas;
00686   Teuchos::LAPACK<int,ScalarType> lapack;
00687   
00688   TEST_FOR_EXCEPTION(!problem_->isProblemSet(),BlockCGSolMgrLinearProblemFailure,
00689                      "Belos::BlockCGSolMgr::solve(): Linear problem is not ready, setProblem() has not been called.");
00690 
00691   // Create indices for the linear systems to be solved.
00692   int startPtr = 0;
00693   int numRHS2Solve = MVT::GetNumberVecs( *(problem_->getRHS()) );
00694   int numCurrRHS = ( numRHS2Solve < blockSize_) ? numRHS2Solve : blockSize_;
00695 
00696   std::vector<int> currIdx, currIdx2;
00697   //  If an adaptive block size is allowed then only the linear systems that need to be solved are solved.
00698   //  Otherwise, the index set is generated that informs the linear problem that some linear systems are augmented.
00699   if ( adaptiveBlockSize_ ) {
00700     blockSize_ = numCurrRHS;
00701     currIdx.resize( numCurrRHS  );
00702     currIdx2.resize( numCurrRHS  );
00703     for (int i=0; i<numCurrRHS; ++i) 
00704       { currIdx[i] = startPtr+i; currIdx2[i]=i; }
00705     
00706   }
00707   else {
00708     currIdx.resize( blockSize_ );
00709     currIdx2.resize( blockSize_ );
00710     for (int i=0; i<numCurrRHS; ++i) 
00711       { currIdx[i] = startPtr+i; currIdx2[i]=i; }
00712     for (int i=numCurrRHS; i<blockSize_; ++i) 
00713       { currIdx[i] = -1; currIdx2[i] = i; }
00714   }
00715 
00716   // Inform the linear problem of the current linear system to solve.
00717   problem_->setLSIndex( currIdx );
00718 
00720   // Parameter list
00721   Teuchos::ParameterList plist;
00722   plist.set("Block Size",blockSize_);
00723   
00724   // Reset the status test.  
00725   outputTest_->reset();
00726 
00727   // Assume convergence is achieved, then let any failed convergence set this to false.
00728   bool isConverged = true;  
00729 
00731   // BlockCG solver
00732 
00733   Teuchos::RCP<CGIteration<ScalarType,MV,OP> > block_cg_iter;
00734   if (blockSize_ == 1)
00735     block_cg_iter = Teuchos::rcp( new CGIter<ScalarType,MV,OP>(problem_,printer_,outputTest_,plist) );
00736   else
00737     block_cg_iter = Teuchos::rcp( new BlockCGIter<ScalarType,MV,OP>(problem_,printer_,outputTest_,ortho_,plist) );
00738   
00739 
00740   // Enter solve() iterations
00741   {
00742 #ifdef BELOS_TEUCHOS_TIME_MONITOR
00743     Teuchos::TimeMonitor slvtimer(*timerSolve_);
00744 #endif
00745 
00746     while ( numRHS2Solve > 0 ) {
00747       //
00748       // Reset the active / converged vectors from this block
00749       std::vector<int> convRHSIdx;
00750       std::vector<int> currRHSIdx( currIdx );
00751       currRHSIdx.resize(numCurrRHS);
00752 
00753       // Reset the number of iterations.
00754       block_cg_iter->resetNumIters();
00755 
00756       // Reset the number of calls that the status test output knows about.
00757       outputTest_->resetNumCalls();
00758 
00759       // Get the current residual for this block of linear systems.
00760       Teuchos::RCP<MV> R_0 = MVT::CloneViewNonConst( *(Teuchos::rcp_const_cast<MV>(problem_->getInitResVec())), currIdx );
00761 
00762       // Set the new state and initialize the solver.
00763       CGIterationState<ScalarType,MV> newstate;
00764       newstate.R = R_0;
00765       block_cg_iter->initializeCG(newstate);
00766 
00767       while(1) {
00768   
00769   // tell block_cg_iter to iterate
00770   try {
00771     block_cg_iter->iterate();
00772     
00774     //
00775     // check convergence first
00776     //
00778     if ( convTest_->getStatus() == Passed ) {
00779       // We have convergence of at least one linear system.
00780 
00781       // Figure out which linear systems converged.
00782       std::vector<int> convIdx = Teuchos::rcp_dynamic_cast<StatusTestGenResNorm<ScalarType,MV,OP> >(convTest_)->convIndices();
00783 
00784       // If the number of converged linear systems is equal to the
00785             // number of current linear systems, then we are done with this block.
00786       if (convIdx.size() == currRHSIdx.size())
00787         break;  // break from while(1){block_cg_iter->iterate()}
00788 
00789       // Inform the linear problem that we are finished with this current linear system.
00790       problem_->setCurrLS();
00791 
00792       // Reset currRHSIdx to have the right-hand sides that are left to converge for this block.
00793       int have = 0;
00794             std::vector<int> unconvIdx(currRHSIdx.size());
00795       for (unsigned int i=0; i<currRHSIdx.size(); ++i) {
00796         bool found = false;
00797         for (unsigned int j=0; j<convIdx.size(); ++j) {
00798     if (currRHSIdx[i] == convIdx[j]) {
00799       found = true;
00800       break;
00801     }
00802         }
00803         if (!found) {
00804                 currIdx2[have] = currIdx2[i];
00805     currRHSIdx[have++] = currRHSIdx[i];
00806         }
00807               else {
00808               } 
00809       }
00810       currRHSIdx.resize(have);
00811       currIdx2.resize(have);
00812 
00813       // Set the remaining indices after deflation.
00814       problem_->setLSIndex( currRHSIdx );
00815 
00816       // Get the current residual vector.
00817       std::vector<MagnitudeType> norms;
00818             R_0 = MVT::CloneCopy( *(block_cg_iter->getNativeResiduals(&norms)),currIdx2 );
00819       for (int i=0; i<have; ++i) { currIdx2[i] = i; }
00820 
00821       // Set the new blocksize for the solver.
00822       block_cg_iter->setBlockSize( have );
00823 
00824       // Set the new state and initialize the solver.
00825       CGIterationState<ScalarType,MV> defstate;
00826       defstate.R = R_0;
00827       block_cg_iter->initializeCG(defstate);
00828     }
00830     //
00831     // check for maximum iterations
00832     //
00834     else if ( maxIterTest_->getStatus() == Passed ) {
00835       // we don't have convergence
00836       isConverged = false;
00837       break;  // break from while(1){block_cg_iter->iterate()}
00838     }
00839 
00841     //
00842     // we returned from iterate(), but none of our status tests Passed.
00843     // something is wrong, and it is probably our fault.
00844     //
00846 
00847     else {
00848       TEST_FOR_EXCEPTION(true,std::logic_error,
00849              "Belos::BlockCGSolMgr::solve(): Invalid return from CGIteration::iterate().");
00850     }
00851   }
00852   catch (const std::exception &e) {
00853     printer_->stream(Errors) << "Error! Caught std::exception in CGIteration::iterate() at iteration " 
00854            << block_cg_iter->getNumIters() << std::endl 
00855            << e.what() << std::endl;
00856     throw;
00857   }
00858       }
00859       
00860       // Inform the linear problem that we are finished with this block linear system.
00861       problem_->setCurrLS();
00862       
00863       // Update indices for the linear systems to be solved.
00864       startPtr += numCurrRHS;
00865       numRHS2Solve -= numCurrRHS;
00866       if ( numRHS2Solve > 0 ) {
00867   numCurrRHS = ( numRHS2Solve < blockSize_) ? numRHS2Solve : blockSize_;
00868 
00869   if ( adaptiveBlockSize_ ) {
00870           blockSize_ = numCurrRHS;
00871     currIdx.resize( numCurrRHS  );
00872     currIdx2.resize( numCurrRHS  );
00873     for (int i=0; i<numCurrRHS; ++i) 
00874       { currIdx[i] = startPtr+i; currIdx2[i] = i; }   
00875   }
00876   else {
00877     currIdx.resize( blockSize_ );
00878     currIdx2.resize( blockSize_ );
00879     for (int i=0; i<numCurrRHS; ++i) 
00880       { currIdx[i] = startPtr+i; currIdx2[i] = i; }
00881     for (int i=numCurrRHS; i<blockSize_; ++i) 
00882       { currIdx[i] = -1; currIdx2[i] = i; }
00883   }
00884   // Set the next indices.
00885   problem_->setLSIndex( currIdx );
00886 
00887   // Set the new blocksize for the solver.
00888   block_cg_iter->setBlockSize( blockSize_ );  
00889       }
00890       else {
00891         currIdx.resize( numRHS2Solve );
00892       }
00893       
00894     }// while ( numRHS2Solve > 0 )
00895     
00896   }
00897 
00898   // print final summary
00899   sTest_->print( printer_->stream(FinalSummary) );
00900  
00901   // print timing information
00902 #ifdef BELOS_TEUCHOS_TIME_MONITOR
00903   // Calling summarize() can be expensive, so don't call unless the
00904   // user wants to print out timing details.  summarize() will do all
00905   // the work even if it's passed a "black hole" output stream.
00906   if (verbosity_ & TimingDetails)
00907     Teuchos::TimeMonitor::summarize( printer_->stream(TimingDetails) );
00908 #endif
00909  
00910   // get iteration information for this solve
00911   numIters_ = maxIterTest_->getNumIters();
00912  
00913   if (!isConverged) {
00914     return Unconverged; // return from BlockCGSolMgr::solve() 
00915   }
00916   return Converged; // return from BlockCGSolMgr::solve() 
00917 }
00918 
00919 //  This method requires the solver manager to return a std::string that describes itself.
00920 template<class ScalarType, class MV, class OP>
00921 std::string BlockCGSolMgr<ScalarType,MV,OP>::description() const
00922 {
00923   std::ostringstream oss;
00924   oss << "Belos::BlockCGSolMgr<...,"<<Teuchos::ScalarTraits<ScalarType>::name()<<">";
00925   oss << "{";
00926   oss << "Ortho Type='"<<orthoType_<<"\', Block Size=" << blockSize_;
00927   oss << "}";
00928   return oss.str();
00929 }
00930   
00931 } // end Belos namespace
00932 
00933 #endif /* BELOS_BLOCK_CG_SOLMGR_HPP */
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines