Belos Version of the Day
Loading...
Searching...
No Matches
BelosBlockCGIter.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_BLOCK_CG_ITER_HPP
11#define BELOS_BLOCK_CG_ITER_HPP
12
17#include "BelosConfigDefs.hpp"
18#include "BelosTypes.hpp"
19#include "BelosCGIteration.hpp"
20
24#include "BelosStatusTest.hpp"
27
28#include "Teuchos_LAPACK.hpp"
29#include "Teuchos_SerialDenseMatrix.hpp"
30#include "Teuchos_SerialDenseVector.hpp"
31#include "Teuchos_SerialSymDenseMatrix.hpp"
32#include "Teuchos_SerialSpdDenseSolver.hpp"
33#include "Teuchos_ScalarTraits.hpp"
34#include "Teuchos_ParameterList.hpp"
35#include "Teuchos_TimeMonitor.hpp"
36
37namespace Belos {
38
40
41
46 template <class ScalarType, class MV>
47 class BlockCGIterationState : public CGIterationStateBase<ScalarType, MV> {
48
49 public:
51
52 BlockCGIterationState(Teuchos::RCP<const MV> tmp) {
54 }
55
56 virtual ~BlockCGIterationState() = default;
57
58 void initialize(Teuchos::RCP<const MV> tmp, int _numVectors) {
60 this->R = MVT::Clone( *tmp, _numVectors );
61 this->Z = MVT::Clone( *tmp, _numVectors );
62 this->P = MVT::Clone( *tmp, _numVectors );
63 this->AP = MVT::Clone(*tmp, _numVectors );
64
66 }
67
68 bool matches(Teuchos::RCP<const MV> tmp, int _numVectors=1) const {
70 }
71
72};
73
79
82template<class ScalarType, class MV, class OP,
83 const bool lapackSupportsScalarType =
85class BlockCGIter : virtual public CGIteration<ScalarType, MV, OP> {
86public:
89 typedef Teuchos::ScalarTraits<ScalarType> SCT;
90 typedef typename SCT::magnitudeType MagnitudeType;
91
92 BlockCGIter( const Teuchos::RCP<LinearProblem<ScalarType,MV,OP> > & /* problem */,
93 const Teuchos::RCP<OutputManager<ScalarType> > & /* printer */,
94 const Teuchos::RCP<StatusTest<ScalarType,MV,OP> > & /* tester */,
95 const Teuchos::RCP<MatOrthoManager<ScalarType,MV,OP> > & /* ortho */,
96 Teuchos::ParameterList & /* params */ )
97 {
98 TEUCHOS_TEST_FOR_EXCEPTION(true, std::logic_error, "Stub");
99 }
100
101 virtual ~BlockCGIter() {}
102
103 void iterate () {
104 TEUCHOS_TEST_FOR_EXCEPTION(true, std::logic_error, "Stub");
105 }
106
107 void initializeCG (Teuchos::RCP<BlockCGIterationState<ScalarType,MV> > /* newstate */, Teuchos::RCP<MV> /* R_0 */) {
108 TEUCHOS_TEST_FOR_EXCEPTION(true, std::logic_error, "Stub");
109 }
110
111 void initialize () {
112 TEUCHOS_TEST_FOR_EXCEPTION(true, std::logic_error, "Stub");
113 }
114
115 Teuchos::RCP<CGIterationStateBase<ScalarType,MV> > getState () const {
116 TEUCHOS_TEST_FOR_EXCEPTION(true, std::logic_error, "Stub");
117 }
118
120 TEUCHOS_TEST_FOR_EXCEPTION(true, std::logic_error, "Stub");
121 }
122
123 int getNumIters() const {
124 TEUCHOS_TEST_FOR_EXCEPTION(true, std::logic_error, "Stub");
125 }
126
127 void resetNumIters( int iter=0 ) {
128 TEUCHOS_TEST_FOR_EXCEPTION(true, std::logic_error, "Stub");
129 }
130
131 Teuchos::RCP<const MV>
132 getNativeResiduals (std::vector<MagnitudeType>* /* norms */) const {
133 TEUCHOS_TEST_FOR_EXCEPTION(true, std::logic_error, "Stub");
134 }
135
136 Teuchos::RCP<MV> getCurrentUpdate() const {
137 TEUCHOS_TEST_FOR_EXCEPTION(true, std::logic_error, "Stub");
138 }
139
141 TEUCHOS_TEST_FOR_EXCEPTION(true, std::logic_error, "Stub");
142 }
143
144 int getBlockSize() const {
145 TEUCHOS_TEST_FOR_EXCEPTION(true, std::logic_error, "Stub");
146 }
147
149 TEUCHOS_TEST_FOR_EXCEPTION(true, std::logic_error, "Stub");
150 }
151
153 TEUCHOS_TEST_FOR_EXCEPTION(true, std::logic_error, "Stub");
154 }
155
156 void setDoCondEst(bool val){
157 TEUCHOS_TEST_FOR_EXCEPTION(true, std::logic_error, "Stub");
158 }
159
160};
161
166template<class ScalarType, class MV, class OP>
168 virtual public CGIteration<ScalarType,MV,OP>
169{
170public:
171 //
172 // Convenience typedefs
173 //
176 using SCT = Teuchos::ScalarTraits<ScalarType>;
177 using MagnitudeType = typename SCT::magnitudeType;
178
180
181
188 const Teuchos::RCP<OutputManager<ScalarType> > &printer,
189 const Teuchos::RCP<StatusTest<ScalarType,MV,OP> > &tester,
190 const Teuchos::RCP<MatOrthoManager<ScalarType,MV,OP> > &ortho,
191 Teuchos::ParameterList &params );
192
194 virtual ~BlockCGIter() = default;
196
197
199
200
213 void iterate();
214
229 void initializeCG(Teuchos::RCP<CGIterationStateBase<ScalarType,MV> > newstate, Teuchos::RCP<MV> R_0);
230
235 {
236 initializeCG(Teuchos::null, Teuchos::null);
237 }
238
245 Teuchos::RCP<CGIterationStateBase<ScalarType,MV> > getState() const {
246 auto state = Teuchos::rcp(new BlockCGIterationState<ScalarType,MV>());
247 state->R = R_;
248 state->P = P_;
249 state->AP = AP_;
250 state->Z = Z_;
251 return state;
252 }
253
255 auto s = Teuchos::rcp_dynamic_cast<BlockCGIterationState<ScalarType,MV> >(state, true);
256 R_ = s->R;
257 Z_ = s->Z;
258 P_ = s->P;
259 AP_ = s->AP;
260 }
261
263
264
266
267
269 int getNumIters() const { return iter_; }
270
272 void resetNumIters( int iter=0 ) { iter_ = iter; }
273
276 Teuchos::RCP<const MV> getNativeResiduals( std::vector<MagnitudeType> * /* norms */ ) const { return R_; }
277
279
281 Teuchos::RCP<MV> getCurrentUpdate() const { return Teuchos::null; }
282
284
286
287
289 const LinearProblem<ScalarType,MV,OP>& getProblem() const { return *lp_; }
290
292 int getBlockSize() const { return blockSize_; }
293
295 void setBlockSize(int blockSize);
296
298 bool isInitialized() { return initialized_; }
299
301 void setDoCondEst(bool /* val */){/*ignored*/}
302
304 Teuchos::ArrayView<MagnitudeType> getDiag() {
305 Teuchos::ArrayView<MagnitudeType> temp;
306 return temp;
307 }
308
310 Teuchos::ArrayView<MagnitudeType> getOffDiag() {
311 Teuchos::ArrayView<MagnitudeType> temp;
312 return temp;
313 }
315
316 private:
317
318 //
319 // Internal methods
320
321 //
322 // Classes inputed through constructor that define the linear problem to be solved.
323 //
324 const Teuchos::RCP<LinearProblem<ScalarType,MV,OP> > lp_;
325 const Teuchos::RCP<OutputManager<ScalarType> > om_;
326 const Teuchos::RCP<StatusTest<ScalarType,MV,OP> > stest_;
327 const Teuchos::RCP<OrthoManager<ScalarType,MV> > ortho_;
328
329 //
330 // Algorithmic parameters
331 //
332 // blockSize_ is the solver block size.
333 int blockSize_;
334
335 //
336 // Current solver state
337 //
338 // initialized_ specifies that the basis vectors have been initialized and the iterate() routine
339 // is capable of running; _initialize is controlled by the initialize() member method
340 // For the implications of the state of initialized_, please see documentation for initialize()
341 bool initialized_;
342
343 // stateStorageInitialized_ specified that the state storage has be initialized.
344 // This initialization may be postponed if the linear problem was generated without
345 // the right-hand side or solution vectors.
346 bool stateStorageInitialized_;
347
348 // Current subspace dimension, and number of iterations performed.
349 int iter_;
350
351 //
352 // State Storage
353 //
354 // Residual
355 Teuchos::RCP<MV> R_;
356 //
357 // Preconditioned residual
358 Teuchos::RCP<MV> Z_;
359 //
360 // Direction std::vector
361 Teuchos::RCP<MV> P_;
362 //
363 // Operator applied to direction std::vector
364 Teuchos::RCP<MV> AP_;
365
366};
367
368 template<class ScalarType, class MV, class OP>
371 const Teuchos::RCP<OutputManager<ScalarType> >& printer,
372 const Teuchos::RCP<StatusTest<ScalarType,MV,OP> >& tester,
373 const Teuchos::RCP<MatOrthoManager<ScalarType,MV,OP> >& ortho,
374 Teuchos::ParameterList& params) :
375 lp_(problem),
376 om_(printer),
377 stest_(tester),
378 ortho_(ortho),
379 blockSize_(0),
380 initialized_(false),
381 stateStorageInitialized_(false),
382 iter_(0)
383 {
384 // Set the block size and allocate data
385 int bs = params.get("Block Size", 1);
386 setBlockSize( bs );
387 }
388
389 template <class ScalarType, class MV, class OP>
391 {
392 // This routine only allocates space; it doesn't not perform any computation
393 // any change in size will invalidate the state of the solver.
395 (blockSize <= 0, std::invalid_argument, "Belos::BlockGmresIter::"
396 "setBlockSize: blockSize = " << blockSize << " <= 0.");
397 if (blockSize == blockSize_) {
398 return; // do nothing
399 }
400 if (blockSize!=blockSize_) {
401 stateStorageInitialized_ = false;
402 }
403 blockSize_ = blockSize;
404 initialized_ = false;
405 }
406
407 template <class ScalarType, class MV, class OP>
409 initializeCG (Teuchos::RCP<CGIterationStateBase<ScalarType,MV> > newstate, Teuchos::RCP<MV> R_0)
410 {
411 const char prefix[] = "Belos::BlockCGIter::initialize: ";
412
413 // Initialize the state storage if it isn't already.
414 Teuchos::RCP<const MV> lhsMV = lp_->getLHS();
415 Teuchos::RCP<const MV> rhsMV = lp_->getRHS();
416 Teuchos::RCP<const MV> tmp = ( (rhsMV!=Teuchos::null)? rhsMV: lhsMV );
417 TEUCHOS_ASSERT(!newstate.is_null());
418 if (!Teuchos::rcp_dynamic_cast<BlockCGIterationState<ScalarType,MV> >(newstate, true)->matches(tmp, blockSize_))
419 newstate->initialize(tmp, blockSize_);
420 setState(newstate);
421
422 // NOTE: In BlockCGIter R_, the initial residual, is required!!!
423 const char errstr[] = "Specified multivectors must have a consistent "
424 "length and width.";
425
426 {
427
429 (MVT::GetGlobalLength(*R_0) != MVT::GetGlobalLength(*R_),
430 std::invalid_argument, prefix << errstr );
432 (MVT::GetNumberVecs(*R_0) != blockSize_,
433 std::invalid_argument, prefix << errstr );
434
435 // Copy basis vectors from newstate into V
436 if (R_0 != R_) {
437 // copy over the initial residual (unpreconditioned).
438 MVT::Assign( *R_0, *R_ );
439 }
440 // Compute initial direction vectors
441 // Initially, they are set to the preconditioned residuals
442 //
443 if ( lp_->getLeftPrec() != Teuchos::null ) {
444 lp_->applyLeftPrec( *R_, *Z_ );
445 if ( lp_->getRightPrec() != Teuchos::null ) {
446 Teuchos::RCP<MV> tmp2 = MVT::Clone( *Z_, blockSize_ );
447 lp_->applyRightPrec( *Z_, *tmp2 );
448 Z_ = tmp2;
449 }
450 }
451 else if ( lp_->getRightPrec() != Teuchos::null ) {
452 lp_->applyRightPrec( *R_, *Z_ );
453 }
454 else {
455 Z_ = R_;
456 }
457 MVT::Assign( *Z_, *P_ );
458 }
459
460 // The solver is initialized
461 initialized_ = true;
462 }
463
464 template <class ScalarType, class MV, class OP>
466 {
467 const char prefix[] = "Belos::BlockCGIter::iterate: ";
468
469 //
470 // Allocate/initialize data structures
471 //
472 if (initialized_ == false) {
473 initialize();
474 }
475 // Allocate data needed for LAPACK work.
476 int info = 0;
477 //char UPLO = 'U';
478 //(void) UPLO; // silence "unused variable" compiler warnings
479 bool uplo = true;
480 Teuchos::LAPACK<int,ScalarType> lapack;
481
482 // Allocate memory for scalars.
483 Teuchos::SerialDenseMatrix<int,ScalarType> alpha( blockSize_, blockSize_ );
484 Teuchos::SerialDenseMatrix<int,ScalarType> beta( blockSize_, blockSize_ );
485 Teuchos::SerialDenseMatrix<int,ScalarType> rHz( blockSize_, blockSize_ ),
486 rHz_old( blockSize_, blockSize_ ), pAp( blockSize_, blockSize_ );
487 Teuchos::SerialSymDenseMatrix<int,ScalarType> pApHerm(Teuchos::View, uplo, pAp.values(), blockSize_, blockSize_);
488
489 // Create dense spd solver.
490 Teuchos::SerialSpdDenseSolver<int,ScalarType> lltSolver;
491
492 // Create convenience variable for one.
493 const ScalarType one = Teuchos::ScalarTraits<ScalarType>::one();
494
495 // Get the current solution std::vector.
496 Teuchos::RCP<MV> cur_soln_vec = lp_->getCurrLHSVec();
497
498 // Check that the current solution std::vector has blockSize_ columns.
500 (MVT::GetNumberVecs(*cur_soln_vec) != blockSize_, CGIterateFailure,
501 prefix << "Current linear system does not have the right number of vectors!" );
502 int rank = ortho_->normalize( *P_, Teuchos::null );
504 (rank != blockSize_, CGIterationOrthoFailure,
505 prefix << "Failed to compute initial block of orthonormal direction vectors.");
506
507 //
508 // Iterate until the status test tells us to stop.
509 //
510 while (stest_->checkStatus(this) != Passed) {
511 // Increment the iteration
512 iter_++;
513
514 // Multiply the current direction std::vector by A and store in Ap_
515 lp_->applyOp( *P_, *AP_ );
516
517 // Compute alpha := <P_,R_> / <P_,AP_>
518 // 1) Compute P^T * A * P = pAp and P^T * R
519 // 2) Compute the Cholesky Factorization of pAp
520 // 3) Back and forward solves to compute alpha
521 //
522 MVT::MvTransMv( one, *P_, *R_, alpha );
523 MVT::MvTransMv( one, *P_, *AP_, pAp );
524
525 // Compute Cholesky factorization of pAp
526 lltSolver.setMatrix( Teuchos::rcp(&pApHerm, false) );
527 lltSolver.factorWithEquilibration( true );
528 info = lltSolver.factor();
531 prefix << "Failed to compute Cholesky factorization using LAPACK routine POTRF.");
532
533 // Compute alpha by performing a back and forward solve with the
534 // Cholesky factorization in pAp.
535 lltSolver.setVectors (Teuchos::rcpFromRef (alpha), Teuchos::rcpFromRef (alpha));
536 info = lltSolver.solve();
539 prefix << "Failed to compute alpha using Cholesky factorization (POTRS).");
540
541 // Update the solution std::vector X := X + alpha * P_
542 MVT::MvTimesMatAddMv( one, *P_, alpha, one, *cur_soln_vec );
543 lp_->updateSolution();
544
545 // Compute the new residual R_ := R_ - alpha * AP_
546 MVT::MvTimesMatAddMv( -one, *AP_, alpha, one, *R_ );
547
548 // Compute the new preconditioned residual, Z_.
549 if ( lp_->getLeftPrec() != Teuchos::null ) {
550 lp_->applyLeftPrec( *R_, *Z_ );
551 if ( lp_->getRightPrec() != Teuchos::null ) {
552 Teuchos::RCP<MV> tmp = MVT::Clone( *Z_, blockSize_ );
553 lp_->applyRightPrec( *Z_, *tmp );
554 Z_ = tmp;
555 }
556 }
557 else if ( lp_->getRightPrec() != Teuchos::null ) {
558 lp_->applyRightPrec( *R_, *Z_ );
559 }
560 else {
561 Z_ = R_;
562 }
563
564 // Compute beta := <AP_,Z_> / <P_,AP_>
565 // 1) Compute AP_^T * Z_
566 // 2) Compute the Cholesky Factorization of pAp (already have)
567 // 3) Back and forward solves to compute beta
568
569 // Compute <AP_,Z>
570 MVT::MvTransMv( -one, *AP_, *Z_, beta );
571
572 lltSolver.setVectors( Teuchos::rcp( &beta, false ), Teuchos::rcp( &beta, false ) );
573 info = lltSolver.solve();
576 prefix << "Failed to compute beta using Cholesky factorization (POTRS).");
577
578 // Compute the new direction vectors P_ = Z_ + P_ * beta
579 Teuchos::RCP<MV> Pnew = MVT::CloneCopy( *Z_ );
580 MVT::MvTimesMatAddMv(one, *P_, beta, one, *Pnew);
581 P_ = Pnew;
582
583 // Compute orthonormal block of new direction vectors.
584 rank = ortho_->normalize( *P_, Teuchos::null );
586 (rank != blockSize_, CGIterationOrthoFailure,
587 prefix << "Failed to compute block of orthonormal direction vectors.");
588
589 } // end while (sTest_->checkStatus(this) != Passed)
590 }
591
592} // namespace Belos
593
594#endif /* BELOS_BLOCK_CG_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.
Templated virtual class for providing orthogonalization/orthonormalization methods with matrix-based ...
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.
Collection of types and exceptions used within the Belos solvers.
void initialize()
Initialize the solver with the initial vectors from the linear problem or random data.
Teuchos::RCP< CGIterationStateBase< ScalarType, MV > > getState() const
Get the current state of the linear solver.
void setDoCondEst(bool)
Sets whether or not to store the diagonal for condition estimation.
const LinearProblem< ScalarType, MV, OP > & getProblem() const
Get a constant reference to the linear problem.
Teuchos::ArrayView< MagnitudeType > getDiag()
Gets the diagonal for condition estimation (NOT_IMPLEMENTED)
virtual ~BlockCGIter()=default
Destructor.
Teuchos::ScalarTraits< ScalarType > SCT
void resetNumIters(int iter=0)
Reset the iteration count.
void setState(Teuchos::RCP< CGIterationStateBase< ScalarType, MV > > state)
Teuchos::ArrayView< MagnitudeType > getOffDiag()
Gets the off-diagonal for condition estimation (NOT_IMPLEMENTED)
int getNumIters() const
Get the current iteration count.
bool isInitialized()
States whether the solver has been initialized or not.
int getBlockSize() const
Get the block size to be used by the iterative solver in solving this linear problem.
Teuchos::RCP< const MV > getNativeResiduals(std::vector< MagnitudeType > *) const
Get the norms of the residuals native to the solver.
Teuchos::RCP< MV > getCurrentUpdate() const
Get the current update to the linear system.
Stub implementation of BlockCGIter, for ScalarType types for which Teuchos::LAPACK does NOT have a va...
OperatorTraits< ScalarType, MV, OP > OPT
Teuchos::RCP< const MV > getNativeResiduals(std::vector< MagnitudeType > *) const
BlockCGIter(const Teuchos::RCP< LinearProblem< ScalarType, MV, OP > > &, const Teuchos::RCP< OutputManager< ScalarType > > &, const Teuchos::RCP< StatusTest< ScalarType, MV, OP > > &, const Teuchos::RCP< MatOrthoManager< ScalarType, MV, OP > > &, Teuchos::ParameterList &)
SCT::magnitudeType MagnitudeType
void resetNumIters(int iter=0)
Reset the iteration count to iter.
void setBlockSize(int blockSize)
Set the blocksize to be used by the iterative solver in solving this linear problem.
int getNumIters() const
Get the current iteration count.
void iterate()
This method performs linear solver iterations until the status test indicates the need to stop or an ...
void setState(Teuchos::RCP< CGIterationStateBase< ScalarType, MV > > state)
void initialize()
Initialize the solver with the initial vectors from the linear problem or random data.
void initializeCG(Teuchos::RCP< BlockCGIterationState< ScalarType, MV > >, Teuchos::RCP< MV >)
const LinearProblem< ScalarType, MV, OP > & getProblem() const
Get a constant reference to the linear problem.
int getBlockSize() const
Get the blocksize to be used by the iterative solver in solving this linear problem.
Teuchos::RCP< MV > getCurrentUpdate() const
Get the current update to the linear system.
Teuchos::RCP< CGIterationStateBase< ScalarType, MV > > getState() const
Get the current state of the linear solver.
Teuchos::ScalarTraits< ScalarType > SCT
bool isInitialized()
States whether the solver has been initialized or not.
void setDoCondEst(bool val)
Sets whether or not to store the diagonal for condition estimation.
MultiVecTraits< ScalarType, MV > MVT
Structure to contain pointers to BlockCGIteration state variables.
virtual ~BlockCGIterationState()=default
void initialize(Teuchos::RCP< const MV > tmp, int _numVectors)
bool matches(Teuchos::RCP< const MV > tmp, int _numVectors=1) const
BlockCGIterationState(Teuchos::RCP< const MV > tmp)
CGIterateFailure is thrown when the CGIteration object is unable to compute the next iterate in the C...
CGIterationLAPACKFailure is thrown when a nonzero return value is passed back from an LAPACK routine.
CGIterationOrthoFailure is thrown when the CGIteration object is unable to compute independent direct...
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)
virtual bool matches(Teuchos::RCP< const MV > tmp, int _numVectors=1) const
Teuchos::RCP< MV > Z
The current preconditioned residual.
Teuchos::RCP< MV > AP
The matrix A applied to current decent direction vector.
Type traits class that says whether Teuchos::LAPACK has a valid implementation for the given ScalarTy...
Alternative run-time polymorphic interface for operators.
Operator()
Default constructor (does nothing).

Generated for Belos by doxygen 1.9.8