Belos Version of the Day
Loading...
Searching...
No Matches
BelosBlockFGmresIter.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_FGMRES_ITER_HPP
11#define BELOS_BLOCK_FGMRES_ITER_HPP
12
17#include "BelosConfigDefs.hpp"
18#include "BelosTypes.hpp"
20
24#include "BelosStatusTest.hpp"
28
29#include "Teuchos_BLAS.hpp"
30#include "Teuchos_ScalarTraits.hpp"
31#include "Teuchos_ParameterList.hpp"
32#include "Teuchos_TimeMonitor.hpp"
33
34#include <vector>
35
49namespace Belos {
50
51template<class ScalarType, class MV, class OP, class DM>
52class BlockFGmresIter : virtual public GmresIteration<ScalarType,MV,OP,DM> {
53
54 public:
55
56 //
57 // Convenience typedefs
58 //
62 typedef Teuchos::ScalarTraits<ScalarType> SCT;
63 typedef typename SCT::magnitudeType MagnitudeType;
64
66
67
78 const Teuchos::RCP<OutputManager<ScalarType> > &printer,
79 const Teuchos::RCP<StatusTest<ScalarType,MV,OP,DM> > &tester,
80 const Teuchos::RCP<MatOrthoManager<ScalarType,MV,OP,DM> > &ortho,
81 Teuchos::ParameterList &params );
82
84 virtual ~BlockFGmresIter() {};
86
87
89
90
112 void iterate();
113
136
145
155 state.curDim = curDim_;
156 state.V = V_;
157 state.Z = Z_;
158 state.H = H_;
159 state.R = R_;
160 state.z = z_;
161 return state;
162 }
163
165
166
168
169
171 int getNumIters() const { return iter_; }
172
174 void resetNumIters( int iter = 0 ) { iter_ = iter; }
175
178 Teuchos::RCP<const MV> getNativeResiduals( std::vector<MagnitudeType> *norms ) const;
179
181
186 Teuchos::RCP<MV> getCurrentUpdate() const;
187
189
192 void updateLSQR( int dim = -1 );
193
195 int getCurSubspaceDim() const {
196 if (!initialized_) return 0;
197 return curDim_;
198 };
199
201 int getMaxSubspaceDim() const { return blockSize_*numBlocks_; }
202
204
205
207
208
210 const LinearProblem<ScalarType,MV,OP,DM>& getProblem() const { return *lp_; }
211
213 int getBlockSize() const { return blockSize_; }
214
216 void setBlockSize(int blockSize) { setSize( blockSize, numBlocks_ ); }
217
219 int getNumBlocks() const { return numBlocks_; }
220
222 void setNumBlocks(int numBlocks) { setSize( blockSize_, numBlocks ); }
223
230 void setSize(int blockSize, int numBlocks);
231
233 bool isInitialized() { return initialized_; }
234
236
237 private:
238
239 //
240 // Internal methods
241 //
243 void setStateSize();
244
245 //
246 // Classes inputed through constructor that define the linear problem to be solved.
247 //
248 const Teuchos::RCP<LinearProblem<ScalarType,MV,OP,DM> > lp_;
249 const Teuchos::RCP<OutputManager<ScalarType> > om_;
250 const Teuchos::RCP<StatusTest<ScalarType,MV,OP,DM> > stest_;
251 const Teuchos::RCP<OrthoManager<ScalarType,MV,DM> > ortho_;
252
253 //
254 // Algorithmic parameters
255 //
256 // blockSize_ is the solver block size.
257 // It controls the number of vectors added to the basis on each iteration.
258 int blockSize_;
259 // numBlocks_ is the size of the allocated space for the Krylov basis, in blocks.
260 int numBlocks_;
261
262 // Storage for QR factorization of the least squares system.
263 std::vector<ScalarType> beta, sn;
264 std::vector<MagnitudeType> cs;
265
266 //
267 // Current solver state
268 //
269 // initialized_ specifies that the basis vectors have been initialized and the iterate() routine
270 // is capable of running; _initialize is controlled by the initialize() member method
271 // For the implications of the state of initialized_, please see documentation for initialize()
272 bool initialized_;
273
274 // stateStorageInitialized_ specified that the state storage has be initialized to the current
275 // blockSize_ and numBlocks_. This initialization may be postponed if the linear problem was
276 // generated without the right-hand side or solution vectors.
277 bool stateStorageInitialized_;
278
279 // keepHessenberg_ specifies that the upper Hessenberg matrix should be stored separately
280 // from the QR-factored least squares system (R_). When false, H_ and R_ point to the
281 // same object and only the QR-rotated form is available via getState().
282 bool keepHessenberg_;
283
284 // Current subspace dimension, and number of iterations performed.
285 int curDim_, iter_;
286
287 //
288 // State Storage
289 //
290 Teuchos::RCP<MV> V_;
291 Teuchos::RCP<MV> Z_;
292 //
293 // Projected matrices
294 // H_ : Projected matrix from the Krylov factorization AV = VH + FE^T
295 //
296 Teuchos::RCP<DM> H_;
297 //
298 // QR decomposition of Projected matrices for solving the least squares system HY = B.
299 // R_: Upper triangular reduction of H
300 // z_: Q applied to right-hand side of the least squares system
301 Teuchos::RCP<DM> R_;
302 Teuchos::RCP<DM> z_;
303};
304
306 // Constructor.
307 template<class ScalarType, class MV, class OP, class DM>
310 const Teuchos::RCP<OutputManager<ScalarType> > &printer,
311 const Teuchos::RCP<StatusTest<ScalarType,MV,OP,DM> > &tester,
312 const Teuchos::RCP<MatOrthoManager<ScalarType,MV,OP,DM> > &ortho,
313 Teuchos::ParameterList &params ):
314 lp_(problem),
315 om_(printer),
316 stest_(tester),
317 ortho_(ortho),
318 blockSize_(0),
319 numBlocks_(0),
320 initialized_(false),
321 stateStorageInitialized_(false),
322 keepHessenberg_(false),
323 curDim_(0),
324 iter_(0)
325 {
326 // Find out whether we are saving the Hessenberg matrix separately from R.
327 if (om_->isVerbosity(Debug))
328 keepHessenberg_ = true;
329 else
330 keepHessenberg_ = params.get("Keep Hessenberg", false);
331
332 // Get the maximum number of blocks allowed for this Krylov subspace
334 ! params.isParameter ("Num Blocks"), std::invalid_argument,
335 "Belos::BlockFGmresIter::constructor: mandatory parameter 'Num Blocks' is not specified.");
336 const int nb = params.get<int> ("Num Blocks");
337
338 // Set the block size and allocate data.
339 const int bs = params.get ("Block Size", 1);
340 setSize (bs, nb);
341 }
342
344 // Set the block size and make necessary adjustments.
345 template <class ScalarType, class MV, class OP, class DM>
347 {
348 // This routine only allocates space; it doesn't not perform any computation
349 // any change in size will invalidate the state of the solver.
350
351 TEUCHOS_TEST_FOR_EXCEPTION(numBlocks <= 0 || blockSize <= 0, std::invalid_argument, "Belos::BlockFGmresIter::setSize was passed a non-positive argument.");
352 if (blockSize == blockSize_ && numBlocks == numBlocks_) {
353 // do nothing
354 return;
355 }
356
357 if (blockSize!=blockSize_ || numBlocks!=numBlocks_)
358 stateStorageInitialized_ = false;
359
360 blockSize_ = blockSize;
361 numBlocks_ = numBlocks;
362
363 initialized_ = false;
364 curDim_ = 0;
365
366 // Use the current blockSize_ and numBlocks_ to initialize the state storage.
367 setStateSize();
368
369 }
370
372 // Setup the state storage.
373 template <class ScalarType, class MV, class OP, class DM>
375 {
376 using Teuchos::RCP;
377 using Teuchos::rcp;
378
379 if (! stateStorageInitialized_) {
380 // Check if there is any multivector to clone from.
381 RCP<const MV> lhsMV = lp_->getLHS();
382 RCP<const MV> rhsMV = lp_->getRHS();
383 if (lhsMV == Teuchos::null && rhsMV == Teuchos::null) {
384 stateStorageInitialized_ = false;
385 return;
386 }
387 else {
389 // blockSize*numBlocks dependent
390 //
391 int newsd = blockSize_*(numBlocks_+1);
392
393 if (blockSize_==1) {
394 cs.resize (newsd);
395 sn.resize (newsd);
396 }
397 else {
398 beta.resize (newsd);
399 }
400
401 // Initialize the state storage
403 blockSize_ * static_cast<ptrdiff_t> (numBlocks_) > MVT::GetGlobalLength (*rhsMV),
404 std::invalid_argument, "Belos::BlockFGmresIter::setStateSize(): "
405 "Cannot generate a Krylov basis with dimension larger the operator!");
406
407 // If the subspace has not be initialized before, generate it using the LHS or RHS from lp_.
408 if (V_ == Teuchos::null) {
409 // Get the multivector that is not null.
410 RCP<const MV> tmp = (rhsMV != Teuchos::null) ? rhsMV : lhsMV;
412 tmp == Teuchos::null, std::invalid_argument,
413 "Belos::BlockFGmresIter::setStateSize(): "
414 "linear problem does not specify multivectors to clone from.");
415 V_ = MVT::Clone (*tmp, newsd);
416 }
417 else {
418 // Generate V_ by cloning itself ONLY if more space is needed.
419 if (MVT::GetNumberVecs (*V_) < newsd) {
420 RCP<const MV> tmp = V_;
421 V_ = MVT::Clone (*tmp, newsd);
422 }
423 }
424
425 if (Z_ == Teuchos::null) {
426 // Get the multivector that is not null.
427 RCP<const MV> tmp = (rhsMV != Teuchos::null) ? rhsMV : lhsMV;
429 tmp == Teuchos::null, std::invalid_argument,
430 "Belos::BlockFGmresIter::setStateSize(): "
431 "linear problem does not specify multivectors to clone from.");
432 Z_ = MVT::Clone (*tmp, newsd);
433 }
434 else {
435 // Generate Z_ by cloning itself ONLY if more space is needed.
436 if (MVT::GetNumberVecs (*Z_) < newsd) {
437 RCP<const MV> tmp = Z_;
438 Z_ = MVT::Clone (*tmp, newsd);
439 }
440 }
441
442 // R_ holds the QR-factored least squares system. Always allocated.
443 if (R_ == Teuchos::null) {
444 R_ = DMT::Create(newsd, newsd-blockSize_);
445 }
446 else {
447 DMT::Reshape(*R_, newsd, newsd - blockSize_);
448 }
449
450 // H_ holds the raw (pre-QR) upper Hessenberg matrix.
451 // When keepHessenberg_ is false, H_ and R_ point to the same object
452 // (matching BlockGmresIter behavior).
453 if (keepHessenberg_) {
454 if (H_ == Teuchos::null) {
455 H_ = DMT::Create(newsd, newsd-blockSize_);
456 }
457 else {
458 DMT::Reshape(*H_, newsd, newsd - blockSize_);
459 }
460 }
461 else {
462 H_ = R_;
463 }
464
465 // Generate z_ only if it doesn't exist, otherwise resize it.
466 if (z_ == Teuchos::null) {
467 z_ = DMT::Create(newsd, blockSize_);
468 }
469 else {
470 DMT::Reshape(*z_, newsd, blockSize_);
471 }
472
473 // State storage has now been initialized.
474 stateStorageInitialized_ = true;
475 }
476 }
477 }
478
479
480 template <class ScalarType, class MV, class OP, class DM>
481 Teuchos::RCP<MV>
483 {
484 Teuchos::RCP<MV> currentUpdate = Teuchos::null;
485 if (curDim_ == 0) {
486 // If this is the first iteration of the Arnoldi factorization,
487 // then there is no update, so return Teuchos::null.
488 return currentUpdate;
489 }
490 else {
491 const ScalarType zero = Teuchos::ScalarTraits<ScalarType>::zero ();
492 const ScalarType one = Teuchos::ScalarTraits<ScalarType>::one ();
493 Teuchos::BLAS<int,ScalarType> blas;
494
495 currentUpdate = MVT::Clone (*Z_, blockSize_);
496
497 // Make a view and then copy the RHS of the least squares problem. DON'T OVERWRITE IT!
498 DMT::SyncDeviceToHost( *z_ );
499 DMT::SyncDeviceToHost( *H_ );
500
501 Teuchos::RCP<DM> y = DMT::SubviewCopy(*z_, curDim_, blockSize_);
502
503 // Solve the least squares problem.
504 blas.TRSM (Teuchos::LEFT_SIDE, Teuchos::UPPER_TRI, Teuchos::NO_TRANS,
505 Teuchos::NON_UNIT_DIAG, curDim_, blockSize_, one,
506 DMT::GetConstRawHostPtr(*R_), DMT::GetStride(*R_),
507 DMT::GetRawHostPtr(*y), DMT::GetStride(*y));
508
509 // Make sure the result goes back to the device
510 DMT::SyncHostToDevice( *y );
511
512 // Compute the current update.
513 std::vector<int> index (curDim_);
514 for (int i = 0; i < curDim_; ++i) {
515 index[i] = i;
516 }
517 Teuchos::RCP<const MV> Zjp1 = MVT::CloneView (*Z_, index);
518 MVT::MvTimesMatAddMv (one, *Zjp1, *y, zero, *currentUpdate);
519 }
520 return currentUpdate;
521 }
522
523
524 template <class ScalarType, class MV, class OP, class DM>
525 Teuchos::RCP<const MV>
527 getNativeResiduals (std::vector<MagnitudeType> *norms) const
528 {
529 // NOTE: Make sure the incoming std::vector is the correct size!
530 if (norms != NULL && (int)norms->size() < blockSize_) {
531 norms->resize (blockSize_);
532 }
533
534 if (norms != NULL) {
535 Teuchos::BLAS<int, ScalarType> blas;
536 DMT::SyncDeviceToHost( *z_ );
537 for (int j = 0; j < blockSize_; ++j) {
538 (*norms)[j] = blas.NRM2 (blockSize_, &DMT::Value(*z_, curDim_, j), 1);
539 }
540 }
541
542 // FGmres does not return a residual (multi)vector.
543 return Teuchos::null;
544 }
545
546
547 template <class ScalarType, class MV, class OP, class DM>
550 {
551 using Teuchos::RCP;
552 using Teuchos::rcp;
553 using std::endl;
554
555 // Initialize the state storage if it isn't already.
556 if (! stateStorageInitialized_) {
557 setStateSize ();
558 }
559
561 ! stateStorageInitialized_, std::invalid_argument,
562 "Belos::BlockFGmresIter::initialize(): Cannot initialize state storage!");
563
564 // NOTE: In BlockFGmresIter, V and Z are required!!! Inconsistent
565 // multivectors widths and lengths will not be tolerated, and will
566 // be treated with exceptions.
567 const char errstr[] = "Belos::BlockFGmresIter::initialize(): The given "
568 "multivectors must have a consistent length and width.";
569
570 if (! newstate.V.is_null () && ! newstate.z.is_null ()) {
571
572 // initialize V_,z_, and curDim_
573
575 MVT::GetGlobalLength(*newstate.V) != MVT::GetGlobalLength(*V_),
576 std::invalid_argument, errstr );
578 MVT::GetNumberVecs(*newstate.V) < blockSize_,
579 std::invalid_argument, errstr );
581 newstate.curDim > blockSize_*(numBlocks_+1),
582 std::invalid_argument, errstr );
583
584 curDim_ = newstate.curDim;
585 const int lclDim = MVT::GetNumberVecs(*newstate.V);
586
587 // check size of Z
589 DMT::GetNumRows(*newstate.z) < curDim_ || DMT::GetNumCols(*newstate.z) < blockSize_,
590 std::invalid_argument, errstr);
591
592 // copy basis vectors from newstate into V
593 if (newstate.V != V_) {
594 // only copy over the first block and print a warning.
595 if (curDim_ == 0 && lclDim > blockSize_) {
596 std::ostream& warn = om_->stream (Warnings);
597 warn << "Belos::BlockFGmresIter::initialize(): the solver was "
598 << "initialized with a kernel of " << lclDim << endl
599 << "The block size however is only " << blockSize_ << endl
600 << "The last " << lclDim - blockSize_
601 << " vectors will be discarded." << endl;
602 }
603 std::vector<int> nevind (curDim_ + blockSize_);
604 for (int i = 0; i < curDim_ + blockSize_; ++i) {
605 nevind[i] = i;
606 }
607 RCP<const MV> newV = MVT::CloneView (*newstate.V, nevind);
608 RCP<MV> lclV = MVT::CloneViewNonConst (*V_, nevind);
609 MVT::Assign(*newV, *lclV);
610
611 // done with local pointers
612 lclV = Teuchos::null;
613 }
614
615 // put data into z_, make sure old information is not still hanging around.
616 if (newstate.z != z_) {
617 DMT::PutScalar(*z_);
618 RCP<const DM> newZ = DMT::SubviewConst(*newstate.z, curDim_ + blockSize_, blockSize_);
619 RCP<DM> lclz = DMT::Subview(*z_, curDim_ + blockSize_, blockSize_);
620 DMT::Assign(*lclz, *newZ);
621 lclz = Teuchos::null; // done with local pointers
622 }
623 }
624 else {
626 newstate.V == Teuchos::null,std::invalid_argument,
627 "Belos::BlockFGmresIter::initialize(): BlockFGmresStateIterState does not have initial kernel V_0.");
628
630 newstate.z == Teuchos::null,std::invalid_argument,
631 "Belos::BlockFGmresIter::initialize(): BlockFGmresStateIterState does not have initial norms z_0.");
632 }
633
634 // the solver is initialized
635 initialized_ = true;
636 }
637
638
639 template <class ScalarType, class MV, class OP, class DM>
641 {
642 using Teuchos::RCP;
643 using Teuchos::rcp;
644
645 // Allocate/initialize data structures
646 if (initialized_ == false) {
647 initialize();
648 }
649
650 // Compute the current search dimension.
651 const int searchDim = blockSize_ * numBlocks_;
652
653 // Iterate until the status test tells us to stop.
654 // Raise an exception if a computed block is not full rank.
655 while (stest_->checkStatus (this) != Passed && curDim_+blockSize_ <= searchDim) {
656 ++iter_;
657
658 // F can be found at the curDim_ block, but the next block is at curDim_ + blockSize_.
659 const int lclDim = curDim_ + blockSize_;
660
661 // Get the current part of the basis.
662 std::vector<int> curind (blockSize_);
663 for (int i = 0; i < blockSize_; ++i) {
664 curind[i] = lclDim + i;
665 }
666 RCP<MV> Vnext = MVT::CloneViewNonConst (*V_, curind);
667
668 // Get a view of the previous vectors.
669 // This is used for orthogonalization and for computing V^H K H.
670 for (int i = 0; i < blockSize_; ++i) {
671 curind[i] = curDim_ + i;
672 }
673 RCP<const MV> Vprev = MVT::CloneView (*V_, curind);
674 RCP<MV> Znext = MVT::CloneViewNonConst (*Z_, curind);
675
676 // Compute the next (multi)vector in the Krylov basis: Znext = M*Vprev
677 lp_->applyRightPrec (*Vprev, *Znext);
678 Vprev = Teuchos::null;
679
680 // Compute the next (multi)vector in the Krylov basis: Vnext = A*Znext
681 lp_->applyOp (*Znext, *Vnext);
682 Znext = Teuchos::null;
683
684 // Remove all previous Krylov basis vectors from Vnext
685 // Get a view of all the previous vectors
686 std::vector<int> prevind (lclDim);
687 for (int i = 0; i < lclDim; ++i) {
688 prevind[i] = i;
689 }
690 Vprev = MVT::CloneView (*V_, prevind);
691 Teuchos::Array<RCP<const MV> > AVprev (1, Vprev);
692
693 // Get a view of the part of the Hessenberg matrix needed to hold the ortho coeffs.
694 // Ortho always writes into H_ (the raw Hessenberg).
695 RCP<DM> subH = DMT::Subview(*H_, lclDim, blockSize_, 0, curDim_);
696 Teuchos::Array<RCP<DM> > AsubH;
697 AsubH.append (subH);
698
699 // Get a view of the part of the Hessenberg matrix needed to hold the norm coeffs.
700 RCP<DM> subH2 = DMT::Subview(*H_, blockSize_, blockSize_, lclDim, curDim_);
701 const int rank = ortho_->projectAndNormalize (*Vnext, AsubH, subH2, AVprev);
703 rank != blockSize_, GmresIterationOrthoFailure,
704 "Belos::BlockFGmresIter::iterate(): After orthogonalization, the new "
705 "basis block does not have full rank. It contains " << blockSize_
706 << " vector" << (blockSize_ != 1 ? "s" : "")
707 << ", but its rank is " << rank << ".");
708
709 // If keeping the Hessenberg separately, copy the new columns into R_
710 // before updateLSQR() overwrites them with the QR factorization.
711 if (keepHessenberg_) {
712 // Copy over the orthogonalization coefficients.
713 RCP<DM> subR = DMT::Subview(*R_,lclDim,blockSize_,0,curDim_ );
714 DMT::Assign(*subR,*subH);
715
716 // Copy over the lower diagonal block of the Hessenberg matrix.
717 RCP<DM> subR2 = DMT::Subview(*R_,blockSize_,blockSize_,lclDim,curDim_ );
718 DMT::Assign(*subR2,*subH2);
719 }
720
721 //
722 // V has been extended, and H has been extended.
723 //
724 // Update the QR factorization of the upper Hessenberg matrix (applied to R_).
725 //
726 updateLSQR ();
727 //
728 // Update basis dim and release all pointers.
729 //
730 Vnext = Teuchos::null;
731 curDim_ += blockSize_;
732 } // end while (statusTest == false)
733 }
734
735
736 template<class ScalarType, class MV, class OP, class DM>
738 {
739 typedef Teuchos::ScalarTraits<ScalarType> STS;
740 typedef Teuchos::ScalarTraits<MagnitudeType> STM;
741
742 const ScalarType zero = STS::zero ();
743 const ScalarType two = (STS::one () + STS::one());
745 Teuchos::BLAS<int, ScalarType> blas;
746
747 // Get correct dimension based on input 'dim'. Remember that
748 // orthogonalization failures result in an exit before
749 // updateLSQR() is called. Therefore, it is possible that dim ==
750 // curDim_.
751 int curDim = curDim_;
752 if (dim >= curDim_ && dim < getMaxSubspaceDim ()) {
753 curDim = dim;
754 }
755
756 // Apply previous transformations, and compute new transformation
757 // to reduce upper Hessenberg system to upper triangular form.
758 // The type of transformation we use depends the block size. We
759 // use Givens rotations for a block size of 1, and Householder
760 // reflectors otherwise.
761 DMT::SyncDeviceToHost( *H_ );
762 DMT::SyncDeviceToHost( *z_ );
763
764 if (blockSize_ == 1) {
765
766 // QR factorization of upper Hessenberg matrix using Givens rotations
767 for (int i = 0; i < curDim; ++i) {
768 // Apply previous Givens rotations to new column of Hessenberg matrix
769 blas.ROT (1, &DMT::Value(*R_,i, curDim), 1, &DMT::Value(*R_,i+1, curDim), 1, &cs[i], &sn[i]);
770 }
771
772 // Calculate new Givens rotation
773 blas.ROTG (&DMT::Value(*R_,curDim, curDim), &DMT::Value(*R_,curDim+1, curDim), &cs[curDim], &sn[curDim]);
774 DMT::Value(*R_,curDim+1, curDim) = zero;
775
776 // Update RHS w/ new transformation
777 blas.ROT (1, &DMT::Value(*z_,curDim,0), 1, &DMT::Value(*z_,curDim+1,0), 1, &cs[curDim], &sn[curDim]);
778 }
779 else {
780 // QR factorization of least-squares system using Householder reflectors.
781 for (int j = 0; j < blockSize_; ++j) {
782 // Apply previous Householder reflectors to new block of Hessenberg matrix
783 for (int i = 0; i < curDim + j; ++i) {
784 sigma = blas.DOT (blockSize_, &DMT::Value(*R_,i+1,i), 1, &DMT::Value(*R_,i+1,curDim+j), 1);
785 sigma += DMT::ValueConst(*R_,i,curDim+j);
786 sigma *= beta[i];
787 blas.AXPY (blockSize_, ScalarType(-sigma), &DMT::Value(*R_,i+1,i), 1, &DMT::Value(*R_,i+1,curDim+j), 1);
788 DMT::Value(*R_,i,curDim+j) -= sigma;
789 }
790
791 // Compute new Householder reflector
792 const int maxidx = blas.IAMAX (blockSize_+1, &DMT::Value(*R_,curDim+j,curDim+j), 1);
793 maxelem = DMT::ValueConst(*R_,curDim + j + maxidx - 1, curDim + j);
794 for (int i = 0; i < blockSize_ + 1; ++i) {
795 DMT::Value(*R_,curDim+j+i,curDim+j) /= maxelem;
796 }
797 sigma = blas.DOT (blockSize_, &DMT::Value(*R_,curDim + j + 1, curDim + j), 1,
798 &DMT::Value(*R_,curDim + j + 1, curDim + j), 1);
799 if (sigma == zero) {
800 beta[curDim + j] = zero;
801 } else {
802 mu = STS::squareroot (DMT::Value(*R_,curDim+j,curDim+j)*DMT::Value(*R_,curDim+j,curDim+j)+sigma);
803 if (STS::real (DMT::Value(*R_,curDim + j, curDim + j)) < STM::zero ()) {
804 vscale = DMT::ValueConst(*R_,curDim+j,curDim+j) - mu;
805 } else {
806 vscale = -sigma / (DMT::Value(*R_,curDim+j, curDim+j) + mu);
807 }
808 beta[curDim+j] = two * vscale * vscale / (sigma + vscale*vscale);
809 DMT::Value(*R_,curDim+j, curDim+j) = maxelem*mu;
810 for (int i = 0; i < blockSize_; ++i) {
811 DMT::Value(*R_,curDim+j+1+i,curDim+j) /= vscale;
812 }
813 }
814
815 // Apply new Householder reflector to the right-hand side.
816 for (int i = 0; i < blockSize_; ++i) {
817 sigma = blas.DOT (blockSize_, &DMT::Value(*R_,curDim+j+1,curDim+j),
818 1, &DMT::Value(*z_,curDim+j+1,i), 1);
819 sigma += DMT::ValueConst(*z_,curDim+j,i);
820 sigma *= beta[curDim+j];
821 blas.AXPY (blockSize_, ScalarType(-sigma), &DMT::Value(*R_,curDim+j+1,curDim+j),
822 1, &DMT::Value(*z_,curDim+j+1,i), 1);
823 DMT::Value(*z_,curDim+j,i) -= sigma;
824 }
825 }
826 } // end if (blockSize_ == 1)
827
828 DMT::SyncHostToDevice( *H_ );
829 DMT::SyncHostToDevice( *z_ );
830
831 // If the least-squares problem is updated wrt "dim" then update curDim_.
832 if (dim >= curDim_ && dim < getMaxSubspaceDim ()) {
833 curDim_ = dim + blockSize_;
834 }
835 } // end updateLSQR()
836
837} // namespace Belos
838
839#endif /* BELOS_BLOCK_FGMRES_ITER_HPP */
Belos header file which uses auto-configuration information to include necessary C++ headers.
Pure virtual base class which augments the basic interface for a Gmres linear solver iteration.
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 block flexible GMRES iteration, where a block Krylov subspace is constructe...
GmresIterationState< ScalarType, MV, DM > getState() const
Get the current state of the linear solver.
void setBlockSize(int blockSize)
Set the blocksize.
const LinearProblem< ScalarType, MV, OP, DM > & getProblem() const
Get a constant reference to the linear problem.
bool isInitialized()
States whether the solver has been initialized or not.
void setSize(int blockSize, int numBlocks)
Set the blocksize and number of blocks to be used by the iterative solver in solving this linear prob...
Teuchos::RCP< MV > getCurrentUpdate() const
Get the current update to the linear system.
void updateLSQR(int dim=-1)
Method for updating QR factorization of upper Hessenberg matrix.
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.
MultiVecTraits< ScalarType, MV, DM > MVT
virtual ~BlockFGmresIter()
Destructor.
void initializeGmres(GmresIterationState< ScalarType, MV, DM > &newstate)
Initialize the solver to an iterate, providing a complete state.
void resetNumIters(int iter=0)
Reset the iteration count.
void setNumBlocks(int numBlocks)
Set the maximum number of blocks used by the iterative solver.
int getNumIters() const
Get the current iteration count.
int getNumBlocks() const
Get the maximum number of blocks used by the iterative solver in solving this linear problem.
int getMaxSubspaceDim() const
Get the maximum dimension allocated for the search subspace.
OperatorTraits< ScalarType, MV, OP > OPT
Teuchos::RCP< const MV > getNativeResiduals(std::vector< MagnitudeType > *norms) const
Get the norms of the residuals native to the solver.
void iterate()
This method performs block FGmres iterations until the status test indicates the need to stop or an e...
SCT::magnitudeType MagnitudeType
Teuchos::ScalarTraits< ScalarType > SCT
int getCurSubspaceDim() const
Get the dimension of the search subspace used to generate the current solution to the linear problem.
DenseMatTraits< ScalarType, DM > DMT
BlockFGmresIter(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< MatOrthoManager< ScalarType, MV, OP, DM > > &ortho, Teuchos::ParameterList &params)
BlockFGmresIter constructor with linear problem, solver utilities, and parameter list of solver optio...
GmresIterationOrthoFailure is thrown when the GmresIteration object is unable to compute independent ...
Alternative run-time polymorphic interface for operators.
Operator()
Default constructor (does nothing).

Generated for Belos by doxygen 1.9.8