10#ifndef BELOS_BLOCK_GMRES_ITER_HPP
11#define BELOS_BLOCK_GMRES_ITER_HPP
29#include "Teuchos_BLAS.hpp"
30#include "Teuchos_LAPACK.hpp"
31#include "Teuchos_ScalarTraits.hpp"
32#include "Teuchos_ParameterList.hpp"
33#include "Teuchos_TimeMonitor.hpp"
52template<
class ScalarType,
class MV,
class OP,
class DM = DefaultDenseMatrix<
int,ScalarType>>
63 typedef Teuchos::ScalarTraits<ScalarType>
SCT;
82 Teuchos::ParameterList ¶ms );
196 if (!initialized_)
return 0;
230 void setSize(
int blockSize,
int numBlocks);
245 CheckList() : checkV(false), checkArn(false) {};
251 std::string accuracyCheck(
const CheckList &chk,
const std::string &where)
const;
259 const Teuchos::RCP<LinearProblem<ScalarType,MV,OP,DM> > lp_;
260 const Teuchos::RCP<OutputManager<ScalarType> > om_;
261 const Teuchos::RCP<StatusTest<ScalarType,MV,OP,DM> > stest_;
262 const Teuchos::RCP<OrthoManager<ScalarType,MV,DM> > ortho_;
274 std::vector<ScalarType> beta, sn;
275 std::vector<MagnitudeType> cs;
288 bool stateStorageInitialized_;
293 bool keepHessenberg_;
297 bool initHessenberg_;
321 template<
class ScalarType,
class MV,
class OP,
class DM>
326 Teuchos::ParameterList ¶ms ):
334 stateStorageInitialized_(false),
335 keepHessenberg_(false),
336 initHessenberg_(false),
341 if ( om_->isVerbosity(
Debug ) )
342 keepHessenberg_ =
true;
344 keepHessenberg_ = params.get(
"Keep Hessenberg",
false);
347 initHessenberg_ = params.get(
"Initialize Hessenberg",
false);
350 TEUCHOS_TEST_FOR_EXCEPTION(!params.isParameter(
"Num Blocks"), std::invalid_argument,
351 "Belos::BlockGmresIter::constructor: mandatory parameter 'Num Blocks' is not specified.");
352 int nb = Teuchos::getParameter<int>(params,
"Num Blocks");
355 int bs = params.get(
"Block Size", 1);
361 template <
class ScalarType,
class MV,
class OP,
class DM>
367 TEUCHOS_TEST_FOR_EXCEPTION(numBlocks <= 0 || blockSize <= 0, std::invalid_argument,
"Belos::BlockGmresIter::setSize was passed a non-positive argument.");
368 if (blockSize == blockSize_ && numBlocks == numBlocks_) {
373 if (blockSize!=blockSize_ || numBlocks!=numBlocks_)
374 stateStorageInitialized_ =
false;
376 blockSize_ = blockSize;
377 numBlocks_ = numBlocks;
379 initialized_ =
false;
389 template <
class ScalarType,
class MV,
class OP,
class DM>
390 void BlockGmresIter<ScalarType,MV,OP,DM>::setStateSize ()
392 if (!stateStorageInitialized_) {
395 Teuchos::RCP<const MV> lhsMV = lp_->getLHS();
396 Teuchos::RCP<const MV> rhsMV = lp_->getRHS();
397 if (lhsMV == Teuchos::null && rhsMV == Teuchos::null) {
398 stateStorageInitialized_ =
false;
406 int newsd = blockSize_*(numBlocks_+1);
413 beta.resize( newsd );
417 TEUCHOS_TEST_FOR_EXCEPTION(blockSize_*
static_cast<ptrdiff_t
>(numBlocks_) > MVT::GetGlobalLength(*rhsMV),std::invalid_argument,
418 "Belos::BlockGmresIter::setStateSize(): Cannot generate a Krylov basis with dimension larger the operator!");
421 if (V_ == Teuchos::null) {
423 Teuchos::RCP<const MV> tmp = ( (rhsMV!=Teuchos::null)? rhsMV: lhsMV );
424 TEUCHOS_TEST_FOR_EXCEPTION(tmp == Teuchos::null,std::invalid_argument,
425 "Belos::BlockGmresIter::setStateSize(): linear problem does not specify multivectors to clone from.");
426 V_ = MVT::Clone( *tmp, newsd );
430 if (MVT::GetNumberVecs(*V_) < newsd) {
431 Teuchos::RCP<const MV> tmp = V_;
432 V_ = MVT::Clone( *tmp, newsd );
437 if (R_ == Teuchos::null) {
440 if (initHessenberg_) {
441 DMT::Reshape(*R_, newsd, newsd-blockSize_,
true);
444 if (DMT::GetNumRows(*R_) < newsd || DMT::GetNumCols(*R_) < newsd-blockSize_) {
445 DMT::Reshape(*R_, newsd, newsd-blockSize_,
false);
450 if (keepHessenberg_) {
451 if (H_ == Teuchos::null) {
454 if (initHessenberg_) {
455 DMT::Reshape(*H_, newsd, newsd-blockSize_,
true);
458 if (DMT::GetNumRows(*H_)< newsd || DMT::GetNumCols(*H_)< newsd-blockSize_) {
459 DMT::Reshape(*H_, newsd, newsd-blockSize_,
false);
469 if (z_ == Teuchos::null) {
472 if (DMT::GetNumRows(*z_) < newsd || DMT::GetNumCols(*z_) < blockSize_) {
473 DMT::Reshape(*z_, newsd, blockSize_);
477 stateStorageInitialized_ =
true;
484 template <
class ScalarType,
class MV,
class OP,
class DM>
491 Teuchos::RCP<MV> currentUpdate = Teuchos::null;
493 return currentUpdate;
495 const ScalarType one = SCT::one();
496 const ScalarType zero = SCT::zero();
497 Teuchos::BLAS<int,ScalarType> blas;
498 currentUpdate =
MVT::Clone( *V_, blockSize_ );
506 blas.TRSM( Teuchos::LEFT_SIDE, Teuchos::UPPER_TRI, Teuchos::NO_TRANS,
507 Teuchos::NON_UNIT_DIAG, curDim_, blockSize_, one,
513 std::vector<int> index(curDim_);
514 for (
int i=0; i<curDim_; i++ ) {
520 return currentUpdate;
527 template <
class ScalarType,
class MV,
class OP,
class DM>
533 if ( norms && (
int)norms->size() < blockSize_ )
534 norms->resize( blockSize_ );
537 Teuchos::BLAS<int,ScalarType> blas;
539 for (
int j=0; j<blockSize_; j++) {
540 Teuchos::RCP<DM> z_j =
DMT::Subview(*z_, blockSize_, 1, curDim_, j);
544 return Teuchos::null;
551 template <
class ScalarType,
class MV,
class OP,
class DM>
555 if (!stateStorageInitialized_)
558 TEUCHOS_TEST_FOR_EXCEPTION(!stateStorageInitialized_,std::invalid_argument,
559 "Belos::BlockGmresIter::initialize(): Cannot initialize state storage!");
565 std::string errstr(
"Belos::BlockGmresIter::initialize(): Specified multivectors must have a consistent length and width.");
567 if (newstate.
V != Teuchos::null && newstate.
z != Teuchos::null) {
572 std::invalid_argument, errstr );
574 std::invalid_argument, errstr );
575 TEUCHOS_TEST_FOR_EXCEPTION( newstate.
curDim > blockSize_*(numBlocks_+1),
576 std::invalid_argument, errstr );
578 curDim_ = newstate.
curDim;
586 if (newstate.
V != V_) {
588 if (curDim_ == 0 && lclDim > blockSize_) {
589 om_->stream(
Warnings) <<
"Belos::BlockGmresIter::initialize(): the solver was initialized with a kernel of " << lclDim << std::endl
590 <<
"The block size however is only " << blockSize_ << std::endl
591 <<
"The last " << lclDim - blockSize_ <<
" vectors will be discarded." << std::endl;
593 std::vector<int> nevind(curDim_+blockSize_);
594 for (
int i=0; i<curDim_+blockSize_; i++) nevind[i] = i;
600 lclV = Teuchos::null;
604 if (newstate.
z != z_) {
607 Teuchos::RCP<const DM> newZ =
DMT::SubviewConst(*newstate.
z,curDim_+blockSize_,blockSize_);
608 Teuchos::RCP<DM> lclZ =
DMT::Subview(*z_,curDim_+blockSize_,blockSize_);
612 lclZ = Teuchos::null;
618 TEUCHOS_TEST_FOR_EXCEPTION(newstate.
V == Teuchos::null,std::invalid_argument,
619 "Belos::BlockGmresIter::initialize(): BlockGmresStateIterState does not have initial kernel V_0.");
621 TEUCHOS_TEST_FOR_EXCEPTION(newstate.
z == Teuchos::null,std::invalid_argument,
622 "Belos::BlockGmresIter::initialize(): BlockGmresStateIterState does not have initial norms z_0.");
628 if (om_->isVerbosity(
Debug ) ) {
633 om_->print(
Debug, accuracyCheck(chk,
": after initialize()") );
641 template <
class ScalarType,
class MV,
class OP,
class DM>
647 if (initialized_ ==
false) {
652 int searchDim = blockSize_*numBlocks_;
659 while (stest_->checkStatus(
this) !=
Passed && curDim_+blockSize_ <= searchDim) {
664 int lclDim = curDim_ + blockSize_;
667 std::vector<int> curind(blockSize_);
668 for (
int i=0; i<blockSize_; i++) { curind[i] = lclDim + i; }
673 for (
int i=0; i<blockSize_; i++) { curind[i] = curDim_ + i; }
677 lp_->apply(*Vprev,*Vnext);
678 Vprev = Teuchos::null;
682 std::vector<int> prevind(lclDim);
683 for (
int i=0; i<lclDim; i++) { prevind[i] = i; }
685 Teuchos::Array<Teuchos::RCP<const MV> > AVprev(1, Vprev);
688 Teuchos::RCP<DM> subH =
DMT::Subview(*H_,lclDim,blockSize_,0,curDim_ );
689 Teuchos::Array<Teuchos::RCP<DM> > AsubH;
690 AsubH.append( subH );
693 Teuchos::RCP<DM> subH2 =
DMT::Subview(*H_,blockSize_,blockSize_,lclDim,curDim_);
703 int rank = ortho_->projectAndNormalize(*Vnext,AsubH,subH2,AVprev);
707 if (keepHessenberg_) {
709 Teuchos::RCP<DM> subR =
DMT::Subview(*R_,lclDim,blockSize_,0,curDim_ );
713 Teuchos::RCP<DM> subR2 =
DMT::Subview(*R_,blockSize_,blockSize_,lclDim,curDim_ );
718 "Belos::BlockGmresIter::iterate(): couldn't generate basis of full rank.");
728 Vnext = Teuchos::null;
729 curDim_ += blockSize_;
732 if (om_->isVerbosity(
Debug ) ) {
737 om_->print(
Debug, accuracyCheck(chk,
": after local update") );
742 om_->print(
OrthoDetails, accuracyCheck(chk,
": after local update") );
750 template<
class ScalarType,
class MV,
class OP,
class DM>
754 ScalarType sigma, mu, vscale, maxelem;
755 const ScalarType zero = SCT::zero();
760 int curDim = curDim_;
765 Teuchos::BLAS<int, ScalarType> blas;
773 if (blockSize_ == 1) {
777 for (i=0; i<curDim; i++) {
781 blas.ROT( 1, &
DMT::Value(*R_,i,curDim), 1, &
DMT::Value(*R_,i+1, curDim), 1, &cs[i], &sn[i] );
786 blas.ROTG( &
DMT::Value(*R_,curDim,curDim), &
DMT::Value(*R_,curDim+1,curDim), &cs[curDim], &sn[curDim] );
791 blas.ROT( 1, &
DMT::Value(*z_,curDim,0), 1, &
DMT::Value(*z_,curDim+1,0), 1, &cs[curDim], &sn[curDim] );
797 for (j=0; j<blockSize_; j++) {
801 for (i=0; i<curDim+j; i++) {
804 sigma *= SCT::conjugate(beta[i]);
805 blas.AXPY(blockSize_, ScalarType(-sigma), &
DMT::Value(*R_,i+1,i), 1, &
DMT::Value(*R_,i+1,curDim+j), 1);
811 maxidx = blas.IAMAX( blockSize_+1, &
DMT::Value(*R_,curDim+j,curDim+j), 1 );
812 maxelem = SCT::magnitude(
DMT::Value(*R_,curDim+j+maxidx-1,curDim+j));
813 for (i=0; i<blockSize_+1; i++)
814 DMT::Value(*R_,curDim+j+i,curDim+j) /= maxelem;
815 sigma = blas.DOT( blockSize_, &
DMT::Value(*R_,curDim+j+1,curDim+j), 1,
818 SCT::magnitude(SCT::real((
DMT::Value(*R_,curDim+j,curDim+j))));
820 beta[curDim + j] = zero;
822 mu = SCT::squareroot(SCT::conjugate(
DMT::Value(*R_,curDim+j,curDim+j))*
DMT::Value(*R_,curDim+j,curDim+j)+sigma);
823 vscale =
DMT::ValueConst(*R_,curDim+j,curDim+j) - Teuchos::as<ScalarType>(sign_Rjj)*mu;
824 beta[curDim+j] = -Teuchos::as<ScalarType>(sign_Rjj) * vscale / mu;
825 DMT::Value(*R_,curDim+j,curDim+j) = Teuchos::as<ScalarType>(sign_Rjj)*maxelem*mu;
826 for (i=0; i<blockSize_; i++)
827 DMT::Value(*R_,curDim+j+1+i,curDim+j) /= vscale;
832 for (i=0; i<blockSize_; i++) {
833 sigma = blas.DOT( blockSize_, &
DMT::Value(*R_,curDim+j+1,curDim+j),
836 sigma *= SCT::conjugate(beta[curDim+j]);
837 blas.AXPY(blockSize_, ScalarType(-sigma), &
DMT::Value(*R_,curDim+j+1,curDim+j),
849 curDim_ = dim + blockSize_;
864 template <
class ScalarType,
class MV,
class OP,
class DM>
865 std::string BlockGmresIter<ScalarType,MV,OP,DM>::accuracyCheck(
const CheckList &chk,
const std::string &where )
const
867 std::stringstream os;
869 os.setf(std::ios::scientific, std::ios::floatfield);
872 os <<
" Debugging checks: iteration " << iter_ << where << std::endl;
875 std::vector<int> lclind(curDim_);
876 for (
int i=0; i<curDim_; i++) lclind[i] = i;
877 std::vector<int> bsind(blockSize_);
878 for (
int i=0; i<blockSize_; i++) { bsind[i] = curDim_ + i; }
880 Teuchos::RCP<const MV> lclV,lclF;
881 Teuchos::RCP<MV> lclAV;
883 lclV = MVT::CloneView(*V_,lclind);
884 lclF = MVT::CloneView(*V_,bsind);
888 tmp = ortho_->orthonormError(*lclV);
889 os <<
" >> Error in V^H M V == I : " << tmp << std::endl;
891 tmp = ortho_->orthonormError(*lclF);
892 os <<
" >> Error in F^H M F == I : " << tmp << std::endl;
894 tmp = ortho_->orthogError(*lclV,*lclF);
895 os <<
" >> Error in V^H M F == 0 : " << tmp << std::endl;
903 lclAV = MVT::Clone(*V_,curDim_);
904 lp_->apply(*lclV,*lclAV);
907 const ScalarType one = Teuchos::ScalarTraits<ScalarType>::one();
908 Teuchos::RCP<DM> subH = DMT::Subview(*H_,curDim_,curDim_);
909 MVT::MvTimesMatAddMv( -one, *lclV, *subH, one, *lclAV );
912 Teuchos::RCP<DM> curB = DMT::Subview(*H_,blockSize_,curDim_,curDim_);
913 MVT::MvTimesMatAddMv( -one, *lclF, *curB, one, *lclAV );
916 std::vector<MagnitudeType> arnNorms( curDim_ );
917 ortho_->norm( *lclAV, arnNorms );
919 for (
int i=0; i<curDim_; i++) {
920 os <<
" >> Error in Krylov factorization (R = AV-VH-FB^H), ||R[" << i <<
"]|| : " << arnNorms[i] << std::endl;
Belos header file which uses auto-configuration information to include necessary C++ headers.
Pure virtual base class which augments the basic interface for a Gmres linear solver iteration.
Class which describes the linear problem to be solved by the iterative solver.
Templated virtual class for providing orthogonalization/orthonormalization methods with matrix-based ...
Declaration of basic traits for the multivector type.
Class which defines basic traits for the operator type.
Class which manages the output and verbosity of the Belos solvers.
Pure virtual base class for defining the status testing capabilities of Belos.
Collection of types and exceptions used within the Belos solvers.
MultiVecTraits< ScalarType, MV, DM > MVT
void setNumBlocks(int numBlocks)
Set the maximum number of blocks used by the iterative solver.
GmresIterationState< ScalarType, MV, DM > getState() const
Get the current state of the linear solver.
int getNumIters() const
Get the current iteration count.
void updateLSQR(int dim=-1)
Method for updating QR factorization of upper Hessenberg matrix.
void resetNumIters(int iter=0)
Reset the iteration count.
void iterate()
This method performs block Gmres iterations until the status test indicates the need to stop or an er...
OperatorTraits< ScalarType, MV, OP > OPT
int getBlockSize() const
Get the blocksize to be used by the iterative solver in solving this linear problem.
Teuchos::RCP< const MV > getNativeResiduals(std::vector< MagnitudeType > *norms) const
bool isInitialized()
States whether the solver has been initialized or not.
Teuchos::ScalarTraits< ScalarType > SCT
int getMaxSubspaceDim() const
Get the maximum dimension allocated for the search subspace.
virtual ~BlockGmresIter()
Destructor.
DenseMatTraits< ScalarType, DM > DMT
const LinearProblem< ScalarType, MV, OP, DM > & getProblem() const
Get a constant reference to the linear problem.
int getCurSubspaceDim() const
Get the dimension of the search subspace used to generate the current solution to the linear problem.
Teuchos::RCP< MV > getCurrentUpdate() const
Get the current update to the linear system.
void initializeGmres(GmresIterationState< ScalarType, MV, DM > &newstate)
Initialize the solver to an iterate, providing a complete state.
void setSize(int blockSize, int numBlocks)
Set the blocksize and number of blocks to be used by the iterative solver in solving this linear prob...
int getNumBlocks() const
Get the maximum number of blocks used by the iterative solver in solving this linear problem.
SCT::magnitudeType MagnitudeType
void setBlockSize(int blockSize)
Set the blocksize.
void initialize()
Initialize the solver with the initial vectors from the linear problem or random data.
BlockGmresIter(const Teuchos::RCP< LinearProblem< ScalarType, MV, OP, DM > > &problem, const Teuchos::RCP< OutputManager< ScalarType > > &printer, const Teuchos::RCP< StatusTest< ScalarType, MV, OP, DM > > &tester, const Teuchos::RCP< MatOrthoManager< ScalarType, MV, OP, DM > > &ortho, Teuchos::ParameterList ¶ms)
BlockGmresIter constructor with linear problem, solver utilities, and parameter list of solver option...
Virtual base class which defines basic traits for the multi-vector type.
static Teuchos::RCP< DM > Subview(DM &source, int numRows, int numCols, int startRow=0, int startCol=0)
Marks host data modified to avoid device sync errors.
static Teuchos::RCP< DM > SubviewCopy(const DM &source, int numRows, int numCols, int startRow=0, int startCol=0)
Returns a deep copy of the requested subview.
static void SyncHostToDevice(DM &dm)
static void PutScalar(DM &dm, ScalarType value=Teuchos::ScalarTraits< ScalarType >::zero())
Fill all entries with value. Value is zero if not specified.
static int GetNumRows(const DM &dm)
Obtain the number of rows of dm.
static ScalarType * GetRawHostPtr(DM &dm)
Returns a raw pointer to the (non-const) data on the host.
static const ScalarType & ValueConst(const DM &dm, const int i, const int j)
Access a const reference to the (i,j) entry of dm, e_i^T dm e_j.
static void SyncDeviceToHost(DM &dm)
static void Assign(DM &thisDM, const DM &sourceDM)
Copies entries of sourceDM to thisDM (deep copy).
static Teuchos::RCP< const DM > SubviewConst(const DM &source, int numRows, int numCols, int startRow=0, int startCol=0)
static ScalarType & Value(DM &dm, const int i, const int j)
Access a reference to the (i,j) entry of dm, e_i^T dm e_j.
static int GetStride(const DM &dm)
Obtain the stride between the columns of dm.
static int GetNumCols(const DM &dm)
Obtain the number of columns of dm.
GmresIterationOrthoFailure is thrown when the GmresIteration object is unable to compute independent ...
Belos's templated virtual class for providing routines for orthogonalization and orthonormzalition of...
Traits class which defines basic operations on multivectors.
static Teuchos::RCP< MV > Clone(const MV &mv, const int numvecs)
static void MvTimesMatAddMv(const ScalarType alpha, const MV &A, const DM &B, const ScalarType beta, MV &mv)
static void Assign(const MV &A, MV &mv)
static Teuchos::RCP< const MV > CloneView(const MV &mv, const std::vector< int > &index)
static ptrdiff_t GetGlobalLength(const MV &mv)
static Teuchos::RCP< MV > CloneViewNonConst(MV &mv, const std::vector< int > &index)
static int GetNumberVecs(const MV &mv)
Class which defines basic traits for the operator type.
Belos's basic output manager for sending information of select verbosity levels to the appropriate ou...
A pure virtual class for defining the status tests for the Belos iterative solvers.
Structure to contain pointers to GmresIteration state variables.
Teuchos::RCP< const DM > z
The current right-hand side of the least squares system RY = Z.
Teuchos::RCP< const DM > R
The current upper-triangular matrix from the QR reduction of H.
Teuchos::RCP< const DM > H
The current Hessenberg matrix.
int curDim
The current dimension of the reduction.
Teuchos::RCP< const MV > V
The current Krylov basis.