Belos Version of the Day
Loading...
Searching...
No Matches
BelosTFQMRIter.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// This file contains an implementation of the TFQMR iteration
11// for solving non-Hermitian linear systems of equations Ax = b,
12// where b is a single-vector and x is the corresponding solution.
13//
14// The implementation is a slight modification on the TFQMR iteration
15// found in Saad's "Iterative Methods for Sparse Linear Systems".
16//
17
18#ifndef BELOS_TFQMR_ITER_HPP
19#define BELOS_TFQMR_ITER_HPP
20
28#include "BelosConfigDefs.hpp"
29#include "BelosIteration.hpp"
30#include "BelosTypes.hpp"
31
34#include "BelosStatusTest.hpp"
37
38#include "Teuchos_ScalarTraits.hpp"
39#include "Teuchos_ParameterList.hpp"
40#include "Teuchos_TimeMonitor.hpp"
41
53namespace Belos {
54
59 template <class ScalarType, class MV>
61
63 Teuchos::RCP<const MV> R;
64 Teuchos::RCP<const MV> W;
65 Teuchos::RCP<const MV> U;
66 Teuchos::RCP<const MV> Rtilde;
67 Teuchos::RCP<const MV> D;
68 Teuchos::RCP<const MV> V;
69
70 TFQMRIterState() : R(Teuchos::null), W(Teuchos::null), U(Teuchos::null),
71 Rtilde(Teuchos::null), D(Teuchos::null), V(Teuchos::null)
72 {}
73 };
74
75
77
78
85 class TFQMRIterateFailure : public BelosError {public:
87 {}};
88
90
91 template<class ScalarType, class MV, class OP, class DM>
92 class TFQMRIter : public Iteration<ScalarType,MV,OP,DM> {
93 public:
94 //
95 // Convenience typedefs
96 //
99 typedef Teuchos::ScalarTraits<ScalarType> SCT;
100 typedef typename SCT::magnitudeType MagnitudeType;
101
103
104
107 const Teuchos::RCP<OutputManager<ScalarType> > &printer,
108 const Teuchos::RCP<StatusTest<ScalarType,MV,OP,DM> > &tester,
109 Teuchos::ParameterList &params );
110
112 virtual ~TFQMRIter() {};
114
115
117
118
129 void iterate();
130
153
162
172 state.R = R_;
173 state.W = W_;
174 state.U = U_;
175 state.Rtilde = Rtilde_;
176 state.D = D_;
177 state.V = V_;
178 state.solnUpdate = solnUpdate_;
179 return state;
180 }
181
183
184
186
187
189 int getNumIters() const { return iter_; }
190
192 void resetNumIters( int iter = 0 ) { iter_ = iter; }
193
196 Teuchos::RCP<const MV> getNativeResiduals( std::vector<MagnitudeType> *norms ) const;
197
199
202 Teuchos::RCP<MV> getCurrentUpdate() const { return solnUpdate_; }
203
205
206
208
209
211 const LinearProblem<ScalarType,MV,OP,DM>& getProblem() const { return *lp_; }
212
214 int getBlockSize() const { return 1; }
215
218 TEUCHOS_TEST_FOR_EXCEPTION(blockSize!=1,std::invalid_argument,
219 "Belos::TFQMRIter::setBlockSize(): Cannot use a block size that is not one.");
220 }
221
223 bool isInitialized() { return initialized_; }
224
226
227
228 private:
229
230 //
231 // Internal methods
232 //
234 void setStateSize();
235
236 //
237 // Classes inputed through constructor that define the linear problem to be solved.
238 //
239 const Teuchos::RCP<LinearProblem<ScalarType,MV,OP,DM> > lp_;
240 const Teuchos::RCP<OutputManager<ScalarType> > om_;
241 const Teuchos::RCP<StatusTest<ScalarType,MV,OP,DM> > stest_;
242
243 //
244 // Algorithmic parameters
245 //
246
247 // Storage for QR factorization of the least squares system.
248 std::vector<ScalarType> alpha_, rho_, rho_old_;
249 std::vector<MagnitudeType> tau_, cs_, theta_;
250
251 //
252 // Current solver state
253 //
254 // initialized_ specifies that the basis vectors have been initialized and the iterate() routine
255 // is capable of running; _initialize is controlled by the initialize() member method
256 // For the implications of the state of initialized_, please see documentation for initialize()
257 bool initialized_;
258
259 // stateStorageInitialized_ specifies that the state storage has be initialized to the current
260 // blockSize_ and numBlocks_. This initialization may be postponed if the linear problem was
261 // generated without the right-hand side or solution vectors.
262 bool stateStorageInitialized_;
263
264 // Current subspace dimension, and number of iterations performed.
265 int iter_;
266
267 //
268 // State Storage
269 //
270 Teuchos::RCP<MV> R_;
271 Teuchos::RCP<MV> W_;
272 Teuchos::RCP<MV> U_, AU_;
273 Teuchos::RCP<MV> Rtilde_;
274 Teuchos::RCP<MV> D_;
275 Teuchos::RCP<MV> V_;
276 Teuchos::RCP<MV> solnUpdate_;
277 };
278
279
280 //
281 // Implementation
282 //
283
285 // Constructor.
286 template <class ScalarType, class MV, class OP, class DM>
288 const Teuchos::RCP<OutputManager<ScalarType> > &printer,
289 const Teuchos::RCP<StatusTest<ScalarType,MV,OP,DM> > &tester,
290 Teuchos::ParameterList &/* params */
291 ) :
292 lp_(problem),
293 om_(printer),
294 stest_(tester),
295 alpha_(1),
296 rho_(1),
297 rho_old_(1),
298 tau_(1),
299 cs_(1),
300 theta_(1),
301 initialized_(false),
302 stateStorageInitialized_(false),
303 iter_(0)
304 {
305 }
306
308 // Compute native residual from TFQMR recurrence.
309 template <class ScalarType, class MV, class OP, class DM>
310 Teuchos::RCP<const MV>
312 {
313 MagnitudeType one = Teuchos::ScalarTraits<MagnitudeType>::one();
314 if (normvec)
315 (*normvec)[0] = Teuchos::ScalarTraits<MagnitudeType>::squareroot( 2*iter_ + one )*tau_[0];
316
317 return Teuchos::null;
318 }
319
320
322 // Setup the state storage.
323 template <class ScalarType, class MV, class OP, class DM>
325 {
326 if (!stateStorageInitialized_) {
327
328 // Check if there is any multivector to clone from.
329 Teuchos::RCP<const MV> lhsMV = lp_->getLHS();
330 Teuchos::RCP<const MV> rhsMV = lp_->getRHS();
331 if (lhsMV == Teuchos::null && rhsMV == Teuchos::null) {
332 stateStorageInitialized_ = false;
333 return;
334 }
335 else {
336
337 // Initialize the state storage
338 // If the subspace has not be initialized before, generate it using the LHS or RHS from lp_.
339 if (R_ == Teuchos::null) {
340 // Get the multivector that is not null.
341 Teuchos::RCP<const MV> tmp = ( (rhsMV!=Teuchos::null)? rhsMV: lhsMV );
342 TEUCHOS_TEST_FOR_EXCEPTION(tmp == Teuchos::null,std::invalid_argument,
343 "Belos::TFQMRIter::setStateSize(): linear problem does not specify multivectors to clone from.");
344 R_ = MVT::Clone( *tmp, 1 );
345 D_ = MVT::Clone( *tmp, 1 );
346 V_ = MVT::Clone( *tmp, 1 );
347 solnUpdate_ = MVT::Clone( *tmp, 1 );
348 }
349
350 // State storage has now been initialized.
351 stateStorageInitialized_ = true;
352 }
353 }
354 }
355
357 // Initialize this iteration object
358 template <class ScalarType, class MV, class OP, class DM>
360 {
361 // Initialize the state storage if it isn't already.
362 if (!stateStorageInitialized_)
363 setStateSize();
364
365 TEUCHOS_TEST_FOR_EXCEPTION(!stateStorageInitialized_,std::invalid_argument,
366 "Belos::TFQMRIter::initialize(): Cannot initialize state storage!");
367
368 // NOTE: In TFQMRIter R_, the initial residual, is required!!!
369 //
370 std::string errstr("Belos::TFQMRIter::initialize(): Specified multivectors must have a consistent length and width.");
371
372 // Create convenience variables for zero and one.
373 const MagnitudeType MTzero = Teuchos::ScalarTraits<MagnitudeType>::zero();
374
375 if (newstate.R != Teuchos::null) {
376
377 TEUCHOS_TEST_FOR_EXCEPTION( MVT::GetGlobalLength(*newstate.R) != MVT::GetGlobalLength(*R_),
378 std::invalid_argument, errstr );
379 TEUCHOS_TEST_FOR_EXCEPTION( MVT::GetNumberVecs(*newstate.R) != 1,
380 std::invalid_argument, errstr );
381
382 // Copy basis vectors from newstate into V
383 if (newstate.R != R_) {
384 // copy over the initial residual (unpreconditioned).
385 MVT::Assign( *newstate.R, *R_ );
386 }
387
388 // Compute initial vectors
389 // Initially, they are set to the preconditioned residuals
390 //
391 W_ = MVT::CloneCopy( *R_ );
392 U_ = MVT::CloneCopy( *R_ );
393 Rtilde_ = MVT::CloneCopy( *R_ );
394 MVT::MvInit( *D_ );
395 MVT::MvInit( *solnUpdate_ );
396 // Multiply the current residual by Op and store in V_
397 // V_ = Op * R_
398 //
399 lp_->apply( *U_, *V_ );
400 AU_ = MVT::CloneCopy( *V_ );
401 //
402 // Compute initial scalars: theta, eta, tau, rho_old
403 //
404 theta_[0] = MTzero;
405 MVT::MvNorm( *R_, tau_ ); // tau = ||r_0||
406 MVT::MvDot( *R_, *Rtilde_, rho_old_ ); // rho = (r_tilde, r0)
407 }
408 else {
409
410 TEUCHOS_TEST_FOR_EXCEPTION(newstate.R == Teuchos::null,std::invalid_argument,
411 "Belos::TFQMRIter::initialize(): TFQMRIterState does not have initial residual.");
412 }
413
414 // The solver is initialized
415 initialized_ = true;
416 }
417
418
420 // Iterate until the status test informs us we should stop.
421 template <class ScalarType, class MV, class OP, class DM>
423 {
424 //
425 // Allocate/initialize data structures
426 //
427 if (initialized_ == false) {
428 initialize();
429 }
430
431 // Create convenience variables for zero and one.
432 const ScalarType STone = Teuchos::ScalarTraits<ScalarType>::one();
433 const MagnitudeType MTone = Teuchos::ScalarTraits<MagnitudeType>::one();
434 const MagnitudeType MTzero = Teuchos::ScalarTraits<MagnitudeType>::zero();
435 const ScalarType STzero = Teuchos::ScalarTraits<ScalarType>::zero();
436 ScalarType eta = STzero, beta = STzero;
437 //
438 // Start executable statements.
439 //
440 // Get the current solution vector.
441 Teuchos::RCP<MV> cur_soln_vec = lp_->getCurrLHSVec();
442
443 // Check that the current solution vector only has one column.
445 "Belos::TFQMRIter::iterate(): current linear system has more than one vector!" );
446
447
449 // Iterate until the status test tells us to stop.
450 //
451 while (stest_->checkStatus(this) != Passed) {
452
453 for (int iIter=0; iIter<2; iIter++)
454 {
455 //
456 //--------------------------------------------------------
457 // Compute the new alpha if we need to
458 //--------------------------------------------------------
459 //
460 if (iIter == 0) {
461 MVT::MvDot( *V_, *Rtilde_, alpha_ ); // alpha = rho / (r_tilde, v)
462 alpha_[0] = rho_old_[0]/alpha_[0];
463 }
464 //
465 //--------------------------------------------------------
466 // Update w.
467 // w = w - alpha*Au
468 //--------------------------------------------------------
469 //
470 MVT::MvAddMv( STone, *W_, -alpha_[0], *AU_, *W_ );
471 //
472 //--------------------------------------------------------
473 // Update d.
474 // d = u + (theta^2/alpha)eta*d
475 //--------------------------------------------------------
476 //
477 MVT::MvAddMv( STone, *U_, (theta_[0]*theta_[0]/alpha_[0])*eta, *D_, *D_ );
478 //
479 //--------------------------------------------------------
480 // Update u if we need to.
481 // u = u - alpha*v
482 //
483 // Note: This is usually computed with alpha (above), but we're trying be memory efficient.
484 //--------------------------------------------------------
485 //
486 if (iIter == 0) {
487 // Compute new U.
488 MVT::MvAddMv( STone, *U_, -alpha_[0], *V_, *U_ );
489
490 // Update Au for the next iteration.
491 lp_->apply( *U_, *AU_ );
492 }
493 //
494 //--------------------------------------------------------
495 // Compute the new theta, c, eta, tau; i.e. the update to the least squares solution.
496 //--------------------------------------------------------
497 //
498 MVT::MvNorm( *W_, theta_ ); // theta = ||w|| / tau
499 theta_[0] /= tau_[0];
500 // cs = 1.0 / sqrt(1.0 + theta^2)
501 cs_[0] = MTone / Teuchos::ScalarTraits<MagnitudeType>::squareroot(MTone + theta_[0]*theta_[0]);
502 tau_[0] *= theta_[0]*cs_[0]; // tau = tau * theta * cs
503 eta = cs_[0]*cs_[0]*alpha_[0]; // eta = cs^2 * alpha
504 //
505 //--------------------------------------------------------
506 // Update the solution.
507 // Don't update the linear problem object, may incur additional preconditioner application.
508 //--------------------------------------------------------
509 //
510 MVT::MvAddMv( STone, *solnUpdate_, eta, *D_, *solnUpdate_ );
511 //
512 //--------------------------------------------------------
513 // Check for breakdown before continuing.
514 //--------------------------------------------------------
515 if ( tau_[0] == MTzero ) {
516 break;
517 }
518 //
519 if (iIter == 1) {
520 //
521 //--------------------------------------------------------
522 // Compute the new rho, beta if we need to.
523 //--------------------------------------------------------
524 //
525 MVT::MvDot( *W_, *Rtilde_, rho_ ); // rho = (r_tilde, w)
526 beta = rho_[0]/rho_old_[0]; // beta = rho / rho_old
527 rho_old_[0] = rho_[0]; // rho_old = rho
528 //
529 //--------------------------------------------------------
530 // Update u, v, and Au if we need to.
531 // Note: We are updating v in two stages to be memory efficient
532 //--------------------------------------------------------
533 //
534 MVT::MvAddMv( STone, *W_, beta, *U_, *U_ ); // u = w + beta*u
535
536 // First stage of v update.
537 MVT::MvAddMv( STone, *AU_, beta, *V_, *V_ ); // v = Au + beta*v
538
539 // Update Au.
540 lp_->apply( *U_, *AU_ ); // Au = A*u
541
542 // Second stage of v update.
543 MVT::MvAddMv( STone, *AU_, beta, *V_, *V_ ); // v = Au + beta*v
544 }
545
546 }
547
548 // Increment the iteration
549 iter_++;
550
551 } // end while (sTest_->checkStatus(this) != Passed)
552 }
553
554} // namespace Belos
555//
556#endif // BELOS_TFQMR_ITER_HPP
557//
558// End of file BelosTFQMRIter.hpp
559
560
Belos header file which uses auto-configuration information to include necessary C++ headers.
Pure virtual base class which describes the basic interface to the linear solver iteration.
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.
Collection of types and exceptions used within the Belos solvers.
Parent class to all Belos exceptions.
Alternative run-time polymorphic interface for operators.
Operator()
Default constructor (does nothing).
This class implements the preconditioned transpose-free QMR algorithm for solving non-Hermitian linea...
void initialize()
Initialize the solver with the initial vectors from the linear problem or random data.
void iterate()
This method performs TFQMR iterations until the status test indicates the need to stop or an error oc...
TFQMRIterState< ScalarType, MV > getState() const
Get the current state of the linear solver.
virtual ~TFQMRIter()
Belos::TFQMRIter destructor.
int getNumIters() const
Get the current iteration count.
void initializeTFQMR(const TFQMRIterState< ScalarType, MV > &newstate)
Initialize the solver to an iterate, providing a complete state.
int getBlockSize() const
Get the blocksize to be used by the iterative solver in solving this linear problem.
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.
SCT::magnitudeType MagnitudeType
Teuchos::RCP< MV > getCurrentUpdate() const
Get the current update to the linear system.
OperatorTraits< ScalarType, MV, OP > OPT
const LinearProblem< ScalarType, MV, OP, DM > & getProblem() const
Get a constant reference to the linear problem.
MultiVecTraits< ScalarType, MV, DM > MVT
TFQMRIter(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)
Belos::TFQMRIter constructor.
void setBlockSize(int blockSize)
Set the blocksize.
void resetNumIters(int iter=0)
Reset the iteration count.
Teuchos::ScalarTraits< ScalarType > SCT
TFQMRIterateFailure is thrown when the TFQMRIter object is unable to compute the next iterate in the ...
TFQMRIterateFailure(const std::string &what_arg)
Structure to contain pointers to TFQMRIter state variables.
Teuchos::RCP< const MV > W
Teuchos::RCP< const MV > V
Teuchos::RCP< const MV > Rtilde
Teuchos::RCP< const MV > R
The current residual basis.
Teuchos::RCP< const MV > D
Teuchos::RCP< const MV > U

Generated for Belos by doxygen 1.9.8