42 #ifndef BELOS_PSEUDO_BLOCK_GMRES_ITER_MP_VECTOR_HPP
43 #define BELOS_PSEUDO_BLOCK_GMRES_ITER_MP_VECTOR_HPP
54 #include "BelosPseudoBlockGmresIter.hpp"
71 template<
class Storage,
class MV,
class OP>
73 virtual public Iteration<Sacado::MP::Vector<Storage>, MV, OP> {
81 typedef MultiVecTraits<ScalarType,MV>
MVT;
82 typedef OperatorTraits<ScalarType,MV,OP>
OPT;
100 const Teuchos::RCP<StatusTest<ScalarType,MV,OP> > &tester,
101 const Teuchos::RCP<MatOrthoManager<ScalarType,MV,OP> > &ortho,
156 void initialize(
const PseudoBlockGmresIterState<ScalarType,MV> & newstate);
163 PseudoBlockGmresIterState<ScalarType,MV> empty;
174 PseudoBlockGmresIterState<ScalarType,MV>
getState()
const {
175 PseudoBlockGmresIterState<ScalarType,MV> state;
176 state.curDim = curDim_;
177 state.V.resize(numRHS_);
178 state.H.resize(numRHS_);
179 state.Z.resize(numRHS_);
180 state.sn.resize(numRHS_);
181 state.cs.resize(numRHS_);
182 for (
int i=0; i<numRHS_; ++i) {
186 state.sn[i] = sn_[i];
187 state.cs[i] = cs_[i];
235 void updateLSQR(
int dim = -1 );
239 if (!initialized_)
return 0;
253 const LinearProblem<ScalarType,MV,OP>&
getProblem()
const {
return *lp_; }
261 "Belos::PseudoBlockGmresIter::setBlockSize(): Cannot use a block size that is not one.");
268 void setNumBlocks(
int numBlocks);
297 std::vector<Teuchos::RCP<Teuchos::SerialDenseVector<int,ScalarType> > >
sn_;
298 std::vector<Teuchos::RCP<Teuchos::SerialDenseVector<int,MagnitudeType> > >
cs_;
320 std::vector<Teuchos::RCP<MV> >
V_;
325 std::vector<Teuchos::RCP<Teuchos::SerialDenseMatrix<int,ScalarType> > >
H_;
330 std::vector<Teuchos::RCP<Teuchos::SerialDenseMatrix<int,ScalarType> > >
R_;
331 std::vector<Teuchos::RCP<Teuchos::SerialDenseVector<int,ScalarType> > >
Z_;
336 #ifdef BELOS_TEUCHOS_TIME_MONITOR
343 template<
class StorageType,
class MV,
class OP>
346 const Teuchos::RCP<OutputManager<ScalarType> > &printer,
347 const Teuchos::RCP<StatusTest<ScalarType,MV,OP> > &tester,
348 const Teuchos::RCP<MatOrthoManager<ScalarType,MV,OP> > &ortho,
359 breakDownTol_(params.get(
"Ensemble Breakdown Tolerance", 0.0))
363 "Belos::PseudoBlockGmresIter::constructor: mandatory parameter 'Num Blocks' is not specified.");
364 int nb = Teuchos::getParameter<int>(params,
"Num Blocks");
371 template <
class StorageType,
class MV,
class OP>
372 void PseudoBlockGmresIter<Sacado::MP::Vector<StorageType>,MV,OP>::setNumBlocks (
int numBlocks)
377 TEUCHOS_TEST_FOR_EXCEPTION(numBlocks <= 0, std::invalid_argument,
"Belos::PseudoBlockGmresIter::setNumBlocks was passed a non-positive argument.");
379 numBlocks_ = numBlocks;
382 initialized_ =
false;
387 template <
class StorageType,
class MV,
class OP>
388 Teuchos::RCP<MV> PseudoBlockGmresIter<Sacado::MP::Vector<StorageType>,MV,OP>::getCurrentUpdate()
const
390 #ifdef BELOS_TEUCHOS_TIME_MONITOR
399 return currentUpdate;
401 currentUpdate = MVT::Clone(*(V_[0]), numRHS_);
402 std::vector<int> index(1), index2(curDim_);
403 for (
int i=0; i<curDim_; ++i) {
410 for (
int i=0; i<numRHS_; ++i) {
412 Teuchos::RCP<MV> cur_block_copy_vec = MVT::CloneViewNonConst( *currentUpdate, index );
422 H_[i]->values(), H_[i]->stride(), y.values(), y.stride() );
426 MVT::MvTimesMatAddMv( one, *Vjp1, y, zero, *cur_block_copy_vec );
429 return currentUpdate;
436 template <
class StorageType,
class MV,
class OP>
438 PseudoBlockGmresIter<Sacado::MP::Vector<StorageType>,MV,OP>::
439 getNativeResiduals (std::vector<MagnitudeType> *norms)
const
447 if (static_cast<int> (norms->size()) < numRHS_)
448 norms->resize (numRHS_);
451 for (
int j = 0;
j < numRHS_; ++
j)
453 const ScalarType curNativeResid = (*Z_[
j])(curDim_);
454 (*norms)[
j] = STS::magnitude (curNativeResid);
461 template <
class StorageType,
class MV,
class OP>
463 PseudoBlockGmresIter<Sacado::MP::Vector<StorageType>,MV,OP>::
464 initialize (
const PseudoBlockGmresIterState<ScalarType,MV> & newstate)
470 this->numRHS_ = MVT::GetNumberVecs (*(lp_->getCurrLHSVec()));
472 #ifdef BELOS_TEUCHOS_TIME_MONITOR
473 std::stringstream ss;
476 std::string updateLabel = ss.str() +
": Update LSQR";
479 std::string solveLabel = ss.str() +
": Solve LSQR";
487 std::string errstr (
"Belos::PseudoBlockGmresIter::initialize(): "
488 "Specified multivectors must have a consistent "
489 "length and width.");
493 std::invalid_argument,
494 "Belos::PseudoBlockGmresIter::initialize(): "
495 "V and/or Z was not specified in the input state; "
496 "the V and/or Z arrays have length zero.");
507 RCP<const MV> lhsMV = lp_->getLHS();
508 RCP<const MV> rhsMV = lp_->getRHS();
512 RCP<const MV> vectorInBasisSpace = rhsMV.is_null() ? lhsMV : rhsMV;
516 std::invalid_argument,
517 "Belos::PseudoBlockGmresIter::initialize(): "
518 "The linear problem to solve does not specify multi"
519 "vectors from which we can clone basis vectors. The "
520 "right-hand side(s), left-hand side(s), or both should "
526 std::invalid_argument,
528 curDim_ = newstate.curDim;
534 for (
int i=0; i<numRHS_; ++i) {
538 if (V_[i].
is_null() || MVT::GetNumberVecs(*V_[i]) < numBlocks_ + 1) {
539 V_[i] = MVT::Clone (*vectorInBasisSpace, numBlocks_ + 1);
544 std::invalid_argument, errstr );
546 std::invalid_argument, errstr );
551 int lclDim = MVT::GetNumberVecs(*newstate.V[i]);
552 if (newstate.V[i] != V_[i]) {
554 if (curDim_ == 0 && lclDim > 1) {
555 om_->stream(Warnings)
556 <<
"Belos::PseudoBlockGmresIter::initialize(): the solver was "
557 <<
"initialized with a kernel of " << lclDim
559 <<
"The block size however is only " << 1
561 <<
"The last " << lclDim - 1 <<
" vectors will be discarded."
564 std::vector<int> nevind (curDim_ + 1);
565 for (
int j = 0;
j < curDim_ + 1; ++
j)
568 RCP<const MV> newV = MVT::CloneView (*newstate.V[i], nevind);
569 RCP<MV> lclV = MVT::CloneViewNonConst( *V_[i], nevind );
572 MVT::MvAddMv (one, *newV, zero, *newV, *lclV);
582 for (
int i=0; i<numRHS_; ++i) {
587 if (Z_[i]->length() < numBlocks_+1) {
588 Z_[i]->shapeUninitialized(numBlocks_+1, 1);
595 if (newstate.Z[i] != Z_[i]) {
612 for (
int i=0; i<numRHS_; ++i) {
617 if (H_[i]->numRows() < numBlocks_+1 || H_[i]->numCols() < numBlocks_) {
618 H_[i]->shapeUninitialized(numBlocks_+1, numBlocks_);
622 if ((
int)newstate.H.size() == numRHS_) {
626 "Belos::PseudoBlockGmresIter::initialize(): Specified Hessenberg matrices must have a consistent size to the current subspace dimension");
628 if (newstate.H[i] != H_[i]) {
649 if ((
int)newstate.cs.size() == numRHS_ && (int)newstate.sn.size() == numRHS_) {
650 for (
int i=0; i<numRHS_; ++i) {
651 if (cs_[i] != newstate.cs[i])
653 if (sn_[i] != newstate.sn[i])
659 for (
int i=0; i<numRHS_; ++i) {
663 cs_[i]->resize(numBlocks_+1);
667 sn_[i]->resize(numBlocks_+1);
689 template <
class StorageType,
class MV,
class OP>
690 void PseudoBlockGmresIter<Sacado::MP::Vector<StorageType>,MV,OP>::iterate()
695 if (initialized_ ==
false) {
703 int searchDim = numBlocks_;
708 std::vector<int> index(1);
709 std::vector<int> index2(1);
716 for (
int i=0; i<numRHS_; ++i) {
720 MVT::MvAddMv( one, *tmp_vec, zero, *tmp_vec, *U_vec_view );
728 while (stest_->checkStatus(
this) != Passed && curDim_ < searchDim) {
734 lp_->apply( *U_vec, *AU_vec );
739 int num_prev = curDim_+1;
740 index.resize( num_prev );
741 for (
int i=0; i<num_prev; ++i) {
747 for (
int i=0; i<numRHS_; ++i) {
776 ortho_->projectAndNormalize( *V_new, h_array, r_new, V_array );
782 index2[0] = curDim_+1;
784 MVT::MvAddMv( one, *V_new, zero, *V_new, *tmp_vec );
799 #ifdef BELOS_TEUCHOS_TIME_MONITOR
831 template<
class StorageType,
class MV,
class OP>
832 void PseudoBlockGmresIter<Sacado::MP::Vector<StorageType>,MV,OP>::updateLSQR(
int dim )
837 int curDim = curDim_;
838 if (dim >= curDim_ && dim < getMaxSubspaceDim()) {
848 for (i=0; i<numRHS_; ++i) {
854 for (j=0; j<curDim; j++) {
858 blas.
ROT( 1, &(*H_[i])(j,curDim), 1, &(*H_[i])(j+1, curDim), 1, &(*cs_[i])[j], &(*sn_[i])[j] );
866 lucky_breakdown_ = ((*Z_[i])(curDim) == zero);
868 auto lucky_breakdown_tmp = ((*H_[i])(curDim+1,curDim) == zero);
869 mask_assign(lucky_breakdown_,(*H_[i])(curDim,curDim)) = one;
870 lucky_breakdown_ = lucky_breakdown_ || lucky_breakdown_tmp;
872 blas.
ROTG( &(*H_[i])(curDim,curDim), &(*H_[i])(curDim+1,curDim), &(*cs_[i])[curDim], &(*sn_[i])[curDim] );
873 (*H_[i])(curDim+1,curDim) = zero;
877 blas.
ROT( 1, &(*Z_[i])(curDim), 1, &(*Z_[i])(curDim+1), 1, &(*cs_[i])[curDim], &(*sn_[i])[curDim] );
Teuchos::ScalarTraits< ScalarType > SCT
void TRSM(ESide side, EUplo uplo, ETransp transa, EDiag diag, const OrdinalType &m, const OrdinalType &n, const alpha_type alpha, const A_type *A, const OrdinalType &lda, ScalarType *B, const OrdinalType &ldb) const
int getNumIters() const
Get the current iteration count.
std::vector< Teuchos::RCP< MV > > V_
bool isInitialized()
States whether the solver has been initialized or not.
int getCurSubspaceDim() const
Get the dimension of the search subspace used to generate the current solution to the linear problem...
void resetNumIters(int iter=0)
Reset the iteration count.
bool is_null(const boost::shared_ptr< T > &p)
void ROT(const OrdinalType &n, ScalarType *dx, const OrdinalType &incx, ScalarType *dy, const OrdinalType &incy, MagnitudeType *c, ScalarType *s) const
const Teuchos::RCP< OrthoManager< ScalarType, MV > > ortho_
#define TEUCHOS_TEST_FOR_EXCEPTION(throw_exception_test, Exception, msg)
const Teuchos::RCP< OutputManager< ScalarType > > om_
Sacado::MP::Vector< Storage > ScalarType
KOKKOS_INLINE_FUNCTION MaskedAssign< scalar > mask_assign(bool b, scalar *s)
bool isParameter(const std::string &name) const
Teuchos::RCP< MV > U_vec_
TEUCHOS_DEPRECATED RCP< T > rcp(T *p, Dealloc_T dealloc, bool owns_mem)
std::vector< Teuchos::RCP< Teuchos::SerialDenseVector< int, MagnitudeType > > > cs_
SCT::magnitudeType MagnitudeType
std::vector< Teuchos::RCP< Teuchos::SerialDenseMatrix< int, ScalarType > > > R_
std::vector< Teuchos::RCP< Teuchos::SerialDenseMatrix< int, ScalarType > > > H_
OperatorTraits< ScalarType, MV, OP > OPT
void setBlockSize(int blockSize)
Set the blocksize.
void initialize()
Initialize the solver with the initial vectors from the linear problem or random data.
void ROTG(ScalarType *da, ScalarType *db, rotg_c_type *c, ScalarType *s) const
SVT::magnitudeType breakDownTol_
const Teuchos::RCP< LinearProblem< ScalarType, MV, OP > > lp_
std::vector< Teuchos::RCP< Teuchos::SerialDenseVector< int, ScalarType > > > Z_
Teuchos::RCP< MV > cur_block_sol_
const LinearProblem< ScalarType, MV, OP > & getProblem() const
Get a constant reference to the linear problem.
int getMaxSubspaceDim() const
Get the maximum dimension allocated for the search subspace.
MultiVecTraits< ScalarType, MV > MVT
int getBlockSize() const
Get the blocksize to be used by the iterative solver in solving this linear problem.
const Teuchos::RCP< StatusTest< ScalarType, MV, OP > > stest_
int getNumBlocks() const
Get the maximum number of blocks used by the iterative solver in solving this linear problem...
Mask< MagnitudeType > lucky_breakdown_
Teuchos::ScalarTraits< typename Storage::value_type > SVT
This class implements the pseudo-block GMRES iteration, where a block Krylov subspace is constructed ...
SerialDenseMatrix< OrdinalType, ScalarType > & assign(const SerialDenseMatrix< OrdinalType, ScalarType > &Source)
PseudoBlockGmresIterState< ScalarType, MV > getState() const
Get the current state of the linear solver.
std::vector< Teuchos::RCP< Teuchos::SerialDenseVector< int, ScalarType > > > sn_