Belos Version of the Day
BelosPseudoBlockGmresSolMgr.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_PSEUDO_BLOCK_GMRES_SOLMGR_HPP
00043 #define BELOS_PSEUDO_BLOCK_GMRES_SOLMGR_HPP
00044 
00049 #include "BelosConfigDefs.hpp"
00050 #include "BelosTypes.hpp"
00051 
00052 #include "BelosLinearProblem.hpp"
00053 #include "BelosSolverManager.hpp"
00054 
00055 #include "BelosPseudoBlockGmresIter.hpp"
00056 #include "BelosDGKSOrthoManager.hpp"
00057 #include "BelosICGSOrthoManager.hpp"
00058 #include "BelosIMGSOrthoManager.hpp"
00059 #include "BelosStatusTestMaxIters.hpp"
00060 #include "BelosStatusTestGenResNorm.hpp"
00061 #include "BelosStatusTestImpResNorm.hpp"
00062 #include "BelosStatusTestCombo.hpp"
00063 #include "BelosStatusTestOutputFactory.hpp"
00064 #include "BelosOutputManager.hpp"
00065 #include "Teuchos_BLAS.hpp"
00066 #ifdef BELOS_TEUCHOS_TIME_MONITOR
00067 #include "Teuchos_TimeMonitor.hpp"
00068 #endif
00069 
00077 namespace Belos {
00078   
00080 
00081   
00088   class PseudoBlockGmresSolMgrLinearProblemFailure : public BelosError {public:
00089     PseudoBlockGmresSolMgrLinearProblemFailure(const std::string& what_arg) : BelosError(what_arg)
00090     {}};
00091   
00098   class PseudoBlockGmresSolMgrOrthoFailure : public BelosError {public:
00099     PseudoBlockGmresSolMgrOrthoFailure(const std::string& what_arg) : BelosError(what_arg)
00100     {}};
00101 
00125   template<class ScalarType, class MV, class OP>
00126   class PseudoBlockGmresSolMgr : public SolverManager<ScalarType,MV,OP> {
00127     
00128   private:
00129     typedef MultiVecTraits<ScalarType,MV> MVT;
00130     typedef OperatorTraits<ScalarType,MV,OP> OPT;
00131     typedef Teuchos::ScalarTraits<ScalarType> SCT;
00132     typedef typename Teuchos::ScalarTraits<ScalarType>::magnitudeType MagnitudeType;
00133     typedef Teuchos::ScalarTraits<MagnitudeType> MT;
00134     
00135   public:
00136     
00138 
00139 
00147     PseudoBlockGmresSolMgr();
00148     
00252     PseudoBlockGmresSolMgr( const Teuchos::RCP<LinearProblem<ScalarType,MV,OP> > &problem,
00253                             const Teuchos::RCP<Teuchos::ParameterList> &pl );
00254     
00256     virtual ~PseudoBlockGmresSolMgr() {};
00258     
00260 
00261     
00262     const LinearProblem<ScalarType,MV,OP>& getProblem() const {
00263       return *problem_;
00264     }
00265     
00267     Teuchos::RCP<const Teuchos::ParameterList> getValidParameters() const;
00268    
00270     Teuchos::RCP<const Teuchos::ParameterList> getCurrentParameters() const { return params_; }
00271  
00277     Teuchos::Array<Teuchos::RCP<Teuchos::Time> > getTimers() const {
00278       return Teuchos::tuple(timerSolve_);
00279     }
00280 
00291     MagnitudeType achievedTol() const {
00292       return achievedTol_;
00293     }
00294 
00296     int getNumIters() const {
00297       return numIters_;
00298     }
00299   
00355     bool isLOADetected() const { return loaDetected_; }
00356   
00358     
00360 
00361    
00363     void setProblem (const Teuchos::RCP<LinearProblem<ScalarType,MV,OP> > &problem) {
00364       problem_ = problem; 
00365     }
00366    
00368     void setParameters (const Teuchos::RCP<Teuchos::ParameterList> &params);
00369 
00376     virtual void setUserConvStatusTest(
00377       const Teuchos::RCP<StatusTest<ScalarType,MV,OP> > &userConvStatusTest
00378       );
00379     
00381 
00383 
00384 
00388     void reset( const ResetType type ) { if ((type & Belos::Problem) && !Teuchos::is_null(problem_)) problem_->setProblem(); }
00390 
00392 
00393     
00411     ReturnType solve();
00412     
00414     
00417     
00419     std::string description() const;
00420     
00422     
00423   private:
00424 
00439     bool checkStatusTest();
00440     
00442     Teuchos::RCP<LinearProblem<ScalarType,MV,OP> > problem_;
00443     
00444     // Output manager.
00445     Teuchos::RCP<OutputManager<ScalarType> > printer_;
00446     Teuchos::RCP<std::ostream> outputStream_;
00447 
00448     // Status tests.
00449     Teuchos::RCP<StatusTest<ScalarType,MV,OP> > userConvStatusTest_;
00450     Teuchos::RCP<StatusTest<ScalarType,MV,OP> > sTest_;
00451     Teuchos::RCP<StatusTestMaxIters<ScalarType,MV,OP> > maxIterTest_;
00452     Teuchos::RCP<StatusTest<ScalarType,MV,OP> > convTest_;
00453     Teuchos::RCP<StatusTestResNorm<ScalarType,MV,OP> > impConvTest_, expConvTest_;
00454     Teuchos::RCP<StatusTestOutput<ScalarType,MV,OP> > outputTest_;
00455 
00456     // Orthogonalization manager.
00457     Teuchos::RCP<MatOrthoManager<ScalarType,MV,OP> > ortho_; 
00458 
00459      // Current parameter list.
00460     Teuchos::RCP<Teuchos::ParameterList> params_;
00461    
00462     // Default solver values.
00463     static const MagnitudeType convtol_default_;
00464     static const MagnitudeType orthoKappa_default_;
00465     static const int maxRestarts_default_;
00466     static const int maxIters_default_;
00467     static const bool showMaxResNormOnly_default_;
00468     static const int blockSize_default_;
00469     static const int numBlocks_default_;
00470     static const int verbosity_default_;
00471     static const int outputStyle_default_;
00472     static const int outputFreq_default_;
00473     static const int defQuorum_default_;
00474     static const std::string impResScale_default_; 
00475     static const std::string expResScale_default_; 
00476     static const std::string label_default_;
00477     static const std::string orthoType_default_;
00478     static const Teuchos::RCP<std::ostream> outputStream_default_;
00479 
00480     // Current solver values.
00481     MagnitudeType convtol_, orthoKappa_, achievedTol_;
00482     int maxRestarts_, maxIters_, numIters_;
00483     int blockSize_, numBlocks_, verbosity_, outputStyle_, outputFreq_, defQuorum_;
00484     bool showMaxResNormOnly_;
00485     std::string orthoType_; 
00486     std::string impResScale_, expResScale_;       
00487  
00488     // Timers.
00489     std::string label_;
00490     Teuchos::RCP<Teuchos::Time> timerSolve_;
00491 
00492     // Internal state variables.
00493     bool isSet_, isSTSet_, expResTest_;
00494     bool loaDetected_;
00495   };
00496   
00497   
00498 // Default solver values.
00499 template<class ScalarType, class MV, class OP>
00500 const typename PseudoBlockGmresSolMgr<ScalarType,MV,OP>::MagnitudeType PseudoBlockGmresSolMgr<ScalarType,MV,OP>::convtol_default_ = 1e-8;
00501 
00502 template<class ScalarType, class MV, class OP>
00503 const typename PseudoBlockGmresSolMgr<ScalarType,MV,OP>::MagnitudeType PseudoBlockGmresSolMgr<ScalarType,MV,OP>::orthoKappa_default_ = -1.0;
00504 
00505 template<class ScalarType, class MV, class OP>
00506 const int PseudoBlockGmresSolMgr<ScalarType,MV,OP>::maxRestarts_default_ = 20;
00507 
00508 template<class ScalarType, class MV, class OP>
00509 const int PseudoBlockGmresSolMgr<ScalarType,MV,OP>::maxIters_default_ = 1000;
00510 
00511 template<class ScalarType, class MV, class OP>
00512 const bool PseudoBlockGmresSolMgr<ScalarType,MV,OP>::showMaxResNormOnly_default_ = false;
00513 
00514 template<class ScalarType, class MV, class OP>
00515 const int PseudoBlockGmresSolMgr<ScalarType,MV,OP>::blockSize_default_ = 1;
00516 
00517 template<class ScalarType, class MV, class OP>
00518 const int PseudoBlockGmresSolMgr<ScalarType,MV,OP>::numBlocks_default_ = 300;
00519 
00520 template<class ScalarType, class MV, class OP>
00521 const int PseudoBlockGmresSolMgr<ScalarType,MV,OP>::verbosity_default_ = Belos::Errors;
00522 
00523 template<class ScalarType, class MV, class OP>
00524 const int PseudoBlockGmresSolMgr<ScalarType,MV,OP>::outputStyle_default_ = Belos::General;
00525 
00526 template<class ScalarType, class MV, class OP>
00527 const int PseudoBlockGmresSolMgr<ScalarType,MV,OP>::outputFreq_default_ = -1;
00528 
00529 template<class ScalarType, class MV, class OP>
00530 const int PseudoBlockGmresSolMgr<ScalarType,MV,OP>::defQuorum_default_ = 1;
00531 
00532 template<class ScalarType, class MV, class OP>
00533 const std::string PseudoBlockGmresSolMgr<ScalarType,MV,OP>::impResScale_default_ = "Norm of Preconditioned Initial Residual";
00534 
00535 template<class ScalarType, class MV, class OP>
00536 const std::string PseudoBlockGmresSolMgr<ScalarType,MV,OP>::expResScale_default_ = "Norm of Initial Residual";
00537 
00538 template<class ScalarType, class MV, class OP>
00539 const std::string PseudoBlockGmresSolMgr<ScalarType,MV,OP>::label_default_ = "Belos";
00540 
00541 template<class ScalarType, class MV, class OP>
00542 const std::string PseudoBlockGmresSolMgr<ScalarType,MV,OP>::orthoType_default_ = "DGKS";
00543 
00544 template<class ScalarType, class MV, class OP>
00545 const Teuchos::RCP<std::ostream> PseudoBlockGmresSolMgr<ScalarType,MV,OP>::outputStream_default_ = Teuchos::rcp(&std::cout,false);
00546 
00547 
00548 // Empty Constructor
00549 template<class ScalarType, class MV, class OP>
00550 PseudoBlockGmresSolMgr<ScalarType,MV,OP>::PseudoBlockGmresSolMgr() :
00551   outputStream_(outputStream_default_),
00552   convtol_(convtol_default_),
00553   orthoKappa_(orthoKappa_default_),
00554   achievedTol_(Teuchos::ScalarTraits<typename Teuchos::ScalarTraits<ScalarType>::magnitudeType>::zero()),
00555   maxRestarts_(maxRestarts_default_),
00556   maxIters_(maxIters_default_),
00557   numIters_(0),
00558   blockSize_(blockSize_default_),
00559   numBlocks_(numBlocks_default_),
00560   verbosity_(verbosity_default_),
00561   outputStyle_(outputStyle_default_),
00562   outputFreq_(outputFreq_default_),
00563   defQuorum_(defQuorum_default_),
00564   showMaxResNormOnly_(showMaxResNormOnly_default_),
00565   orthoType_(orthoType_default_),
00566   impResScale_(impResScale_default_),
00567   expResScale_(expResScale_default_),
00568   label_(label_default_),
00569   isSet_(false),
00570   isSTSet_(false),
00571   expResTest_(false),
00572   loaDetected_(false)
00573 {}
00574 
00575 // Basic Constructor
00576 template<class ScalarType, class MV, class OP>
00577 PseudoBlockGmresSolMgr<ScalarType,MV,OP>::
00578 PseudoBlockGmresSolMgr (const Teuchos::RCP<LinearProblem<ScalarType,MV,OP> > &problem,
00579                         const Teuchos::RCP<Teuchos::ParameterList> &pl) : 
00580   problem_(problem),
00581   outputStream_(outputStream_default_),
00582   convtol_(convtol_default_),
00583   orthoKappa_(orthoKappa_default_),
00584   achievedTol_(Teuchos::ScalarTraits<typename Teuchos::ScalarTraits<ScalarType>::magnitudeType>::zero()),
00585   maxRestarts_(maxRestarts_default_),
00586   maxIters_(maxIters_default_),
00587   numIters_(0),
00588   blockSize_(blockSize_default_),
00589   numBlocks_(numBlocks_default_),
00590   verbosity_(verbosity_default_),
00591   outputStyle_(outputStyle_default_),
00592   outputFreq_(outputFreq_default_),
00593   defQuorum_(defQuorum_default_),
00594   showMaxResNormOnly_(showMaxResNormOnly_default_),
00595   orthoType_(orthoType_default_),
00596   impResScale_(impResScale_default_),
00597   expResScale_(expResScale_default_),
00598   label_(label_default_),
00599   isSet_(false),
00600   isSTSet_(false),
00601   expResTest_(false),
00602   loaDetected_(false)
00603 {
00604   TEUCHOS_TEST_FOR_EXCEPTION(problem_ == Teuchos::null, std::invalid_argument, "Problem not given to solver manager.");
00605 
00606   // If the parameter list pointer is null, then set the current parameters to the default parameter list.
00607   if (!is_null(pl)) {
00608     // Set the parameters using the list that was passed in.
00609     setParameters( pl );  
00610   }
00611 }
00612 
00613 template<class ScalarType, class MV, class OP>
00614 void PseudoBlockGmresSolMgr<ScalarType,MV,OP>::setParameters( const Teuchos::RCP<Teuchos::ParameterList> &params )
00615 {
00616   // Create the internal parameter list if ones doesn't already exist.
00617   if (params_ == Teuchos::null) {
00618     params_ = Teuchos::rcp( new Teuchos::ParameterList(*getValidParameters()) );
00619   }
00620   else {
00621     params->validateParameters(*getValidParameters());
00622   }
00623 
00624   // Check for maximum number of restarts
00625   if (params->isParameter("Maximum Restarts")) {
00626     maxRestarts_ = params->get("Maximum Restarts",maxRestarts_default_);
00627 
00628     // Update parameter in our list.
00629     params_->set("Maximum Restarts", maxRestarts_);
00630   }
00631 
00632   // Check for maximum number of iterations
00633   if (params->isParameter("Maximum Iterations")) {
00634     maxIters_ = params->get("Maximum Iterations",maxIters_default_);
00635 
00636     // Update parameter in our list and in status test.
00637     params_->set("Maximum Iterations", maxIters_);
00638     if (maxIterTest_!=Teuchos::null)
00639       maxIterTest_->setMaxIters( maxIters_ );
00640   }
00641 
00642   // Check for blocksize
00643   if (params->isParameter("Block Size")) {
00644     blockSize_ = params->get("Block Size",blockSize_default_);    
00645     TEUCHOS_TEST_FOR_EXCEPTION(blockSize_ <= 0, std::invalid_argument,
00646         "Belos::PseudoBlockGmresSolMgr: \"Block Size\" must be strictly positive.");
00647 
00648     // Update parameter in our list.
00649     params_->set("Block Size", blockSize_);
00650   }
00651 
00652   // Check for the maximum number of blocks.
00653   if (params->isParameter("Num Blocks")) {
00654     numBlocks_ = params->get("Num Blocks",numBlocks_default_);
00655     TEUCHOS_TEST_FOR_EXCEPTION(numBlocks_ <= 0, std::invalid_argument,
00656         "Belos::PseudoBlockGmresSolMgr: \"Num Blocks\" must be strictly positive.");
00657 
00658     // Update parameter in our list.
00659     params_->set("Num Blocks", numBlocks_);
00660   }
00661 
00662   // Check to see if the timer label changed.
00663   if (params->isParameter("Timer Label")) {
00664     std::string tempLabel = params->get("Timer Label", label_default_);
00665 
00666     // Update parameter in our list and solver timer
00667     if (tempLabel != label_) {
00668       label_ = tempLabel;
00669       params_->set("Timer Label", label_);
00670       std::string solveLabel = label_ + ": PseudoBlockGmresSolMgr total solve time";
00671 #ifdef BELOS_TEUCHOS_TIME_MONITOR
00672       timerSolve_ = Teuchos::TimeMonitor::getNewTimer(solveLabel);
00673 #endif
00674     }
00675   }
00676 
00677   // Check if the orthogonalization changed.
00678   if (params->isParameter("Orthogonalization")) {
00679     std::string tempOrthoType = params->get("Orthogonalization",orthoType_default_);
00680     TEUCHOS_TEST_FOR_EXCEPTION( tempOrthoType != "DGKS" && tempOrthoType != "ICGS" && tempOrthoType != "IMGS", 
00681                         std::invalid_argument,
00682                         "Belos::PseudoBlockGmresSolMgr: \"Orthogonalization\" must be either \"DGKS\",\"ICGS\", or \"IMGS\".");
00683     if (tempOrthoType != orthoType_) {
00684       orthoType_ = tempOrthoType;
00685       // Create orthogonalization manager
00686       if (orthoType_=="DGKS") {
00687         if (orthoKappa_ <= 0) {
00688           ortho_ = Teuchos::rcp( new DGKSOrthoManager<ScalarType,MV,OP>( label_ ) );
00689         }
00690         else {
00691           ortho_ = Teuchos::rcp( new DGKSOrthoManager<ScalarType,MV,OP>( label_ ) );
00692           Teuchos::rcp_dynamic_cast<DGKSOrthoManager<ScalarType,MV,OP> >(ortho_)->setDepTol( orthoKappa_ );
00693         }
00694       }
00695       else if (orthoType_=="ICGS") {
00696         ortho_ = Teuchos::rcp( new ICGSOrthoManager<ScalarType,MV,OP>( label_ ) );
00697       } 
00698       else if (orthoType_=="IMGS") {
00699         ortho_ = Teuchos::rcp( new IMGSOrthoManager<ScalarType,MV,OP>( label_ ) );
00700       } 
00701     }  
00702   }
00703 
00704   // Check which orthogonalization constant to use.
00705   if (params->isParameter("Orthogonalization Constant")) {
00706     orthoKappa_ = params->get("Orthogonalization Constant",orthoKappa_default_);
00707 
00708     // Update parameter in our list.
00709     params_->set("Orthogonalization Constant",orthoKappa_);
00710     if (orthoType_=="DGKS") {
00711       if (orthoKappa_ > 0 && ortho_ != Teuchos::null) {
00712         Teuchos::rcp_dynamic_cast<DGKSOrthoManager<ScalarType,MV,OP> >(ortho_)->setDepTol( orthoKappa_ );
00713       }
00714     } 
00715   }
00716 
00717   // Check for a change in verbosity level
00718   if (params->isParameter("Verbosity")) {
00719     if (Teuchos::isParameterType<int>(*params,"Verbosity")) {
00720       verbosity_ = params->get("Verbosity", verbosity_default_);
00721     } else {
00722       verbosity_ = (int)Teuchos::getParameter<Belos::MsgType>(*params,"Verbosity");
00723     }
00724 
00725     // Update parameter in our list.
00726     params_->set("Verbosity", verbosity_);
00727     if (printer_ != Teuchos::null)
00728       printer_->setVerbosity(verbosity_);
00729   }
00730 
00731   // Check for a change in output style.
00732   if (params->isParameter("Output Style")) {
00733     if (Teuchos::isParameterType<int>(*params,"Output Style")) {
00734       outputStyle_ = params->get("Output Style", outputStyle_default_);
00735     } else {
00736       outputStyle_ = (int)Teuchos::getParameter<Belos::OutputType>(*params,"Output Style");
00737     }
00738 
00739     // Update parameter in our list.
00740     params_->set("Output Style", verbosity_);
00741     if (outputTest_ != Teuchos::null)
00742       isSTSet_ = false;
00743   }
00744 
00745   // output stream
00746   if (params->isParameter("Output Stream")) {
00747     outputStream_ = Teuchos::getParameter<Teuchos::RCP<std::ostream> >(*params,"Output Stream");
00748 
00749     // Update parameter in our list.
00750     params_->set("Output Stream", outputStream_);
00751     if (printer_ != Teuchos::null)
00752       printer_->setOStream( outputStream_ );
00753   }
00754 
00755   // frequency level
00756   if (verbosity_ & Belos::StatusTestDetails) {
00757     if (params->isParameter("Output Frequency")) {
00758       outputFreq_ = params->get("Output Frequency", outputFreq_default_);
00759     }
00760 
00761     // Update parameter in out list and output status test.
00762     params_->set("Output Frequency", outputFreq_);
00763     if (outputTest_ != Teuchos::null)
00764       outputTest_->setOutputFrequency( outputFreq_ );
00765   }
00766 
00767   // Create output manager if we need to.
00768   if (printer_ == Teuchos::null) {
00769     printer_ = Teuchos::rcp( new OutputManager<ScalarType>(verbosity_, outputStream_) );
00770   }
00771   
00772   // Convergence
00773   typedef Belos::StatusTestCombo<ScalarType,MV,OP>  StatusTestCombo_t;
00774   typedef Belos::StatusTestGenResNorm<ScalarType,MV,OP>  StatusTestResNorm_t;
00775 
00776   // Check for convergence tolerance
00777   if (params->isParameter("Convergence Tolerance")) {
00778     convtol_ = params->get("Convergence Tolerance",convtol_default_);
00779 
00780     // Update parameter in our list and residual tests.
00781     params_->set("Convergence Tolerance", convtol_);
00782     if (impConvTest_ != Teuchos::null)
00783       impConvTest_->setTolerance( convtol_ );
00784     if (expConvTest_ != Teuchos::null)
00785       expConvTest_->setTolerance( convtol_ );
00786   }
00787 
00788   // Check for a change in scaling, if so we need to build new residual tests.
00789   if (params->isParameter("Implicit Residual Scaling")) {
00790     std::string tempImpResScale = Teuchos::getParameter<std::string>( *params, "Implicit Residual Scaling" );
00791 
00792     // Only update the scaling if it's different.
00793     if (impResScale_ != tempImpResScale) {
00794       Belos::ScaleType impResScaleType = convertStringToScaleType( tempImpResScale );
00795       impResScale_ = tempImpResScale;
00796 
00797       // Update parameter in our list and residual tests
00798       params_->set("Implicit Residual Scaling", impResScale_);
00799       if (impConvTest_ != Teuchos::null) {
00800         try {
00801           impConvTest_->defineScaleForm( impResScaleType, Belos::TwoNorm );
00802         }
00803         catch (std::exception& e) {
00804           // Make sure the convergence test gets constructed again.
00805           isSTSet_ = false;
00806         }
00807       }
00808     }      
00809   }
00810 
00811   if (params->isParameter("Explicit Residual Scaling")) {
00812     std::string tempExpResScale = Teuchos::getParameter<std::string>( *params, "Explicit Residual Scaling" );
00813 
00814     // Only update the scaling if it's different.
00815     if (expResScale_ != tempExpResScale) {
00816       Belos::ScaleType expResScaleType = convertStringToScaleType( tempExpResScale );
00817       expResScale_ = tempExpResScale;
00818 
00819       // Update parameter in our list and residual tests
00820       params_->set("Explicit Residual Scaling", expResScale_);
00821       if (expConvTest_ != Teuchos::null) {
00822         try {
00823           expConvTest_->defineScaleForm( expResScaleType, Belos::TwoNorm );
00824         }
00825         catch (std::exception& e) {
00826           // Make sure the convergence test gets constructed again.
00827           isSTSet_ = false;
00828         }
00829       }
00830     }      
00831   }
00832 
00833 
00834   if (params->isParameter("Show Maximum Residual Norm Only")) {
00835     showMaxResNormOnly_ = Teuchos::getParameter<bool>(*params,"Show Maximum Residual Norm Only");
00836 
00837     // Update parameter in our list and residual tests
00838     params_->set("Show Maximum Residual Norm Only", showMaxResNormOnly_);
00839     if (impConvTest_ != Teuchos::null)
00840       impConvTest_->setShowMaxResNormOnly( showMaxResNormOnly_ );
00841     if (expConvTest_ != Teuchos::null)
00842       expConvTest_->setShowMaxResNormOnly( showMaxResNormOnly_ );
00843   }
00844 
00845   // Create status tests if we need to.
00846 
00847   // Get the deflation quorum, or number of converged systems before deflation is allowed
00848   if (params->isParameter("Deflation Quorum")) {
00849     defQuorum_ = params->get("Deflation Quorum", defQuorum_);
00850     TEUCHOS_TEST_FOR_EXCEPTION(defQuorum_ > blockSize_, std::invalid_argument,
00851         "Belos::PseudoBlockGmresSolMgr: \"Deflation Quorum\" cannot be larger than \"Block Size\".");
00852     params_->set("Deflation Quorum", defQuorum_);
00853     if (impConvTest_ != Teuchos::null)
00854       impConvTest_->setQuorum( defQuorum_ );
00855     if (expConvTest_ != Teuchos::null)
00856       expConvTest_->setQuorum( defQuorum_ );
00857   }
00858 
00859   // Create orthogonalization manager if we need to.
00860   if (ortho_ == Teuchos::null) {
00861     if (orthoType_=="DGKS") {
00862       if (orthoKappa_ <= 0) {
00863         ortho_ = Teuchos::rcp( new DGKSOrthoManager<ScalarType,MV,OP>( label_ ) );
00864       }
00865       else {
00866         ortho_ = Teuchos::rcp( new DGKSOrthoManager<ScalarType,MV,OP>( label_ ) );
00867         Teuchos::rcp_dynamic_cast<DGKSOrthoManager<ScalarType,MV,OP> >(ortho_)->setDepTol( orthoKappa_ );
00868       }
00869     }
00870     else if (orthoType_=="ICGS") {
00871       ortho_ = Teuchos::rcp( new ICGSOrthoManager<ScalarType,MV,OP>( label_ ) );
00872     } 
00873     else if (orthoType_=="IMGS") {
00874       ortho_ = Teuchos::rcp( new IMGSOrthoManager<ScalarType,MV,OP>( label_ ) );
00875     } 
00876     else {
00877       TEUCHOS_TEST_FOR_EXCEPTION(orthoType_!="ICGS"&&orthoType_!="DGKS"&&orthoType_!="IMGS",std::logic_error,
00878           "Belos::PseudoBlockGmresSolMgr(): Invalid orthogonalization type.");
00879     }  
00880   }
00881 
00882   // Create the timer if we need to.
00883   if (timerSolve_ == Teuchos::null) {
00884     std::string solveLabel = label_ + ": PseudoBlockGmresSolMgr total solve time";
00885 #ifdef BELOS_TEUCHOS_TIME_MONITOR
00886     timerSolve_ = Teuchos::TimeMonitor::getNewTimer(solveLabel);
00887 #endif
00888   }
00889 
00890   // Inform the solver manager that the current parameters were set.
00891   isSet_ = true;
00892 }
00893 
00894     
00895 template<class ScalarType, class MV, class OP>
00896 void 
00897 PseudoBlockGmresSolMgr<ScalarType,MV,OP>::setUserConvStatusTest(
00898   const Teuchos::RCP<StatusTest<ScalarType,MV,OP> > &userConvStatusTest
00899   )
00900 {
00901   userConvStatusTest_ = userConvStatusTest;
00902 }
00903 
00904     
00905 template<class ScalarType, class MV, class OP>
00906 Teuchos::RCP<const Teuchos::ParameterList>
00907 PseudoBlockGmresSolMgr<ScalarType,MV,OP>::getValidParameters() const
00908 {
00909   static Teuchos::RCP<const Teuchos::ParameterList> validPL;
00910   if (is_null(validPL)) {
00911     Teuchos::RCP<Teuchos::ParameterList> pl = Teuchos::parameterList();
00912   // Set all the valid parameters and their default values.
00913     pl= Teuchos::rcp( new Teuchos::ParameterList() );
00914     pl->set("Convergence Tolerance", convtol_default_,
00915       "The relative residual tolerance that needs to be achieved by the\n"
00916       "iterative solver in order for the linear system to be declared converged.");
00917     pl->set("Maximum Restarts", maxRestarts_default_,
00918       "The maximum number of restarts allowed for each\n"
00919       "set of RHS solved.");
00920     pl->set("Maximum Iterations", maxIters_default_,
00921       "The maximum number of block iterations allowed for each\n"
00922       "set of RHS solved.");
00923     pl->set("Num Blocks", numBlocks_default_,
00924       "The maximum number of vectors allowed in the Krylov subspace\n"
00925       "for each set of RHS solved.");
00926     pl->set("Block Size", blockSize_default_,
00927       "The number of RHS solved simultaneously.");
00928     pl->set("Verbosity", verbosity_default_,
00929       "What type(s) of solver information should be outputted\n"
00930       "to the output stream.");
00931     pl->set("Output Style", outputStyle_default_,
00932       "What style is used for the solver information outputted\n"
00933       "to the output stream.");
00934     pl->set("Output Frequency", outputFreq_default_,
00935       "How often convergence information should be outputted\n"
00936       "to the output stream.");  
00937     pl->set("Deflation Quorum", defQuorum_default_,
00938       "The number of linear systems that need to converge before\n"
00939       "they are deflated.  This number should be <= block size.");
00940     pl->set("Output Stream", outputStream_default_,
00941       "A reference-counted pointer to the output stream where all\n"
00942       "solver output is sent.");
00943     pl->set("Show Maximum Residual Norm Only", showMaxResNormOnly_default_,
00944       "When convergence information is printed, only show the maximum\n"
00945       "relative residual norm when the block size is greater than one.");
00946     pl->set("Implicit Residual Scaling", impResScale_default_,
00947       "The type of scaling used in the implicit residual convergence test.");
00948     pl->set("Explicit Residual Scaling", expResScale_default_,
00949       "The type of scaling used in the explicit residual convergence test.");
00950     pl->set("Timer Label", label_default_,
00951       "The string to use as a prefix for the timer labels.");
00952     //  defaultParams_->set("Restart Timers", restartTimers_);
00953     pl->set("Orthogonalization", orthoType_default_,
00954       "The type of orthogonalization to use: DGKS, ICGS, IMGS.");
00955     pl->set("Orthogonalization Constant",orthoKappa_default_,
00956       "The constant used by DGKS orthogonalization to determine\n"
00957       "whether another step of classical Gram-Schmidt is necessary.");
00958     validPL = pl;
00959   }
00960   return validPL;
00961 }
00962 
00963 // Check the status test versus the defined linear problem
00964 template<class ScalarType, class MV, class OP>
00965 bool PseudoBlockGmresSolMgr<ScalarType,MV,OP>::checkStatusTest() {
00966 
00967   typedef Belos::StatusTestCombo<ScalarType,MV,OP>  StatusTestCombo_t;
00968   typedef Belos::StatusTestGenResNorm<ScalarType,MV,OP>  StatusTestGenResNorm_t;
00969   typedef Belos::StatusTestImpResNorm<ScalarType,MV,OP>  StatusTestImpResNorm_t;
00970 
00971   // Basic test checks maximum iterations and native residual.
00972   maxIterTest_ = Teuchos::rcp( new StatusTestMaxIters<ScalarType,MV,OP>( maxIters_ ) );
00973 
00974   // If there is a left preconditioner, we create a combined status test that checks the implicit
00975   // and then explicit residual norm to see if we have convergence.
00976   if ( !Teuchos::is_null(problem_->getLeftPrec()) ) {
00977     expResTest_ = true;
00978   }
00979 
00980   if (expResTest_) {
00981    
00982     // Implicit residual test, using the native residual to determine if convergence was achieved.
00983     Teuchos::RCP<StatusTestGenResNorm_t> tmpImpConvTest =
00984       Teuchos::rcp( new StatusTestGenResNorm_t( convtol_, defQuorum_ ) );
00985     tmpImpConvTest->defineScaleForm( convertStringToScaleType(impResScale_), Belos::TwoNorm );
00986     tmpImpConvTest->setShowMaxResNormOnly( showMaxResNormOnly_ );
00987     impConvTest_ = tmpImpConvTest;
00988 
00989     // Explicit residual test once the native residual is below the tolerance
00990     Teuchos::RCP<StatusTestGenResNorm_t> tmpExpConvTest =
00991       Teuchos::rcp( new StatusTestGenResNorm_t( convtol_, defQuorum_ ) );
00992     tmpExpConvTest->defineResForm( StatusTestGenResNorm_t::Explicit, Belos::TwoNorm );
00993     tmpExpConvTest->defineScaleForm( convertStringToScaleType(expResScale_), Belos::TwoNorm );
00994     tmpExpConvTest->setShowMaxResNormOnly( showMaxResNormOnly_ );
00995     expConvTest_ = tmpExpConvTest;
00996 
00997     // The convergence test is a combination of the "cheap" implicit test and explicit test.
00998     convTest_ = Teuchos::rcp( new StatusTestCombo_t( StatusTestCombo_t::SEQ, impConvTest_, expConvTest_ ) );
00999   }
01000   else {
01001 
01002     // Implicit residual test, using the native residual to determine if convergence was achieved.
01003     // Use test that checks for loss of accuracy.
01004     Teuchos::RCP<StatusTestImpResNorm_t> tmpImpConvTest =
01005       Teuchos::rcp( new StatusTestImpResNorm_t( convtol_, defQuorum_ ) );
01006     tmpImpConvTest->defineScaleForm( convertStringToScaleType(impResScale_), Belos::TwoNorm );
01007     tmpImpConvTest->setShowMaxResNormOnly( showMaxResNormOnly_ );
01008     impConvTest_ = tmpImpConvTest;
01009     
01010     // Set the explicit and total convergence test to this implicit test that checks for accuracy loss.
01011     expConvTest_ = impConvTest_;
01012     convTest_ = impConvTest_;
01013   }
01014 
01015   if (nonnull(userConvStatusTest_) ) {
01016     // Override the overall convergence test with the users convergence test
01017     convTest_ = Teuchos::rcp(
01018       new StatusTestCombo_t( StatusTestCombo_t::SEQ, convTest_, userConvStatusTest_ ) );
01019     // NOTE: Above, you have to run the other convergence tests also because
01020     // the logic in this class depends on it.  This is very unfortunate.
01021   }
01022 
01023   sTest_ = Teuchos::rcp( new StatusTestCombo_t( StatusTestCombo_t::OR, maxIterTest_, convTest_ ) );
01024 
01025   // Create the status test output class.
01026   // This class manages and formats the output from the status test.
01027   StatusTestOutputFactory<ScalarType,MV,OP> stoFactory( outputStyle_ );
01028   outputTest_ = stoFactory.create( printer_, sTest_, outputFreq_, Passed+Failed+Undefined );
01029   
01030   // Set the solver string for the output test
01031   std::string solverDesc = " Pseudo Block Gmres ";
01032   outputTest_->setSolverDesc( solverDesc );
01033 
01034 
01035   // The status test is now set.
01036   isSTSet_ = true;
01037 
01038   return false;
01039 }
01040 
01041 
01042 // solve()
01043 template<class ScalarType, class MV, class OP>
01044 ReturnType PseudoBlockGmresSolMgr<ScalarType,MV,OP>::solve() {
01045 
01046   // Set the current parameters if they were not set before.
01047   // NOTE:  This may occur if the user generated the solver manager with the default constructor and 
01048   // then didn't set any parameters using setParameters().
01049   if (!isSet_) { setParameters( params_ ); }
01050   
01051   Teuchos::BLAS<int,ScalarType> blas;
01052   
01053   TEUCHOS_TEST_FOR_EXCEPTION(!problem_->isProblemSet(),PseudoBlockGmresSolMgrLinearProblemFailure,
01054                      "Belos::PseudoBlockGmresSolMgr::solve(): Linear problem is not ready, setProblem() has not been called.");
01055 
01056   // Check if we have to create the status tests.
01057   if (!isSTSet_ || (!expResTest_ && !Teuchos::is_null(problem_->getLeftPrec())) ) {
01058     TEUCHOS_TEST_FOR_EXCEPTION( checkStatusTest(),PseudoBlockGmresSolMgrLinearProblemFailure,
01059       "Belos::BlockGmresSolMgr::solve(): Linear problem and requested status tests are incompatible.");
01060   }
01061 
01062   // Create indices for the linear systems to be solved.
01063   int startPtr = 0;
01064   int numRHS2Solve = MVT::GetNumberVecs( *(problem_->getRHS()) );
01065   int numCurrRHS = ( numRHS2Solve < blockSize_) ? numRHS2Solve : blockSize_;
01066 
01067   std::vector<int> currIdx( numCurrRHS );
01068   blockSize_ = numCurrRHS;
01069   for (int i=0; i<numCurrRHS; ++i) 
01070     { currIdx[i] = startPtr+i; }
01071 
01072   // Inform the linear problem of the current linear system to solve.
01073   problem_->setLSIndex( currIdx );
01074 
01076   // Parameter list
01077   Teuchos::ParameterList plist;
01078   plist.set("Num Blocks",numBlocks_);
01079   
01080   // Reset the status test.  
01081   outputTest_->reset();
01082   loaDetected_ = false;
01083 
01084   // Assume convergence is achieved, then let any failed convergence set this to false.
01085   bool isConverged = true;
01086 
01088   // BlockGmres solver
01089 
01090   Teuchos::RCP<PseudoBlockGmresIter<ScalarType,MV,OP> > block_gmres_iter
01091     = Teuchos::rcp( new PseudoBlockGmresIter<ScalarType,MV,OP>(problem_,printer_,outputTest_,ortho_,plist) );  
01092 
01093   // Enter solve() iterations
01094   {
01095 #ifdef BELOS_TEUCHOS_TIME_MONITOR
01096     Teuchos::TimeMonitor slvtimer(*timerSolve_);
01097 #endif
01098 
01099     while ( numRHS2Solve > 0 ) {
01100 
01101       // Reset the active / converged vectors from this block
01102       std::vector<int> convRHSIdx;
01103       std::vector<int> currRHSIdx( currIdx );
01104       currRHSIdx.resize(numCurrRHS);
01105 
01106       // Set the current number of blocks with the pseudo Gmres iteration.
01107       block_gmres_iter->setNumBlocks( numBlocks_ );
01108 
01109       // Reset the number of iterations.
01110       block_gmres_iter->resetNumIters();
01111 
01112       // Reset the number of calls that the status test output knows about.
01113       outputTest_->resetNumCalls();
01114 
01115       // Get a new state struct and initialize the solver.
01116       PseudoBlockGmresIterState<ScalarType,MV> newState;
01117 
01118       // Create the first block in the current Krylov basis for each right-hand side.
01119       std::vector<int> index(1);
01120       Teuchos::RCP<MV> tmpV, R_0 = MVT::CloneCopy( *(problem_->getInitPrecResVec()), currIdx );
01121       newState.V.resize( blockSize_ );
01122       newState.Z.resize( blockSize_ );
01123       for (int i=0; i<blockSize_; ++i) {
01124         index[0]=i;
01125         tmpV = MVT::CloneViewNonConst( *R_0, index );
01126 
01127         // Get a matrix to hold the orthonormalization coefficients.
01128         Teuchos::RCP<Teuchos::SerialDenseVector<int,ScalarType> > tmpZ
01129           = Teuchos::rcp( new Teuchos::SerialDenseVector<int,ScalarType>( 1 ));
01130 
01131         // Orthonormalize the new V_0
01132         int rank = ortho_->normalize( *tmpV, tmpZ );
01133         TEUCHOS_TEST_FOR_EXCEPTION(rank != 1, PseudoBlockGmresSolMgrOrthoFailure,
01134             "Belos::PseudoBlockGmresSolMgr::solve(): Failed to compute initial block of orthonormal vectors.");
01135 
01136         newState.V[i] = tmpV;
01137         newState.Z[i] = tmpZ;
01138       }
01139 
01140       newState.curDim = 0;
01141       block_gmres_iter->initialize(newState);
01142       int numRestarts = 0;
01143 
01144       while(1) {
01145         
01146         // tell block_gmres_iter to iterate
01147         try {
01148           block_gmres_iter->iterate();
01149           
01151           //
01152           // check convergence first
01153           //
01155           if ( convTest_->getStatus() == Passed ) {
01156         
01157             if ( expConvTest_->getLOADetected() ) {
01158         // Oops!  There was a loss of accuracy (LOA) for one or
01159         // more right-hand sides.  That means the implicit
01160         // (a.k.a. "native") residuals claim convergence,
01161         // whereas the explicit (hence expConvTest_, i.e.,
01162         // "explicit convergence test") residuals have not
01163         // converged.
01164         //
01165         // We choose to deal with this situation by deflating
01166         // out the affected right-hand sides and moving on.
01167               loaDetected_ = true;
01168               printer_->stream(Warnings) <<
01169                 "Belos::PseudoBlockGmresSolMgr::solve(): Warning! Solver has experienced a loss of accuracy!" << std::endl;
01170               isConverged = false;
01171             }
01172         
01173             // Figure out which linear systems converged.
01174             std::vector<int> convIdx = expConvTest_->convIndices();
01175         
01176             // If the number of converged linear systems is equal to the
01177             // number of current linear systems, then we are done with this block.
01178             if (convIdx.size() == currRHSIdx.size())
01179               break;  // break from while(1){block_gmres_iter->iterate()}
01180         
01181             // Get a new state struct and initialize the solver.
01182             PseudoBlockGmresIterState<ScalarType,MV> defState;
01183         
01184             // Inform the linear problem that we are finished with this current linear system.
01185             problem_->setCurrLS();
01186         
01187             // Get the state.
01188             PseudoBlockGmresIterState<ScalarType,MV> oldState = block_gmres_iter->getState();
01189             int curDim = oldState.curDim;
01190         
01191             // Get a new state struct and reset currRHSIdx to have the right-hand sides that 
01192             // are left to converge for this block.
01193             int have = 0;
01194             std::vector<int> oldRHSIdx( currRHSIdx );
01195             std::vector<int> defRHSIdx;
01196             for (unsigned int i=0; i<currRHSIdx.size(); ++i) {
01197               bool found = false;
01198               for (unsigned int j=0; j<convIdx.size(); ++j) {
01199                 if (currRHSIdx[i] == convIdx[j]) {
01200                   found = true;
01201                   break;
01202                 }
01203               }
01204               if (found) {
01205                 defRHSIdx.push_back( i );
01206               }
01207               else {
01208                 defState.V.push_back( Teuchos::rcp_const_cast<MV>( oldState.V[i] ) );
01209                 defState.Z.push_back( Teuchos::rcp_const_cast<Teuchos::SerialDenseVector<int,ScalarType> >( oldState.Z[i] ) );
01210                 defState.H.push_back( Teuchos::rcp_const_cast<Teuchos::SerialDenseMatrix<int,ScalarType> >( oldState.H[i] ) );
01211                 defState.sn.push_back( Teuchos::rcp_const_cast<Teuchos::SerialDenseVector<int,ScalarType> >( oldState.sn[i] ) );
01212                 defState.cs.push_back( Teuchos::rcp_const_cast<Teuchos::SerialDenseVector<int,MagnitudeType> >(oldState.cs[i] ) );
01213                 currRHSIdx[have] = currRHSIdx[i];
01214                 have++;
01215               }
01216             }
01217             defRHSIdx.resize(currRHSIdx.size()-have);
01218             currRHSIdx.resize(have);
01219         
01220             // Compute the current solution that needs to be deflated if this solver has taken any steps.
01221             if (curDim) {
01222               Teuchos::RCP<MV> update = block_gmres_iter->getCurrentUpdate();
01223               Teuchos::RCP<MV> defUpdate = MVT::CloneViewNonConst( *update, defRHSIdx );
01224               
01225               // Set the deflated indices so we can update the solution.
01226               problem_->setLSIndex( convIdx );
01227               
01228               // Update the linear problem.
01229               problem_->updateSolution( defUpdate, true );
01230             }
01231             
01232             // Set the remaining indices after deflation.
01233             problem_->setLSIndex( currRHSIdx );
01234             
01235             // Set the dimension of the subspace, which is the same as the old subspace size.
01236             defState.curDim = curDim;
01237             
01238             // Initialize the solver with the deflated system.
01239             block_gmres_iter->initialize(defState);
01240           }
01242           //
01243           // check for maximum iterations
01244           //
01246           else if ( maxIterTest_->getStatus() == Passed ) {
01247             // we don't have convergence
01248             isConverged = false;
01249             break;  // break from while(1){block_gmres_iter->iterate()}
01250           }
01252           //
01253           // check for restarting, i.e. the subspace is full
01254           //
01256           else if ( block_gmres_iter->getCurSubspaceDim() == block_gmres_iter->getMaxSubspaceDim() ) {
01257         
01258             if ( numRestarts >= maxRestarts_ ) {
01259               isConverged = false;
01260               break; // break from while(1){block_gmres_iter->iterate()}
01261             }
01262             numRestarts++;
01263         
01264             printer_->stream(Debug) << " Performing restart number " << numRestarts << " of " << maxRestarts_ << std::endl << std::endl;
01265             
01266             // Update the linear problem.
01267             Teuchos::RCP<MV> update = block_gmres_iter->getCurrentUpdate();
01268             problem_->updateSolution( update, true );
01269             
01270             // Get the state.
01271             PseudoBlockGmresIterState<ScalarType,MV> oldState = block_gmres_iter->getState();
01272             
01273             // Set the new state.
01274             PseudoBlockGmresIterState<ScalarType,MV> newstate;
01275             newstate.V.resize(currRHSIdx.size());
01276             newstate.Z.resize(currRHSIdx.size());
01277         
01278             // Compute the restart vectors
01279             // NOTE: Force the linear problem to update the current residual since the solution was updated.
01280             R_0 = MVT::Clone( *(problem_->getInitPrecResVec()), currRHSIdx.size() );
01281             problem_->computeCurrPrecResVec( &*R_0 );
01282             for (unsigned int i=0; i<currRHSIdx.size(); ++i) {
01283               index[0] = i;  // index(1) vector declared on line 891
01284         
01285               tmpV = MVT::CloneViewNonConst( *R_0, index );
01286         
01287               // Get a matrix to hold the orthonormalization coefficients.
01288               Teuchos::RCP<Teuchos::SerialDenseVector<int,ScalarType> > tmpZ
01289                 = Teuchos::rcp( new Teuchos::SerialDenseVector<int,ScalarType>( 1 ));
01290               
01291               // Orthonormalize the new V_0
01292               int rank = ortho_->normalize( *tmpV, tmpZ );
01293               TEUCHOS_TEST_FOR_EXCEPTION(rank != 1 ,PseudoBlockGmresSolMgrOrthoFailure,
01294                   "Belos::PseudoBlockGmresSolMgr::solve(): Failed to compute initial block of orthonormal vectors after the restart.");
01295               
01296               newstate.V[i] = tmpV;
01297               newstate.Z[i] = tmpZ;
01298             }
01299         
01300             // Initialize the solver.
01301             newstate.curDim = 0;
01302             block_gmres_iter->initialize(newstate);
01303         
01304           } // end of restarting
01305         
01307           //
01308           // we returned from iterate(), but none of our status tests Passed.
01309           // something is wrong, and it is probably our fault.
01310           //
01312         
01313           else {
01314             TEUCHOS_TEST_FOR_EXCEPTION(true,std::logic_error,
01315                 "Belos::PseudoBlockGmresSolMgr::solve(): Invalid return from PseudoBlockGmresIter::iterate().");
01316           }
01317         }
01318         catch (const PseudoBlockGmresIterOrthoFailure &e) {
01319         
01320           // Try to recover the most recent least-squares solution
01321           block_gmres_iter->updateLSQR( block_gmres_iter->getCurSubspaceDim() );
01322         
01323           // Check to see if the most recent least-squares solution yielded convergence.
01324           sTest_->checkStatus( &*block_gmres_iter );
01325           if (convTest_->getStatus() != Passed)
01326             isConverged = false;
01327           break;
01328         }
01329         catch (const std::exception &e) {
01330           printer_->stream(Errors) << "Error! Caught std::exception in PseudoBlockGmresIter::iterate() at iteration " 
01331                                    << block_gmres_iter->getNumIters() << std::endl 
01332                                    << e.what() << std::endl;
01333           throw;
01334         }
01335       }
01336       
01337       // Compute the current solution.
01338       // Update the linear problem.
01339       if (nonnull(userConvStatusTest_)) {
01340         //std::cout << "\nnonnull(userConvStatusTest_)\n";
01341         Teuchos::RCP<MV> update = block_gmres_iter->getCurrentUpdate();
01342         problem_->updateSolution( update, true );
01343       }
01344       else if (nonnull(expConvTest_->getSolution())) {
01345         //std::cout << "\nexpConvTest_->getSolution()\n";
01346         Teuchos::RCP<MV> newX = expConvTest_->getSolution();
01347         Teuchos::RCP<MV> curX = problem_->getCurrLHSVec();
01348         MVT::MvAddMv( 0.0, *newX, 1.0, *newX, *curX );
01349       }
01350       else {
01351         //std::cout << "\nblock_gmres_iter->getCurrentUpdate()\n";
01352         Teuchos::RCP<MV> update = block_gmres_iter->getCurrentUpdate();
01353         problem_->updateSolution( update, true );
01354       }
01355 
01356       // Inform the linear problem that we are finished with this block linear system.
01357       problem_->setCurrLS();
01358       
01359       // Update indices for the linear systems to be solved.
01360       startPtr += numCurrRHS;
01361       numRHS2Solve -= numCurrRHS;
01362       if ( numRHS2Solve > 0 ) {
01363         numCurrRHS = ( numRHS2Solve < blockSize_) ? numRHS2Solve : blockSize_;
01364 
01365         blockSize_ = numCurrRHS;
01366         currIdx.resize( numCurrRHS  );
01367         for (int i=0; i<numCurrRHS; ++i) 
01368         { currIdx[i] = startPtr+i; }
01369 
01370         // Adapt the status test quorum if we need to.
01371         if (defQuorum_ > blockSize_) {
01372           if (impConvTest_ != Teuchos::null)
01373             impConvTest_->setQuorum( blockSize_ );
01374           if (expConvTest_ != Teuchos::null)
01375             expConvTest_->setQuorum( blockSize_ );
01376         }
01377 
01378         // Set the next indices.
01379         problem_->setLSIndex( currIdx );
01380       }
01381       else {
01382         currIdx.resize( numRHS2Solve );
01383       }
01384 
01385     }// while ( numRHS2Solve > 0 )
01386 
01387   }
01388 
01389   // print final summary
01390   sTest_->print( printer_->stream(FinalSummary) );
01391  
01392   // print timing information
01393 #ifdef BELOS_TEUCHOS_TIME_MONITOR
01394   // Calling summarize() can be expensive, so don't call unless the
01395   // user wants to print out timing details.  summarize() will do all
01396   // the work even if it's passed a "black hole" output stream.
01397   if (verbosity_ & TimingDetails)
01398     Teuchos::TimeMonitor::summarize( printer_->stream(TimingDetails) );
01399 #endif
01400  
01401   // get iteration information for this solve
01402   numIters_ = maxIterTest_->getNumIters();
01403 
01404   // Save the convergence test value ("achieved tolerance") for this
01405   // solve.  For this solver, convTest_ may either be a single
01406   // residual norm test, or a combination of two residual norm tests.
01407   // In the latter case, the master convergence test convTest_ is a
01408   // SEQ combo of the implicit resp. explicit tests.  If the implicit
01409   // test never passes, then the explicit test won't ever be executed.
01410   // This manifests as expConvTest_->getTestValue()->size() < 1.  We
01411   // deal with this case by using the values returned by
01412   // impConvTest_->getTestValue().
01413   {
01414     // We'll fetch the vector of residual norms one way or the other.
01415     const std::vector<MagnitudeType>* pTestValues = NULL;
01416     if (expResTest_) {
01417       pTestValues = expConvTest_->getTestValue();
01418       if (pTestValues == NULL || pTestValues->size() < 1) {
01419   pTestValues = impConvTest_->getTestValue();
01420       }
01421     } 
01422     else {
01423       // Only the implicit residual norm test is being used.
01424       pTestValues = impConvTest_->getTestValue();
01425     }
01426     TEUCHOS_TEST_FOR_EXCEPTION(pTestValues == NULL, std::logic_error,
01427       "Belos::PseudoBlockGmresSolMgr::solve(): The implicit convergence test's "
01428       "getTestValue() method returned NULL.  Please report this bug to the "
01429       "Belos developers.");
01430     TEUCHOS_TEST_FOR_EXCEPTION(pTestValues->size() < 1, std::logic_error,
01431       "Belos::PseudoBlockGmresSolMgr::solve(): The implicit convergence test's "
01432       "getTestValue() method returned a vector of length zero.  Please report "
01433       "this bug to the Belos developers.");
01434 
01435     // FIXME (mfh 12 Dec 2011) Does pTestValues really contain the
01436     // achieved tolerances for all vectors in the current solve(), or
01437     // just for the vectors from the last deflation?
01438     achievedTol_ = *std::max_element (pTestValues->begin(), pTestValues->end());
01439   }
01440  
01441   if (!isConverged || loaDetected_) {
01442     return Unconverged; // return from PseudoBlockGmresSolMgr::solve() 
01443   }
01444   return Converged; // return from PseudoBlockGmresSolMgr::solve() 
01445 }
01446 
01447 //  This method requires the solver manager to return a std::string that describes itself.
01448 template<class ScalarType, class MV, class OP>
01449 std::string PseudoBlockGmresSolMgr<ScalarType,MV,OP>::description() const
01450 {
01451   std::ostringstream oss;
01452   oss << "Belos::PseudoBlockGmresSolMgr<...,"<<Teuchos::ScalarTraits<ScalarType>::name()<<">";
01453   oss << "{";
01454   oss << "Ortho Type='"<<orthoType_<<"\', Block Size=" <<blockSize_;
01455   oss << ", Num Blocks="<<numBlocks_<< ", Max Restarts=" << maxRestarts_;
01456   oss << "}";
01457   return oss.str();
01458 }
01459   
01460 } // end Belos namespace
01461 
01462 #endif /* BELOS_PSEUDO_BLOCK_GMRES_SOLMGR_HPP */
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines