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>
63 typedef Teuchos::ScalarTraits<ScalarType>
SCT;
82 Teuchos::ParameterList &
params );
156 state.curDim = curDim_;
196 if (!initialized_)
return 0;
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 &
params ):
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);
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>
374 stateStorageInitialized_ =
false;
379 initialized_ =
false;
389 template <
class ScalarType,
class MV,
class OP,
class DM>
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 );
418 "Belos::BlockGmresIter::setStateSize(): Cannot generate a Krylov basis with dimension larger the operator!");
421 if (V_ == Teuchos::null) {
425 "Belos::BlockGmresIter::setStateSize(): linear problem does not specify multivectors to clone from.");
430 if (MVT::GetNumberVecs(*V_) <
newsd) {
431 Teuchos::RCP<const MV>
tmp = V_;
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>
497 Teuchos::BLAS<int,ScalarType>
blas;
502 Teuchos::RCP<DM> y = DMT::SubviewCopy(*z_, curDim_, blockSize_);
506 blas.TRSM( Teuchos::LEFT_SIDE, Teuchos::UPPER_TRI, Teuchos::NO_TRANS,
507 Teuchos::NON_UNIT_DIAG, curDim_, blockSize_,
one,
508 DMT::GetRawHostPtr(*R_), DMT::GetStride(*R_), DMT::GetRawHostPtr(*y), DMT::GetStride(*y) );
509 DMT::SyncHostToDevice(*y);
513 std::vector<int> index(curDim_);
514 for (
int i=0;
i<curDim_;
i++ ) {
517 Teuchos::RCP<const MV>
Vjp1 = MVT::CloneView( *V_, index );
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;
538 DMT::SyncDeviceToHost(*z_);
539 for (
int j=0;
j<blockSize_;
j++) {
540 Teuchos::RCP<DM>
z_j = DMT::Subview(*z_, blockSize_, 1, curDim_,
j);
541 (*norms)[
j] =
blas.NRM2( blockSize_, DMT::GetRawHostPtr(*
z_j), 1);
544 return Teuchos::null;
551 template <
class ScalarType,
class MV,
class OP,
class DM>
555 if (!stateStorageInitialized_)
559 "Belos::BlockGmresIter::initialize(): Cannot initialize state storage!");
565 std::string
errstr(
"Belos::BlockGmresIter::initialize(): Specified multivectors must have a consistent length and width.");
572 std::invalid_argument,
errstr );
574 std::invalid_argument,
errstr );
576 std::invalid_argument,
errstr );
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;
596 Teuchos::RCP<MV>
lclV = MVT::CloneViewNonConst( *V_,
nevind );
600 lclV = Teuchos::null;
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;
619 "Belos::BlockGmresIter::initialize(): BlockGmresStateIterState does not have initial kernel V_0.");
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) {
659 while (stest_->checkStatus(
this) !=
Passed && curDim_+blockSize_ <=
searchDim) {
664 int lclDim = curDim_ + blockSize_;
667 std::vector<int>
curind(blockSize_);
669 Teuchos::RCP<MV>
Vnext = MVT::CloneViewNonConst(*V_,
curind);
673 for (
int i=0;
i<blockSize_;
i++) {
curind[
i] = curDim_ +
i; }
674 Teuchos::RCP<const MV>
Vprev = MVT::CloneView(*V_,
curind);
678 Vprev = Teuchos::null;
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;
693 Teuchos::RCP<DM>
subH2 = DMT::Subview(*H_,blockSize_,blockSize_,
lclDim,curDim_);
694 DMT::PutScalar(*
subH2);
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>
760 int curDim = curDim_;
761 if (
dim >= curDim_ &&
dim < getMaxSubspaceDim()) {
765 Teuchos::BLAS<int, ScalarType>
blas;
770 DMT::SyncDeviceToHost(*R_);
771 DMT::SyncDeviceToHost(*z_);
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] );
787 DMT::Value(*R_,curDim+1,curDim) =
zero;
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++) {
802 sigma =
blas.DOT( blockSize_, &DMT::Value(*R_,
i+1,
i), 1, &DMT::Value(*R_,
i+1,curDim+
j), 1);
803 sigma += DMT::ValueConst(*R_,
i,curDim+
j);
804 sigma *= SCT::conjugate(beta[
i]);
806 DMT::Value(*R_,
i,curDim+
j) -=
sigma;
811 maxidx =
blas.IAMAX( blockSize_+1, &DMT::Value(*R_,curDim+
j,curDim+
j), 1 );
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,
816 &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;
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),
834 1, &DMT::Value(*z_,curDim+
j+1,
i), 1);
835 sigma += DMT::ValueConst(*z_,curDim+
j,
i);
836 sigma *= SCT::conjugate(beta[curDim+
j]);
838 1, &DMT::Value(*z_,curDim+
j+1,
i), 1);
839 DMT::Value(*z_,curDim+
j,
i) -=
sigma;
844 DMT::SyncHostToDevice(*z_);
845 DMT::SyncHostToDevice(*R_);
848 if (
dim >= curDim_ &&
dim < getMaxSubspaceDim()) {
849 curDim_ =
dim + blockSize_;
864 template <
class ScalarType,
class MV,
class OP,
class DM>
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_);
877 std::vector<int>
bsind(blockSize_);
878 for (
int i=0;
i<blockSize_;
i++) {
bsind[
i] = curDim_ +
i; }
881 Teuchos::RCP<MV>
lclAV;
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;
895 os <<
" >> Error in V^H M F == 0 : " <<
tmp << std::endl;
903 lclAV = MVT::Clone(*V_,curDim_);
907 const ScalarType one = Teuchos::ScalarTraits<ScalarType>::one();
908 Teuchos::RCP<DM>
subH = DMT::Subview(*H_,curDim_,curDim_);
912 Teuchos::RCP<DM>
curB = DMT::Subview(*H_,blockSize_,curDim_,curDim_);
916 std::vector<MagnitudeType>
arnNorms( curDim_ );
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.
This class implements the block GMRES iteration, where a block Krylov subspace is constructed....
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
Get the norms of the residuals native to the solver.
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...
GmresIterationOrthoFailure is thrown when the GmresIteration object is unable to compute independent ...
Alternative run-time polymorphic interface for operators.
Operator()
Default constructor (does nothing).