Belos  Version of the Day
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
BelosCGIter.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_ITER_HPP
11 #define BELOS_CG_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 CGIterationState : public CGIterationStateBase<ScalarType, MV> {
55 
56  public:
57  CGIterationState() = default;
58 
60  initialize(tmp);
61  }
62 
63  virtual ~CGIterationState() = default;
64 
65  void initialize(Teuchos::RCP<const MV> tmp, int _numVectors) {
67  TEUCHOS_ASSERT(_numVectors == 1);
68 
69  // S = (R, Z)
70  // This allows to compute the inner products (R, S) = ((R, R), (R, Z)) using a single reduction.
71  S = MVT::Clone( *tmp, 2 );
72  std::vector<int> index(1,0);
73  index[0] = 0;
74  this->R = MVT::CloneViewNonConst( *S, index );
75  index[0] = 1;
76  this->Z = MVT::CloneViewNonConst( *S, index );
77 
78  this->P = MVT::Clone( *tmp, 1 );
79  this->AP = MVT::Clone(*tmp, 1);
80 
82  }
83 
84  bool matches(Teuchos::RCP<const MV> tmp, int _numVectors=1) const {
85  return (CGIterationStateBase<ScalarType, MV>::matches(tmp, _numVectors) &&
86  !S.is_null());
87  }
88 
90 
91 };
92 
93 template<class ScalarType, class MV, class OP>
94 class CGIter : virtual public CGIteration<ScalarType,MV,OP> {
95 
96  public:
97 
98  //
99  // Convenience typedefs
100  //
105 
107 
108 
115  const Teuchos::RCP<OutputManager<ScalarType> > &printer,
118  Teuchos::ParameterList &params );
119 
121  virtual ~CGIter() = default;
123 
124 
126 
127 
140  void iterate();
141 
157 
161  void initialize()
162  {
163  initializeCG(Teuchos::null, Teuchos::null);
164  }
165 
173  auto state = Teuchos::rcp(new CGIterationState<ScalarType,MV>());
174  state->R = R_;
175  state->P = P_;
176  state->AP = AP_;
177  state->Z = Z_;
178  state->S = S_;
179  return state;
180  }
181 
183  auto s = Teuchos::rcp_dynamic_cast<CGIterationState<ScalarType,MV> >(state, true);
184  R_ = s->R;
185  Z_ = s->Z;
186  P_ = s->P;
187  AP_ = s->AP;
188  S_ = s->S;
189  }
190 
192 
193 
195 
196 
198  int getNumIters() const { return iter_; }
199 
201  void resetNumIters( int iter = 0 ) { iter_ = iter; }
202 
205  Teuchos::RCP<const MV> getNativeResiduals( std::vector<MagnitudeType> * norms ) const {
206  if (foldConvergenceDetectionIntoAllreduce_ && convTest_->getResNormType() == Belos::TwoNorm) {
207  (*norms)[0] = std::sqrt(Teuchos::ScalarTraits<ScalarType>::magnitude(rHr_));
208  return Teuchos::null;
209  } else
210  return R_;
211  }
212 
214 
216  Teuchos::RCP<MV> getCurrentUpdate() const { return Teuchos::null; }
217 
219 
221 
222 
224  const LinearProblem<ScalarType,MV,OP>& getProblem() const { return *lp_; }
225 
227  int getBlockSize() const { return 1; }
228 
230  void setBlockSize(int blockSize) {
231  TEUCHOS_TEST_FOR_EXCEPTION(blockSize!=1,std::invalid_argument,
232  "Belos::CGIter::setBlockSize(): Cannot use a block size that is not one.");
233  }
234 
236  bool isInitialized() { return initialized_; }
237 
238 
240  void setDoCondEst(bool val) {
241  if (numEntriesForCondEst_ != 0) doCondEst_=val;
242  }
243 
246  // NOTE (mfh 30 Jul 2015) See note on getOffDiag() below.
247  // getDiag() didn't actually throw for me in that case, but why
248  // not be cautious?
249  using size_type = typename Teuchos::ArrayView<MagnitudeType>::size_type;
250  if (static_cast<size_type> (iter_) >= diag_.size ()) {
251  return diag_ ();
252  } else {
253  return diag_ (0, iter_);
254  }
255  }
256 
259  // NOTE (mfh 30 Jul 2015) The implementation as I found it
260  // returned "offdiag(0,iter_)". This breaks (Teuchos throws in
261  // debug mode) when the maximum number of iterations has been
262  // reached, because iter_ == offdiag_.size() in that case. The
263  // new logic fixes this.
264  using size_type = typename Teuchos::ArrayView<MagnitudeType>::size_type;
265  if (static_cast<size_type> (iter_) >= offdiag_.size ()) {
266  return offdiag_ ();
267  } else {
268  return offdiag_ (0, iter_);
269  }
270  }
271 
273 
274  private:
275 
276  //
277  // Internal methods
278  //
279  // Classes inputed through constructor that define the linear problem to be solved.
280  //
285 
286  //
287  // Current solver state
288  //
289  // initialized_ specifies that the basis vectors have been initialized and the iterate() routine
290  // is capable of running; _initialize is controlled by the initialize() member method
291  // For the implications of the state of initialized_, please see documentation for initialize()
292  bool initialized_;
293 
294  // Current number of iterations performed.
295  int iter_;
296 
297  // Should the allreduce for convergence detection be merged with one of the inner products?
298  bool foldConvergenceDetectionIntoAllreduce_;
299 
300  // <r,r>
301  ScalarType rHr_;
302 
303  // Assert that the matrix is positive definite
304  bool assertPositiveDefiniteness_;
305 
306  // Tridiagonal system for condition estimation (if needed)
307  Teuchos::ArrayRCP<MagnitudeType> diag_, offdiag_;
308  int numEntriesForCondEst_;
309  bool doCondEst_;
310 
311 
312 
313  //
314  // State Storage
315  //
316  // Residual
317  Teuchos::RCP<MV> R_;
318  //
319  // Preconditioned residual
320  Teuchos::RCP<MV> Z_;
321  //
322  // Direction vector
323  Teuchos::RCP<MV> P_;
324  //
325  // Operator applied to direction vector
326  Teuchos::RCP<MV> AP_;
327 
328  Teuchos::RCP<MV> S_;
329 
330 };
331 
333  // Constructor.
334  template<class ScalarType, class MV, class OP>
336  const Teuchos::RCP<OutputManager<ScalarType> > &printer,
339  Teuchos::ParameterList &params ):
340  lp_(problem),
341  om_(printer),
342  stest_(tester),
343  convTest_(convTester),
344  initialized_(false),
345  iter_(0),
346  assertPositiveDefiniteness_( params.get("Assert Positive Definiteness", true) ),
347  numEntriesForCondEst_(params.get("Max Size For Condest",0) ),
348  doCondEst_(false)
349  {
350  foldConvergenceDetectionIntoAllreduce_ = params.get<bool>("Fold Convergence Detection Into Allreduce",false);
351  }
352 
353 
355  // Initialize this iteration object
356  template <class ScalarType, class MV, class OP>
358  {
359  // Initialize the state storage if it isn't already.
360  Teuchos::RCP<const MV> lhsMV = lp_->getLHS();
361  Teuchos::RCP<const MV> rhsMV = lp_->getRHS();
362  Teuchos::RCP<const MV> tmp = ( (rhsMV!=Teuchos::null)? rhsMV: lhsMV );
363  TEUCHOS_ASSERT(!newstate.is_null());
364  if (!Teuchos::rcp_dynamic_cast<CGIterationState<ScalarType,MV> >(newstate, true)->matches(tmp, 1))
365  newstate->initialize(tmp, 1);
366  setState(newstate);
367 
368  // Tracking information for condition number estimation
369  if(numEntriesForCondEst_ > 0) {
370  diag_.resize(numEntriesForCondEst_);
371  offdiag_.resize(numEntriesForCondEst_-1);
372  }
373 
374  std::string errstr("Belos::CGIter::initialize(): Specified multivectors must have a consistent length and width.");
375  {
376 
377  TEUCHOS_TEST_FOR_EXCEPTION( MVT::GetGlobalLength(*R_0) != MVT::GetGlobalLength(*R_),
378  std::invalid_argument, errstr );
379  TEUCHOS_TEST_FOR_EXCEPTION( MVT::GetNumberVecs(*R_0) != 1,
380  std::invalid_argument, errstr );
381 
382  // Copy basis vectors from newstate into V
383  if (R_0 != R_) {
384  // copy over the initial residual (unpreconditioned).
385  MVT::Assign( *R_0, *R_ );
386  }
387 
388  // Compute initial direction vectors
389  // Initially, they are set to the preconditioned residuals
390  //
391  if ( lp_->getLeftPrec() != Teuchos::null ) {
392  lp_->applyLeftPrec( *R_, *Z_ );
393  if ( lp_->getRightPrec() != Teuchos::null ) {
394  Teuchos::RCP<MV> tmp2 = MVT::CloneCopy( *Z_ );
395  lp_->applyRightPrec( *tmp2, *Z_ );
396  }
397  }
398  else if ( lp_->getRightPrec() != Teuchos::null ) {
399  lp_->applyRightPrec( *R_, *Z_ );
400  }
401  else {
402  MVT::Assign( *R_, *Z_ );
403  }
404  MVT::Assign( *Z_, *P_ );
405  }
406 
407  // The solver is initialized
408  initialized_ = true;
409  }
410 
411 
413  // Iterate until the status test informs us we should stop.
414  template <class ScalarType, class MV, class OP>
416  {
417  //
418  // Allocate/initialize data structures
419  //
420  if (!initialized_) {
421  initialize();
422  }
423 
424  // Allocate memory for scalars.
425  std::vector<ScalarType> alpha(1);
426  std::vector<ScalarType> beta(1);
427  std::vector<ScalarType> rHz(1);
428  std::vector<ScalarType> rHz_old(1);
429  std::vector<ScalarType> pAp(1);
431 
432  // Create convenience variables for zero and one.
433  const ScalarType one = Teuchos::ScalarTraits<ScalarType>::one();
435 
436  // Scalars for condition estimation (if needed) - These will always use entry zero, for convenience
437  ScalarType pAp_old = one;
438  ScalarType beta_old = one;
439  ScalarType rHz_old2 = one;
440 
441  // Get the current solution vector.
442  Teuchos::RCP<MV> cur_soln_vec = lp_->getCurrLHSVec();
443 
444  // Check that the current solution vector only has one column.
445  TEUCHOS_TEST_FOR_EXCEPTION( MVT::GetNumberVecs(*cur_soln_vec) != 1, CGIterateFailure,
446  "Belos::CGIter::iterate(): current linear system has more than one vector!" );
447 
448  // Compute first <r,z> a.k.a. rHz
449  if (foldConvergenceDetectionIntoAllreduce_ && convTest_->getResNormType() == Belos::TwoNorm) {
450  MVT::MvTransMv( one, *R_, *S_, rHs );
451  rHr_ = rHs(0,0);
452  rHz[0] = rHs(0,1);
453  } else
454  MVT::MvDot( *R_, *Z_, rHz );
455 
457  // Iterate until the status test tells us to stop.
458  //
459  while (stest_->checkStatus(this) != Passed) {
460 
461  // Increment the iteration
462  iter_++;
463 
464  // Multiply the current direction vector by A and store in AP_
465  lp_->applyOp( *P_, *AP_ );
466 
467  // Compute alpha := <R_,Z_> / <P_,AP_>
468  MVT::MvDot( *P_, *AP_, pAp );
469  alpha[0] = rHz[0] / pAp[0];
470 
471  // Check that alpha is a positive number!
472  if(assertPositiveDefiniteness_) {
473  TEUCHOS_TEST_FOR_EXCEPTION( SCT::real(alpha[0]) <= zero, CGPositiveDefiniteFailure,
474  "Belos::CGIter::iterate(): non-positive value for p^H*A*p encountered!" );
475  }
476 
477  //
478  // Update the solution vector x := x + alpha * P_
479  //
480  MVT::MvAddMv( one, *cur_soln_vec, alpha[0], *P_, *cur_soln_vec );
481  lp_->updateSolution();
482  //
483  // Save the denominator of beta before residual is updated [ old <R_, Z_> ]
484  //
485  rHz_old[0] = rHz[0];
486  //
487  // Compute the new residual R_ := R_ - alpha * AP_
488  //
489  MVT::MvAddMv( one, *R_, -alpha[0], *AP_, *R_ );
490  //
491  // Compute beta := [ new <R_, Z_> ] / [ old <R_, Z_> ],
492  // and the new direction vector p.
493  //
494  if ( lp_->getLeftPrec() != Teuchos::null ) {
495  lp_->applyLeftPrec( *R_, *Z_ );
496  if ( lp_->getRightPrec() != Teuchos::null ) {
497  Teuchos::RCP<MV> tmp = MVT::CloneCopy( *Z_);
498  lp_->applyRightPrec( *tmp, *Z_ );
499  }
500  }
501  else if ( lp_->getRightPrec() != Teuchos::null ) {
502  lp_->applyRightPrec( *R_, *Z_ );
503  }
504  else {
505  MVT::Assign( *R_, *Z_ );
506  }
507  //
508  if (foldConvergenceDetectionIntoAllreduce_ && convTest_->getResNormType() == Belos::TwoNorm) {
509  MVT::MvTransMv( one, *R_, *S_, rHs );
510  rHr_ = rHs(0,0);
511  rHz[0] = rHs(0,1);
512  } else
513  MVT::MvDot( *R_, *Z_, rHz );
514  //
515  beta[0] = rHz[0] / rHz_old[0];
516  //
517  MVT::MvAddMv( one, *Z_, beta[0], *P_, *P_ );
518 
519  // Condition estimate (if needed)
520  if (doCondEst_) {
521  if (iter_ > 1) {
522  diag_[iter_-1] = Teuchos::ScalarTraits<ScalarType>::real((beta_old * beta_old * pAp_old + pAp[0]) / rHz_old[0]);
523  offdiag_[iter_-2] = -Teuchos::ScalarTraits<ScalarType>::real(beta_old * pAp_old / (sqrt( rHz_old[0] * rHz_old2)));
524  }
525  else {
526  diag_[iter_-1] = Teuchos::ScalarTraits<ScalarType>::real(pAp[0] / rHz_old[0]);
527  }
528  rHz_old2 = rHz_old[0];
529  beta_old = beta[0];
530  pAp_old = pAp[0];
531  }
532 
533  } // end while (sTest_->checkStatus(this) != Passed)
534  }
535 
536 } // end Belos namespace
537 
538 #endif /* BELOS_CG_ITER_HPP */
Collection of types and exceptions used within the Belos solvers.
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 > S
Definition: BelosCGIter.hpp:89
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 val)
Sets whether or not to store the diagonal for condition estimation.
This class implements the preconditioned Conjugate Gradient (CG) iteration.
Definition: BelosCGIter.hpp:94
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)
Teuchos::RCP< CGIterationStateBase< ScalarType, MV > > getState() const
Get the current state of the linear solver.
virtual ~CGIterationState()=default
Pure virtual base class for defining the status testing capabilities of Belos.
#define TEUCHOS_TEST_FOR_EXCEPTION(throw_exception_test, Exception, msg)
static magnitudeType real(T a)
Declaration of basic traits for the multivector type.
void setBlockSize(int blockSize)
Set the blocksize to be used by the iterative solver in solving this linear problem.
An implementation of StatusTestResNorm using a family of residual norms.
size_type size() const
A pure virtual class for defining the status tests for the Belos iterative solvers.
CGIter(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)
CGIter constructor with linear problem, solver utilities, and parameter list of solver options...
Class which defines basic traits for the operator type.
CGIterateFailure is thrown when the CGIteration object is unable to compute the next iterate in the C...
Teuchos::RCP< MV > P
The current decent direction vector.
Teuchos::RCP< const MV > getNativeResiduals(std::vector< MagnitudeType > *norms) const
Get the norms of the residuals native to the solver.
bool isInitialized()
States whether the solver has been initialized or not.
bool matches(Teuchos::RCP< const MV > tmp, int _numVectors=1) const
Definition: BelosCGIter.hpp:84
int getNumIters() const
Get the current iteration count.
Traits class which defines basic operations on multivectors.
CGPositiveDefiniteFailure is thrown when the the CG &#39;alpha = p^H*A*P&#39; value is less than zero...
void initialize(Teuchos::RCP< const MV > tmp, int _numVectors)
Definition: BelosCGIter.hpp:65
Teuchos::ArrayView< MagnitudeType > getDiag()
Gets the diagonal for condition estimation.
TEUCHOS_DEPRECATED RCP< T > rcp(T *p, Dealloc_T dealloc, bool owns_mem)
virtual ~CGIter()=default
Destructor.
int getBlockSize() const
Get the blocksize to be used by the iterative solver in solving this linear problem.
void iterate()
This method performs CG iterations until the status test indicates the need to stop or an error occur...
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.
void setState(Teuchos::RCP< CGIterationStateBase< ScalarType, MV > > state)
Teuchos::ArrayView< MagnitudeType > getOffDiag()
Gets the off-diagonal for condition estimation.
Structure to contain pointers to CGIteration state variables.
Teuchos::RCP< MV > Z
The current preconditioned residual.
void initialize()
Initialize the solver with the initial vectors from the linear problem or random data.
Teuchos::RCP< MV > AP
The matrix A applied to current decent direction vector.
Teuchos::RCP< MV > getCurrentUpdate() const
Get the current update to the linear system.
Structure to contain pointers to CGIteration state variables.
Definition: BelosCGIter.hpp:54
Belos::StatusTestResNorm for specifying general residual norm stopping criteria.
typename SCT::magnitudeType MagnitudeType
void resetNumIters(int iter=0)
Reset the iteration count.
const LinearProblem< ScalarType, MV, OP > & getProblem() const
Get a constant reference to the linear problem.
Class which defines basic traits for the operator type.
#define TEUCHOS_ASSERT(assertion_test)
Teuchos::RCP< MV > R
The current residual.
Belos header file which uses auto-configuration information to include necessary C++ headers...
CGIterationState(Teuchos::RCP< const MV > tmp)
Definition: BelosCGIter.hpp:59
bool is_null() const

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