Belos  Version of the Day
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
BelosCGSingleRedIter.hpp
Go to the documentation of this file.
1 // @HEADER
2 // *****************************************************************************
3 // Belos: Block Linear Solvers Package
4 //
5 // Copyright 2004-2016 NTESS and the Belos contributors.
6 // SPDX-License-Identifier: BSD-3-Clause
7 // *****************************************************************************
8 // @HEADER
9 
10 #ifndef BELOS_CG_SINGLE_RED_ITER_HPP
11 #define BELOS_CG_SINGLE_RED_ITER_HPP
12 
17 #include "BelosConfigDefs.hpp"
18 #include "BelosTypes.hpp"
19 #include "BelosCGIteration.hpp"
20 
21 #include "BelosLinearProblem.hpp"
22 #include "BelosOutputManager.hpp"
23 #include "BelosStatusTest.hpp"
25 #include "BelosOperatorTraits.hpp"
26 #include "BelosMultiVecTraits.hpp"
27 
30 #include "Teuchos_ScalarTraits.hpp"
32 #include "Teuchos_TimeMonitor.hpp"
33 
44 namespace Belos {
45 
47 
48 
53  template <class ScalarType, class MV>
54  class CGSingleRedIterationState : public CGIterationStateBase<ScalarType, MV> {
55 
56  public:
57  CGSingleRedIterationState() = default;
58 
60  initialize(tmp);
61  }
62 
63  virtual ~CGSingleRedIterationState() = default;
64 
65  void initialize(Teuchos::RCP<const MV> tmp, int _numVectors) {
67 
68  TEUCHOS_ASSERT(_numVectors == 1);
69 
70  // W = (AZ, R, Z)
71  W = MVT::Clone( *tmp, 3 );
72  std::vector<int> index2(2,0);
73  std::vector<int> index(1,0);
74 
75  // S = (AZ, R)
76  index2[0] = 0;
77  index2[1] = 1;
78  S = MVT::CloneViewNonConst( *W, index2 );
79 
80  // U = (AZ, Z)
81  index2[0] = 0;
82  index2[1] = 2;
83  U = MVT::CloneViewNonConst( *W, index2 );
84 
85  index[0] = 1;
86  this->R = MVT::CloneViewNonConst( *W, index );
87  index[0] = 0;
88  AZ = MVT::CloneViewNonConst( *W, index );
89  index[0] = 2;
90  this->Z = MVT::CloneViewNonConst( *W, index );
91 
92  // T = (R, Z)
93  index2[0] = 1;
94  index2[1] = 2;
95  T = MVT::CloneViewNonConst( *W, index2 );
96 
97  // V = (AP, P)
98  V = MVT::Clone( *tmp, 2 );
99  index[0] = 0;
100  this->AP = MVT::CloneViewNonConst( *V, index );
101  index[0] = 1;
102  this->P = MVT::CloneViewNonConst( *V, index );
103 
105  }
106 
107  bool matches(Teuchos::RCP<const MV> tmp, int _numVectors=1) const {
108  return (CGIterationStateBase<ScalarType, MV>::matches(tmp, _numVectors) &&
109  !W.is_null() &&
110  !V.is_null() &&
111  !U.is_null() &&
112  !S.is_null() &&
113  !T.is_null() &&
114  !AZ.is_null());
115  }
116 
123 
124  };
125 
126 template<class ScalarType, class MV, class OP>
127 class CGSingleRedIter : virtual public CGIteration<ScalarType,MV,OP> {
128 
129  public:
130 
131  //
132  // Convenience typedefs
133  //
138 
140 
141 
148  const Teuchos::RCP<OutputManager<ScalarType> > &printer,
151  Teuchos::ParameterList &params );
152 
154  virtual ~CGSingleRedIter() = default;
156 
157 
159 
160 
173  void iterate();
174 
190 
194  void initialize()
195  {
196  initializeCG(Teuchos::null, Teuchos::null);
197  }
198 
207  state->W = W_;
208  state->V = V_;
209  state->U = U_;
210  state->S = S_;
211  state->T = T_;
212  state->R = R_;
213  state->Z = Z_;
214  state->P = P_;
215  state->AP = AP_;
216  state->AZ = AZ_;
217  return state;
218  }
219 
221  auto s = Teuchos::rcp_dynamic_cast<CGSingleRedIterationState<ScalarType,MV> >(state, true);
222  W_ = s->W;
223  V_ = s->V;
224  U_ = s->U;
225  S_ = s->S;
226  T_ = s->T;
227  R_ = s->R;
228  Z_ = s->Z;
229  P_ = s->P;
230  AP_ = s->AP;
231  AZ_ = s->AZ;
232  }
233 
235 
236 
238 
239 
241  int getNumIters() const { return iter_; }
242 
244  void resetNumIters( int iter = 0 ) { iter_ = iter; }
245 
248  Teuchos::RCP<const MV> getNativeResiduals( std::vector<MagnitudeType> *norms ) const;
249 
251 
253  Teuchos::RCP<MV> getCurrentUpdate() const { return Teuchos::null; }
254 
256 
258 
259 
261  const LinearProblem<ScalarType,MV,OP>& getProblem() const { return *lp_; }
262 
264  int getBlockSize() const { return 1; }
265 
267  void setBlockSize(int blockSize) {
268  TEUCHOS_TEST_FOR_EXCEPTION(blockSize!=1,std::invalid_argument,
269  "Belos::CGSingleRedIter::setBlockSize(): Cannot use a block size that is not one.");
270  }
271 
273  bool isInitialized() { return initialized_; }
274 
276  void setDoCondEst(bool /* val */){/*ignored*/}
277 
281  return temp;
282  }
283 
287  return temp;
288  }
289 
291 
292  private:
293 
294  //
295  // Internal methods
296  //
297 
298  // Classes inputed through constructor that define the linear problem to be solved.
299  //
304 
305  //
306  // Current solver state
307  //
308  // initialized_ specifies that the basis vectors have been initialized and the iterate() routine
309  // is capable of running; _initialize is controlled by the initialize() member method
310  // For the implications of the state of initialized_, please see documentation for initialize()
311  bool initialized_;
312 
313  // Current number of iterations performed.
314  int iter_;
315 
316  // Should the allreduce for convergence detection be merged with the inner products?
317  bool foldConvergenceDetectionIntoAllreduce_;
318 
319  // <r,z>
320  ScalarType rHz_;
321  // <r,r>
322  ScalarType rHr_;
323 
324  //
325  // State Storage
326  //
327  // Residual
328  Teuchos::RCP<MV> R_;
329  // Preconditioned residual
330  Teuchos::RCP<MV> Z_;
331  // Operator applied to preconditioned residual
332  Teuchos::RCP<MV> AZ_;
333  // Direction vector
334  Teuchos::RCP<MV> P_;
335  // Operator applied to direction vector
336  Teuchos::RCP<MV> AP_;
337  //
338  // W_ = (R_, AZ_, Z_)
339  Teuchos::RCP<MV> W_;
340  // S_ = (R_, AZ_)
341  Teuchos::RCP<MV> S_;
342  // T_ = (Z_, R_)
343  Teuchos::RCP<MV> T_;
344  // U_ = (AZ_, Z_)
345  Teuchos::RCP<MV> U_;
346  // V_ = (AP_, P_)
347  Teuchos::RCP<MV> V_;
348 
349 };
350 
352  // Constructor.
353  template<class ScalarType, class MV, class OP>
355  const Teuchos::RCP<OutputManager<ScalarType> > &printer,
358  Teuchos::ParameterList &params ):
359  lp_(problem),
360  om_(printer),
361  stest_(tester),
362  convTest_(convTester),
363  initialized_(false),
364  iter_(0)
365  {
366  foldConvergenceDetectionIntoAllreduce_ = params.get<bool>("Fold Convergence Detection Into Allreduce",false);
367  }
368 
370  // Initialize this iteration object
371  template <class ScalarType, class MV, class OP>
373  {
374  // Initialize the state storage if it isn't already.
375  Teuchos::RCP<const MV> lhsMV = lp_->getLHS();
376  Teuchos::RCP<const MV> rhsMV = lp_->getRHS();
377  Teuchos::RCP<const MV> tmp = ( (rhsMV!=Teuchos::null)? rhsMV: lhsMV );
378  TEUCHOS_ASSERT(!newstate.is_null());
379  if (!Teuchos::rcp_dynamic_cast<CGSingleRedIterationState<ScalarType,MV> >(newstate, true)->matches(tmp, 1))
380  newstate->initialize(tmp, 1);
381  setState(newstate);
382 
383  std::string errstr("Belos::CGSingleRedIter::initialize(): Specified multivectors must have a consistent length and width.");
384 
385  {
386 
387  TEUCHOS_TEST_FOR_EXCEPTION( MVT::GetGlobalLength(*newstate->R) != MVT::GetGlobalLength(*R_),
388  std::invalid_argument, errstr );
389  TEUCHOS_TEST_FOR_EXCEPTION( MVT::GetNumberVecs(*newstate->R) != 1,
390  std::invalid_argument, errstr );
391 
392  // Copy basis vectors from newstate into V
393  if (R_0 != R_) {
394  // copy over the initial residual (unpreconditioned).
395  MVT::Assign( *R_0, *R_ );
396  }
397 
398  // Compute initial direction vectors
399  // Initially, they are set to the preconditioned residuals
400  //
401  if ( lp_->getLeftPrec() != Teuchos::null ) {
402  lp_->applyLeftPrec( *R_, *Z_ );
403  if ( lp_->getRightPrec() != Teuchos::null ) {
404  Teuchos::RCP<MV> tmp2 = MVT::Clone( *Z_, 1 );
405  lp_->applyRightPrec( *Z_, *tmp2 );
406  MVT::Assign( *tmp2, *Z_ );
407  }
408  }
409  else if ( lp_->getRightPrec() != Teuchos::null ) {
410  lp_->applyRightPrec( *R_, *Z_ );
411  }
412  else {
413  MVT::Assign( *R_, *Z_ );
414  }
415 
416  // Multiply the current preconditioned residual vector by A and store in AZ_
417  lp_->applyOp( *Z_, *AZ_ );
418 
419  // P_ := Z_
420  // Logically, AP_ := AZ_
421  MVT::Assign( *U_, *V_);
422  }
423 
424  // The solver is initialized
425  initialized_ = true;
426  }
427 
428 
430  // Get the norms of the residuals native to the solver.
431  template <class ScalarType, class MV, class OP>
433  CGSingleRedIter<ScalarType,MV,OP>::getNativeResiduals( std::vector<MagnitudeType> *norms ) const {
434  if (convTest_->getResNormType() == Belos::PreconditionerNorm) {
435  (*norms)[0] = std::sqrt(Teuchos::ScalarTraits<ScalarType>::magnitude(rHz_));
436  return Teuchos::null;
437  } else if (foldConvergenceDetectionIntoAllreduce_ && convTest_->getResNormType() == Belos::TwoNorm) {
438  (*norms)[0] = std::sqrt(Teuchos::ScalarTraits<ScalarType>::magnitude(rHr_));
439  return Teuchos::null;
440  } else
441  return R_;
442  }
443 
444 
446  // Iterate until the status test informs us we should stop.
447  template <class ScalarType, class MV, class OP>
449  {
450  //
451  // Allocate/initialize data structures
452  //
453  if (!initialized_) {
454  initialize();
455  }
456 
457  // Allocate memory for scalars.
460  ScalarType rHz_old;
461  ScalarType alpha;
462  ScalarType beta;
463  ScalarType delta;
464 
465  // Create convenience variables for zero and one.
466  const ScalarType one = Teuchos::ScalarTraits<ScalarType>::one();
468 
469  // Get the current solution vector.
470  Teuchos::RCP<MV> cur_soln_vec = lp_->getCurrLHSVec();
471 
472  // Check that the current solution vector only has one column.
473  TEUCHOS_TEST_FOR_EXCEPTION( MVT::GetNumberVecs(*cur_soln_vec) != 1, CGIterateFailure,
474  "Belos::CGSingleRedIter::iterate(): current linear system has more than one vector!" );
475 
476  if (foldConvergenceDetectionIntoAllreduce_ && convTest_->getResNormType() == Belos::TwoNorm) {
477  // Compute first <S_,T_> a.k.a. <R_,Z_>, <AZ_,Z_> and <R_,R_> combined (also computes unneeded <AZ_,R_>)
478  MVT::MvTransMv( one, *S_, *T_, sHt );
479  rHz_ = sHt(1,1);
480  delta = sHt(0,1);
481  rHr_ = sHt(1,0);
482  } else {
483  // Compute first <s,z> a.k.a. <r,z> and <Az,z> combined
484  MVT::MvTransMv( one, *S_, *Z_, sHz );
485  rHz_ = sHz(1,0);
486  delta = sHz(0,0);
487  }
489  (stest_->checkStatus(this) == Passed))
490  return;
491  alpha = rHz_ / delta;
492 
493  // Check that alpha is a positive number!
494  TEUCHOS_TEST_FOR_EXCEPTION( SCT::real(alpha) <= zero, CGPositiveDefiniteFailure,
495  "Belos::CGSingleRedIter::iterate(): non-positive value for p^H*A*p encountered!" );
496 
498  // Iterate until the status test tells us to stop.
499  //
500  if (foldConvergenceDetectionIntoAllreduce_ && convTest_->getResNormType() == Belos::TwoNorm) {
502  // Iterate until the status test tells us to stop.
503  //
504  while (true) {
505 
506  // Update the solution vector x := x + alpha * P_
507  //
508  MVT::MvAddMv( one, *cur_soln_vec, alpha, *P_, *cur_soln_vec );
509  //
510  // Compute the new residual R_ := R_ - alpha * AP_
511  //
512  MVT::MvAddMv( one, *R_, -alpha, *AP_, *R_ );
513  //
514  // Apply preconditioner to new residual to update Z_
515  //
516  if ( lp_->getLeftPrec() != Teuchos::null ) {
517  lp_->applyLeftPrec( *R_, *Z_ );
518  if ( lp_->getRightPrec() != Teuchos::null ) {
519  Teuchos::RCP<MV> tmp = MVT::CloneCopy( *Z_ );
520  lp_->applyRightPrec( *tmp, *Z_ );
521  }
522  }
523  else if ( lp_->getRightPrec() != Teuchos::null ) {
524  lp_->applyRightPrec( *R_, *Z_ );
525  }
526  else {
527  MVT::Assign( *R_, *Z_ );
528  }
529  //
530  // Multiply the current preconditioned residual vector by A and store in AZ_
531  lp_->applyOp( *Z_, *AZ_ );
532  //
533  // Compute <S_,T_> a.k.a. <R_,Z_>, <AZ_,Z_> and <R_,R_> combined (also computes unneeded <AZ_,R_>)
534  MVT::MvTransMv( one, *S_, *T_, sHt );
535  //
536  // Update scalars.
537  rHz_old = rHz_;
538  rHz_ = sHt(1,1);
539  delta = sHt(0,1);
540  rHr_ = sHt(1,0);
541 
542  // Increment the iteration
543  iter_++;
544  //
545  // Check the status test, now that the solution and residual have been updated
546  //
547  if (stest_->checkStatus(this) == Passed) {
548  break;
549  }
550  //
551  beta = rHz_ / rHz_old;
552  alpha = rHz_ / (delta - (beta*rHz_ / alpha));
553  //
554  // Check that alpha is a positive number!
555  TEUCHOS_TEST_FOR_EXCEPTION( SCT::real(alpha) <= zero, CGPositiveDefiniteFailure,
556  "Belos::CGSingleRedIter::iterate(): non-positive value for p^H*A*p encountered!" );
557 
558  //
559  // Update the direction vector P_ := Z_ + beta * P_
560  // Update AP_ through recurrence relation AP_ := AZ_ + beta * AP_
561  // Hence: V_ = (AP_, P_) := (AZ_, Z_) + beta (AP_, P_) = U_ + beta * V_
562  //
563  MVT::MvAddMv( one, *U_, beta, *V_, *V_ );
564 
565  } // end while (1)
566  } else {
568  // Iterate until the status test tells us to stop.
569  //
570  while (true) {
571 
572  // Update the solution vector x := x + alpha * P_
573  //
574  MVT::MvAddMv( one, *cur_soln_vec, alpha, *P_, *cur_soln_vec );
575  //
576  // Compute the new residual R_ := R_ - alpha * AP_
577  //
578  MVT::MvAddMv( one, *R_, -alpha, *AP_, *R_ );
579 
580  // Increment the iteration
581  iter_++;
582  //
583  // Check the status test, now that the solution and residual have been updated
584  //
585  if (stest_->checkStatus(this) == Passed) {
586  break;
587  }
588  //
589  // Apply preconditioner to new residual to update Z_
590  //
591  if ( lp_->getLeftPrec() != Teuchos::null ) {
592  lp_->applyLeftPrec( *R_, *Z_ );
593  if ( lp_->getRightPrec() != Teuchos::null ) {
594  Teuchos::RCP<MV> tmp = MVT::CloneCopy( *Z_ );
595  lp_->applyRightPrec( *tmp, *Z_ );
596  }
597  }
598  else if ( lp_->getRightPrec() != Teuchos::null ) {
599  lp_->applyRightPrec( *R_, *Z_ );
600  }
601  else {
602  MVT::Assign( *R_, *Z_ );
603  }
604  //
605  // Multiply the current preconditioned residual vector by A and store in AZ_
606  lp_->applyOp( *Z_, *AZ_ );
607  //
608  // Compute <S_,Z_> a.k.a. <R_,Z_> and <AZ_,Z_> combined
609  MVT::MvTransMv( one, *S_, *Z_, sHz );
610  //
611  // Update scalars.
612  rHz_old = rHz_;
613  rHz_ = sHz(1,0);
614  delta = sHz(0,0);
615  //
616  beta = rHz_ / rHz_old;
617  alpha = rHz_ / (delta - (beta*rHz_ / alpha));
618  //
619  // Check that alpha is a positive number!
620  TEUCHOS_TEST_FOR_EXCEPTION( SCT::real(alpha) <= zero, CGPositiveDefiniteFailure,
621  "Belos::CGSingleRedIter::iterate(): non-positive value for p^H*A*p encountered!" );
622 
623  //
624  // Update the direction vector P_ := Z_ + beta * P_
625  // Update AP_ through recurrence relation AP_ := AZ_ + beta * AP_
626  // Hence: V_ = (AP_, P_) := (AZ_, Z_) + beta (AP_, P_) = U_ + beta * V_
627  //
628  MVT::MvAddMv( one, *U_, beta, *V_, *V_ );
629 
630  } // end while (1)
631  }
632  }
633 
634 } // end Belos namespace
635 
636 #endif /* BELOS_CG_SINGLE_RED_ITER_HPP */
virtual ~CGSingleRedIterationState()=default
Collection of types and exceptions used within the Belos solvers.
void setState(Teuchos::RCP< CGIterationStateBase< ScalarType, MV > > state)
int getBlockSize() const
Get the blocksize to be used by the iterative solver in solving this linear problem.
Belos&#39;s basic output manager for sending information of select verbosity levels to the appropriate ou...
Class which manages the output and verbosity of the Belos solvers.
Teuchos::RCP< MV > getCurrentUpdate() const
Get the current update to the linear system.
int getNumIters() const
Get the current iteration count.
const LinearProblem< ScalarType, MV, OP > & getProblem() const
Get a constant reference to the linear problem.
void initialize(Teuchos::RCP< const MV > tmp, int _numVectors)
Pure virtual base class which augments the basic interface for a conjugate gradient linear solver ite...
T & get(const std::string &name, T def_value)
Structure to contain pointers to CGSingleRedIteration state variables.
Pure virtual base class for defining the status testing capabilities of Belos.
#define TEUCHOS_TEST_FOR_EXCEPTION(throw_exception_test, Exception, msg)
Declaration of basic traits for the multivector type.
An implementation of StatusTestResNorm using a family of residual norms.
void iterate()
This method performs CG iterations until the status test indicates the need to stop or an error occur...
A pure virtual class for defining the status tests for the Belos iterative solvers.
Class which defines basic traits for the operator type.
bool matches(Teuchos::RCP< const MV > tmp, int _numVectors=1) const
CGIterateFailure is thrown when the CGIteration object is unable to compute the next iterate in the C...
CGSingleRedIterationState(Teuchos::RCP< const MV > tmp)
Teuchos::RCP< const MV > getNativeResiduals(std::vector< MagnitudeType > *norms) const
Get the norms of the residuals native to the solver.
Teuchos::RCP< MV > P
The current decent direction vector.
Traits class which defines basic operations on multivectors.
void initialize()
Initialize the solver with the initial vectors from the linear problem or random data.
CGPositiveDefiniteFailure is thrown when the the CG &#39;alpha = p^H*A*P&#39; value is less than zero...
typename SCT::magnitudeType MagnitudeType
Teuchos::ArrayView< MagnitudeType > getOffDiag()
Gets the off-diagonal for condition estimation (NOT_IMPLEMENTED)
TEUCHOS_DEPRECATED RCP< T > rcp(T *p, Dealloc_T dealloc, bool owns_mem)
void setBlockSize(int blockSize)
Set the blocksize to be used by the iterative solver in solving this linear problem.
virtual void initialize(Teuchos::RCP< const MV > tmp, int _numVectors)
A linear system to solve, and its associated information.
Class which describes the linear problem to be solved by the iterative solver.
bool isInitialized()
States whether the solver has been initialized or not.
Teuchos::RCP< CGIterationStateBase< ScalarType, MV > > getState() const
Get the current state of the linear solver.
Structure to contain pointers to CGIteration state variables.
Teuchos::RCP< MV > Z
The current preconditioned residual.
Teuchos::RCP< MV > AP
The matrix A applied to current decent direction vector.
CGSingleRedIter(const Teuchos::RCP< LinearProblem< ScalarType, MV, OP > > &problem, const Teuchos::RCP< OutputManager< ScalarType > > &printer, const Teuchos::RCP< StatusTest< ScalarType, MV, OP > > &tester, const Teuchos::RCP< StatusTestGenResNorm< ScalarType, MV, OP > > &convTester, Teuchos::ParameterList &params)
CGSingleRedIter constructor with linear problem, solver utilities, and parameter list of solver optio...
Belos::StatusTestResNorm for specifying general residual norm stopping criteria.
Class which defines basic traits for the operator type.
This class implements the preconditioned single-reduction Conjugate Gradient (CG) iteration...
#define TEUCHOS_ASSERT(assertion_test)
virtual ~CGSingleRedIter()=default
Destructor.
Teuchos::RCP< MV > R
The current residual.
Belos header file which uses auto-configuration information to include necessary C++ headers...
void resetNumIters(int iter=0)
Reset the iteration count.
void initializeCG(Teuchos::RCP< CGIterationStateBase< ScalarType, MV > > newstate, Teuchos::RCP< MV > R_0)
Initialize the solver to an iterate, providing a complete state.
void setDoCondEst(bool)
Sets whether or not to store the diagonal for condition estimation.
Teuchos::ArrayView< MagnitudeType > getDiag()
Gets the diagonal for condition estimation (NOT_IMPLEMENTED)
bool is_null() const

Generated on Fri Feb 21 2025 09:24:40 for Belos by doxygen 1.8.5