10 #ifndef BELOS_PSEUDO_BLOCK_GMRES_ITER_MP_VECTOR_HPP
11 #define BELOS_PSEUDO_BLOCK_GMRES_ITER_MP_VECTOR_HPP
22 #include "BelosPseudoBlockGmresIter.hpp"
39 template<
class Storage,
class MV,
class OP>
41 virtual public Iteration<Sacado::MP::Vector<Storage>, MV, OP> {
49 typedef MultiVecTraits<ScalarType,MV>
MVT;
50 typedef OperatorTraits<ScalarType,MV,OP>
OPT;
68 const Teuchos::RCP<StatusTest<ScalarType,MV,OP> > &tester,
69 const Teuchos::RCP<MatOrthoManager<ScalarType,MV,OP> > &ortho,
124 void initialize(
const PseudoBlockGmresIterState<ScalarType,MV> & newstate);
131 PseudoBlockGmresIterState<ScalarType,MV> empty;
142 PseudoBlockGmresIterState<ScalarType,MV>
getState()
const {
143 PseudoBlockGmresIterState<ScalarType,MV> state;
144 state.curDim = curDim_;
145 state.V.resize(numRHS_);
146 state.H.resize(numRHS_);
147 state.Z.resize(numRHS_);
148 state.sn.resize(numRHS_);
149 state.cs.resize(numRHS_);
150 for (
int i=0; i<numRHS_; ++i) {
154 state.sn[i] = sn_[i];
155 state.cs[i] = cs_[i];
203 void updateLSQR(
int dim = -1 );
207 if (!initialized_)
return 0;
221 const LinearProblem<ScalarType,MV,OP>&
getProblem()
const {
return *lp_; }
229 "Belos::PseudoBlockGmresIter::setBlockSize(): Cannot use a block size that is not one.");
236 void setNumBlocks(
int numBlocks);
265 std::vector<Teuchos::RCP<Teuchos::SerialDenseVector<int,ScalarType> > >
sn_;
266 std::vector<Teuchos::RCP<Teuchos::SerialDenseVector<int,MagnitudeType> > >
cs_;
288 std::vector<Teuchos::RCP<MV> >
V_;
293 std::vector<Teuchos::RCP<Teuchos::SerialDenseMatrix<int,ScalarType> > >
H_;
298 std::vector<Teuchos::RCP<Teuchos::SerialDenseMatrix<int,ScalarType> > >
R_;
299 std::vector<Teuchos::RCP<Teuchos::SerialDenseVector<int,ScalarType> > >
Z_;
304 #ifdef BELOS_TEUCHOS_TIME_MONITOR
311 template<
class StorageType,
class MV,
class OP>
314 const Teuchos::RCP<OutputManager<ScalarType> > &printer,
315 const Teuchos::RCP<StatusTest<ScalarType,MV,OP> > &tester,
316 const Teuchos::RCP<MatOrthoManager<ScalarType,MV,OP> > &ortho,
327 breakDownTol_(params.get(
"Ensemble Breakdown Tolerance", 0.0))
331 "Belos::PseudoBlockGmresIter::constructor: mandatory parameter 'Num Blocks' is not specified.");
332 int nb = Teuchos::getParameter<int>(params,
"Num Blocks");
339 template <
class StorageType,
class MV,
class OP>
340 void PseudoBlockGmresIter<Sacado::MP::Vector<StorageType>,MV,OP>::setNumBlocks (
int numBlocks)
345 TEUCHOS_TEST_FOR_EXCEPTION(numBlocks <= 0, std::invalid_argument,
"Belos::PseudoBlockGmresIter::setNumBlocks was passed a non-positive argument.");
347 numBlocks_ = numBlocks;
350 initialized_ =
false;
355 template <
class StorageType,
class MV,
class OP>
356 Teuchos::RCP<MV> PseudoBlockGmresIter<Sacado::MP::Vector<StorageType>,MV,OP>::getCurrentUpdate()
const
358 #ifdef BELOS_TEUCHOS_TIME_MONITOR
367 return currentUpdate;
369 currentUpdate = MVT::Clone(*(V_[0]), numRHS_);
370 std::vector<int> index(1), index2(curDim_);
371 for (
int i=0; i<curDim_; ++i) {
378 for (
int i=0; i<numRHS_; ++i) {
380 Teuchos::RCP<MV> cur_block_copy_vec = MVT::CloneViewNonConst( *currentUpdate, index );
390 H_[i]->values(), H_[i]->stride(), y.values(), y.stride() );
394 MVT::MvTimesMatAddMv( one, *Vjp1, y, zero, *cur_block_copy_vec );
397 return currentUpdate;
404 template <
class StorageType,
class MV,
class OP>
406 PseudoBlockGmresIter<Sacado::MP::Vector<StorageType>,MV,OP>::
407 getNativeResiduals (std::vector<MagnitudeType> *norms)
const
415 if (static_cast<int> (norms->size()) < numRHS_)
416 norms->resize (numRHS_);
419 for (
int j = 0;
j < numRHS_; ++
j)
421 const ScalarType curNativeResid = (*Z_[
j])(curDim_);
422 (*norms)[
j] = STS::magnitude (curNativeResid);
429 template <
class StorageType,
class MV,
class OP>
431 PseudoBlockGmresIter<Sacado::MP::Vector<StorageType>,MV,OP>::
432 initialize (
const PseudoBlockGmresIterState<ScalarType,MV> & newstate)
438 this->numRHS_ = MVT::GetNumberVecs (*(lp_->getCurrLHSVec()));
440 #ifdef BELOS_TEUCHOS_TIME_MONITOR
441 std::stringstream ss;
444 std::string updateLabel = ss.str() +
": Update LSQR";
447 std::string solveLabel = ss.str() +
": Solve LSQR";
455 std::string errstr (
"Belos::PseudoBlockGmresIter::initialize(): "
456 "Specified multivectors must have a consistent "
457 "length and width.");
461 std::invalid_argument,
462 "Belos::PseudoBlockGmresIter::initialize(): "
463 "V and/or Z was not specified in the input state; "
464 "the V and/or Z arrays have length zero.");
475 RCP<const MV> lhsMV = lp_->getLHS();
476 RCP<const MV> rhsMV = lp_->getRHS();
480 RCP<const MV> vectorInBasisSpace = rhsMV.is_null() ? lhsMV : rhsMV;
484 std::invalid_argument,
485 "Belos::PseudoBlockGmresIter::initialize(): "
486 "The linear problem to solve does not specify multi"
487 "vectors from which we can clone basis vectors. The "
488 "right-hand side(s), left-hand side(s), or both should "
494 std::invalid_argument,
496 curDim_ = newstate.curDim;
502 for (
int i=0; i<numRHS_; ++i) {
506 if (V_[i].
is_null() || MVT::GetNumberVecs(*V_[i]) < numBlocks_ + 1) {
507 V_[i] = MVT::Clone (*vectorInBasisSpace, numBlocks_ + 1);
512 std::invalid_argument, errstr );
514 std::invalid_argument, errstr );
519 int lclDim = MVT::GetNumberVecs(*newstate.V[i]);
520 if (newstate.V[i] != V_[i]) {
522 if (curDim_ == 0 && lclDim > 1) {
523 om_->stream(Warnings)
524 <<
"Belos::PseudoBlockGmresIter::initialize(): the solver was "
525 <<
"initialized with a kernel of " << lclDim
527 <<
"The block size however is only " << 1
529 <<
"The last " << lclDim - 1 <<
" vectors will be discarded."
532 std::vector<int> nevind (curDim_ + 1);
533 for (
int j = 0;
j < curDim_ + 1; ++
j)
536 RCP<const MV> newV = MVT::CloneView (*newstate.V[i], nevind);
537 RCP<MV> lclV = MVT::CloneViewNonConst( *V_[i], nevind );
540 MVT::MvAddMv (one, *newV, zero, *newV, *lclV);
550 for (
int i=0; i<numRHS_; ++i) {
555 if (Z_[i]->length() < numBlocks_+1) {
556 Z_[i]->shapeUninitialized(numBlocks_+1, 1);
563 if (newstate.Z[i] != Z_[i]) {
580 for (
int i=0; i<numRHS_; ++i) {
585 if (H_[i]->numRows() < numBlocks_+1 || H_[i]->numCols() < numBlocks_) {
586 H_[i]->shapeUninitialized(numBlocks_+1, numBlocks_);
590 if ((
int)newstate.H.size() == numRHS_) {
594 "Belos::PseudoBlockGmresIter::initialize(): Specified Hessenberg matrices must have a consistent size to the current subspace dimension");
596 if (newstate.H[i] != H_[i]) {
617 if ((
int)newstate.cs.size() == numRHS_ && (int)newstate.sn.size() == numRHS_) {
618 for (
int i=0; i<numRHS_; ++i) {
619 if (cs_[i] != newstate.cs[i])
621 if (sn_[i] != newstate.sn[i])
627 for (
int i=0; i<numRHS_; ++i) {
631 cs_[i]->resize(numBlocks_+1);
635 sn_[i]->resize(numBlocks_+1);
657 template <
class StorageType,
class MV,
class OP>
658 void PseudoBlockGmresIter<Sacado::MP::Vector<StorageType>,MV,OP>::iterate()
663 if (initialized_ ==
false) {
671 int searchDim = numBlocks_;
676 std::vector<int> index(1);
677 std::vector<int> index2(1);
684 for (
int i=0; i<numRHS_; ++i) {
688 MVT::MvAddMv( one, *tmp_vec, zero, *tmp_vec, *U_vec_view );
696 while (stest_->checkStatus(
this) != Passed && curDim_ < searchDim) {
702 lp_->apply( *U_vec, *AU_vec );
707 int num_prev = curDim_+1;
708 index.resize( num_prev );
709 for (
int i=0; i<num_prev; ++i) {
715 for (
int i=0; i<numRHS_; ++i) {
744 ortho_->projectAndNormalize( *V_new, h_array, r_new, V_array );
750 index2[0] = curDim_+1;
752 MVT::MvAddMv( one, *V_new, zero, *V_new, *tmp_vec );
767 #ifdef BELOS_TEUCHOS_TIME_MONITOR
799 template<
class StorageType,
class MV,
class OP>
800 void PseudoBlockGmresIter<Sacado::MP::Vector<StorageType>,MV,OP>::updateLSQR(
int dim )
805 int curDim = curDim_;
806 if (dim >= curDim_ && dim < getMaxSubspaceDim()) {
816 for (i=0; i<numRHS_; ++i) {
822 for (j=0; j<curDim; j++) {
826 blas.
ROT( 1, &(*H_[i])(j,curDim), 1, &(*H_[i])(j+1, curDim), 1, &(*cs_[i])[j], &(*sn_[i])[j] );
834 lucky_breakdown_ = ((*Z_[i])(curDim) == zero);
836 auto lucky_breakdown_tmp = ((*H_[i])(curDim+1,curDim) == zero);
837 mask_assign(lucky_breakdown_,(*H_[i])(curDim,curDim)) = one;
838 lucky_breakdown_ = lucky_breakdown_ || lucky_breakdown_tmp;
840 blas.
ROTG( &(*H_[i])(curDim,curDim), &(*H_[i])(curDim+1,curDim), &(*cs_[i])[curDim], &(*sn_[i])[curDim] );
841 (*H_[i])(curDim+1,curDim) = zero;
845 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_