Stokhos Package Browser (Single Doxygen Collection)  Version of the Day
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
Belos_PseudoBlockGmresIter_MP_Vector.hpp
Go to the documentation of this file.
1 // @HEADER
2 // *****************************************************************************
3 // Belos: Block Linear Solvers Package
4 //
5 // Copyright 2004 NTESS and the Belos contributors.
6 // SPDX-License-Identifier: BSD-3-Clause
7 // *****************************************************************************
8 // @HEADER
9 
10 #ifndef BELOS_PSEUDO_BLOCK_GMRES_ITER_MP_VECTOR_HPP
11 #define BELOS_PSEUDO_BLOCK_GMRES_ITER_MP_VECTOR_HPP
12 
22 #include "BelosPseudoBlockGmresIter.hpp"
23 
37 namespace Belos {
38 
39  template<class Storage, class MV, class OP>
40  class PseudoBlockGmresIter<Sacado::MP::Vector<Storage>, MV, OP> :
41  virtual public Iteration<Sacado::MP::Vector<Storage>, MV, OP> {
42 
43  public:
44 
45  //
46  // Convenience typedefs
47  //
49  typedef MultiVecTraits<ScalarType,MV> MVT;
50  typedef OperatorTraits<ScalarType,MV,OP> OPT;
52  typedef typename SCT::magnitudeType MagnitudeType;
54 
56 
57 
66  PseudoBlockGmresIter( const Teuchos::RCP<LinearProblem<ScalarType,MV,OP> > &problem,
67  const Teuchos::RCP<OutputManager<ScalarType> > &printer,
68  const Teuchos::RCP<StatusTest<ScalarType,MV,OP> > &tester,
69  const Teuchos::RCP<MatOrthoManager<ScalarType,MV,OP> > &ortho,
70  Teuchos::ParameterList &params );
71 
73  virtual ~PseudoBlockGmresIter() = default;
75 
76 
78 
79 
101  void iterate();
102 
124  void initialize(const PseudoBlockGmresIterState<ScalarType,MV> & newstate);
125 
129  void initialize()
130  {
131  PseudoBlockGmresIterState<ScalarType,MV> empty;
132  initialize(empty);
133  }
134 
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) {
151  state.V[i] = V_[i];
152  state.H[i] = H_[i];
153  state.Z[i] = Z_[i];
154  state.sn[i] = sn_[i];
155  state.cs[i] = cs_[i];
156  }
157  return state;
158  }
159 
161 
162 
164 
165 
167  int getNumIters() const { return iter_; }
168 
170  void resetNumIters( int iter = 0 ) { iter_ = iter; }
171 
189  Teuchos::RCP<const MV> getNativeResiduals( std::vector<MagnitudeType> *norms ) const;
190 
192 
197  Teuchos::RCP<MV> getCurrentUpdate() const;
198 
200 
203  void updateLSQR( int dim = -1 );
204 
206  int getCurSubspaceDim() const {
207  if (!initialized_) return 0;
208  return curDim_;
209  }
210 
212  int getMaxSubspaceDim() const { return numBlocks_; }
213 
215 
216 
218 
219 
221  const LinearProblem<ScalarType,MV,OP>& getProblem() const { return *lp_; }
222 
224  int getBlockSize() const { return 1; }
225 
227  void setBlockSize(int blockSize) {
228  TEUCHOS_TEST_FOR_EXCEPTION(blockSize!=1,std::invalid_argument,
229  "Belos::PseudoBlockGmresIter::setBlockSize(): Cannot use a block size that is not one.");
230  }
231 
233  int getNumBlocks() const { return numBlocks_; }
234 
236  void setNumBlocks(int numBlocks);
237 
239  bool isInitialized() { return initialized_; }
240 
242 
243  private:
244 
245  //
246  // Classes inputed through constructor that define the linear problem to be solved.
247  //
252 
253  //
254  // Algorithmic parameters
255  //
256  // numRHS_ is the current number of linear systems being solved.
257  int numRHS_;
258  // numBlocks_ is the size of the allocated space for the Krylov basis, in blocks.
260 
261  // Mask used to store whether the ensemble GMRES has faced lucky breakdown or not.
263 
264  // Storage for QR factorization of the least squares system.
265  std::vector<Teuchos::RCP<Teuchos::SerialDenseVector<int,ScalarType> > > sn_;
266  std::vector<Teuchos::RCP<Teuchos::SerialDenseVector<int,MagnitudeType> > > cs_;
267 
268  // Pointers to a work vector used to improve aggregate performance.
270 
271  // Pointers to the current right-hand side and solution multivecs being solved for.
273 
274  //
275  // Current solver state
276  //
277  // initialized_ specifies that the basis vectors have been initialized and the iterate() routine
278  // is capable of running; _initialize is controlled by the initialize() member method
279  // For the implications of the state of initialized_, please see documentation for initialize()
281 
282  // Current subspace dimension, and number of iterations performed.
283  int curDim_, iter_;
284 
285  //
286  // State Storage
287  //
288  std::vector<Teuchos::RCP<MV> > V_;
289  //
290  // Projected matrices
291  // H_ : Projected matrix from the Krylov factorization AV = VH + FE^T
292  //
293  std::vector<Teuchos::RCP<Teuchos::SerialDenseMatrix<int,ScalarType> > > H_;
294  //
295  // QR decomposition of Projected matrices for solving the least squares system HY = B.
296  // R_: Upper triangular reduction of H
297  // Z_: Q applied to right-hand side of the least squares system
298  std::vector<Teuchos::RCP<Teuchos::SerialDenseMatrix<int,ScalarType> > > R_;
299  std::vector<Teuchos::RCP<Teuchos::SerialDenseVector<int,ScalarType> > > Z_;
300 
301  // Tolerance for ensemble breakdown
303 
304 #ifdef BELOS_TEUCHOS_TIME_MONITOR
305  Teuchos::RCP<Teuchos::Time> timerUpdateLSQR_, timerSolveLSQR_;
306 #endif
307  };
308 
310  // Constructor.
311  template<class StorageType, class MV, class OP>
313  PseudoBlockGmresIter(const Teuchos::RCP<LinearProblem<ScalarType,MV,OP> > &problem,
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,
317  Teuchos::ParameterList &params ):
318  lp_(problem),
319  om_(printer),
320  stest_(tester),
321  ortho_(ortho),
322  numRHS_(0),
323  numBlocks_(0),
324  initialized_(false),
325  curDim_(0),
326  iter_(0),
327  breakDownTol_(params.get("Ensemble Breakdown Tolerance", 0.0))
328  {
329  // Get the maximum number of blocks allowed for each Krylov subspace
330  TEUCHOS_TEST_FOR_EXCEPTION(!params.isParameter("Num Blocks"), std::invalid_argument,
331  "Belos::PseudoBlockGmresIter::constructor: mandatory parameter 'Num Blocks' is not specified.");
332  int nb = Teuchos::getParameter<int>(params, "Num Blocks");
333 
334  setNumBlocks( nb );
335  }
336 
338  // Set the block size and make necessary adjustments.
339  template <class StorageType, class MV, class OP>
340  void PseudoBlockGmresIter<Sacado::MP::Vector<StorageType>,MV,OP>::setNumBlocks (int numBlocks)
341  {
342  // This routine only allocates space; it doesn't not perform any computation
343  // any change in size will invalidate the state of the solver.
344 
345  TEUCHOS_TEST_FOR_EXCEPTION(numBlocks <= 0, std::invalid_argument, "Belos::PseudoBlockGmresIter::setNumBlocks was passed a non-positive argument.");
346 
347  numBlocks_ = numBlocks;
348  curDim_ = 0;
349 
350  initialized_ = false;
351  }
352 
354  // Get the current update from this subspace.
355  template <class StorageType, class MV, class OP>
356  Teuchos::RCP<MV> PseudoBlockGmresIter<Sacado::MP::Vector<StorageType>,MV,OP>::getCurrentUpdate() const
357  {
358 #ifdef BELOS_TEUCHOS_TIME_MONITOR
359  Teuchos::TimeMonitor updateTimer( *timerSolveLSQR_ );
360 #endif
361  //
362  // If this is the first iteration of the Arnoldi factorization,
363  // there is no update, so return Teuchos::null.
364  //
365  Teuchos::RCP<MV> currentUpdate = Teuchos::null;
366  if (curDim_==0) {
367  return currentUpdate;
368  } else {
369  currentUpdate = MVT::Clone(*(V_[0]), numRHS_);
370  std::vector<int> index(1), index2(curDim_);
371  for (int i=0; i<curDim_; ++i) {
372  index2[i] = i;
373  }
374  const ScalarType one = Teuchos::ScalarTraits<ScalarType>::one();
375  const ScalarType zero = Teuchos::ScalarTraits<ScalarType>::zero();
377 
378  for (int i=0; i<numRHS_; ++i) {
379  index[0] = i;
380  Teuchos::RCP<MV> cur_block_copy_vec = MVT::CloneViewNonConst( *currentUpdate, index );
381  //
382  // Make a view and then copy the RHS of the least squares problem. DON'T OVERWRITE IT!
383  //
384  Teuchos::SerialDenseVector<int,ScalarType> y( Teuchos::Copy, Z_[i]->values(), curDim_ );
385  //
386  // Solve the least squares problem and compute current solutions.
387  //
389  Teuchos::NON_UNIT_DIAG, curDim_, 1, one,
390  H_[i]->values(), H_[i]->stride(), y.values(), y.stride() );
391 
392 
393  Teuchos::RCP<const MV> Vjp1 = MVT::CloneView( *V_[i], index2 );
394  MVT::MvTimesMatAddMv( one, *Vjp1, y, zero, *cur_block_copy_vec );
395  }
396  }
397  return currentUpdate;
398  }
399 
400 
402  // Get the native residuals stored in this iteration.
403  // Note: No residual vector will be returned by Gmres.
404  template <class StorageType, class MV, class OP>
406  PseudoBlockGmresIter<Sacado::MP::Vector<StorageType>,MV,OP>::
407  getNativeResiduals (std::vector<MagnitudeType> *norms) const
408  {
409  typedef typename Teuchos::ScalarTraits<ScalarType> STS;
410 
411  if (norms)
412  { // Resize the incoming std::vector if necessary. The type
413  // cast avoids the compiler warning resulting from a signed /
414  // unsigned integer comparison.
415  if (static_cast<int> (norms->size()) < numRHS_)
416  norms->resize (numRHS_);
417 
419  for (int j = 0; j < numRHS_; ++j)
420  {
421  const ScalarType curNativeResid = (*Z_[j])(curDim_);
422  (*norms)[j] = STS::magnitude (curNativeResid);
423  }
424  }
425  return Teuchos::null;
426  }
427 
428 
429  template <class StorageType, class MV, class OP>
430  void
431  PseudoBlockGmresIter<Sacado::MP::Vector<StorageType>,MV,OP>::
432  initialize (const PseudoBlockGmresIterState<ScalarType,MV> & newstate)
433  {
434  using Teuchos::RCP;
435 
436  // (Re)set the number of right-hand sides, by interrogating the
437  // current LinearProblem to solve.
438  this->numRHS_ = MVT::GetNumberVecs (*(lp_->getCurrLHSVec()));
439 
440 #ifdef BELOS_TEUCHOS_TIME_MONITOR
441  std::stringstream ss;
442  ss << "Belos";
443 
444  std::string updateLabel = ss.str() + ": Update LSQR";
445  timerUpdateLSQR_ = Teuchos::TimeMonitor::getNewCounter(updateLabel);
446 
447  std::string solveLabel = ss.str() + ": Solve LSQR";
448  timerSolveLSQR_ = Teuchos::TimeMonitor::getNewCounter(solveLabel);
449 #endif
450 
451  // NOTE: In PseudoBlockGmresIter, V and Z are required!!!
452  // Inconsistent multivectors widths and lengths will not be tolerated, and
453  // will be treated with exceptions.
454  //
455  std::string errstr ("Belos::PseudoBlockGmresIter::initialize(): "
456  "Specified multivectors must have a consistent "
457  "length and width.");
458 
459  // Check that newstate has V and Z arrays with nonzero length.
460  TEUCHOS_TEST_FOR_EXCEPTION((int)newstate.V.size()==0 || (int)newstate.Z.size()==0,
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.");
465 
466  // In order to create basis multivectors, we have to clone them
467  // from some already existing multivector. We require that at
468  // least one of the right-hand side B and left-hand side X in the
469  // LinearProblem be non-null. Thus, we can clone from either B or
470  // X. We prefer to close from B, since B is in the range of the
471  // operator A and the basis vectors should also be in the range of
472  // A (the first basis vector is a scaled residual vector).
473  // However, if B is not given, we will try our best by cloning
474  // from X.
475  RCP<const MV> lhsMV = lp_->getLHS();
476  RCP<const MV> rhsMV = lp_->getRHS();
477 
478  // If the right-hand side is null, we make do with the left-hand
479  // side, otherwise we use the right-hand side.
480  RCP<const MV> vectorInBasisSpace = rhsMV.is_null() ? lhsMV : rhsMV;
481  //RCP<const MV> tmp = ( (rhsMV!=Teuchos::null)? rhsMV: lhsMV );
482 
483  TEUCHOS_TEST_FOR_EXCEPTION(vectorInBasisSpace.is_null(),
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 "
489  "be nonnull.");
490 
491  // Check the new dimension is not more that the maximum number of
492  // allowable blocks.
493  TEUCHOS_TEST_FOR_EXCEPTION(newstate.curDim > numBlocks_+1,
494  std::invalid_argument,
495  errstr);
496  curDim_ = newstate.curDim;
497 
498  // Initialize the state storage. If the subspace has not be
499  // initialized before, generate it using the right-hand side or
500  // left-hand side from the LinearProblem lp_ to solve.
501  V_.resize(numRHS_);
502  for (int i=0; i<numRHS_; ++i) {
503  // Create a new vector if we need to. We "need to" if the
504  // current vector V_[i] is null, or if it doesn't have enough
505  // columns.
506  if (V_[i].is_null() || MVT::GetNumberVecs(*V_[i]) < numBlocks_ + 1) {
507  V_[i] = MVT::Clone (*vectorInBasisSpace, numBlocks_ + 1);
508  }
509  // Check that the newstate vector newstate.V[i] has dimensions
510  // consistent with those of V_[i].
511  TEUCHOS_TEST_FOR_EXCEPTION( MVT::GetGlobalLength(*newstate.V[i]) != MVT::GetGlobalLength(*V_[i]),
512  std::invalid_argument, errstr );
513  TEUCHOS_TEST_FOR_EXCEPTION( MVT::GetNumberVecs(*newstate.V[i]) < newstate.curDim,
514  std::invalid_argument, errstr );
515  //
516  // If newstate.V[i] and V_[i] are not identically the same
517  // vector, then copy newstate.V[i] into V_[i].
518  //
519  int lclDim = MVT::GetNumberVecs(*newstate.V[i]);
520  if (newstate.V[i] != V_[i]) {
521  // Only copy over the first block and print a warning.
522  if (curDim_ == 0 && lclDim > 1) {
523  om_->stream(Warnings)
524  << "Belos::PseudoBlockGmresIter::initialize(): the solver was "
525  << "initialized with a kernel of " << lclDim
526  << std::endl
527  << "The block size however is only " << 1
528  << std::endl
529  << "The last " << lclDim - 1 << " vectors will be discarded."
530  << std::endl;
531  }
532  std::vector<int> nevind (curDim_ + 1);
533  for (int j = 0; j < curDim_ + 1; ++j)
534  nevind[j] = j;
535 
536  RCP<const MV> newV = MVT::CloneView (*newstate.V[i], nevind);
537  RCP<MV> lclV = MVT::CloneViewNonConst( *V_[i], nevind );
538  const ScalarType one = Teuchos::ScalarTraits<ScalarType>::one();
539  const ScalarType zero = Teuchos::ScalarTraits<ScalarType>::zero();
540  MVT::MvAddMv (one, *newV, zero, *newV, *lclV);
541 
542  // Done with local pointers
543  lclV = Teuchos::null;
544  }
545  }
546 
547 
548  // Check size of Z
549  Z_.resize(numRHS_);
550  for (int i=0; i<numRHS_; ++i) {
551  // Create a vector if we need to.
552  if (Z_[i] == Teuchos::null) {
554  }
555  if (Z_[i]->length() < numBlocks_+1) {
556  Z_[i]->shapeUninitialized(numBlocks_+1, 1);
557  }
558 
559  // Check that the newstate vector is consistent.
560  TEUCHOS_TEST_FOR_EXCEPTION(newstate.Z[i]->numRows() < curDim_, std::invalid_argument, errstr);
561 
562  // Put data into Z_, make sure old information is not still hanging around.
563  if (newstate.Z[i] != Z_[i]) {
564  if (curDim_==0)
565  Z_[i]->putScalar();
566 
567  Teuchos::SerialDenseVector<int,ScalarType> newZ(Teuchos::View,newstate.Z[i]->values(),curDim_+1);
569  lclZ = Teuchos::rcp( new Teuchos::SerialDenseVector<int,ScalarType>(Teuchos::View,Z_[i]->values(),curDim_+1) );
570  lclZ->assign(newZ);
571 
572  // Done with local pointers
573  lclZ = Teuchos::null;
574  }
575  }
576 
577 
578  // Check size of H
579  H_.resize(numRHS_);
580  for (int i=0; i<numRHS_; ++i) {
581  // Create a matrix if we need to.
582  if (H_[i] == Teuchos::null) {
584  }
585  if (H_[i]->numRows() < numBlocks_+1 || H_[i]->numCols() < numBlocks_) {
586  H_[i]->shapeUninitialized(numBlocks_+1, numBlocks_);
587  }
588 
589  // Put data into H_ if it exists, make sure old information is not still hanging around.
590  if ((int)newstate.H.size() == numRHS_) {
591 
592  // Check that the newstate matrix is consistent.
593  TEUCHOS_TEST_FOR_EXCEPTION((newstate.H[i]->numRows() < curDim_ || newstate.H[i]->numCols() < curDim_), std::invalid_argument,
594  "Belos::PseudoBlockGmresIter::initialize(): Specified Hessenberg matrices must have a consistent size to the current subspace dimension");
595 
596  if (newstate.H[i] != H_[i]) {
597  // H_[i]->putScalar();
598 
599  Teuchos::SerialDenseMatrix<int,ScalarType> newH(Teuchos::View,*newstate.H[i],curDim_+1, curDim_);
601  lclH = Teuchos::rcp( new Teuchos::SerialDenseMatrix<int,ScalarType>(Teuchos::View,*H_[i],curDim_+1, curDim_) );
602  lclH->assign(newH);
603 
604  // Done with local pointers
605  lclH = Teuchos::null;
606  }
607  }
608  }
609 
611  // Reinitialize storage for least squares solve
612  //
613  cs_.resize(numRHS_);
614  sn_.resize(numRHS_);
615 
616  // Copy over rotation angles if they exist
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])
620  cs_[i] = Teuchos::rcp( new Teuchos::SerialDenseVector<int,MagnitudeType>(*newstate.cs[i]) );
621  if (sn_[i] != newstate.sn[i])
622  sn_[i] = Teuchos::rcp( new Teuchos::SerialDenseVector<int,ScalarType>(*newstate.sn[i]) );
623  }
624  }
625 
626  // Resize or create the vectors as necessary
627  for (int i=0; i<numRHS_; ++i) {
628  if (cs_[i] == Teuchos::null)
629  cs_[i] = Teuchos::rcp( new Teuchos::SerialDenseVector<int,MagnitudeType>(numBlocks_+1) );
630  else
631  cs_[i]->resize(numBlocks_+1);
632  if (sn_[i] == Teuchos::null)
633  sn_[i] = Teuchos::rcp( new Teuchos::SerialDenseVector<int,ScalarType>(numBlocks_+1) );
634  else
635  sn_[i]->resize(numBlocks_+1);
636  }
637 
638  // the solver is initialized
639  initialized_ = true;
640 
641  /*
642  if (om_->isVerbosity( Debug ) ) {
643  // Check almost everything here
644  CheckList chk;
645  chk.checkV = true;
646  chk.checkArn = true;
647  chk.checkAux = true;
648  om_->print( Debug, accuracyCheck(chk, ": after initialize()") );
649  }
650  */
651 
652  }
653 
654 
656  // Iterate until the status test informs us we should stop.
657  template <class StorageType, class MV, class OP>
658  void PseudoBlockGmresIter<Sacado::MP::Vector<StorageType>,MV,OP>::iterate()
659  {
660  //
661  // Allocate/initialize data structures
662  //
663  if (initialized_ == false) {
664  initialize();
665  }
666 
667  const ScalarType one = Teuchos::ScalarTraits<ScalarType>::one();
668  const ScalarType zero = Teuchos::ScalarTraits<ScalarType>::zero();
669 
670  // Compute the current search dimension.
671  int searchDim = numBlocks_;
672  //
673  // Associate each initial block of V_[i] with U_vec[i]
674  // Reset the index vector (this might have been changed if there was a restart)
675  //
676  std::vector<int> index(1);
677  std::vector<int> index2(1);
678  index[0] = curDim_;
679  Teuchos::RCP<MV> U_vec = MVT::Clone( *V_[0], numRHS_ );
680 
681  // Create AU_vec to hold A*U_vec.
682  Teuchos::RCP<MV> AU_vec = MVT::Clone( *V_[0], numRHS_ );
683 
684  for (int i=0; i<numRHS_; ++i) {
685  index2[0] = i;
686  Teuchos::RCP<const MV> tmp_vec = MVT::CloneView( *V_[i], index );
687  Teuchos::RCP<MV> U_vec_view = MVT::CloneViewNonConst( *U_vec, index2 );
688  MVT::MvAddMv( one, *tmp_vec, zero, *tmp_vec, *U_vec_view );
689  }
690 
692  // iterate until the status test tells us to stop.
693  //
694  // also break if our basis is full
695  //
696  while (stest_->checkStatus(this) != Passed && curDim_ < searchDim) {
697  iter_++;
698  //
699  // Apply the operator to _work_vector
700  //
701 
702  lp_->apply( *U_vec, *AU_vec );
703  //
704  //
705  // Resize index.
706  //
707  int num_prev = curDim_+1;
708  index.resize( num_prev );
709  for (int i=0; i<num_prev; ++i) {
710  index[i] = i;
711  }
712  //
713  // Orthogonalize next Krylov vector for each right-hand side.
714  //
715  for (int i=0; i<numRHS_; ++i) {
716  //
717  // Get previous Krylov vectors.
718  //
719  Teuchos::RCP<const MV> V_prev = MVT::CloneView( *V_[i], index );
720  Teuchos::Array< Teuchos::RCP<const MV> > V_array( 1, V_prev );
721 
722  //
723  // Get a view of the new candidate std::vector.
724  //
725  index2[0] = i;
726  Teuchos::RCP<MV> V_new = MVT::CloneViewNonConst( *AU_vec, index2 );
727 
728  //
729  // Get a view of the current part of the upper-hessenberg matrix.
730  //
733  ( Teuchos::View, *H_[i], num_prev, 1, 0, curDim_ ) );
735 
738  ( Teuchos::View, *H_[i], 1, 1, num_prev, curDim_ ) );
739 
740  //
741  // Orthonormalize the new block of the Krylov expansion
742  // NOTE: Rank deficiencies are not checked because this is a single-std::vector Krylov method.
743  //
744  ortho_->projectAndNormalize( *V_new, h_array, r_new, V_array );
745 
746  //
747  // NOTE: V_new is a copy of the iter+1 vector in V_[i], so the normalized vector has to be
748  // be copied back in when V_new is changed.
749  //
750  index2[0] = curDim_+1;
751  Teuchos::RCP<MV> tmp_vec = MVT::CloneViewNonConst( *V_[i], index2 );
752  MVT::MvAddMv( one, *V_new, zero, *V_new, *tmp_vec );
753  }
754  //
755  // Now _AU_vec is the new _U_vec, so swap these two vectors.
756  // NOTE: This alleviates the need for allocating a vector for AU_vec each iteration.
757  //
758  Teuchos::RCP<MV> tmp_AU_vec = U_vec;
759  U_vec = AU_vec;
760  AU_vec = tmp_AU_vec;
761  //
762  // V has been extended, and H has been extended.
763  //
764  // Update the QR factorization of the upper Hessenberg matrix
765  //
766  {
767 #ifdef BELOS_TEUCHOS_TIME_MONITOR
768  Teuchos::TimeMonitor updateTimer( *timerUpdateLSQR_ );
769 #endif
770  updateLSQR();
771  }
772  //
773  // Update basis dim and release all pointers.
774  //
775  curDim_ += 1;
776  //
777  /*
778  // When required, monitor some orthogonalities
779  if (om_->isVerbosity( Debug ) ) {
780  // Check almost everything here
781  CheckList chk;
782  chk.checkV = true;
783  chk.checkArn = true;
784  om_->print( Debug, accuracyCheck(chk, ": after local update") );
785  }
786  else if (om_->isVerbosity( OrthoDetails ) ) {
787  CheckList chk;
788  chk.checkV = true;
789  om_->print( OrthoDetails, accuracyCheck(chk, ": after local update") );
790  }
791  */
792 
793  } // end while (statusTest == false)
794 
795  }
796 
798  // Update the least squares solution for each right-hand side.
799  template<class StorageType, class MV, class OP>
800  void PseudoBlockGmresIter<Sacado::MP::Vector<StorageType>,MV,OP>::updateLSQR( int dim )
801  {
802  // Get correct dimension based on input "dim"
803  // Remember that ortho failures result in an exit before updateLSQR() is called.
804  // Therefore, it is possible that dim == curDim_.
805  int curDim = curDim_;
806  if (dim >= curDim_ && dim < getMaxSubspaceDim()) {
807  curDim = dim;
808  }
809 
810  int i, j;
811  const ScalarType zero = Teuchos::ScalarTraits<ScalarType>::zero();
812  const ScalarType one = Teuchos::ScalarTraits<ScalarType>::one();
813 
815 
816  for (i=0; i<numRHS_; ++i) {
817  //
818  // Update the least-squares QR for each linear system.
819  //
820  // QR factorization of Least-Squares system with Givens rotations
821  //
822  for (j=0; j<curDim; j++) {
823  //
824  // Apply previous Givens rotations to new column of Hessenberg matrix
825  //
826  blas.ROT( 1, &(*H_[i])(j,curDim), 1, &(*H_[i])(j+1, curDim), 1, &(*cs_[i])[j], &(*sn_[i])[j] );
827  }
828  //
829  // Calculate new Givens rotation
830  //
831  if ( curDim == 0)
832  {
833  // Initialize the lucky_breakdown_ mask to take account of perfect initial guess
834  lucky_breakdown_ = ((*Z_[i])(curDim) == zero);
835  }
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;
839  //Teuchos::my_GivensRotator<ScalarType> GR;
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;
842  //
843  // Update RHS w/ new transformation
844  //
845  blas.ROT( 1, &(*Z_[i])(curDim), 1, &(*Z_[i])(curDim+1), 1, &(*cs_[i])[curDim], &(*sn_[i])[curDim] );
846  }
847 
848  } // end updateLSQR()
849 
850 } // end Belos namespace
851 
852 #endif /* BELOS_PSEUDO_BLOCK_GMRES_ITER_MP_VECTOR_HPP */
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
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...
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
static RCP< Time > getNewCounter(const std::string &name)
#define TEUCHOS_TEST_FOR_EXCEPTION(throw_exception_test, Exception, msg)
KOKKOS_INLINE_FUNCTION MaskedAssign< scalar > mask_assign(bool b, scalar *s)
bool isParameter(const std::string &name) const
TEUCHOS_DEPRECATED RCP< T > rcp(T *p, Dealloc_T dealloc, bool owns_mem)
std::vector< Teuchos::RCP< Teuchos::SerialDenseVector< int, MagnitudeType > > > cs_
std::vector< Teuchos::RCP< Teuchos::SerialDenseMatrix< int, ScalarType > > > R_
std::vector< Teuchos::RCP< Teuchos::SerialDenseMatrix< int, ScalarType > > > H_
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
std::vector< Teuchos::RCP< Teuchos::SerialDenseVector< int, ScalarType > > > Z_
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.
int getBlockSize() const
Get the blocksize to be used by the iterative solver in solving this linear problem.
int getNumBlocks() const
Get the maximum number of blocks used by the iterative solver in solving this linear problem...
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_