Belos Version of the Day
Loading...
Searching...
No Matches
BelosBlockGCRODRIter.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_GCRODR_ITER_HPP
11#define BELOS_BLOCK_GCRODR_ITER_HPP
12
13
18#include "BelosConfigDefs.hpp"
19#include "BelosTypes.hpp"
20
24#include "BelosStatusTest.hpp"
27
28#include "Teuchos_BLAS.hpp"
29#include "Teuchos_SerialDenseMatrix.hpp"
30#include "Teuchos_SerialDenseVector.hpp"
31#include "Teuchos_ScalarTraits.hpp"
32#include "Teuchos_ParameterList.hpp"
33#include "Teuchos_TimeMonitor.hpp"
34
35// MLP
36#include <unistd.h>
37
52namespace Belos{
53
55
56
62 template <class ScalarType, class MV>
69 int curDim;
70
72 Teuchos::RCP<MV> V;
73
75 Teuchos::RCP<MV> U, C;
76
82 Teuchos::RCP<Teuchos::SerialDenseMatrix<int,ScalarType> > H;
83
86 Teuchos::RCP<Teuchos::SerialDenseMatrix<int,ScalarType> > B;
87
88 BlockGCRODRIterState() : curDim(0), V(Teuchos::null),
89 U(Teuchos::null), C(Teuchos::null),
90 H(Teuchos::null), B(Teuchos::null)
91 {}
92
93 };
94
96
97
98
100
101
115 public:
117 };
118
127 public:
129 };
130
132
133
134 template<class ScalarType, class MV, class OP, class DM = DefaultDenseMatrix<int,ScalarType> >
135 class BlockGCRODRIter : virtual public Iteration<ScalarType,MV,OP,DM> {
136 public:
137
138 //
139 //Convenience typedefs
140 //
143 typedef Teuchos::ScalarTraits<ScalarType> SCT;
144 typedef typename SCT::magnitudeType MagnitudeType;
145 typedef Teuchos::SerialDenseMatrix<int,ScalarType> SDM;
146 typedef Teuchos::SerialDenseVector<int,ScalarType> SDV;
147
149
150
160 const Teuchos::RCP<OutputManager<ScalarType> > &printer,
161 const Teuchos::RCP<StatusTest<ScalarType,MV,OP> > &tester,
162 const Teuchos::RCP<MatOrthoManager<ScalarType,MV,OP> > &ortho,
163 Teuchos::ParameterList &params );
164
166 virtual ~BlockGCRODRIter() {};
168
170
171
193 void iterate();
194
221
226
236 state.curDim = curDim_;
237 state.V = V_;
238 state.U = U_;
239 state.C = C_;
240 state.H = H_;
241 state.B = B_;
242 return state;
243 }
245
247
248
250 bool isInitialized(){ return initialized_;};
251
253 int getNumIters() const { return iter_; };
254
256 void resetNumIters( int iter = 0 ) { iter_ = iter; };
257
260 Teuchos::RCP<const MV> getNativeResiduals( std::vector<MagnitudeType> *norms ) const;
261
263
268 Teuchos::RCP<MV> getCurrentUpdate() const;
269
270
272
273
275
276
277
279 const LinearProblem<ScalarType,MV,OP,DM>& getProblem() const { return *lp_; };
280
282 int getNumBlocks() const { return numBlocks_; }
283
285 int getBlockSize() const { return blockSize_; };
286
288 int getCurSubspaceDim() const {
289 if (!initialized_) return 0;
290 return curDim_;
291 };
292
294 int getMaxSubspaceDim() const { return numBlocks_*blockSize_; };
295
297
298
300
301
302 void updateLSQR( int dim = -1);
303
305 void setBlockSize(int blockSize){ blockSize_ = blockSize; }
306
308 void setNumBlocks(int numBlocks) { setSize( recycledBlocks_, numBlocks ); };
309
312 // only call resize if size changed
313 if ( (recycledBlocks_ != recycledBlocks) || (numBlocks_ != numBlocks) ) {
314 recycledBlocks_ = recycledBlocks;
315 numBlocks_ = numBlocks;
316 cs_.resize( numBlocks_ );
317 sn_.resize( numBlocks_ );
318 Z_.shapeUninitialized( numBlocks_*blockSize_, blockSize_ );
319 }
320 }
321
323
324 private:
325
326 //
327 // Internal methods
328 //
329
330
331
332 //Classes inputed through constructor that define the linear problem to be solved
333 //
334 const Teuchos::RCP<LinearProblem<ScalarType,MV,OP,DM> > lp_;
335 const Teuchos::RCP<OutputManager<ScalarType> > om_;
336 const Teuchos::RCP<StatusTest<ScalarType,MV,OP> > stest_;
337 const Teuchos::RCP<OrthoManager<ScalarType,MV> > ortho_;
338
339 //
340 //Algorithmic Parameters
341 //
342
343 //numBlocks_ is the size of the allocated space for the Krylov basis, in blocks.
344 //blockSize_ is the number of columns in each block Krylov vector.
345 int numBlocks_, blockSize_;
346
347 //boolean vector indicating which right-hand sides we care about
348 //when we are testing residual norms. THIS IS NOT IMPLEMENTED. RIGHT NOW JUST
349 //SELECTS ALL RIGHT HANDS SIDES FOR NORM COMPUTATION.
350 std::vector<bool> trueRHSIndices_;
351
352 // recycledBlocks_ is the size of the allocated space for the recycled subspace, in vectors.
353 int recycledBlocks_;
354
355 // Storage for QR factorization of the least squares system.
356 std::vector<ScalarType> sn_;
357 std::vector<MagnitudeType> cs_;
358
359 //Storage for QR factorization of the least squares system if using Householder reflections
360 //Per block Krylov vector, we actually construct a 2*blockSize_ by 2*blockSize_ matrix which
361 //is the product of all Householder transformations for that block. This has been shown to yield
362 //speed ups without losing accuracy because we can apply previous Householder transformations
363 //with BLAS3 operations.
364 std::vector< SDM >House_;
365
366 //
367 //Current Solver State
368 //
369 //initialized_ specifies that the basis vectors have been initialized and the iterate() routine
370 //is capable of running; _initialize is controlled by the initialize() member method
371 //For the implications of the state of initialized_, please see documentation for initialize()
372 bool initialized_;
373
374 // Current subspace dimension, number of iterations performed, and number of iterations performed in this cycle.
375 int curDim_, iter_, lclIter_;
376
377 //
378 // Recycled Krylov Method Storage
379 //
380
381
383 Teuchos::RCP<MV> V_;
384
386 Teuchos::RCP<MV> U_, C_;
387
388
390
391
395 Teuchos::RCP<SDM > H_;
396
400 Teuchos::RCP<SDM > B_;
401
408 Teuchos::RCP<SDM> R_;
409
411 SDM Z_;
412
414
415 // File stream variables to use Mike Parks' Matlab output codes.
416 std::ofstream ofs;
417 char filename[30];
418
419 };//End BlockGCRODRIter Class Definition
420
422 //Constructor.
423 template<class ScalarType, class MV, class OP, class DM>
425 const Teuchos::RCP<OutputManager<ScalarType> > &printer,
426 const Teuchos::RCP<StatusTest<ScalarType,MV,OP> > &tester,
427 const Teuchos::RCP<MatOrthoManager<ScalarType,MV,OP> > &ortho,
428 Teuchos::ParameterList &params ):lp_(problem),
429 om_(printer), stest_(tester), ortho_(ortho) {
430 numBlocks_ = 0;
431 blockSize_ = 0;
432 recycledBlocks_ = 0;
433 initialized_ = false;
434 curDim_ = 0;
435 iter_ = 0;
436 lclIter_ = 0;
437 V_ = Teuchos::null;
438 U_ = Teuchos::null;
439 C_ = Teuchos::null;
440 H_ = Teuchos::null;
441 B_ = Teuchos::null;
442 R_ = Teuchos::null;
443 // Get the maximum number of blocks allowed for this Krylov subspace
444 TEUCHOS_TEST_FOR_EXCEPTION(!params.isParameter("Num Blocks"), std::invalid_argument, "Belos::BlockGCRODRIter::constructor: mandatory parameter \"Num Blocks\" is not specified.");
445 int nb = Teuchos::getParameter<int>(params, "Num Blocks");
446
447 TEUCHOS_TEST_FOR_EXCEPTION(!params.isParameter("Recycled Blocks"), std::invalid_argument,"Belos::BlockGCRODRIter::constructor: mandatory parameter \"Recycled Blocks\" is not specified.");
448 int rb = Teuchos::getParameter<int>(params, "Recycled Blocks");
449
450 TEUCHOS_TEST_FOR_EXCEPTION(nb <= 0, std::invalid_argument, "Belos::BlockGCRODRIter() was passed a non-positive argument for \"Num Blocks\".");
451 TEUCHOS_TEST_FOR_EXCEPTION(rb >= nb, std::invalid_argument, "Belos::BlockGCRODRIter() the number of recycled blocks is larger than the allowable subspace.");
452
453
454 int bs = Teuchos::getParameter<int>(params, "Block Size");
455
456 TEUCHOS_TEST_FOR_EXCEPTION(bs <= 0, std::invalid_argument, "Belos::BlockGCRODRIter() the block size was passed a non-postitive argument.");
457
458
459 numBlocks_ = nb;
460 recycledBlocks_ = rb;
461 blockSize_ = bs;
462
463 //INITIALIZE ENTRIES OF trueRHSIndices_ TO CHECK EVERY NORM FOR NOW. LATER, THE USER
464 //SHOULD SPECIFY WHICH RIGHT HAND SIDES ARE IMPORTANT FOR CONVERGENCE TESTING
465 trueRHSIndices_.resize(blockSize_);
466 int i;
467 for(i=0; i<blockSize_; i++){
468 trueRHSIndices_[i] = true;
469 }
470
471 //THIS MAKES SPACE FOR GIVENS ROTATIONS BUT IN REALITY WE NEED TO DO TESTING ON BLOCK SIZE
472 //AND CHOOSE BETWEEN GIVENS ROTATIONS AND HOUSEHOLDER TRANSFORMATIONS.
473 cs_.resize( numBlocks_+1 );
474 sn_.resize( numBlocks_+1 );
475 Z_.shapeUninitialized( (numBlocks_+1)*blockSize_,blockSize_ );
476
477 House_.resize(numBlocks_);
478
479 for(i=0; i<numBlocks_;i++){
480 House_[i].shapeUninitialized(2*blockSize_, 2*blockSize_);
481 }
482 }//End Constructor Definition
483
485 // Iterate until the status test informs us we should stop.
486 template <class ScalarType, class MV, class OP, class DM>
488 TEUCHOS_TEST_FOR_EXCEPTION( initialized_ == false, BlockGCRODRIterInitFailure,"Belos::BlockGCRODRIter::iterate(): GCRODRIter class not initialized." );
489
490// MLP
491//sleep(1);
492//std::cout << "Calling setSize" << std::endl;
493 // Force call to setsize to ensure internal storage is correct dimension
494 setSize( recycledBlocks_, numBlocks_ );
495
496 Teuchos::RCP<MV> Vnext;
497 Teuchos::RCP<const MV> Vprev;
498 std::vector<int> curind(blockSize_);
499
500 // z_ must be zeroed out in order to compute Givens rotations correctly
501 Z_.putScalar(0.0);
502
503 // Orthonormalize the new V_0
504 for(int i = 0; i<blockSize_; i++){curind[i] = i;};
505
506// MLP
507//sleep(1);
508//std::cout << "Calling normalize" << std::endl;
509 Vnext = MVT::CloneViewNonConst(*V_,curind);
510 //Orthonormalize Initial Columns
511 //Store orthogonalization coefficients in Z0
512 Teuchos::RCP<SDM > Z0 =
513 Teuchos::rcp( new SDM(blockSize_,blockSize_) );
514 int rank = ortho_->normalize(*Vnext,Z0);
515
516// MLP
517//sleep(1);
518//std::cout << "Assigning Z" << std::endl;
519 TEUCHOS_TEST_FOR_EXCEPTION(rank != blockSize_,BlockGCRODRIterOrthoFailure, "Belos::BlockGCRODRIter::iterate(): couldn't generate basis of full rank at the initial step.");
520 // Copy Z0 into the leading blockSize_ by blockSize_ block of Z_
521 Teuchos::RCP<SDM > Z_block = Teuchos::rcp( new SDM(Teuchos::View, Z_, blockSize_,blockSize_) );
522 Z_block->assign(*Z0);
523
524 std::vector<int> prevind(blockSize_*(numBlocks_ + 1));
525
527 // iterate until the status test tells us to stop.
528 //
529 // also break if the basis is full
530 //
531 while( (stest_->checkStatus(this) != Passed) && (curDim_+blockSize_-1) < (numBlocks_*blockSize_)) {
532 lclIter_++;
533 iter_++;
534//KMS
535//std::cout << "Iter=" << iter_ << std::endl << "lclIter=" << lclIter_ << std::endl;
536
537 int HFirstCol = curDim_-blockSize_;//First column of H we need view of
538 int HLastCol = HFirstCol + blockSize_-1 ;//last column of H we need a view of
539 int HLastOrthRow = HLastCol;//Last row of H we will put orthog coefficients in
540 int HFirstNormRow = HLastOrthRow + 1;//First row of H where normalization matrix goes
541//KMS
542//std::cout << "curDim_ = " << curDim_ << ", HFirstCol = " << HFirstCol << ", HLastCol = " << HLastCol <<", HLastOrthRow = " << HLastOrthRow << ", HFirstNormRow = " << HFirstNormRow << std::endl;
543 // Get next basis indices
544 for(int i = 0; i< blockSize_; i++){
545 curind[i] = curDim_ + i;
546 }
547 Vnext = MVT::CloneViewNonConst(*V_,curind);
548
549 //Get a view of the previous block Krylov vector.
550 //This is used for orthogonalization and for computing V^H K H
551 // Get next basis indices
552 for(int i = 0; i< blockSize_; i++){
553 curind[blockSize_ - 1 - i] = curDim_ - i - 1;
554 }
555 Vprev = MVT::CloneView(*V_,curind);
556 // Compute the next vector in the Krylov basis: Vnext = Op*Vprev
557 lp_->apply(*Vprev,*Vnext);
558 Vprev = Teuchos::null;
559
560 //First, remove the recycled subspace (C) from Vnext and put coefficients in B.
561
562 //Get a view of the matrix B and put the pointer into an array
563 //Put a pointer to C in another array
564 Teuchos::Array<Teuchos::RCP<const MV> > C(1, C_);
565
566 Teuchos::RCP<SDM >
567 subB = Teuchos::rcp( new SDM ( Teuchos::View,*B_,recycledBlocks_,blockSize_,0, HFirstCol ) );
568
569 Teuchos::Array<Teuchos::RCP<SDM > > AsubB;
570 AsubB.append( subB );
571 // Project out the recycled subspace.
572 ortho_->project( *Vnext, AsubB, C );
573 //Now, remove block Krylov Subspace from Vnext and store coefficients in H_ and R_
574
575 // Get a view of all the previous vectors
576 prevind.resize(curDim_);
577 for (int i=0; i<curDim_; i++) { prevind[i] = i; }
578 Vprev = MVT::CloneView(*V_,prevind);
579 Teuchos::Array<Teuchos::RCP<const MV> > AVprev(1, Vprev);
580
581 // Get a view of the part of the Hessenberg matrix needed to hold the ortho coeffs.
582 Teuchos::RCP<SDM> subH = Teuchos::rcp( new SDM ( Teuchos::View,*H_,curDim_,blockSize_,0,HFirstCol ) );
583 Teuchos::Array<Teuchos::RCP<SDM > > AsubH;
584 AsubH.append( subH );
585 // Get a view of the part of the Hessenberg matrix needed to hold the norm coeffs.
586 Teuchos::RCP<SDM > subR = Teuchos::rcp( new SDM ( Teuchos::View,*H_,blockSize_,blockSize_,HFirstNormRow,HFirstCol ) );
587 // Project out the previous Krylov vectors and normalize the next vector.
588 int rank = ortho_->projectAndNormalize(*Vnext,AsubH,subR,AVprev);
589
590 // Copy over the coefficients to R just in case we run into an error.
591 SDM subR2( Teuchos::View,*R_,(lclIter_+1)*blockSize_,blockSize_,0,HFirstCol);
592 SDM subH2( Teuchos::View,*H_,(lclIter_+1)*blockSize_,blockSize_,0,HFirstCol);
593 subR2.assign(subH2);
594
595 TEUCHOS_TEST_FOR_EXCEPTION(rank != blockSize_,BlockGCRODRIterOrthoFailure, "Belos::BlockGCRODRIter::iterate(): couldn't generate basis of full rank.");
596
597 // Update the QR factorization of the upper Hessenberg matrix
598 updateLSQR();
599
600 // Update basis dim
601 curDim_ = curDim_ + blockSize_;
602
603
604
605 }//end while(stest_->checkStatus(this) ~= Passed && curDim_+1 <= numBlocks_*blockSize_)
606
607 }//end iterate() defintition
608
610 //Initialize this iteration object.
611 template <class ScalarType, class MV, class OP, class DM>
613 if (newstate.V != Teuchos::null && newstate.H != Teuchos::null) {
614 curDim_ = newstate.curDim;
615 V_ = newstate.V;
616 U_ = newstate.U;
617 C_ = newstate.C;
618 H_ = newstate.H;
619 B_ = newstate.B;
620 lclIter_ = 0;//resets the count of local iterations for the new cycle
621 R_ = Teuchos::rcp(new SDM(H_->numRows(), H_->numCols() )); //R_ should look like H but point to separate memory
622
623 //All Householder product matrices start out as identity matrices.
624 //We construct an identity from which to copy.
625 SDM Identity(2*blockSize_, 2*blockSize_);
626 for(int i=0;i<2*blockSize_; i++){
627 Identity[i][i] = 1;
628 }
629 for(int i=0; i<numBlocks_;i++){
630 House_[i].assign(Identity);
631 }
632 }
633 else {
634 TEUCHOS_TEST_FOR_EXCEPTION(newstate.V == Teuchos::null,std::invalid_argument,"Belos::GCRODRIter::initialize(): BlockGCRODRIterState does not have V initialized.");
635 TEUCHOS_TEST_FOR_EXCEPTION(newstate.H == Teuchos::null,std::invalid_argument,"Belos::GCRODRIter::initialize(): BlockGCRODRIterState does not have H initialized.");
636 }
637 // the solver is initialized
638 initialized_ = true;
639 }//end initialize() defintition
640
642 //Get the native residuals stored in this iteration.
643 //This function will only compute the native residuals for
644 //right-hand sides we are interested in, as dictated by
645 //std::vector<int> trueRHSIndices_ (THIS IS NOT YET IMPLEMENTED. JUST GETS ALL RESIDUALS)
646 //A norm of -1 is entered for all residuals about which we do not care.
647 template <class ScalarType, class MV, class OP, class DM>
648 Teuchos::RCP<const MV>
650 {
651 //
652 // NOTE: Make sure the incoming std::vector is the correct size!
653 //
654 if (norms != NULL) {
655 if (static_cast<int> (norms->size()) < blockSize_) {
656 norms->resize( blockSize_ );
657 }
658 Teuchos::BLAS<int,ScalarType> blas;
659 for (int j=0; j<blockSize_; j++) {
660 if(trueRHSIndices_[j]){
661 (*norms)[j] = blas.NRM2( blockSize_, &Z_(curDim_-blockSize_+j, j), 1);
662 }
663 else{
664 (*norms)[j] = -1;
665 }
666 }
667 return Teuchos::null;
668 } else { // norms is NULL
669 // FIXME If norms is NULL, return residual vectors.
670 return Teuchos::null;
671 }
672 }//end getNativeResiduals() definition
673
675 //Get the current update from this subspace.
676 template <class ScalarType, class MV, class OP, class DM>
678 //
679 // If this is the first iteration of the Arnoldi factorization,
680 // there is no update, so return Teuchos::null.
681 //
682 Teuchos::RCP<MV> currentUpdate = Teuchos::null;
683//KMS if(curDim_==0) {
684 if(curDim_<=blockSize_) {
685 return currentUpdate;
686 }
687 else{
688 const ScalarType one = Teuchos::ScalarTraits<ScalarType>::one();
689 const ScalarType zero = Teuchos::ScalarTraits<ScalarType>::zero();
690 Teuchos::BLAS<int,ScalarType> blas;
691 currentUpdate = MVT::Clone( *V_, blockSize_ );
692 //
693 // Make a view and then copy the RHS of the least squares problem. DON'T OVERWRITE IT!
694 //
695 SDM Y( Teuchos::Copy, Z_, curDim_-blockSize_, blockSize_ );
696 Teuchos::RCP<SDM> Rtmp = Teuchos::rcp(new SDM(Teuchos::View, *R_, curDim_, curDim_-blockSize_));
697//KMS
698//sleep(1);
699//std::cout << "Before TRSM" << std::endl;
700//sleep(1);
701//std::cout << "The size of Rtmp is " << Rtmp -> numRows() << " by " << Rtmp -> numCols() << std::endl;
702//std::cout << "The size of Y is " << Y.numRows() << " by " << Y.numCols() << std::endl;
703//std::cout << "blockSize_ = " << blockSize_ << std::endl;
704//std::cout << "curDim_ = " << curDim_ << std::endl;
705//std::cout << "curDim_ - blockSize_ = " << curDim_ - blockSize_ << std::endl;
706 //
707 // Solve the least squares problem.
708 // Observe that in calling TRSM, we use the value
709 // curDim_ -blockSize_. This is because curDim_ has
710 // already been incremented but the proper size of R is still
711 // based on the previous value.
712 //
713 blas.TRSM( Teuchos::LEFT_SIDE, Teuchos::UPPER_TRI, Teuchos::NO_TRANS,
714 Teuchos::NON_UNIT_DIAG, curDim_-blockSize_, blockSize_, one,
715 Rtmp->values(), Rtmp->stride(), Y.values(), Y.stride() );
716//KMS
717//sleep(1);
718//std::cout << "After TRSM" << std::endl;
719 //
720 // Compute the current update from the Krylov basis; V(:,1:curDim_)*y.
721 //
722 std::vector<int> index(curDim_-blockSize_);
723 for ( int i=0; i<curDim_-blockSize_; i++ ) index[i] = i;
724 Teuchos::RCP<const MV> Vjp1 = MVT::CloneView( *V_, index );
725 MVT::MvTimesMatAddMv( one, *Vjp1, Y, zero, *currentUpdate );
726
727
728
729 //
730 // Add in portion of update from recycled subspace U; U(:,1:recycledBlocks_)*B*y.
731 //
732 if (U_ != Teuchos::null) {
733 SDM z(recycledBlocks_,blockSize_);
734 SDM subB( Teuchos::View, *B_, recycledBlocks_, curDim_-blockSize_ );
735 z.multiply( Teuchos::NO_TRANS, Teuchos::NO_TRANS, one, subB, Y, zero );
736
737 //std::cout << (*U_).MyLength() << " " << (*U_).NumVectors() << " " << subB.numRows() << " " << subB.numCols() << " " << Y.numRows() << " " << Y.numCols()<< " " << curDim_ << " " << recycledBlocks_;
738 MVT::MvTimesMatAddMv( -one, *U_, z, one, *currentUpdate );
739 }
740 }
741
742
743
744 return currentUpdate;
745 }//end getCurrentUpdate() definition
746
747 template<class ScalarType, class MV, class OP, class DM>
749
750 int i;
751 const ScalarType zero = Teuchos::ScalarTraits<ScalarType>::zero();
752 const ScalarType one = Teuchos::ScalarTraits<ScalarType>::one();
753
754 using Teuchos::rcp;
755
756 // Get correct dimension based on input "dim"
757 // Remember that ortho failures result in an exit before updateLSQR() is called.
758 // Therefore, it is possible that dim == curDim_.
759 int curDim = curDim_;
760 if ( (dim >= curDim_) && (dim < getMaxSubspaceDim()) ){
761 curDim = dim;
762 }
763
764 Teuchos::BLAS<int, ScalarType> blas;
765
766 if(blockSize_ == 1){//if only one right-hand side then use Givens rotations
767 //
768 // Apply previous rotations and compute new rotations to reduce upper-Hessenberg
769 // system to upper-triangular form.
770 //
771 // QR factorization of Least-Squares system with Givens rotations
772 //
773 for (i=0; i<curDim-1; i++) {
774 //
775 // Apply previous Givens rotations to new column of Hessenberg matrix
776 //
777 blas.ROT( 1, &(*R_)(i,curDim-1), 1, &(*R_)(i+1, curDim-1), 1, &cs_[i], &sn_[i] );
778 }
779 //
780 // Calculate new Givens rotation
781 //
782 blas.ROTG( &(*R_)(curDim-1,curDim-1), &(*R_)(curDim,curDim-1), &cs_[curDim-1], &sn_[curDim-1] );
783 (*R_)(curDim,curDim-1) = zero;
784 //
785 // Update RHS w/ new transformation
786 //
787 blas.ROT( 1, &Z_(curDim-1,0), 1, &Z_(curDim,0), 1, &cs_[curDim-1], &sn_[curDim-1] );
788 }
789 else{//if multiple right-hand sides then use Householder transormations
790 //
791 //apply previous reflections and compute new reflections to reduce upper-Hessenberg
792 //system to upper-triagular form.
793
794 //In Matlab, applying the reflection to a matrix M would look like
795 // M_refl = M - 2*v_refl*(v_refl'*M)/(norm(v_refl)^2)
796
797 //In order to take advantage of BLAS while applying reflections to a matrix, we
798 //perform it in a two step process
799 //1. workvec = M'*v_refl {using BLAS.GEMV()}
800 //2. M_refl = M_refl - 2*v_refl*workvec'/(norm(v_refl)^2) {using BLAS.GER()}
801
802 Teuchos::RCP< SDM > workmatrix = Teuchos::null;//matrix of column vectors onto which we apply the reflection
803 Teuchos::RCP< SDV > workvec = Teuchos::null;//where we store the result of the first step of the 2-step reflection process
804 Teuchos::RCP<SDV> v_refl = Teuchos::null;//the reflection vector
805 int R_colStart = curDim_-blockSize_;
806 Teuchos::RCP< SDM >Rblock = Teuchos::null;
807
808 //
809 //Apply previous reflections
810 //
811 for(i=0; i<lclIter_-1; i++){
812 int R_rowStart = i*blockSize_;
813 //get a view of the part of R_ effected by these reflections.
814 Teuchos::RCP< SDM > RblockCopy = rcp(new SDM (Teuchos::Copy, *R_, 2*blockSize_,blockSize_, R_rowStart, R_colStart));
815 Teuchos::RCP< SDM > RblockView = rcp(new SDM (Teuchos::View, *R_, 2*blockSize_,blockSize_, R_rowStart, R_colStart));
816 blas.GEMM(Teuchos::NO_TRANS,Teuchos::NO_TRANS, 2*blockSize_,blockSize_,2*blockSize_,one,House_[i].values(),House_[i].stride(), RblockCopy->values(),RblockCopy -> stride(), zero, RblockView->values(),RblockView -> stride());
817
818 }
819
820
821 //Get a view of last 2*blockSize entries of entire block to
822 //generate new reflections.
823 Rblock = rcp(new SDM (Teuchos::View, *R_, 2*blockSize_,blockSize_, curDim_-blockSize_, curDim_-blockSize_));
824
825 //Calculate and apply the new reflections
826 for(i=0; i<blockSize_; i++){
827 //
828 //Calculating Reflection
829 //
830 int curcol = (lclIter_ - 1)*blockSize_ + i;//current column of R_
831 int lclCurcol = i;//current column of Rblock
832 ScalarType signDiag = (*R_)(curcol,curcol) / Teuchos::ScalarTraits<ScalarType>::magnitude((*R_)(curcol,curcol));
833
834 // Norm of the vector to be reflected.
835 // BLAS returns a ScalarType, but it really should be a magnitude.
836 ScalarType nvs = blas.NRM2(blockSize_+1,&((*R_)[curcol][curcol]),1);
837 ScalarType alpha = -signDiag*nvs;
838
839 //norm of reflection vector which is just the vector being reflected
840 //i.e. v = R_(curcol:curcol+blockSize_,curcol))
841 //v_refl = v - alpha*e1
842 //norm(v_refl) = norm(v) + alpha^2 - 2*v*alpha
843 //store in v_refl
844
845 // Beware, nvs should have a zero imaginary part (since
846 // it is a norm of a vector), but it may not due to rounding
847 // error.
848 //nvs = nvs + alpha*alpha - 2*(*R_)(curcol,curcol)*alpha;
849 //(*R_)(curcol,curcol) -= alpha;
850
851 //Copy relevant values of the current column of R_ into the reflection vector
852 //Modify first entry
853 //Take norm of reflection vector
854 //Square the norm
855 v_refl = rcp(new SDV(Teuchos::Copy, &((*R_)(curcol,curcol)), blockSize_ + 1 ));
856 (*v_refl)[0] -= alpha;
857 nvs = blas.NRM2(blockSize_+1,v_refl -> values(),1);
858 nvs *= nvs;
859
860 //
861 //Apply new reflector to:
862 //1. To subsequent columns of R_ in the current block
863 //2. To House[iter_] to store product of reflections for this column
864 //3. To the least-squares right-hand side.
865 //4. The current column
866 //
867 //
868
869
870 //
871 //1.
872 //
873 if(i < blockSize_ - 1){//only do this when there are subsquent columns in the block to apply to
874 workvec = Teuchos::rcp(new SDV(blockSize_ - i -1));
875 //workvec = Teuchos::rcp(new SDV(2*blockSize_));
876 workmatrix = Teuchos::rcp(new SDM (Teuchos::View, *Rblock, blockSize_+1, blockSize_ - i -1, lclCurcol, lclCurcol +1 ) );
877 blas.GEMV(Teuchos::TRANS, workmatrix->numRows(), workmatrix->numCols(), one, workmatrix->values(), workmatrix->stride(), v_refl->values(), 1, zero, workvec->values(), 1);
878 blas.GER(workmatrix->numRows(),workmatrix->numCols(), -2.0*one/nvs, v_refl->values(),1,workvec->values(),1,workmatrix->values(),workmatrix->stride());
879 }
880
881
882 //
883 //2.
884 //
885 workvec = Teuchos::rcp(new SDV(2*blockSize_));
886 workmatrix = Teuchos::rcp(new SDM (Teuchos::View, House_[lclIter_ -1], blockSize_+1, 2*blockSize_, i, 0 ) );
887 blas.GEMV(Teuchos::TRANS,workmatrix->numRows(),workmatrix->numCols(),one,workmatrix->values(),workmatrix->stride(), v_refl->values(), 1,zero,workvec->values(),1);
888 blas.GER(workmatrix->numRows(),workmatrix->numCols(), -2.0*one/nvs, v_refl -> values(),1,workvec->values(),1,workmatrix->values(),(*workmatrix).stride());
889
890 //
891 //3.
892 //
893 workvec = Teuchos::rcp(new SDV(blockSize_));
894 workmatrix = Teuchos::rcp(new SDM (Teuchos::View, Z_, blockSize_+1, blockSize_, curcol, 0 ) );
895 blas.GEMV(Teuchos::TRANS, workmatrix->numRows(), workmatrix->numCols(), one, workmatrix-> values(), workmatrix->stride(), v_refl -> values(), 1, zero, workvec->values(), 1);
896 blas.GER((*workmatrix).numRows(),(*workmatrix).numCols(), -2.0*one/nvs,v_refl -> values(), 1,&((*workvec)[0]),1,(*workmatrix)[0],(*workmatrix).stride());
897
898 //
899 //4.
900 //
901 (*R_)[curcol][curcol] = alpha;
902 for(int ii=1; ii<= blockSize_; ii++){
903 (*R_)[curcol][curcol+ii] = 0;
904 }
905 }
906
907 }
908
909 } // end updateLSQR()
910
911
912}//End Belos Namespace
913
914#endif /* BELOS_BLOCK_GCRODR_ITER_HPP */
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.
Parent class to all Belos exceptions.
Implementation of the Block GCRO-DR (Block Recycling GMRES) iteration.
void setBlockSize(int blockSize)
Set the blocksize.
int getNumIters() const
Get the current iteration count.
int getCurSubspaceDim() const
Get the dimension of the search subspace used to generate the current solution to the linear problem.
BlockGCRODRIterState< ScalarType, MV > getState() const
Get the current state of the linear solver.
int getBlockSize() const
Get the blocksize to be used by the iterative solver in solving this linear problem.
void initialize()
Initialize the solver to an iterate, providing a complete state.
MultiVecTraits< ScalarType, MV, DM > MVT
BlockGCRODRIter(const Teuchos::RCP< LinearProblem< ScalarType, MV, OP, DM > > &problem, const Teuchos::RCP< OutputManager< ScalarType > > &printer, const Teuchos::RCP< StatusTest< ScalarType, MV, OP > > &tester, const Teuchos::RCP< MatOrthoManager< ScalarType, MV, OP > > &ortho, Teuchos::ParameterList &params)
BlockGCRODRIter constructor with linear problem, solver utilities, and parameter list of solver optio...
Teuchos::RCP< MV > getCurrentUpdate() const
Get the current update to the linear system.
bool isInitialized()
States whether the solver has been initialized or not.
int getNumBlocks() const
Get the maximum number of blocks used by the iterative solver in solving this linear problem.
void setSize(int recycledBlocks, int numBlocks)
Set the maximum number of blocks used by the iterative solver and the number of recycled vectors.
Teuchos::RCP< const MV > getNativeResiduals(std::vector< MagnitudeType > *norms) const
Get the norms of the residuals native to the solver.
Teuchos::SerialDenseMatrix< int, ScalarType > SDM
OperatorTraits< ScalarType, MV, OP > OPT
virtual ~BlockGCRODRIter()
Destructor.
Teuchos::SerialDenseVector< int, ScalarType > SDV
void setNumBlocks(int numBlocks)
Set the maximum number of blocks used by the iterative solver.
Teuchos::ScalarTraits< ScalarType > SCT
int getMaxSubspaceDim() const
Get the maximum dimension allocated for the search subspace.
void iterate()
This method performs block GCRODR iterations until the status test indicates the need to stop or an e...
void resetNumIters(int iter=0)
Reset the iteration count.
const LinearProblem< ScalarType, MV, OP, DM > & getProblem() const
Get a constant reference to the linear problem.
BlockGCRODRIterInitFailure is thrown when the BlockGCRODRIter object is unable to generate an initial...
BlockGCRODRIterInitFailure(const std::string &what_arg)
BlockGCRODRIterOrthoFailure is thrown when the BlockGCRODRIter object is unable to compute independen...
BlockGCRODRIterOrthoFailure(const std::string &what_arg)
Alternative run-time polymorphic interface for operators.
Operator()
Default constructor (does nothing).
Structure to contain pointers to BlockGCRODRIter state variables.
Teuchos::RCP< MV > V
The current Krylov basis.
Teuchos::RCP< MV > U
The recycled subspace and its projection.
Teuchos::RCP< Teuchos::SerialDenseMatrix< int, ScalarType > > B
The projection of the Krylov subspace against the recycled subspace *
Teuchos::RCP< Teuchos::SerialDenseMatrix< int, ScalarType > > H
The current Hessenberg matrix.
int curDim
The current dimension of the reduction.

Generated for Belos by doxygen 1.9.8