Belos Version of the Day
Loading...
Searching...
No Matches
BelosBiCGStabIter.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_BICGSTAB_ITER_HPP
11#define BELOS_BICGSTAB_ITER_HPP
12
17#include "BelosConfigDefs.hpp"
18#include "BelosTypes.hpp"
19#include "BelosCGIteration.hpp"
20
24#include "BelosStatusTest.hpp"
27
28#include "Teuchos_ScalarTraits.hpp"
29#include "Teuchos_ParameterList.hpp"
30#include "Teuchos_TimeMonitor.hpp"
31
43namespace Belos {
44
46
47
52 template <class ScalarType, class MV>
54
56 Teuchos::RCP<const MV> R;
57
59 Teuchos::RCP<const MV> Rhat;
60
62 Teuchos::RCP<const MV> P;
63
65 Teuchos::RCP<const MV> V;
66
67 std::vector<ScalarType> rho_old, alpha, omega;
68
69 BiCGStabIterationState() : R(Teuchos::null), Rhat(Teuchos::null),
70 P(Teuchos::null), V(Teuchos::null)
71 {
72 rho_old.clear();
73 alpha.clear();
74 omega.clear();
75 }
76 };
77
78 template<class ScalarType, class MV, class OP, class DM>
79 class BiCGStabIter : virtual public Iteration<ScalarType,MV,OP,DM> {
80
81 public:
82
83 //
84 // Convenience typedefs
85 //
88 typedef Teuchos::ScalarTraits<ScalarType> SCT;
89 typedef typename SCT::magnitudeType MagnitudeType;
90 typedef Teuchos::ScalarTraits<MagnitudeType> MT;
91
93
94
101 const Teuchos::RCP<OutputManager<ScalarType> > &printer,
102 const Teuchos::RCP<StatusTest<ScalarType,MV,OP,DM> > &tester,
103 Teuchos::ParameterList &params );
104
106 virtual ~BiCGStabIter() {};
108
109
111
112
126 void iterate();
127
149
158
168 state.R = R_;
169 state.Rhat = Rhat_;
170 state.P = P_;
171 state.V = V_;
172 state.rho_old = rho_old_;
173 state.alpha = alpha_;
174 state.omega = omega_;
175 return state;
176 }
177
179
180
182
183
185 int getNumIters() const { return iter_; }
186
188 void resetNumIters( int iter = 0 ) { iter_ = iter; }
189
192 // amk TODO: are the residuals actually being set? What is a native residual?
193 Teuchos::RCP<const MV> getNativeResiduals( std::vector<MagnitudeType> * /* norms */ ) const { return R_; }
194
196
198 // amk TODO: what is this supposed to be doing?
199 Teuchos::RCP<MV> getCurrentUpdate() const { return Teuchos::null; }
200
202 bool breakdownDetected() { return breakdown_; }
203
205
207
208
210 const LinearProblem<ScalarType,MV,OP,DM>& getProblem() const { return *lp_; }
211
213 int getBlockSize() const { return 1; }
214
217 TEUCHOS_TEST_FOR_EXCEPTION(blockSize!=1,std::invalid_argument,
218 "Belos::BiCGStabIter::setBlockSize(): Cannot use a block size that is not one.");
219 }
220
222 bool isInitialized() { return initialized_; }
223
225
226 private:
227
228 void axpy(const ScalarType alpha, const MV & A,
229 const std::vector<ScalarType> beta, const MV& B, MV& mv, bool minus=false);
230
231 //
232 // Classes inputed through constructor that define the linear problem to be solved.
233 //
234 const Teuchos::RCP<LinearProblem<ScalarType,MV,OP,DM> > lp_;
235 const Teuchos::RCP<OutputManager<ScalarType> > om_;
236 const Teuchos::RCP<StatusTest<ScalarType,MV,OP,DM> > stest_;
237
238 //
239 // Algorithmic parameters
240 //
241 // numRHS_ is the current number of linear systems being solved.
242 int numRHS_;
243
244 //
245 // Current solver state
246 //
247 // initialized_ specifies that the basis vectors have been initialized and the iterate() routine
248 // is capable of running; _initialize is controlled by the initialize() member method
249 // For the implications of the state of initialized_, please see documentation for initialize()
250 bool initialized_;
251
252 // Breakdown has been observed for at least one of the linear systems
253 bool breakdown_;
254
255 // Current number of iterations performed.
256 int iter_;
257
258 //
259 // State Storage
260 //
261 // Initial residual
262 Teuchos::RCP<MV> Rhat_;
263 //
264 // Residual
265 Teuchos::RCP<MV> R_;
266 //
267 // Direction vector 1
268 Teuchos::RCP<MV> P_;
269 //
270 // Operator applied to preconditioned direction vector 1
271 Teuchos::RCP<MV> V_;
272 //
273 std::vector<ScalarType> rho_old_, alpha_, omega_;
274 };
275
277 // Constructor.
278 template<class ScalarType, class MV, class OP, class DM>
280 const Teuchos::RCP<OutputManager<ScalarType> > &printer,
281 const Teuchos::RCP<StatusTest<ScalarType,MV,OP,DM> > &tester,
282 Teuchos::ParameterList &/* params */ ):
283 lp_(problem),
284 om_(printer),
285 stest_(tester),
286 numRHS_(0),
287 initialized_(false),
288 breakdown_(false),
289 iter_(0)
290 {
291 }
292
293
295 // Initialize this iteration object
296 template<class ScalarType, class MV, class OP, class DM>
298 {
299 // Check if there is any multivector to clone from.
300 Teuchos::RCP<const MV> lhsMV = lp_->getCurrLHSVec();
301 Teuchos::RCP<const MV> rhsMV = lp_->getCurrRHSVec();
302 TEUCHOS_TEST_FOR_EXCEPTION((lhsMV==Teuchos::null && rhsMV==Teuchos::null),std::invalid_argument,
303 "Belos::BiCGStabIter::initialize(): Cannot initialize state storage!");
304
305 // Get the multivector that is not null.
306 Teuchos::RCP<const MV> tmp = ( (rhsMV!=Teuchos::null)? rhsMV: lhsMV );
307
308 // Get the number of right-hand sides we're solving for now.
309 int numRHS = MVT::GetNumberVecs(*tmp);
310 numRHS_ = numRHS;
311
312 // Initialize the state storage
313 // If the subspace has not be initialized before or has changed sizes, generate it using the LHS or RHS from lp_.
314 if (Teuchos::is_null(R_) || MVT::GetNumberVecs(*R_)!=numRHS_) {
315 R_ = MVT::Clone( *tmp, numRHS_ );
316 Rhat_ = MVT::Clone( *tmp, numRHS_ );
317 P_ = MVT::Clone( *tmp, numRHS_ );
318 V_ = MVT::Clone( *tmp, numRHS_ );
319
320 rho_old_.resize(numRHS_);
321 alpha_.resize(numRHS_);
322 omega_.resize(numRHS_);
323 }
324
325 // Reset breakdown to false before initializing iteration
326 breakdown_ = false;
327
328 // NOTE: In BiCGStabIter R_, the initial residual, is required!!!
329 //
330 std::string errstr("Belos::BlockPseudoCGIter::initialize(): Specified multivectors must have a consistent length and width.");
331
332 // Create convenience variable for one.
333 const ScalarType one = SCT::one();
334
335 if (!Teuchos::is_null(newstate.R)) {
336
337 TEUCHOS_TEST_FOR_EXCEPTION( MVT::GetGlobalLength(*newstate.R) != MVT::GetGlobalLength(*R_),
338 std::invalid_argument, errstr );
339 TEUCHOS_TEST_FOR_EXCEPTION( MVT::GetNumberVecs(*newstate.R) != numRHS_,
340 std::invalid_argument, errstr );
341
342 // Copy residual vectors from newstate into R
343 if (newstate.R != R_) {
344 // Assigned by the new state
345 MVT::Assign(*newstate.R, *R_);
346 }
347 else {
348 // Computed
349 lp_->computeCurrResVec(R_.get());
350 }
351
352 // Set Rhat
353 if (!Teuchos::is_null(newstate.Rhat) && newstate.Rhat != Rhat_) {
354 // Assigned by the new state
355 MVT::Assign(*newstate.Rhat, *Rhat_);
356 }
357 else {
358 // Set to be the initial residual
359 MVT::Assign(*R_, *Rhat_);
360 }
361
362 // Set V
363 if (!Teuchos::is_null(newstate.V) && newstate.V != V_) {
364 // Assigned by the new state
365 MVT::Assign(*newstate.V, *V_);
366 }
367 else {
368 // Initial V = 0
369 MVT::MvInit(*V_);
370 }
371
372 // Set P
373 if (!Teuchos::is_null(newstate.P) && newstate.P != P_) {
374 // Assigned by the new state
375 MVT::Assign(*newstate.P, *P_);
376 }
377 else {
378 // Initial P = 0
379 MVT::MvInit(*P_);
380 }
381
382 // Set rho_old
383 if (newstate.rho_old.size () == static_cast<size_t> (numRHS_)) {
384 // Assigned by the new state
385 rho_old_ = newstate.rho_old;
386 }
387 else {
388 // Initial rho = 1
389 rho_old_.assign(numRHS_,one);
390 }
391
392 // Set alpha
393 if (newstate.alpha.size() == static_cast<size_t> (numRHS_)) {
394 // Assigned by the new state
395 alpha_ = newstate.alpha;
396 }
397 else {
398 // Initial rho = 1
399 alpha_.assign(numRHS_,one);
400 }
401
402 // Set omega
403 if (newstate.omega.size() == static_cast<size_t> (numRHS_)) {
404 // Assigned by the new state
405 omega_ = newstate.omega;
406 }
407 else {
408 // Initial rho = 1
409 omega_.assign(numRHS_,one);
410 }
411
412 }
413 else {
414
415 TEUCHOS_TEST_FOR_EXCEPTION(Teuchos::is_null(newstate.R),std::invalid_argument,
416 "Belos::BiCGStabIter::initialize(): BiCGStabStateIterState does not have initial residual.");
417 }
418
419 // The solver is initialized
420 initialized_ = true;
421 }
422
423
425 // Iterate until the status test informs us we should stop.
426 template<class ScalarType, class MV, class OP, class DM>
428 {
429 using Teuchos::RCP;
430
431 //
432 // Allocate/initialize data structures
433 //
434 if (initialized_ == false) {
435 initialize();
436 }
437
438 // Allocate memory for scalars.
439 int i=0;
440 std::vector<ScalarType> rho_new( numRHS_ ), beta( numRHS_ );
441 std::vector<ScalarType> rhatV( numRHS_ ), tT( numRHS_ ), tS( numRHS_ );
442
443 // Create convenience variable for one.
444 const ScalarType one = SCT::one();
445
446 // TODO: We may currently be using more space than is required
448
449 RCP<MV> Y, Z, S, T;
450 S = MVT::Clone( *R_, numRHS_ );
451 T = MVT::Clone( *R_, numRHS_ );
452 if (lp_->isLeftPrec() || lp_->isRightPrec()) {
453 Y = MVT::Clone( *R_, numRHS_ );
454 Z = MVT::Clone( *R_, numRHS_ );
455 }
456 else {
457 Y = P_;
458 Z = S;
459 }
460
461 // Get the current solution std::vector.
462 Teuchos::RCP<MV> X = lp_->getCurrLHSVec();
463
465 // Iterate until the status test tells us to stop.
466 //
467 while (stest_->checkStatus(this) != Passed && !breakdown_) {
468
469 // Increment the iteration
470 iter_++;
471
472 // rho_new = <R_, Rhat_>
473 MVT::MvDot(*R_,*Rhat_,rho_new);
474
475 // beta = ( rho_new / rho_old ) (alpha / omega )
476 // TODO: None of these loops are currently threaded
477 for(i=0; i<numRHS_; i++) {
478 // Catch breakdown in rho_old here, since
479 // it is just rho_new from the previous iteration.
480 if (SCT::magnitude(rho_new[i]) < MT::sfmin())
481 breakdown_ = true;
482
483 beta[i] = (rho_new[i] / rho_old_[i]) * (alpha_[i] / omega_[i]);
484 }
485
486 // p = r + beta (p - omega v)
487 // TODO: Is it safe to call MvAddMv with A or B = mv?
488 // TODO: Not all of these things have to be part of the state
489 axpy(one, *P_, omega_, *V_, *P_, true); // p = p - omega v
490 axpy(one, *R_, beta, *P_, *P_); // p = r + beta (p - omega v)
491
492 // y = K\p, unless K does not exist
493 // TODO: There may be a more efficient way to apply the preconditioners
494 if(lp_->isLeftPrec()) {
495 if(lp_->isRightPrec()) {
496 if(leftPrecVec == Teuchos::null) {
497 leftPrecVec = MVT::Clone( *R_, numRHS_ );
498 }
499 lp_->applyLeftPrec(*P_,*leftPrecVec);
500 lp_->applyRightPrec(*leftPrecVec,*Y);
501 }
502 else {
503 lp_->applyLeftPrec(*P_,*Y);
504 }
505 }
506 else if(lp_->isRightPrec()) {
507 lp_->applyRightPrec(*P_,*Y);
508 }
509
510 // v = Ay
511 lp_->applyOp(*Y,*V_);
512
513 // alpha = rho_new / <Rhat, V>
514 MVT::MvDot(*V_,*Rhat_,rhatV);
515 for(i=0; i<numRHS_; i++) {
516 if (SCT::magnitude(rhatV[i]) < MT::sfmin())
517 {
518 breakdown_ = true;
519 return;
520 }
521 else
522 alpha_[i] = rho_new[i] / rhatV[i];
523 }
524
525 // s = r - alpha v
526 axpy(one, *R_, alpha_, *V_, *S, true);
527
528 // z = K\s, unless K does not exist
529 if(lp_->isLeftPrec()) {
530 if(lp_->isRightPrec()) {
531 if(leftPrecVec == Teuchos::null) {
532 leftPrecVec = MVT::Clone( *R_, numRHS_ );
533 }
534 lp_->applyLeftPrec(*S,*leftPrecVec);
535 lp_->applyRightPrec(*leftPrecVec,*Z);
536 }
537 else {
538 lp_->applyLeftPrec(*S,*Z);
539 }
540 }
541 else if(lp_->isRightPrec()) {
542 lp_->applyRightPrec(*S,*Z);
543 }
544
545 // t = Az
546 lp_->applyOp(*Z,*T);
547
548 // omega = <K1\t,K1\s> / <K1\t,K1\t>
549 if(lp_->isLeftPrec()) {
550 if(leftPrecVec == Teuchos::null) {
551 leftPrecVec = MVT::Clone( *R_, numRHS_ );
552 }
553 if(leftPrecVec2 == Teuchos::null) {
554 leftPrecVec2 = MVT::Clone( *R_, numRHS_ );
555 }
556 lp_->applyLeftPrec(*T,*leftPrecVec2);
557 MVT::MvDot(*leftPrecVec2,*leftPrecVec2,tT);
558 MVT::MvDot(*leftPrecVec,*leftPrecVec2,tS);
559 }
560 else {
561 MVT::MvDot(*T,*T,tT);
562 MVT::MvDot(*S,*T,tS);
563 }
564 for(i=0; i<numRHS_; i++) {
565 if (SCT::magnitude(tT[i]) < MT::sfmin())
566 {
567 omega_[i] = SCT::zero();
568 breakdown_ = true;
569 }
570 else
571 omega_[i] = tS[i] / tT[i];
572 }
573
574 // x = x + alpha y + omega z
575 axpy(one, *X, alpha_, *Y, *X); // x = x + alpha y
576 axpy(one, *X, omega_, *Z, *X); // x = x + alpha y + omega z
577
578 // r = s - omega t
579 axpy(one, *S, omega_, *T, *R_, true);
580
581 // Update rho_old
582 rho_old_ = rho_new;
583 } // end while (sTest_->checkStatus(this) != Passed)
584 }
585
586
588 // Iterate until the status test informs us we should stop.
589 template<class ScalarType, class MV, class OP, class DM>
590 void BiCGStabIter<ScalarType,MV,OP,DM>::axpy(const ScalarType alpha, const MV & A,
591 const std::vector<ScalarType> beta, const MV& B, MV& mv, bool minus)
592 {
593 Teuchos::RCP<const MV> A1, B1;
594 Teuchos::RCP<MV> mv1;
595 std::vector<int> index(1);
596
597 for(int i=0; i<numRHS_; i++) {
598 index[0] = i;
599 A1 = MVT::CloneView(A,index);
600 B1 = MVT::CloneView(B,index);
601 mv1 = MVT::CloneViewNonConst(mv,index);
602 if(minus) {
603 MVT::MvAddMv(alpha,*A1,-beta[i],*B1,*mv1);
604 }
605 else {
606 MVT::MvAddMv(alpha,*A1,beta[i],*B1,*mv1);
607 }
608 }
609 }
610
611} // end Belos namespace
612
613#endif /* BELOS_BICGSTAB_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.
This class implements the pseudo-block BiCGStab iteration, where the basic BiCGStab algorithm is perf...
void iterate()
This method performs BiCGStab iterations on each linear system until the status test indicates the ne...
BiCGStabIterationState< ScalarType, MV > getState() const
Get the current state of the linear solver.
bool isInitialized()
States whether the solver has been initialized or not.
MultiVecTraits< ScalarType, MV, DM > MVT
BiCGStabIter(const Teuchos::RCP< LinearProblem< ScalarType, MV, OP, DM > > &problem, const Teuchos::RCP< OutputManager< ScalarType > > &printer, const Teuchos::RCP< StatusTest< ScalarType, MV, OP, DM > > &tester, Teuchos::ParameterList &params)
BiCGStabIter constructor with linear problem, solver utilities, and parameter list of solver options.
int getNumIters() const
Get the current iteration count.
virtual ~BiCGStabIter()
Destructor.
Teuchos::RCP< MV > getCurrentUpdate() const
Get the current update to the linear system.
Teuchos::ScalarTraits< MagnitudeType > MT
const LinearProblem< ScalarType, MV, OP, DM > & getProblem() const
Get a constant reference to the linear problem.
void resetNumIters(int iter=0)
Reset the iteration count.
bool breakdownDetected()
Has breakdown been detected in any linear system.
Teuchos::ScalarTraits< ScalarType > SCT
void setBlockSize(int blockSize)
Set the blocksize.
int getBlockSize() const
Get the blocksize to be used by the iterative solver in solving this linear problem.
void initialize()
Initialize the solver with the initial vectors from the linear problem or random data.
OperatorTraits< ScalarType, MV, OP > OPT
void initializeBiCGStab(BiCGStabIterationState< ScalarType, MV > &newstate)
Initialize the solver to an iterate, providing a complete state.
Teuchos::RCP< const MV > getNativeResiduals(std::vector< MagnitudeType > *) const
Get the norms of the residuals native to the solver.
SCT::magnitudeType MagnitudeType
Alternative run-time polymorphic interface for operators.
Operator()
Default constructor (does nothing).
Structure to contain pointers to BiCGStabIteration state variables.
std::vector< ScalarType > omega
Teuchos::RCP< const MV > R
The current residual.
Teuchos::RCP< const MV > Rhat
The initial residual.
std::vector< ScalarType > rho_old
Teuchos::RCP< const MV > P
The first decent direction vector.
std::vector< ScalarType > alpha
Teuchos::RCP< const MV > V
A * M * the first decent direction vector.

Generated for Belos by doxygen 1.9.8