10#ifndef BELOS_BLOCK_FGMRES_ITER_HPP
11#define BELOS_BLOCK_FGMRES_ITER_HPP
29#include "Teuchos_BLAS.hpp"
30#include "Teuchos_ScalarTraits.hpp"
31#include "Teuchos_ParameterList.hpp"
32#include "Teuchos_TimeMonitor.hpp"
51template<
class ScalarType,
class MV,
class OP,
class DM>
62 typedef Teuchos::ScalarTraits<ScalarType>
SCT;
81 Teuchos::ParameterList &
params );
155 state.curDim = curDim_;
196 if (!initialized_)
return 0;
248 const Teuchos::RCP<LinearProblem<ScalarType,MV,OP,DM> > lp_;
249 const Teuchos::RCP<OutputManager<ScalarType> > om_;
250 const Teuchos::RCP<StatusTest<ScalarType,MV,OP,DM> > stest_;
251 const Teuchos::RCP<OrthoManager<ScalarType,MV,DM> > ortho_;
263 std::vector<ScalarType> beta, sn;
264 std::vector<MagnitudeType> cs;
277 bool stateStorageInitialized_;
282 bool keepHessenberg_;
307 template<
class ScalarType,
class MV,
class OP,
class DM>
313 Teuchos::ParameterList &
params ):
321 stateStorageInitialized_(
false),
322 keepHessenberg_(
false),
327 if (om_->isVerbosity(
Debug))
328 keepHessenberg_ =
true;
330 keepHessenberg_ =
params.get(
"Keep Hessenberg",
false);
334 !
params.isParameter (
"Num Blocks"), std::invalid_argument,
335 "Belos::BlockFGmresIter::constructor: mandatory parameter 'Num Blocks' is not specified.");
336 const int nb =
params.get<
int> (
"Num Blocks");
339 const int bs =
params.get (
"Block Size", 1);
345 template <
class ScalarType,
class MV,
class OP,
class DM>
358 stateStorageInitialized_ =
false;
363 initialized_ =
false;
373 template <
class ScalarType,
class MV,
class OP,
class DM>
379 if (! stateStorageInitialized_) {
383 if (
lhsMV == Teuchos::null &&
rhsMV == Teuchos::null) {
384 stateStorageInitialized_ =
false;
391 int newsd = blockSize_*(numBlocks_+1);
403 blockSize_ *
static_cast<ptrdiff_t> (numBlocks_) > MVT::GetGlobalLength (*
rhsMV),
404 std::invalid_argument,
"Belos::BlockFGmresIter::setStateSize(): "
405 "Cannot generate a Krylov basis with dimension larger the operator!");
408 if (V_ == Teuchos::null) {
412 tmp == Teuchos::null, std::invalid_argument,
413 "Belos::BlockFGmresIter::setStateSize(): "
414 "linear problem does not specify multivectors to clone from.");
419 if (MVT::GetNumberVecs (*V_) <
newsd) {
425 if (Z_ == Teuchos::null) {
429 tmp == Teuchos::null, std::invalid_argument,
430 "Belos::BlockFGmresIter::setStateSize(): "
431 "linear problem does not specify multivectors to clone from.");
436 if (MVT::GetNumberVecs (*Z_) <
newsd) {
443 if (R_ == Teuchos::null) {
453 if (keepHessenberg_) {
454 if (H_ == Teuchos::null) {
466 if (z_ == Teuchos::null) {
467 z_ = DMT::Create(
newsd, blockSize_);
470 DMT::Reshape(*z_,
newsd, blockSize_);
474 stateStorageInitialized_ =
true;
480 template <
class ScalarType,
class MV,
class OP,
class DM>
491 const ScalarType zero = Teuchos::ScalarTraits<ScalarType>::zero ();
492 const ScalarType one = Teuchos::ScalarTraits<ScalarType>::one ();
493 Teuchos::BLAS<int,ScalarType>
blas;
498 DMT::SyncDeviceToHost( *z_ );
499 DMT::SyncDeviceToHost( *H_ );
501 Teuchos::RCP<DM> y = DMT::SubviewCopy(*z_, curDim_, blockSize_);
504 blas.TRSM (Teuchos::LEFT_SIDE, Teuchos::UPPER_TRI, Teuchos::NO_TRANS,
505 Teuchos::NON_UNIT_DIAG, curDim_, blockSize_,
one,
506 DMT::GetConstRawHostPtr(*R_), DMT::GetStride(*R_),
507 DMT::GetRawHostPtr(*y), DMT::GetStride(*y));
510 DMT::SyncHostToDevice( *y );
513 std::vector<int> index (curDim_);
514 for (
int i = 0;
i < curDim_; ++
i) {
517 Teuchos::RCP<const MV>
Zjp1 = MVT::CloneView (*Z_, index);
524 template <
class ScalarType,
class MV,
class OP,
class DM>
525 Teuchos::RCP<const MV>
531 norms->resize (blockSize_);
535 Teuchos::BLAS<int, ScalarType>
blas;
536 DMT::SyncDeviceToHost( *z_ );
537 for (
int j = 0;
j < blockSize_; ++
j) {
538 (*norms)[
j] =
blas.NRM2 (blockSize_, &DMT::Value(*z_, curDim_,
j), 1);
543 return Teuchos::null;
547 template <
class ScalarType,
class MV,
class OP,
class DM>
556 if (! stateStorageInitialized_) {
561 ! stateStorageInitialized_, std::invalid_argument,
562 "Belos::BlockFGmresIter::initialize(): Cannot initialize state storage!");
567 const char errstr[] =
"Belos::BlockFGmresIter::initialize(): The given "
568 "multivectors must have a consistent length and width.";
575 MVT::GetGlobalLength(*
newstate.V) != MVT::GetGlobalLength(*V_),
576 std::invalid_argument,
errstr );
578 MVT::GetNumberVecs(*
newstate.V) < blockSize_,
579 std::invalid_argument,
errstr );
581 newstate.curDim > blockSize_*(numBlocks_+1),
582 std::invalid_argument,
errstr );
589 DMT::GetNumRows(*
newstate.z) < curDim_ || DMT::GetNumCols(*
newstate.z) < blockSize_,
590 std::invalid_argument,
errstr);
595 if (curDim_ == 0 &&
lclDim > blockSize_) {
597 warn <<
"Belos::BlockFGmresIter::initialize(): the solver was "
598 <<
"initialized with a kernel of " <<
lclDim << endl
599 <<
"The block size however is only " << blockSize_ << endl
600 <<
"The last " <<
lclDim - blockSize_
601 <<
" vectors will be discarded." << endl;
603 std::vector<int>
nevind (curDim_ + blockSize_);
604 for (
int i = 0;
i < curDim_ + blockSize_; ++
i) {
612 lclV = Teuchos::null;
619 RCP<DM> lclz = DMT::Subview(*z_, curDim_ + blockSize_, blockSize_);
621 lclz = Teuchos::null;
626 newstate.V == Teuchos::null,std::invalid_argument,
627 "Belos::BlockFGmresIter::initialize(): BlockFGmresStateIterState does not have initial kernel V_0.");
630 newstate.z == Teuchos::null,std::invalid_argument,
631 "Belos::BlockFGmresIter::initialize(): BlockFGmresStateIterState does not have initial norms z_0.");
639 template <
class ScalarType,
class MV,
class OP,
class DM>
646 if (initialized_ ==
false) {
651 const int searchDim = blockSize_ * numBlocks_;
655 while (stest_->checkStatus (
this) !=
Passed && curDim_+blockSize_ <=
searchDim) {
659 const int lclDim = curDim_ + blockSize_;
662 std::vector<int>
curind (blockSize_);
663 for (
int i = 0;
i < blockSize_; ++
i) {
670 for (
int i = 0;
i < blockSize_; ++
i) {
678 Vprev = Teuchos::null;
682 Znext = Teuchos::null;
696 Teuchos::Array<RCP<DM> >
AsubH;
704 "Belos::BlockFGmresIter::iterate(): After orthogonalization, the new "
705 "basis block does not have full rank. It contains " << blockSize_
706 <<
" vector" << (blockSize_ != 1 ?
"s" :
"")
707 <<
", but its rank is " <<
rank <<
".");
711 if (keepHessenberg_) {
730 Vnext = Teuchos::null;
731 curDim_ += blockSize_;
736 template<
class ScalarType,
class MV,
class OP,
class DM>
739 typedef Teuchos::ScalarTraits<ScalarType> STS;
740 typedef Teuchos::ScalarTraits<MagnitudeType> STM;
745 Teuchos::BLAS<int, ScalarType>
blas;
751 int curDim = curDim_;
752 if (
dim >= curDim_ &&
dim < getMaxSubspaceDim ()) {
761 DMT::SyncDeviceToHost( *H_ );
762 DMT::SyncDeviceToHost( *z_ );
764 if (blockSize_ == 1) {
767 for (
int i = 0;
i < curDim; ++
i) {
769 blas.ROT (1, &DMT::Value(*R_,
i, curDim), 1, &DMT::Value(*R_,
i+1, curDim), 1, &cs[
i], &sn[
i]);
773 blas.ROTG (&DMT::Value(*R_,curDim, curDim), &DMT::Value(*R_,curDim+1, curDim), &cs[curDim], &sn[curDim]);
774 DMT::Value(*R_,curDim+1, curDim) =
zero;
777 blas.ROT (1, &DMT::Value(*z_,curDim,0), 1, &DMT::Value(*z_,curDim+1,0), 1, &cs[curDim], &sn[curDim]);
781 for (
int j = 0;
j < blockSize_; ++
j) {
783 for (
int i = 0;
i < curDim +
j; ++
i) {
784 sigma =
blas.DOT (blockSize_, &DMT::Value(*R_,
i+1,
i), 1, &DMT::Value(*R_,
i+1,curDim+
j), 1);
785 sigma += DMT::ValueConst(*R_,
i,curDim+
j);
788 DMT::Value(*R_,
i,curDim+
j) -=
sigma;
792 const int maxidx =
blas.IAMAX (blockSize_+1, &DMT::Value(*R_,curDim+
j,curDim+
j), 1);
794 for (
int i = 0;
i < blockSize_ + 1; ++
i) {
795 DMT::Value(*R_,curDim+
j+
i,curDim+
j) /=
maxelem;
797 sigma =
blas.DOT (blockSize_, &DMT::Value(*R_,curDim +
j + 1, curDim +
j), 1,
798 &DMT::Value(*R_,curDim +
j + 1, curDim +
j), 1);
800 beta[curDim +
j] =
zero;
802 mu = STS::squareroot (DMT::Value(*R_,curDim+
j,curDim+
j)*DMT::Value(*R_,curDim+
j,curDim+
j)+
sigma);
803 if (STS::real (DMT::Value(*R_,curDim +
j, curDim +
j)) < STM::zero ()) {
804 vscale = DMT::ValueConst(*R_,curDim+
j,curDim+
j) -
mu;
810 for (
int i = 0;
i < blockSize_; ++
i) {
811 DMT::Value(*R_,curDim+
j+1+
i,curDim+
j) /=
vscale;
816 for (
int i = 0;
i < blockSize_; ++
i) {
817 sigma =
blas.DOT (blockSize_, &DMT::Value(*R_,curDim+
j+1,curDim+
j),
818 1, &DMT::Value(*z_,curDim+
j+1,
i), 1);
819 sigma += DMT::ValueConst(*z_,curDim+
j,
i);
822 1, &DMT::Value(*z_,curDim+
j+1,
i), 1);
823 DMT::Value(*z_,curDim+
j,
i) -=
sigma;
828 DMT::SyncHostToDevice( *H_ );
829 DMT::SyncHostToDevice( *z_ );
832 if (
dim >= curDim_ &&
dim < getMaxSubspaceDim ()) {
833 curDim_ =
dim + blockSize_;
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 flexible GMRES iteration, where a block Krylov subspace is constructe...
GmresIterationState< ScalarType, MV, DM > getState() const
Get the current state of the linear solver.
void setBlockSize(int blockSize)
Set the blocksize.
const LinearProblem< ScalarType, MV, OP, DM > & getProblem() const
Get a constant reference to the linear problem.
bool isInitialized()
States whether the solver has been initialized or not.
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...
Teuchos::RCP< MV > getCurrentUpdate() const
Get the current update to the linear system.
void updateLSQR(int dim=-1)
Method for updating QR factorization of upper Hessenberg matrix.
int getBlockSize() const
Get the blocksize to be used by the iterative solver in solving this linear problem.
void initialize()
Initialize the solver with the initial vectors from the linear problem or random data.
MultiVecTraits< ScalarType, MV, DM > MVT
virtual ~BlockFGmresIter()
Destructor.
void initializeGmres(GmresIterationState< ScalarType, MV, DM > &newstate)
Initialize the solver to an iterate, providing a complete state.
void resetNumIters(int iter=0)
Reset the iteration count.
void setNumBlocks(int numBlocks)
Set the maximum number of blocks used by the iterative solver.
int getNumIters() const
Get the current iteration count.
int getNumBlocks() const
Get the maximum number of blocks used by the iterative solver in solving this linear problem.
int getMaxSubspaceDim() const
Get the maximum dimension allocated for the search subspace.
OperatorTraits< ScalarType, MV, OP > OPT
Teuchos::RCP< const MV > getNativeResiduals(std::vector< MagnitudeType > *norms) const
Get the norms of the residuals native to the solver.
void iterate()
This method performs block FGmres iterations until the status test indicates the need to stop or an e...
SCT::magnitudeType MagnitudeType
Teuchos::ScalarTraits< ScalarType > SCT
int getCurSubspaceDim() const
Get the dimension of the search subspace used to generate the current solution to the linear problem.
DenseMatTraits< ScalarType, DM > DMT
BlockFGmresIter(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)
BlockFGmresIter constructor with linear problem, solver utilities, and parameter list of solver optio...
GmresIterationOrthoFailure is thrown when the GmresIteration object is unable to compute independent ...
Alternative run-time polymorphic interface for operators.
Operator()
Default constructor (does nothing).