Belos Version of the Day
Loading...
Searching...
No Matches
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
23#include "BelosStatusTest.hpp"
27
28#include "Teuchos_SerialDenseMatrix.hpp"
29#include "Teuchos_SerialDenseVector.hpp"
30#include "Teuchos_ScalarTraits.hpp"
31#include "Teuchos_ParameterList.hpp"
32#include "Teuchos_TimeMonitor.hpp"
33
44namespace Belos {
45
47
48
53 template <class ScalarType, class MV>
54 class CGSingleRedIterationState : public CGIterationStateBase<ScalarType, MV> {
55
56 public:
58
59 CGSingleRedIterationState(Teuchos::RCP<const MV> tmp) {
61 }
62
63 virtual ~CGSingleRedIterationState() = default;
64
65 void initialize(Teuchos::RCP<const MV> tmp, int _numVectors) {
67
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 {
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
117 Teuchos::RCP<MV> W;
118 Teuchos::RCP<MV> V;
119 Teuchos::RCP<MV> U;
120 Teuchos::RCP<MV> S;
121 Teuchos::RCP<MV> T;
122 Teuchos::RCP<MV> AZ;
123
124 };
125
126template<class ScalarType, class MV, class OP>
127class CGSingleRedIter : virtual public CGIteration<ScalarType,MV,OP> {
128
129 public:
130
131 //
132 // Convenience typedefs
133 //
136 using SCT = Teuchos::ScalarTraits<ScalarType>;
137 using MagnitudeType = typename SCT::magnitudeType;
138
140
141
148 const Teuchos::RCP<OutputManager<ScalarType> > &printer,
149 const Teuchos::RCP<StatusTest<ScalarType,MV,OP> > &tester,
151 Teuchos::ParameterList &params );
152
154 virtual ~CGSingleRedIter() = default;
156
157
159
160
173 void iterate();
174
189 void initializeCG(Teuchos::RCP<CGIterationStateBase<ScalarType,MV> > newstate, Teuchos::RCP<MV> R_0);
190
195 {
196 initializeCG(Teuchos::null, Teuchos::null);
197 }
198
205 Teuchos::RCP<CGIterationStateBase<ScalarType,MV> > getState() const {
206 auto state = Teuchos::rcp(new CGSingleRedIterationState<ScalarType,MV>());
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
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
279 Teuchos::ArrayView<MagnitudeType> getDiag() {
280 Teuchos::ArrayView<MagnitudeType> temp;
281 return temp;
282 }
283
285 Teuchos::ArrayView<MagnitudeType> getOffDiag() {
286 Teuchos::ArrayView<MagnitudeType> temp;
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 //
300 const Teuchos::RCP<LinearProblem<ScalarType,MV,OP> > lp_;
301 const Teuchos::RCP<OutputManager<ScalarType> > om_;
302 const Teuchos::RCP<StatusTest<ScalarType,MV,OP> > stest_;
303 const Teuchos::RCP<StatusTestGenResNorm<ScalarType,MV,OP> > convTest_;
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,
356 const Teuchos::RCP<StatusTest<ScalarType,MV,OP> > &tester,
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>
432 Teuchos::RCP<const MV>
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.
458 Teuchos::SerialDenseMatrix<int,ScalarType> sHz( 2, 1 );
459 Teuchos::SerialDenseMatrix<int,ScalarType> sHt( 2, 2 );
461 ScalarType alpha;
462 ScalarType beta;
464
465 // Create convenience variables for zero and one.
466 const ScalarType one = Teuchos::ScalarTraits<ScalarType>::one();
467 const MagnitudeType zero = Teuchos::ScalarTraits<MagnitudeType>::zero();
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 }
488 if ((Teuchos::ScalarTraits<ScalarType>::magnitude(delta) < Teuchos::ScalarTraits<ScalarType>::eps()) &&
489 (stest_->checkStatus(this) == Passed))
490 return;
491 alpha = rHz_ / delta;
492
493 // Check that alpha is a positive number!
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!
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!
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 */
Pure virtual base class which augments the basic interface for a conjugate gradient linear solver ite...
Belos header file which uses auto-configuration information to include necessary C++ headers.
Class which describes the linear problem to be solved by the iterative solver.
Declaration of basic traits for the multivector type.
Class which defines basic traits for the operator type.
Class which manages the output and verbosity of the Belos solvers.
Belos::StatusTestResNorm for specifying general residual norm stopping criteria.
Pure virtual base class for defining the status testing capabilities of Belos.
Collection of types and exceptions used within the Belos solvers.
CGIterateFailure is thrown when the CGIteration object is unable to compute the next iterate in the C...
Structure to contain pointers to CGIteration state variables.
Teuchos::RCP< MV > R
The current residual.
Teuchos::RCP< MV > P
The current decent direction vector.
virtual void initialize(Teuchos::RCP< const MV > tmp, int _numVectors)
Teuchos::RCP< MV > Z
The current preconditioned residual.
Teuchos::RCP< MV > AP
The matrix A applied to current decent direction vector.
CGPositiveDefiniteFailure is thrown when the the CG 'alpha = p^H*A*P' value is less than zero,...
This class implements the preconditioned single-reduction Conjugate Gradient (CG) iteration.
int getBlockSize() const
Get the blocksize to be used by the iterative solver in solving this linear problem.
typename SCT::magnitudeType MagnitudeType
const LinearProblem< ScalarType, MV, OP > & getProblem() const
Get a constant reference to the linear problem.
void setState(Teuchos::RCP< CGIterationStateBase< ScalarType, MV > > state)
Teuchos::RCP< MV > getCurrentUpdate() const
Get the current update to the linear system.
Teuchos::ArrayView< MagnitudeType > getOffDiag()
Gets the off-diagonal for condition estimation (NOT_IMPLEMENTED)
void resetNumIters(int iter=0)
Reset the iteration count.
Teuchos::RCP< CGIterationStateBase< ScalarType, MV > > getState() const
Get the current state of the linear solver.
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.
virtual ~CGSingleRedIter()=default
Destructor.
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...
Teuchos::RCP< const MV > getNativeResiduals(std::vector< MagnitudeType > *norms) const
Get the norms of the residuals native to the solver.
void setBlockSize(int blockSize)
Set the blocksize to be used by the iterative solver in solving this linear problem.
Teuchos::ArrayView< MagnitudeType > getDiag()
Gets the diagonal for condition estimation (NOT_IMPLEMENTED)
void iterate()
This method performs CG iterations until the status test indicates the need to stop or an error occur...
Teuchos::ScalarTraits< ScalarType > SCT
bool isInitialized()
States whether the solver has been initialized or not.
int getNumIters() const
Get the current iteration count.
void initialize()
Initialize the solver with the initial vectors from the linear problem or random data.
Structure to contain pointers to CGSingleRedIteration state variables.
virtual ~CGSingleRedIterationState()=default
CGSingleRedIterationState(Teuchos::RCP< const MV > tmp)
bool matches(Teuchos::RCP< const MV > tmp, int _numVectors=1) const
void initialize(Teuchos::RCP< const MV > tmp, int _numVectors)
Alternative run-time polymorphic interface for operators.
Operator()
Default constructor (does nothing).
@ PreconditionerNorm

Generated for Belos by doxygen 1.9.8