Belos Version of the Day
BelosBlockCGIter.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_ITER_HPP
00043 #define BELOS_BLOCK_CG_ITER_HPP
00044 
00049 #include "BelosConfigDefs.hpp"
00050 #include "BelosTypes.hpp"
00051 #include "BelosCGIteration.hpp"
00052 
00053 #include "BelosLinearProblem.hpp"
00054 #include "BelosMatOrthoManager.hpp"
00055 #include "BelosOutputManager.hpp"
00056 #include "BelosStatusTest.hpp"
00057 #include "BelosOperatorTraits.hpp"
00058 #include "BelosMultiVecTraits.hpp"
00059 
00060 #include "Teuchos_BLAS.hpp"
00061 #include "Teuchos_LAPACK.hpp"
00062 #include "Teuchos_SerialDenseMatrix.hpp"
00063 #include "Teuchos_SerialDenseVector.hpp"
00064 #include "Teuchos_ScalarTraits.hpp"
00065 #include "Teuchos_ParameterList.hpp"
00066 #include "Teuchos_TimeMonitor.hpp"
00067 
00078 namespace Belos {
00079   
00080 template<class ScalarType, class MV, class OP>
00081 class BlockCGIter : virtual public CGIteration<ScalarType,MV,OP> {
00082 
00083   public:
00084     
00085   //
00086   // Convenience typedefs
00087   //
00088   typedef MultiVecTraits<ScalarType,MV> MVT;
00089   typedef OperatorTraits<ScalarType,MV,OP> OPT;
00090   typedef Teuchos::ScalarTraits<ScalarType> SCT;
00091   typedef typename SCT::magnitudeType MagnitudeType;
00092 
00094 
00095 
00101   BlockCGIter( const Teuchos::RCP<LinearProblem<ScalarType,MV,OP> > &problem, 
00102          const Teuchos::RCP<OutputManager<ScalarType> > &printer,
00103          const Teuchos::RCP<StatusTest<ScalarType,MV,OP> > &tester,
00104          const Teuchos::RCP<MatOrthoManager<ScalarType,MV,OP> > &ortho,
00105          Teuchos::ParameterList &params );
00106 
00108   virtual ~BlockCGIter() {};
00110 
00111 
00113 
00114   
00127   void iterate();
00128 
00143   void initializeCG(CGIterationState<ScalarType,MV> newstate);
00144 
00148   void initialize()
00149   {
00150     CGIterationState<ScalarType,MV> empty;
00151     initializeCG(empty);
00152   }
00153   
00160   CGIterationState<ScalarType,MV> getState() const {
00161     CGIterationState<ScalarType,MV> state;
00162     state.R = R_;
00163     state.P = P_;
00164     state.AP = AP_;
00165     state.Z = Z_;
00166     return state;
00167   }
00168 
00170 
00171   
00173 
00174 
00176   int getNumIters() const { return iter_; }
00177   
00179   void resetNumIters( int iter=0 ) { iter_ = iter; }
00180 
00183   Teuchos::RCP<const MV> getNativeResiduals( std::vector<MagnitudeType> *norms ) const { return R_; }
00184 
00186 
00188   Teuchos::RCP<MV> getCurrentUpdate() const { return Teuchos::null; }
00189 
00191   
00193 
00194 
00196   const LinearProblem<ScalarType,MV,OP>& getProblem() const { return *lp_; }
00197 
00199   int getBlockSize() const { return blockSize_; }
00200 
00202   void setBlockSize(int blockSize);
00203 
00205   bool isInitialized() { return initialized_; }
00206 
00208 
00209   private:
00210 
00211   //
00212   // Internal methods
00213   //
00215   void setStateSize();
00216   
00217   //
00218   // Classes inputed through constructor that define the linear problem to be solved.
00219   //
00220   const Teuchos::RCP<LinearProblem<ScalarType,MV,OP> >    lp_;
00221   const Teuchos::RCP<OutputManager<ScalarType> >          om_;
00222   const Teuchos::RCP<StatusTest<ScalarType,MV,OP> >       stest_;
00223   const Teuchos::RCP<OrthoManager<ScalarType,MV> >        ortho_;
00224 
00225   //
00226   // Algorithmic parameters
00227   //
00228   // blockSize_ is the solver block size.
00229   int blockSize_;
00230 
00231   //  
00232   // Current solver state
00233   //
00234   // initialized_ specifies that the basis vectors have been initialized and the iterate() routine
00235   // is capable of running; _initialize is controlled  by the initialize() member method
00236   // For the implications of the state of initialized_, please see documentation for initialize()
00237   bool initialized_;
00238 
00239   // stateStorageInitialized_ specified that the state storage has be initialized.
00240   // This initialization may be postponed if the linear problem was generated without 
00241   // the right-hand side or solution vectors.
00242   bool stateStorageInitialized_;
00243 
00244   // Current subspace dimension, and number of iterations performed.
00245   int iter_;
00246   
00247   // 
00248   // State Storage
00249   // 
00250   // Residual
00251   Teuchos::RCP<MV> R_;
00252   //
00253   // Preconditioned residual
00254   Teuchos::RCP<MV> Z_;
00255   //
00256   // Direction std::vector
00257   Teuchos::RCP<MV> P_;
00258   //
00259   // Operator applied to direction std::vector
00260   Teuchos::RCP<MV> AP_;
00261 
00262 };
00263 
00265   // Constructor.
00266   template<class ScalarType, class MV, class OP>
00267   BlockCGIter<ScalarType,MV,OP>::BlockCGIter(const Teuchos::RCP<LinearProblem<ScalarType,MV,OP> > &problem, 
00268                const Teuchos::RCP<OutputManager<ScalarType> > &printer,
00269                const Teuchos::RCP<StatusTest<ScalarType,MV,OP> > &tester,
00270                const Teuchos::RCP<MatOrthoManager<ScalarType,MV,OP> > &ortho,
00271                Teuchos::ParameterList &params ):
00272     lp_(problem),
00273     om_(printer),
00274     stest_(tester),
00275     ortho_(ortho),
00276     blockSize_(0),
00277     initialized_(false),
00278     stateStorageInitialized_(false),
00279     iter_(0)
00280   {
00281     // Set the block size and allocate data
00282     int bs = params.get("Block Size", 1);
00283     setBlockSize( bs );
00284   }
00285 
00287   // Setup the state storage.
00288   template <class ScalarType, class MV, class OP>
00289   void BlockCGIter<ScalarType,MV,OP>::setStateSize ()
00290   {
00291     if (!stateStorageInitialized_) {
00292 
00293       // Check if there is any multivector to clone from.
00294       Teuchos::RCP<const MV> lhsMV = lp_->getLHS();
00295       Teuchos::RCP<const MV> rhsMV = lp_->getRHS();
00296       if (lhsMV == Teuchos::null && rhsMV == Teuchos::null) {
00297   stateStorageInitialized_ = false;
00298   return;
00299       }
00300       else {
00301   
00302   // Initialize the state storage
00303   // If the subspace has not be initialized before, generate it using the LHS or RHS from lp_.
00304   if (R_ == Teuchos::null || MVT::GetNumberVecs(*R_)!=blockSize_) {
00305     // Get the multivector that is not null.
00306     Teuchos::RCP<const MV> tmp = ( (rhsMV!=Teuchos::null)? rhsMV: lhsMV );
00307     TEUCHOS_TEST_FOR_EXCEPTION(tmp == Teuchos::null,std::invalid_argument,
00308            "Belos::BlockCGIter::setStateSize(): linear problem does not specify multivectors to clone from.");
00309     R_ = MVT::Clone( *tmp, blockSize_ );
00310     Z_ = MVT::Clone( *tmp, blockSize_ );
00311     P_ = MVT::Clone( *tmp, blockSize_ );
00312     AP_ = MVT::Clone( *tmp, blockSize_ );
00313   }
00314   
00315   // State storage has now been initialized.
00316   stateStorageInitialized_ = true;
00317       }
00318     }
00319   }
00320 
00322   // Set the block size and make necessary adjustments.
00323   template <class ScalarType, class MV, class OP>
00324   void BlockCGIter<ScalarType,MV,OP>::setBlockSize (int blockSize)
00325   {
00326     // This routine only allocates space; it doesn't not perform any computation
00327     // any change in size will invalidate the state of the solver.
00328 
00329     TEUCHOS_TEST_FOR_EXCEPTION(blockSize <= 0, std::invalid_argument, "Belos::BlockGmresIter::setBlockSize was passed a non-positive argument.");
00330     if (blockSize == blockSize_) {
00331       // do nothing
00332       return;
00333     }
00334 
00335     if (blockSize!=blockSize_)
00336       stateStorageInitialized_ = false;
00337 
00338     blockSize_ = blockSize;
00339 
00340     initialized_ = false;
00341 
00342     // Use the current blockSize_ to initialize the state storage.
00343     setStateSize();
00344 
00345   }
00346 
00348   // Initialize this iteration object
00349   template <class ScalarType, class MV, class OP>
00350   void BlockCGIter<ScalarType,MV,OP>::initializeCG(CGIterationState<ScalarType,MV> newstate)
00351   {
00352     // Initialize the state storage if it isn't already.
00353     if (!stateStorageInitialized_) 
00354       setStateSize();
00355 
00356     TEUCHOS_TEST_FOR_EXCEPTION(!stateStorageInitialized_,std::invalid_argument,
00357            "Belos::BlockCGIter::initialize(): Cannot initialize state storage!");
00358     
00359     // NOTE:  In BlockCGIter R_, the initial residual, is required!!!  
00360     //
00361     std::string errstr("Belos::BlockCGIter::initialize(): Specified multivectors must have a consistent length and width.");
00362 
00363     // Create convenience variables for zero and one.
00364     const ScalarType one = Teuchos::ScalarTraits<ScalarType>::one();
00365     const MagnitudeType zero = Teuchos::ScalarTraits<MagnitudeType>::zero();
00366 
00367     if (newstate.R != Teuchos::null) {
00368 
00369       TEUCHOS_TEST_FOR_EXCEPTION( MVT::GetVecLength(*newstate.R) != MVT::GetVecLength(*R_),
00370                           std::invalid_argument, errstr );
00371       TEUCHOS_TEST_FOR_EXCEPTION( MVT::GetNumberVecs(*newstate.R) != blockSize_,
00372                           std::invalid_argument, errstr );
00373 
00374       // Copy basis vectors from newstate into V
00375       if (newstate.R != R_) {
00376         // copy over the initial residual (unpreconditioned).
00377   MVT::MvAddMv( one, *newstate.R, zero, *newstate.R, *R_ );
00378       }
00379       // Compute initial direction vectors
00380       // Initially, they are set to the preconditioned residuals
00381       //
00382       if ( lp_->getLeftPrec() != Teuchos::null ) {
00383         lp_->applyLeftPrec( *R_, *Z_ );
00384         if ( lp_->getRightPrec() != Teuchos::null ) {
00385           Teuchos::RCP<MV> tmp = MVT::Clone( *Z_, blockSize_ );
00386           lp_->applyRightPrec( *Z_, *tmp );
00387           Z_ = tmp;
00388         }
00389       }
00390       else if ( lp_->getRightPrec() != Teuchos::null ) {
00391         lp_->applyRightPrec( *R_, *Z_ );
00392       } 
00393       else {
00394         Z_ = R_;
00395       }
00396       MVT::MvAddMv( one, *Z_, zero, *Z_, *P_ );
00397     }
00398     else {
00399 
00400       TEUCHOS_TEST_FOR_EXCEPTION(newstate.R == Teuchos::null,std::invalid_argument,
00401                          "Belos::BlockCGIter::initialize(): BlockCGStateIterState does not have initial residual.");
00402     }
00403 
00404     // The solver is initialized
00405     initialized_ = true;
00406   }
00407 
00408 
00410   // Iterate until the status test informs us we should stop.
00411   template <class ScalarType, class MV, class OP>
00412   void BlockCGIter<ScalarType,MV,OP>::iterate()
00413   {
00414     //
00415     // Allocate/initialize data structures
00416     //
00417     if (initialized_ == false) {
00418       initialize();
00419     }
00420     // Allocate data needed for LAPACK work.
00421     int info = 0;
00422     char UPLO = 'U';
00423     Teuchos::LAPACK<int,ScalarType> lapack;
00424 
00425     // Allocate memory for scalars.
00426     Teuchos::SerialDenseMatrix<int,ScalarType> alpha( blockSize_, blockSize_ );
00427     Teuchos::SerialDenseMatrix<int,ScalarType> beta( blockSize_, blockSize_ );
00428     Teuchos::SerialDenseMatrix<int,ScalarType> rHz( blockSize_, blockSize_ ), 
00429       rHz_old( blockSize_, blockSize_ ), pAp( blockSize_, blockSize_ );
00430 
00431     // Create convenience variables for zero and one.
00432     const ScalarType one = Teuchos::ScalarTraits<ScalarType>::one();
00433     
00434     // Get the current solution std::vector.
00435     Teuchos::RCP<MV> cur_soln_vec = lp_->getCurrLHSVec();
00436 
00437     // Check that the current solution std::vector has blockSize_ columns. 
00438     TEUCHOS_TEST_FOR_EXCEPTION( MVT::GetNumberVecs(*cur_soln_vec) != blockSize_, CGIterateFailure,
00439                         "Belos::BlockCGIter::iterate(): current linear system does not have the right number of vectors!" );
00440     int rank = ortho_->normalize( *P_, Teuchos::null );
00441     TEUCHOS_TEST_FOR_EXCEPTION(rank != blockSize_,CGIterationOrthoFailure,
00442                          "Belos::BlockCGIter::iterate(): Failed to compute initial block of orthonormal direction vectors.");
00443 
00444 
00446     // Iterate until the status test tells us to stop.
00447     //
00448     while (stest_->checkStatus(this) != Passed) {
00449         
00450       // Increment the iteration
00451       iter_++;
00452     
00453       // Multiply the current direction std::vector by A and store in Ap_
00454       lp_->applyOp( *P_, *AP_ );
00455       
00456       // Compute alpha := <P_,R_> / <P_,AP_>
00457       // 1) Compute P^T * A * P = pAp and P^T * R 
00458       // 2) Compute the Cholesky Factorization of pAp
00459       // 3) Back and forward solves to compute alpha
00460       //
00461       MVT::MvTransMv( one, *P_, *R_, alpha );
00462       MVT::MvTransMv( one, *P_, *AP_, pAp );      
00463      
00464       // Compute Cholesky factorization of pAp
00465       lapack.POTRF(UPLO, blockSize_, pAp.values(), blockSize_, &info);
00466       TEUCHOS_TEST_FOR_EXCEPTION(info != 0,CGIterationLAPACKFailure,
00467                          "Belos::BlockCGIter::iterate(): Failed to compute Cholesky factorization using LAPACK routine POTRF.");
00468 
00469       // Compute alpha by performing a back and forward solve with the Cholesky factorization in pAp.
00470       lapack.POTRS(UPLO, blockSize_, blockSize_, pAp.values(), blockSize_, 
00471        alpha.values(), blockSize_, &info);
00472       TEUCHOS_TEST_FOR_EXCEPTION(info != 0,CGIterationLAPACKFailure,
00473                          "Belos::BlockCGIter::iterate(): Failed to compute alpha using Cholesky factorization (POTRS).");
00474       
00475       //
00476       // Update the solution std::vector X := X + alpha * P_
00477       //
00478       MVT::MvTimesMatAddMv( one, *P_, alpha, one, *cur_soln_vec );
00479       lp_->updateSolution();
00480       //
00481       // Compute the new residual R_ := R_ - alpha * AP_
00482       //
00483       MVT::MvTimesMatAddMv( -one, *AP_, alpha, one, *R_ );
00484       //
00485       // Compute the new preconditioned residual, Z_.
00486       if ( lp_->getLeftPrec() != Teuchos::null ) {
00487         lp_->applyLeftPrec( *R_, *Z_ );
00488         if ( lp_->getRightPrec() != Teuchos::null ) {
00489           Teuchos::RCP<MV> tmp = MVT::Clone( *Z_, blockSize_ );
00490           lp_->applyRightPrec( *Z_, *tmp );
00491           Z_ = tmp;
00492         }
00493       }
00494       else if ( lp_->getRightPrec() != Teuchos::null ) {
00495         lp_->applyRightPrec( *R_, *Z_ );
00496       } 
00497       else {
00498         Z_ = R_;
00499       }
00500       //
00501       // Compute beta := <AP_,Z_> / <P_,AP_> 
00502       // 1) Compute AP_^T * Z_ 
00503       // 2) Compute the Cholesky Factorization of pAp (already have)
00504       // 3) Back and forward solves to compute beta
00505 
00506       // Compute <AP_,Z>
00507       MVT::MvTransMv( -one, *AP_, *Z_, beta );
00508       //
00509       lapack.POTRS(UPLO, blockSize_, blockSize_, pAp.values(), blockSize_, 
00510        beta.values(), blockSize_, &info);
00511       TEUCHOS_TEST_FOR_EXCEPTION(info != 0,CGIterationLAPACKFailure,
00512                          "Belos::BlockCGIter::iterate(): Failed to compute beta using Cholesky factorization (POTRS).");
00513       //
00514       // Compute the new direction vectors P_ = Z_ + P_ * beta 
00515       //
00516       Teuchos::RCP<MV> Pnew = MVT::CloneCopy( *Z_ );
00517       MVT::MvTimesMatAddMv(one, *P_, beta, one, *Pnew);
00518       P_ = Pnew;
00519 
00520       // Compute orthonormal block of new direction vectors.
00521       rank = ortho_->normalize( *P_, Teuchos::null );
00522       TEUCHOS_TEST_FOR_EXCEPTION(rank != blockSize_,CGIterationOrthoFailure,
00523                          "Belos::BlockCGIter::iterate(): Failed to compute block of orthonormal direction vectors.");
00524       
00525     } // end while (sTest_->checkStatus(this) != Passed)
00526   }
00527 
00528 } // end Belos namespace
00529 
00530 #endif /* BELOS_BLOCK_CG_ITER_HPP */
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines