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"
28
29#include "Teuchos_ScalarTraits.hpp"
30#include "Teuchos_ParameterList.hpp"
31#include "Teuchos_TimeMonitor.hpp"
32
43namespace Belos {
44
46
47
52 template <class ScalarType, class MV, class DM>
53 class CGSingleRedIterationState : public CGIterationStateBase<ScalarType, MV, DM> {
54
55 public:
57
58 CGSingleRedIterationState(Teuchos::RCP<const MV> tmp) {
60 }
61
62 virtual ~CGSingleRedIterationState() = default;
63
64 void initialize(Teuchos::RCP<const MV> tmp, int _numVectors) {
66
68
69 // W = (AZ, R, Z)
70 W = MVT::Clone( *tmp, 3 );
71 std::vector<int> index2(2,0);
72 std::vector<int> index(1,0);
73
74 // S = (AZ, R)
75 index2[0] = 0;
76 index2[1] = 1;
77 S = MVT::CloneViewNonConst( *W, index2 );
78
79 // U = (AZ, Z)
80 index2[0] = 0;
81 index2[1] = 2;
82 U = MVT::CloneViewNonConst( *W, index2 );
83
84 index[0] = 1;
85 this->R = MVT::CloneViewNonConst( *W, index );
86 index[0] = 0;
87 AZ = MVT::CloneViewNonConst( *W, index );
88 index[0] = 2;
89 this->Z = MVT::CloneViewNonConst( *W, index );
90
91 // T = (R, Z)
92 index2[0] = 1;
93 index2[1] = 2;
94 T = MVT::CloneViewNonConst( *W, index2 );
95
96 // V = (AP, P)
97 V = MVT::Clone( *tmp, 2 );
98 index[0] = 0;
99 this->AP = MVT::CloneViewNonConst( *V, index );
100 index[0] = 1;
101 this->P = MVT::CloneViewNonConst( *V, index );
102
104 }
105
106 bool matches(Teuchos::RCP<const MV> tmp, int _numVectors=1) const {
108 !W.is_null() &&
109 !V.is_null() &&
110 !U.is_null() &&
111 !S.is_null() &&
112 !T.is_null() &&
113 !AZ.is_null());
114 }
115
116 Teuchos::RCP<MV> W;
117 Teuchos::RCP<MV> V;
118 Teuchos::RCP<MV> U;
119 Teuchos::RCP<MV> S;
120 Teuchos::RCP<MV> T;
121 Teuchos::RCP<MV> AZ;
122
123 };
124
125template<class ScalarType, class MV, class OP, class DM>
126class CGSingleRedIter : virtual public CGIteration<ScalarType,MV,OP,DM> {
127
128 public:
129
130 //
131 // Convenience typedefs
132 //
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,DM> > &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,DM> > newstate, Teuchos::RCP<MV> R_0);
190
195 {
196 initializeCG(Teuchos::null, Teuchos::null);
197 }
198
205 Teuchos::RCP<CGIterationStateBase<ScalarType,MV,DM> > getState() const {
206 auto state = Teuchos::rcp(new CGSingleRedIterationState<ScalarType,MV,DM>());
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,DM> >(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,DM>& 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,DM> > lp_;
301 const Teuchos::RCP<OutputManager<ScalarType> > om_;
302 const Teuchos::RCP<StatusTest<ScalarType,MV,OP,DM> > stest_;
303 const Teuchos::RCP<StatusTestGenResNorm<ScalarType,MV,OP,DM> > 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, class DM>
355 const Teuchos::RCP<OutputManager<ScalarType> > &printer,
356 const Teuchos::RCP<StatusTest<ScalarType,MV,OP,DM> > &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 // Setup the state storage.
371 template<class ScalarType, class MV, class OP, class DM>
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,DM> >(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, class DM>
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, class DM>
449 {
450 //
451 // Allocate/initialize data structures
452 //
453 if (!initialized_) {
454 initialize();
455 }
456
457 // Allocate memory for scalars.
458 Teuchos::RCP<DM> sHz = DMT::Create( 2, 1 );
459 Teuchos::RCP<DM> sHt = DMT::Create( 2, 2 );
460 ScalarType rHz_old, alpha, beta, delta;
461
462 // Create convenience variables for zero and one.
463 const ScalarType one = Teuchos::ScalarTraits<ScalarType>::one();
464 const MagnitudeType zero = Teuchos::ScalarTraits<MagnitudeType>::zero();
465
466 // Get the current solution vector.
467 Teuchos::RCP<MV> cur_soln_vec = lp_->getCurrLHSVec();
468
469 // Check that the current solution vector only has one column.
470 TEUCHOS_TEST_FOR_EXCEPTION( MVT::GetNumberVecs(*cur_soln_vec) != 1, CGIterateFailure,
471 "Belos::CGSingleRedIter::iterate(): current linear system has more than one vector!" );
472
473 if (foldConvergenceDetectionIntoAllreduce_ && convTest_->getResNormType() == Belos::TwoNorm) {
474 // Compute first <S_,T_> a.k.a. <R_,Z_>, <AZ_,Z_> and <R_,R_> combined (also computes unneeded <AZ_,R_>)
475 MVT::MvTransMv( one, *S_, *T_, *sHt );
476 DMT::SyncDeviceToHost( *sHt );
477 rHz_ = DMT::ValueConst(*sHt,1,1);
478 delta = DMT::ValueConst(*sHt,0,1);
479 rHr_ = DMT::ValueConst(*sHt,1,0);
480 } else {
481 // Compute first <s,z> a.k.a. <r,z> and <Az,z> combined
482 MVT::MvTransMv( one, *S_, *Z_, *sHz );
483 DMT::SyncDeviceToHost( *sHz );
484 rHz_ = DMT::ValueConst(*sHz,1,0);
485 delta = DMT::ValueConst(*sHz,0,0);
486 }
487 if ((Teuchos::ScalarTraits<ScalarType>::magnitude(delta) < Teuchos::ScalarTraits<ScalarType>::eps()) &&
488 (stest_->checkStatus(this) == Passed))
489 return;
490 alpha = rHz_ / delta;
491
492 // Check that alpha is a positive number!
494 "Belos::CGSingleRedIter::iterate(): non-positive value for p^H*A*p encountered!" );
495
497 // Iterate until the status test tells us to stop.
498 //
499 if (foldConvergenceDetectionIntoAllreduce_ && convTest_->getResNormType() == Belos::TwoNorm) {
501 // Iterate until the status test tells us to stop.
502 //
503 while (true) {
504
505 // Update the solution vector x := x + alpha * P_
506 //
507 MVT::MvAddMv( one, *cur_soln_vec, alpha, *P_, *cur_soln_vec );
508 //
509 // Compute the new residual R_ := R_ - alpha * AP_
510 //
511 MVT::MvAddMv( one, *R_, -alpha, *AP_, *R_ );
512 //
513 // Apply preconditioner to new residual to update Z_
514 //
515 if ( lp_->getLeftPrec() != Teuchos::null ) {
516 lp_->applyLeftPrec( *R_, *Z_ );
517 if ( lp_->getRightPrec() != Teuchos::null ) {
518 Teuchos::RCP<MV> tmp = MVT::CloneCopy( *Z_ );
519 lp_->applyRightPrec( *tmp, *Z_ );
520 }
521 }
522 else if ( lp_->getRightPrec() != Teuchos::null ) {
523 lp_->applyRightPrec( *R_, *Z_ );
524 }
525 else {
526 MVT::Assign( *R_, *Z_ );
527 }
528 //
529 // Multiply the current preconditioned residual vector by A and store in AZ_
530 lp_->applyOp( *Z_, *AZ_ );
531 //
532 // Compute <S_,T_> a.k.a. <R_,Z_>, <AZ_,Z_> and <R_,R_> combined (also computes unneeded <AZ_,R_>)
533 MVT::MvTransMv( one, *S_, *T_, *sHt );
534 DMT::SyncDeviceToHost( *sHt );
535 //
536 // Update scalars.
537 rHz_old = rHz_;
538 rHz_ = DMT::ValueConst(*sHt,1,1);
539 delta = DMT::ValueConst(*sHt,0,1);
540 rHr_ = DMT::ValueConst(*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 DMT::SyncDeviceToHost( *sHz );
611 //
612 // Update scalars.
613 rHz_old = rHz_;
614 rHz_ = DMT::ValueConst(*sHz,1,0);
615 delta = DMT::ValueConst(*sHz,0,0);
616 //
617 beta = rHz_ / rHz_old;
618 alpha = rHz_ / (delta - (beta*rHz_ / alpha));
619 //
620 // Check that alpha is a positive number!
622 "Belos::CGSingleRedIter::iterate(): non-positive value for p^H*A*p encountered!" );
623
624 //
625 // Update the direction vector P_ := Z_ + beta * P_
626 // Update AP_ through recurrence relation AP_ := AZ_ + beta * AP_
627 // Hence: V_ = (AP_, P_) := (AZ_, Z_) + beta (AP_, P_) = U_ + beta * V_
628 //
629 MVT::MvAddMv( one, *U_, beta, *V_, *V_ );
630
631 } // end while (1)
632 }
633 }
634
635} // end Belos namespace
636
637#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.
Pure virtual base class for defining the status testing capabilities of Belos.
Belos::StatusTestResNorm for specifying general residual norm stopping criteria.
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 > AP
The matrix A applied to current decent direction vector.
Teuchos::RCP< MV > P
The current decent direction vector.
Teuchos::RCP< MV > R
The current residual.
virtual void initialize(Teuchos::RCP< const MV > tmp, int _numVectors)
Teuchos::RCP< MV > Z
The current preconditioned residual.
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.
typename SCT::magnitudeType MagnitudeType
bool isInitialized()
States whether the solver has been initialized or not.
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, DM > & getProblem() const
Get a constant reference to the linear problem.
void initialize()
Initialize the solver with the initial vectors from the linear problem or random data.
virtual ~CGSingleRedIter()=default
Destructor.
void resetNumIters(int iter=0)
Reset the iteration count.
Teuchos::ScalarTraits< ScalarType > SCT
Teuchos::RCP< CGIterationStateBase< ScalarType, MV, DM > > getState() const
Get the current state of the linear solver.
void iterate()
This method performs CG iterations until the status test indicates the need to stop or an error occur...
Teuchos::ArrayView< MagnitudeType > getOffDiag()
Gets the off-diagonal for condition estimation (NOT_IMPLEMENTED)
CGSingleRedIter(const Teuchos::RCP< LinearProblem< ScalarType, MV, OP, DM > > &problem, const Teuchos::RCP< OutputManager< ScalarType > > &printer, const Teuchos::RCP< StatusTest< ScalarType, MV, OP, DM > > &tester, const Teuchos::RCP< StatusTestGenResNorm< ScalarType, MV, OP, DM > > &convTester, Teuchos::ParameterList &params)
CGSingleRedIter constructor with linear problem, solver utilities, and parameter list of solver optio...
void setDoCondEst(bool)
Sets whether or not to store the diagonal for condition estimation.
void setState(Teuchos::RCP< CGIterationStateBase< ScalarType, MV, DM > > state)
void initializeCG(Teuchos::RCP< CGIterationStateBase< ScalarType, MV, DM > > newstate, Teuchos::RCP< MV > R_0)
Initialize the solver to an iterate, providing a complete state.
Teuchos::ArrayView< MagnitudeType > getDiag()
Gets the diagonal for condition estimation (NOT_IMPLEMENTED)
Teuchos::RCP< const MV > getNativeResiduals(std::vector< MagnitudeType > *norms) const
Get the norms of the residuals native to the solver.
int getBlockSize() const
Get the blocksize to be used by the iterative solver in solving this linear problem.
void setBlockSize(int blockSize)
Set the blocksize to be used by the iterative solver in solving this linear problem.
Structure to contain pointers to CGSingleRedIteration state variables.
CGSingleRedIterationState(Teuchos::RCP< const MV > tmp)
void initialize(Teuchos::RCP< const MV > tmp, int _numVectors)
virtual ~CGSingleRedIterationState()=default
bool matches(Teuchos::RCP< const MV > tmp, int _numVectors=1) const
Alternative run-time polymorphic interface for operators.
Operator()
Default constructor (does nothing).
@ PreconditionerNorm

Generated for Belos by doxygen 1.9.8