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 = DefaultDenseMatrix<
int,ScalarType>>
62 typedef Teuchos::ScalarTraits<ScalarType>
SCT;
81 Teuchos::ParameterList ¶ms );
196 if (!initialized_)
return 0;
230 void setSize(
int blockSize,
int numBlocks);
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 ¶ms ):
321 stateStorageInitialized_(false),
322 keepHessenberg_(false),
327 if (om_->isVerbosity(
Debug))
328 keepHessenberg_ =
true;
330 keepHessenberg_ = params.get(
"Keep Hessenberg",
false);
333 TEUCHOS_TEST_FOR_EXCEPTION(
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>
351 TEUCHOS_TEST_FOR_EXCEPTION(numBlocks <= 0 || blockSize <= 0, std::invalid_argument,
"Belos::BlockFGmresIter::setSize was passed a non-positive argument.");
352 if (blockSize == blockSize_ && numBlocks == numBlocks_) {
357 if (blockSize!=blockSize_ || numBlocks!=numBlocks_)
358 stateStorageInitialized_ =
false;
360 blockSize_ = blockSize;
361 numBlocks_ = numBlocks;
363 initialized_ =
false;
373 template <
class ScalarType,
class MV,
class OP,
class DM>
374 void BlockFGmresIter<ScalarType,MV,OP,DM>::setStateSize ()
379 if (! stateStorageInitialized_) {
381 RCP<const MV> lhsMV = lp_->getLHS();
382 RCP<const MV> rhsMV = lp_->getRHS();
383 if (lhsMV == Teuchos::null && rhsMV == Teuchos::null) {
384 stateStorageInitialized_ =
false;
391 int newsd = blockSize_*(numBlocks_+1);
402 TEUCHOS_TEST_FOR_EXCEPTION(
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) {
410 RCP<const MV> tmp = (rhsMV != Teuchos::null) ? rhsMV : lhsMV;
411 TEUCHOS_TEST_FOR_EXCEPTION(
412 tmp == Teuchos::null, std::invalid_argument,
413 "Belos::BlockFGmresIter::setStateSize(): "
414 "linear problem does not specify multivectors to clone from.");
415 V_ = MVT::Clone (*tmp, newsd);
419 if (MVT::GetNumberVecs (*V_) < newsd) {
420 RCP<const MV> tmp = V_;
421 V_ = MVT::Clone (*tmp, newsd);
425 if (Z_ == Teuchos::null) {
427 RCP<const MV> tmp = (rhsMV != Teuchos::null) ? rhsMV : lhsMV;
428 TEUCHOS_TEST_FOR_EXCEPTION(
429 tmp == Teuchos::null, std::invalid_argument,
430 "Belos::BlockFGmresIter::setStateSize(): "
431 "linear problem does not specify multivectors to clone from.");
432 Z_ = MVT::Clone (*tmp, newsd);
436 if (MVT::GetNumberVecs (*Z_) < newsd) {
437 RCP<const MV> tmp = Z_;
438 Z_ = MVT::Clone (*tmp, newsd);
443 if (R_ == Teuchos::null) {
444 R_ = DMT::Create(newsd, newsd-blockSize_);
447 DMT::Reshape(*R_, newsd, newsd - blockSize_);
453 if (keepHessenberg_) {
454 if (H_ == Teuchos::null) {
455 H_ = DMT::Create(newsd, newsd-blockSize_);
458 DMT::Reshape(*H_, newsd, newsd - blockSize_);
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>
484 Teuchos::RCP<MV> currentUpdate = Teuchos::null;
488 return currentUpdate;
491 const ScalarType zero = Teuchos::ScalarTraits<ScalarType>::zero ();
492 const ScalarType one = Teuchos::ScalarTraits<ScalarType>::one ();
493 Teuchos::BLAS<int,ScalarType> blas;
504 blas.TRSM (Teuchos::LEFT_SIDE, Teuchos::UPPER_TRI, Teuchos::NO_TRANS,
505 Teuchos::NON_UNIT_DIAG, curDim_, blockSize_, one,
513 std::vector<int> index (curDim_);
514 for (
int i = 0; i < curDim_; ++i) {
520 return currentUpdate;
524 template <
class ScalarType,
class MV,
class OP,
class DM>
525 Teuchos::RCP<const MV>
530 if (norms != NULL && (
int)norms->size() < blockSize_) {
531 norms->resize (blockSize_);
535 Teuchos::BLAS<int, ScalarType> blas;
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_) {
560 TEUCHOS_TEST_FOR_EXCEPTION(
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.";
570 if (! newstate.
V.is_null () && ! newstate.
z.is_null ()) {
574 TEUCHOS_TEST_FOR_EXCEPTION(
576 std::invalid_argument, errstr );
577 TEUCHOS_TEST_FOR_EXCEPTION(
579 std::invalid_argument, errstr );
580 TEUCHOS_TEST_FOR_EXCEPTION(
581 newstate.
curDim > blockSize_*(numBlocks_+1),
582 std::invalid_argument, errstr );
584 curDim_ = newstate.
curDim;
588 TEUCHOS_TEST_FOR_EXCEPTION(
590 std::invalid_argument, errstr);
593 if (newstate.
V != V_) {
595 if (curDim_ == 0 && lclDim > blockSize_) {
596 std::ostream& warn = om_->stream (
Warnings);
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;
616 if (newstate.
z != z_) {
618 RCP<const DM> newZ =
DMT::SubviewConst(*newstate.
z, curDim_ + blockSize_, blockSize_);
619 RCP<DM> lclz =
DMT::Subview(*z_, curDim_ + blockSize_, blockSize_);
621 lclz = Teuchos::null;
625 TEUCHOS_TEST_FOR_EXCEPTION(
626 newstate.
V == Teuchos::null,std::invalid_argument,
627 "Belos::BlockFGmresIter::initialize(): BlockFGmresStateIterState does not have initial kernel V_0.");
629 TEUCHOS_TEST_FOR_EXCEPTION(
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) {
664 curind[i] = lclDim + i;
670 for (
int i = 0; i < blockSize_; ++i) {
671 curind[i] = curDim_ + i;
677 lp_->applyRightPrec (*Vprev, *Znext);
678 Vprev = Teuchos::null;
681 lp_->applyOp (*Znext, *Vnext);
682 Znext = Teuchos::null;
686 std::vector<int> prevind (lclDim);
687 for (
int i = 0; i < lclDim; ++i) {
691 Teuchos::Array<RCP<const MV> > AVprev (1, Vprev);
695 RCP<DM> subH =
DMT::Subview(*H_, lclDim, blockSize_, 0, curDim_);
696 Teuchos::Array<RCP<DM> > AsubH;
700 RCP<DM> subH2 =
DMT::Subview(*H_, blockSize_, blockSize_, lclDim, curDim_);
701 const int rank = ortho_->projectAndNormalize (*Vnext, AsubH, subH2, AVprev);
702 TEUCHOS_TEST_FOR_EXCEPTION(
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_) {
713 RCP<DM> subR =
DMT::Subview(*R_,lclDim,blockSize_,0,curDim_ );
717 RCP<DM> subR2 =
DMT::Subview(*R_,blockSize_,blockSize_,lclDim,curDim_ );
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;
742 const ScalarType zero = STS::zero ();
743 const ScalarType two = (STS::one () + STS::one());
744 ScalarType sigma, mu, vscale, maxelem;
745 Teuchos::BLAS<int, ScalarType> blas;
751 int curDim = curDim_;
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]);
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) {
787 blas.AXPY (blockSize_, ScalarType(-sigma), &
DMT::Value(*R_,i+1,i), 1, &
DMT::Value(*R_,i+1,curDim+j), 1);
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 ()) {
806 vscale = -sigma / (
DMT::Value(*R_,curDim+j, curDim+j) + mu);
808 beta[curDim+j] = two * vscale * vscale / (sigma + vscale*vscale);
809 DMT::Value(*R_,curDim+j, curDim+j) = maxelem*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),
820 sigma *= beta[curDim+j];
821 blas.AXPY (blockSize_, ScalarType(-sigma), &
DMT::Value(*R_,curDim+j+1,curDim+j),
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.
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
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...
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 const * GetConstRawHostPtr(const DM &dm)
Returns a raw pointer to const data on the host.
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 MV > Z
The current preconditioned Krylov basis (only used in flexible GMRES).
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.