14#ifndef ANASAZI_BLOCK_KRYLOV_SCHUR_HPP
15#define ANASAZI_BLOCK_KRYLOV_SCHUR_HPP
22#include "Teuchos_ScalarTraits.hpp"
23#include "AnasaziHelperTraits.hpp"
27#include "Teuchos_LAPACK.hpp"
28#include "Teuchos_BLAS.hpp"
29#include "Teuchos_SerialDenseMatrix.hpp"
30#include "Teuchos_ParameterList.hpp"
31#include "Teuchos_TimeMonitor.hpp"
56 template <
class ScalarType,
class MulVec>
64 Teuchos::RCP<const MulVec>
V;
70 Teuchos::RCP<const Teuchos::SerialDenseMatrix<int,ScalarType> >
H;
72 Teuchos::RCP<const Teuchos::SerialDenseMatrix<int,ScalarType> >
S;
74 Teuchos::RCP<const Teuchos::SerialDenseMatrix<int,ScalarType> >
Q;
76 H(Teuchos::null),
S(Teuchos::null),
114 template <
class ScalarType,
class MV,
class OP>
132 const Teuchos::RCP<
SortManager<
typename Teuchos::ScalarTraits<ScalarType>::magnitudeType> > &sorter,
136 Teuchos::ParameterList ¶ms
254 std::vector<Value<ScalarType> > ret = ritzValues_;
255 ret.resize(ritzIndex_.size());
270 std::vector<typename Teuchos::ScalarTraits<ScalarType>::magnitudeType>
getResNorms() {
271 std::vector<typename Teuchos::ScalarTraits<ScalarType>::magnitudeType> ret(0);
279 std::vector<typename Teuchos::ScalarTraits<ScalarType>::magnitudeType>
getRes2Norms() {
280 std::vector<typename Teuchos::ScalarTraits<ScalarType>::magnitudeType> ret(0);
288 std::vector<typename Teuchos::ScalarTraits<ScalarType>::magnitudeType>
getRitzRes2Norms() {
289 std::vector<typename Teuchos::ScalarTraits<ScalarType>::magnitudeType> ret = ritzResiduals_;
290 ret.resize(ritzIndex_.size());
303 Teuchos::RCP<StatusTest<ScalarType,MV,OP> >
getStatusTest()
const;
314 void setSize(
int blockSize,
int numBlocks);
340 if (!initialized_)
return 0;
345 int getMaxSubspaceDim()
const {
return (problem_->isHermitian()?blockSize_*numBlocks_:blockSize_*numBlocks_+1); }
360 void setAuxVecs(
const Teuchos::Array<Teuchos::RCP<const MV> > &auxvecs);
363 Teuchos::Array<Teuchos::RCP<const MV> >
getAuxVecs()
const {
return auxVecs_;}
409 typedef Teuchos::ScalarTraits<ScalarType> SCT;
410 typedef typename SCT::magnitudeType MagnitudeType;
411 typedef typename std::vector<ScalarType>::iterator STiter;
412 typedef typename std::vector<MagnitudeType>::iterator MTiter;
413 const MagnitudeType MT_ONE;
414 const MagnitudeType MT_ZERO;
415 const MagnitudeType NANVAL;
416 const ScalarType ST_ONE;
417 const ScalarType ST_ZERO;
425 CheckList() : checkV(false), checkArn(false), checkAux(false) {};
430 std::string accuracyCheck(
const CheckList &chk,
const std::string &where)
const;
431 void sortSchurForm( Teuchos::SerialDenseMatrix<int,ScalarType>& H,
432 Teuchos::SerialDenseMatrix<int,ScalarType>& Q,
433 std::vector<int>& order );
437 const Teuchos::RCP<Eigenproblem<ScalarType,MV,OP> > problem_;
438 const Teuchos::RCP<SortManager<typename Teuchos::ScalarTraits<ScalarType>::magnitudeType> > sm_;
439 const Teuchos::RCP<OutputManager<ScalarType> > om_;
440 Teuchos::RCP<StatusTest<ScalarType,MV,OP> > tester_;
441 const Teuchos::RCP<OrthoManager<ScalarType,MV> > orthman_;
445 Teuchos::RCP<const OP> Op_;
449 Teuchos::RCP<Teuchos::Time> timerOp_, timerSortRitzVal_,
450 timerCompSF_, timerSortSF_,
451 timerCompRitzVec_, timerOrtho_;
485 Teuchos::RCP<MV> ritzVectors_, V_;
491 Teuchos::RCP<Teuchos::SerialDenseMatrix<int,ScalarType> > H_;
496 Teuchos::RCP<Teuchos::SerialDenseMatrix<int,ScalarType> > schurH_;
497 Teuchos::RCP<Teuchos::SerialDenseMatrix<int,ScalarType> > Q_;
500 Teuchos::Array<Teuchos::RCP<const MV> > auxVecs_;
507 bool ritzVecsCurrent_, ritzValsCurrent_, schurCurrent_;
510 std::vector<Value<ScalarType> > ritzValues_;
511 std::vector<MagnitudeType> ritzResiduals_;
514 std::vector<int> ritzIndex_;
515 std::vector<int> ritzOrder_;
524 template <
class ScalarType,
class MV,
class OP>
527 const Teuchos::RCP<
SortManager<
typename Teuchos::ScalarTraits<ScalarType>::magnitudeType> > &sorter,
531 Teuchos::ParameterList ¶ms
533 MT_ONE(Teuchos::ScalarTraits<MagnitudeType>::one()),
534 MT_ZERO(Teuchos::ScalarTraits<MagnitudeType>::zero()),
535 NANVAL(Teuchos::ScalarTraits<MagnitudeType>::nan()),
536 ST_ONE(Teuchos::ScalarTraits<ScalarType>::one()),
537 ST_ZERO(Teuchos::ScalarTraits<ScalarType>::zero()),
545#ifdef ANASAZI_TEUCHOS_TIME_MONITOR
546 timerOp_(Teuchos::TimeMonitor::getNewTimer(
"Anasazi: BlockKrylovSchur::Operation Op*x")),
547 timerSortRitzVal_(Teuchos::TimeMonitor::getNewTimer(
"Anasazi: BlockKrylovSchur::Sorting Ritz values")),
548 timerCompSF_(Teuchos::TimeMonitor::getNewTimer(
"Anasazi: BlockKrylovSchur::Computing Schur form")),
549 timerSortSF_(Teuchos::TimeMonitor::getNewTimer(
"Anasazi: BlockKrylovSchur::Sorting Schur form")),
550 timerCompRitzVec_(Teuchos::TimeMonitor::getNewTimer(
"Anasazi: BlockKrylovSchur::Computing Ritz vectors")),
551 timerOrtho_(Teuchos::TimeMonitor::getNewTimer(
"Anasazi: BlockKrylovSchur::Orthogonalization")),
561 auxVecs_( Teuchos::Array<Teuchos::RCP<const MV> >(0) ),
564 ritzVecsCurrent_(false),
565 ritzValsCurrent_(false),
566 schurCurrent_(false),
569 TEUCHOS_TEST_FOR_EXCEPTION(problem_ == Teuchos::null,std::invalid_argument,
570 "Anasazi::BlockKrylovSchur::constructor: user specified null problem pointer.");
571 TEUCHOS_TEST_FOR_EXCEPTION(sm_ == Teuchos::null,std::invalid_argument,
572 "Anasazi::BlockKrylovSchur::constructor: user passed null sort manager pointer.");
573 TEUCHOS_TEST_FOR_EXCEPTION(om_ == Teuchos::null,std::invalid_argument,
574 "Anasazi::BlockKrylovSchur::constructor: user passed null output manager pointer.");
575 TEUCHOS_TEST_FOR_EXCEPTION(tester_ == Teuchos::null,std::invalid_argument,
576 "Anasazi::BlockKrylovSchur::constructor: user passed null status test pointer.");
577 TEUCHOS_TEST_FOR_EXCEPTION(orthman_ == Teuchos::null,std::invalid_argument,
578 "Anasazi::BlockKrylovSchur::constructor: user passed null orthogonalization manager pointer.");
579 TEUCHOS_TEST_FOR_EXCEPTION(problem_->isProblemSet() ==
false, std::invalid_argument,
580 "Anasazi::BlockKrylovSchur::constructor: user specified problem is not set.");
581 TEUCHOS_TEST_FOR_EXCEPTION(sorter == Teuchos::null,std::invalid_argument,
582 "Anasazi::BlockKrylovSchur::constructor: user specified null sort manager pointer.");
583 TEUCHOS_TEST_FOR_EXCEPTION(printer == Teuchos::null,std::invalid_argument,
584 "Anasazi::BlockKrylovSchur::constructor: user specified null output manager pointer.");
585 TEUCHOS_TEST_FOR_EXCEPTION(tester == Teuchos::null,std::invalid_argument,
586 "Anasazi::BlockKrylovSchur::constructor: user specified null status test pointer.");
587 TEUCHOS_TEST_FOR_EXCEPTION(ortho == Teuchos::null,std::invalid_argument,
588 "Anasazi::BlockKrylovSchur::constructor: user specified null ortho manager pointer.");
591 Op_ = problem_->getOperator();
594 TEUCHOS_TEST_FOR_EXCEPTION(!params.isParameter(
"Step Size"), std::invalid_argument,
595 "Anasazi::BlockKrylovSchur::constructor: mandatory parameter 'Step Size' is not specified.");
596 int ss = params.get(
"Step Size",numBlocks_);
600 int bs = params.get(
"Block Size", 1);
601 int nb = params.get(
"Num Blocks", 3*problem_->getNEV());
606 int numRitzVecs = params.get(
"Number of Ritz Vectors", 0);
610 numRitzPrint_ = params.get(
"Print Number of Ritz Values", bs);
617 template <
class ScalarType,
class MV,
class OP>
620 setSize(blockSize,numBlocks_);
626 template <
class ScalarType,
class MV,
class OP>
629 TEUCHOS_TEST_FOR_EXCEPTION(stepSize <= 0, std::invalid_argument,
"Anasazi::BlockKrylovSchur::setStepSize(): new step size must be positive and non-zero.");
630 stepSize_ = stepSize;
635 template <
class ScalarType,
class MV,
class OP>
641 TEUCHOS_TEST_FOR_EXCEPTION(numRitzVecs < 0, std::invalid_argument,
"Anasazi::BlockKrylovSchur::setNumRitzVectors(): number of Ritz vectors to compute must be positive.");
644 if (numRitzVecs != numRitzVecs_) {
646 ritzVectors_ = Teuchos::null;
647 ritzVectors_ = MVT::Clone(*V_, numRitzVecs);
649 ritzVectors_ = Teuchos::null;
651 numRitzVecs_ = numRitzVecs;
652 ritzVecsCurrent_ =
false;
658 template <
class ScalarType,
class MV,
class OP>
664 TEUCHOS_TEST_FOR_EXCEPTION(numBlocks <= 0 || blockSize <= 0, std::invalid_argument,
"Anasazi::BlockKrylovSchur::setSize was passed a non-positive argument.");
665 TEUCHOS_TEST_FOR_EXCEPTION(numBlocks < 3, std::invalid_argument,
"Anasazi::BlockKrylovSchur::setSize(): numBlocks must be at least three.");
666 if (blockSize == blockSize_ && numBlocks == numBlocks_) {
671 blockSize_ = blockSize;
672 numBlocks_ = numBlocks;
674 Teuchos::RCP<const MV> tmp;
680 if (problem_->getInitVec() != Teuchos::null) {
681 tmp = problem_->getInitVec();
685 TEUCHOS_TEST_FOR_EXCEPTION(tmp == Teuchos::null,std::invalid_argument,
686 "Anasazi::BlockKrylovSchur::setSize(): eigenproblem did not specify initial vectors to clone from.");
694 if (problem_->isHermitian()) {
695 newsd = blockSize_*numBlocks_;
697 newsd = blockSize_*numBlocks_+1;
700 TEUCHOS_TEST_FOR_EXCEPTION(
static_cast<ptrdiff_t
>(newsd) > MVT::GetGlobalLength(*tmp),std::invalid_argument,
701 "Anasazi::BlockKrylovSchur::setSize(): maximum basis size is larger than problem dimension.");
703 ritzValues_.resize(newsd);
704 ritzResiduals_.resize(newsd,MT_ONE);
705 ritzOrder_.resize(newsd);
707 V_ = MVT::Clone(*tmp,newsd+blockSize_);
708 H_ = Teuchos::rcp(
new Teuchos::SerialDenseMatrix<int,ScalarType>(newsd+blockSize_,newsd) );
709 Q_ = Teuchos::rcp(
new Teuchos::SerialDenseMatrix<int,ScalarType>(newsd,newsd) );
711 initialized_ =
false;
718 template <
class ScalarType,
class MV,
class OP>
720 typedef typename Teuchos::Array<Teuchos::RCP<const MV> >::iterator tarcpmv;
725 if (om_->isVerbosity(
Debug ) ) {
729 om_->print(
Debug, accuracyCheck(chk,
": in setAuxVecs()") );
733 for (tarcpmv i=auxVecs_.begin(); i != auxVecs_.end(); i++) {
734 numAuxVecs_ += MVT::GetNumberVecs(**i);
738 if (numAuxVecs_ > 0 && initialized_) {
739 initialized_ =
false;
752 template <
class ScalarType,
class MV,
class OP>
757 std::vector<int> bsind(blockSize_);
758 for (
int i=0; i<blockSize_; i++) bsind[i] = i;
766 std::string errstr(
"Anasazi::BlockKrylovSchur::initialize(): specified multivectors must have a consistent length and width.");
770 if (newstate.
V != Teuchos::null && newstate.
H != Teuchos::null) {
774 TEUCHOS_TEST_FOR_EXCEPTION( MVT::GetGlobalLength(*newstate.
V) != MVT::GetGlobalLength(*V_),
775 std::invalid_argument, errstr );
776 if (newstate.
V != V_) {
777 TEUCHOS_TEST_FOR_EXCEPTION( MVT::GetNumberVecs(*newstate.
V) < blockSize_,
778 std::invalid_argument, errstr );
779 TEUCHOS_TEST_FOR_EXCEPTION( MVT::GetNumberVecs(*newstate.
V) > getMaxSubspaceDim(),
780 std::invalid_argument, errstr );
782 TEUCHOS_TEST_FOR_EXCEPTION( newstate.
curDim > getMaxSubspaceDim(),
783 std::invalid_argument, errstr );
785 curDim_ = newstate.
curDim;
786 int lclDim = MVT::GetNumberVecs(*newstate.
V);
789 TEUCHOS_TEST_FOR_EXCEPTION(newstate.
H->numRows() < curDim_ || newstate.
H->numCols() < curDim_, std::invalid_argument, errstr);
791 if (curDim_ == 0 && lclDim > blockSize_) {
792 om_->stream(
Warnings) <<
"Anasazi::BlockKrylovSchur::initialize(): the solver was initialized with a kernel of " << lclDim << std::endl
793 <<
"The block size however is only " << blockSize_ << std::endl
794 <<
"The last " << lclDim - blockSize_ <<
" vectors of the kernel will be overwritten on the first call to iterate()." << std::endl;
799 if (newstate.
V != V_) {
800 std::vector<int> nevind(lclDim);
801 for (
int i=0; i<lclDim; i++) nevind[i] = i;
802 MVT::SetBlock(*newstate.
V,nevind,*V_);
806 if (newstate.
H != H_) {
807 H_->putScalar( ST_ZERO );
808 Teuchos::SerialDenseMatrix<int,ScalarType> newH(Teuchos::View,*newstate.
H,curDim_+blockSize_,curDim_);
809 Teuchos::RCP<Teuchos::SerialDenseMatrix<int,ScalarType> > lclH;
810 lclH = Teuchos::rcp(
new Teuchos::SerialDenseMatrix<int,ScalarType>(Teuchos::View,*H_,curDim_+blockSize_,curDim_) );
814 lclH = Teuchos::null;
821 Teuchos::RCP<const MV> ivec = problem_->getInitVec();
822 TEUCHOS_TEST_FOR_EXCEPTION(ivec == Teuchos::null,std::invalid_argument,
823 "Anasazi::BlockKrylovSchur::initialize(): eigenproblem did not specify initial vectors to clone from.");
825 int lclDim = MVT::GetNumberVecs(*ivec);
826 bool userand =
false;
827 if (lclDim < blockSize_) {
835 std::vector<int> dimind2(lclDim);
836 for (
int i=0; i<lclDim; i++) { dimind2[i] = i; }
839 Teuchos::RCP<MV> newV1 = MVT::CloneViewNonConst(*V_,dimind2);
842 MVT::SetBlock(*ivec,dimind2,*newV1);
845 dimind2.resize(blockSize_-lclDim);
846 for (
int i=0; i<blockSize_-lclDim; i++) { dimind2[i] = lclDim + i; }
849 Teuchos::RCP<MV> newV2 = MVT::CloneViewNonConst(*V_,dimind2);
850 MVT::MvRandom(*newV2);
854 Teuchos::RCP<MV> newV1 = MVT::CloneViewNonConst(*V_,bsind);
857 Teuchos::RCP<const MV> ivecV = MVT::CloneView(*ivec,bsind);
860 MVT::SetBlock(*ivecV,bsind,*newV1);
864 Teuchos::RCP<MV> newV = MVT::CloneViewNonConst(*V_,bsind);
867 if (auxVecs_.size() > 0) {
868#ifdef ANASAZI_TEUCHOS_TIME_MONITOR
869 Teuchos::TimeMonitor lcltimer( *timerOrtho_ );
872 Teuchos::Array<Teuchos::RCP<Teuchos::SerialDenseMatrix<int,ScalarType> > > dummy;
873 int rank = orthman_->projectAndNormalize(*newV,auxVecs_);
875 "Anasazi::BlockKrylovSchur::initialize(): couldn't generate initial basis of full rank." );
878#ifdef ANASAZI_TEUCHOS_TIME_MONITOR
879 Teuchos::TimeMonitor lcltimer( *timerOrtho_ );
882 int rank = orthman_->normalize(*newV);
884 "Anasazi::BlockKrylovSchur::initialize(): couldn't generate initial basis of full rank." );
891 newV = Teuchos::null;
895 ritzVecsCurrent_ =
false;
896 ritzValsCurrent_ =
false;
897 schurCurrent_ =
false;
902 if (om_->isVerbosity(
Debug ) ) {
908 om_->print(
Debug, accuracyCheck(chk,
": after initialize()") );
912 if (om_->isVerbosity(
Debug)) {
913 currentStatus( om_->stream(
Debug) );
923 template <
class ScalarType,
class MV,
class OP>
933 template <
class ScalarType,
class MV,
class OP>
939 if (initialized_ ==
false) {
945 int searchDim = blockSize_*numBlocks_;
946 if (problem_->isHermitian() ==
false) {
955 while (tester_->checkStatus(
this) !=
Passed && curDim_+blockSize_ <= searchDim) {
960 int lclDim = curDim_ + blockSize_;
963 std::vector<int> curind(blockSize_);
964 for (
int i=0; i<blockSize_; i++) { curind[i] = lclDim + i; }
965 Teuchos::RCP<MV> Vnext = MVT::CloneViewNonConst(*V_,curind);
969 for (
int i=0; i<blockSize_; i++) { curind[i] = curDim_ + i; }
970 Teuchos::RCP<const MV> Vprev = MVT::CloneView(*V_,curind);
976#ifdef ANASAZI_TEUCHOS_TIME_MONITOR
977 Teuchos::TimeMonitor lcltimer( *timerOp_ );
979 OPT::Apply(*Op_,*Vprev,*Vnext);
980 count_ApplyOp_ += blockSize_;
984 Vprev = Teuchos::null;
988#ifdef ANASAZI_TEUCHOS_TIME_MONITOR
989 Teuchos::TimeMonitor lcltimer( *timerOrtho_ );
993 std::vector<int> prevind(lclDim);
994 for (
int i=0; i<lclDim; i++) { prevind[i] = i; }
995 Vprev = MVT::CloneView(*V_,prevind);
996 Teuchos::Array<Teuchos::RCP<const MV> > AVprev(1, Vprev);
999 Teuchos::RCP<Teuchos::SerialDenseMatrix<int,ScalarType> >
1000 subH = Teuchos::rcp(
new Teuchos::SerialDenseMatrix<int,ScalarType>
1001 ( Teuchos::View,*H_,lclDim,blockSize_,0,curDim_ ) );
1002 Teuchos::Array<Teuchos::RCP<Teuchos::SerialDenseMatrix<int,ScalarType> > > AsubH;
1003 AsubH.append( subH );
1006 if (auxVecs_.size() > 0) {
1007 for (Array_size_type i=0; i<auxVecs_.size(); i++) {
1008 AVprev.append( auxVecs_[i] );
1009 AsubH.append( Teuchos::null );
1016 Teuchos::RCP<Teuchos::SerialDenseMatrix<int,ScalarType> >
1017 subR = Teuchos::rcp(
new Teuchos::SerialDenseMatrix<int,ScalarType>
1018 ( Teuchos::View,*H_,blockSize_,blockSize_,lclDim,curDim_ ) );
1019 int rank = orthman_->projectAndNormalize(*Vnext,AVprev,AsubH,subR);
1026 "Anasazi::BlockKrylovSchur::iterate(): couldn't generate basis of full rank.");
1032 Vnext = Teuchos::null;
1033 curDim_ += blockSize_;
1035 ritzVecsCurrent_ =
false;
1036 ritzValsCurrent_ =
false;
1037 schurCurrent_ =
false;
1040 if (!(iter_%stepSize_)) {
1041 computeRitzValues();
1045 if (om_->isVerbosity(
Debug ) ) {
1049 chk.checkArn =
true;
1050 om_->print(
Debug, accuracyCheck(chk,
": after local update") );
1055 om_->print(
OrthoDetails, accuracyCheck(chk,
": after local update") );
1059 if (om_->isVerbosity(
Debug)) {
1060 currentStatus( om_->stream(
Debug) );
1084 template <
class ScalarType,
class MV,
class OP>
1087 std::stringstream os;
1089 os.setf(std::ios::scientific, std::ios::floatfield);
1092 os <<
" Debugging checks: iteration " << iter_ << where << std::endl;
1095 std::vector<int> lclind(curDim_);
1096 for (
int i=0; i<curDim_; i++) lclind[i] = i;
1097 std::vector<int> bsind(blockSize_);
1098 for (
int i=0; i<blockSize_; i++) { bsind[i] = curDim_ + i; }
1100 Teuchos::RCP<const MV> lclV,lclF;
1101 Teuchos::RCP<MV> lclAV;
1103 lclV = MVT::CloneView(*V_,lclind);
1104 lclF = MVT::CloneView(*V_,bsind);
1108 tmp = orthman_->orthonormError(*lclV);
1109 os <<
" >> Error in V^H M V == I : " << tmp << std::endl;
1111 tmp = orthman_->orthonormError(*lclF);
1112 os <<
" >> Error in F^H M F == I : " << tmp << std::endl;
1114 tmp = orthman_->orthogError(*lclV,*lclF);
1115 os <<
" >> Error in V^H M F == 0 : " << tmp << std::endl;
1117 for (Array_size_type i=0; i<auxVecs_.size(); i++) {
1119 tmp = orthman_->orthogError(*lclV,*auxVecs_[i]);
1120 os <<
" >> Error in V^H M Aux[" << i <<
"] == 0 : " << tmp << std::endl;
1122 tmp = orthman_->orthogError(*lclF,*auxVecs_[i]);
1123 os <<
" >> Error in F^H M Aux[" << i <<
"] == 0 : " << tmp << std::endl;
1131 lclAV = MVT::Clone(*V_,curDim_);
1133#ifdef ANASAZI_TEUCHOS_TIME_MONITOR
1134 Teuchos::TimeMonitor lcltimer( *timerOp_ );
1136 OPT::Apply(*Op_,*lclV,*lclAV);
1140 Teuchos::SerialDenseMatrix<int,ScalarType> subH(Teuchos::View,*H_,curDim_,curDim_);
1141 MVT::MvTimesMatAddMv( -ST_ONE, *lclV, subH, ST_ONE, *lclAV );
1144 Teuchos::SerialDenseMatrix<int,ScalarType> curB(Teuchos::View,*H_,
1145 blockSize_,curDim_, curDim_ );
1146 MVT::MvTimesMatAddMv( -ST_ONE, *lclF, curB, ST_ONE, *lclAV );
1149 std::vector<MagnitudeType> arnNorms( curDim_ );
1150 orthman_->norm( *lclAV, arnNorms );
1152 for (
int i=0; i<curDim_; i++) {
1153 os <<
" >> Error in Krylov-Schur factorization (R = AV-VS-FB^H), ||R[" << i <<
"]|| : " << arnNorms[i] << std::endl;
1159 for (Array_size_type i=0; i<auxVecs_.size(); i++) {
1160 tmp = orthman_->orthonormError(*auxVecs_[i]);
1161 os <<
" >> Error in Aux[" << i <<
"]^H M Aux[" << i <<
"] == I : " << tmp << std::endl;
1162 for (Array_size_type j=i+1; j<auxVecs_.size(); j++) {
1163 tmp = orthman_->orthogError(*auxVecs_[i],*auxVecs_[j]);
1164 os <<
" >> Error in Aux[" << i <<
"]^H M Aux[" << j <<
"] == 0 : " << tmp << std::endl;
1185 template <
class ScalarType,
class MV,
class OP>
1193 if (!ritzValsCurrent_) {
1196 computeSchurForm(
false );
1213 template <
class ScalarType,
class MV,
class OP>
1216#ifdef ANASAZI_TEUCHOS_TIME_MONITOR
1217 Teuchos::TimeMonitor LocalTimer(*timerCompRitzVec_);
1220 TEUCHOS_TEST_FOR_EXCEPTION(numRitzVecs_==0, std::invalid_argument,
1221 "Anasazi::BlockKrylovSchur::computeRitzVectors(): no Ritz vectors were required from this solver.");
1223 TEUCHOS_TEST_FOR_EXCEPTION(curDim_ < numRitzVecs_, std::invalid_argument,
1224 "Anasazi::BlockKrylovSchur::computeRitzVectors(): the current subspace is not large enough to compute the number of requested Ritz vectors.");
1228 if (curDim_ && initialized_) {
1231 if (!ritzVecsCurrent_) {
1234 if (!schurCurrent_) {
1237 computeSchurForm(
true );
1242 TEUCHOS_TEST_FOR_EXCEPTION(ritzIndex_[numRitzVecs_-1]==1, std::logic_error,
1243 "Anasazi::BlockKrylovSchur::computeRitzVectors(): the number of required Ritz vectors splits a complex conjugate pair.");
1245 Teuchos::LAPACK<int,ScalarType> lapack;
1246 Teuchos::LAPACK<int,MagnitudeType> lapack_mag;
1256 std::vector<int> curind( curDim_ );
1257 for (
int i=0; i<curDim_; i++) { curind[i] = i; }
1258 Teuchos::RCP<const MV> Vtemp = MVT::CloneView( *V_, curind );
1259 if (problem_->isHermitian()) {
1261 Teuchos::SerialDenseMatrix<int,ScalarType> subQ( Teuchos::View, *Q_, curDim_, numRitzVecs_ );
1264 MVT::MvTimesMatAddMv( ST_ONE, *Vtemp, subQ, ST_ZERO, *ritzVectors_ );
1267 bool complexRitzVals =
false;
1268 for (
int i=0; i<numRitzVecs_; i++) {
1269 if (ritzIndex_[i] != 0) {
1270 complexRitzVals =
true;
1274 if (complexRitzVals)
1275 om_->stream(
Warnings) <<
" Eigenproblem is Hermitian and complex eigenvalues have converged, corresponding eigenvectors will be incorrect!!!"
1280 Teuchos::SerialDenseMatrix<int,ScalarType> subQ( Teuchos::View, *Q_, curDim_, curDim_ );
1283 Teuchos::RCP<MV> tmpritzVectors_ = MVT::Clone( *V_, curDim_ );
1286 MVT::MvTimesMatAddMv( ST_ONE, *Vtemp, subQ, ST_ZERO, *tmpritzVectors_ );
1294 int lwork = 3*curDim_;
1295 std::vector<ScalarType> work( lwork );
1296 std::vector<MagnitudeType> rwork( curDim_ );
1300 ScalarType vl[ ldvl ];
1301 Teuchos::SerialDenseMatrix<int,ScalarType> copyQ( Teuchos::Copy, *Q_, curDim_, curDim_ );
1302 lapack.TREVC( side, curDim_, schurH_->values(), schurH_->stride(), vl, ldvl,
1303 copyQ.values(), copyQ.stride(), curDim_, &mm, &work[0], &rwork[0], &info );
1304 TEUCHOS_TEST_FOR_EXCEPTION(info != 0, std::logic_error,
1305 "Anasazi::BlockKrylovSchur::computeRitzVectors(): TREVC(n==" << curDim_ <<
") returned info " << info <<
" != 0.");
1308 Teuchos::SerialDenseMatrix<int,ScalarType> subCopyQ( Teuchos::View, copyQ, curDim_, numRitzVecs_ );
1311 curind.resize( numRitzVecs_ );
1312 Teuchos::RCP<MV> view_ritzVectors = MVT::CloneViewNonConst( *ritzVectors_, curind );
1313 MVT::MvTimesMatAddMv( ST_ONE, *tmpritzVectors_, subCopyQ, ST_ZERO, *view_ritzVectors );
1316 std::vector<MagnitudeType> ritzNrm( numRitzVecs_ );
1317 MVT::MvNorm( *view_ritzVectors, ritzNrm );
1320 tmpritzVectors_ = Teuchos::null;
1321 view_ritzVectors = Teuchos::null;
1324 ScalarType ritzScale = ST_ONE;
1325 for (
int i=0; i<numRitzVecs_; i++) {
1328 if (ritzIndex_[i] == 1 ) {
1329 ritzScale = ST_ONE/lapack_mag.LAPY2(ritzNrm[i],ritzNrm[i+1]);
1330 std::vector<int> newind(2);
1331 newind[0] = i; newind[1] = i+1;
1332 tmpritzVectors_ = MVT::CloneCopy( *ritzVectors_, newind );
1333 view_ritzVectors = MVT::CloneViewNonConst( *ritzVectors_, newind );
1334 MVT::MvAddMv( ritzScale, *tmpritzVectors_, ST_ZERO, *tmpritzVectors_, *view_ritzVectors );
1341 std::vector<int> newind(1);
1343 tmpritzVectors_ = MVT::CloneCopy( *ritzVectors_, newind );
1344 view_ritzVectors = MVT::CloneViewNonConst( *ritzVectors_, newind );
1345 MVT::MvAddMv( ST_ONE/ritzNrm[i], *tmpritzVectors_, ST_ZERO, *tmpritzVectors_, *view_ritzVectors );
1352 ritzVecsCurrent_ =
true;
1361 template <
class ScalarType,
class MV,
class OP>
1363 TEUCHOS_TEST_FOR_EXCEPTION(test == Teuchos::null,std::invalid_argument,
1364 "Anasazi::BlockKrylovSchur::setStatusTest() was passed a null StatusTest.");
1370 template <
class ScalarType,
class MV,
class OP>
1388 template <
class ScalarType,
class MV,
class OP>
1392#ifdef ANASAZI_TEUCHOS_TIME_MONITOR
1393 Teuchos::TimeMonitor LocalTimer(*timerCompSF_);
1400 if (!schurCurrent_) {
1404 if (!ritzValsCurrent_) {
1405 Teuchos::LAPACK<int,ScalarType> lapack;
1406 Teuchos::LAPACK<int,MagnitudeType> lapack_mag;
1407 Teuchos::BLAS<int,ScalarType> blas;
1408 Teuchos::BLAS<int,MagnitudeType> blas_mag;
1411 Teuchos::SerialDenseMatrix<int,ScalarType> subQ( Teuchos::View, *Q_, curDim_, curDim_ );
1414 schurH_ = Teuchos::rcp(
new Teuchos::SerialDenseMatrix<int,ScalarType>( Teuchos::Copy, *H_, curDim_, curDim_ ) );
1428 int lwork = 3*curDim_;
1429 std::vector<ScalarType> work( lwork );
1430 std::vector<MagnitudeType> rwork( curDim_ );
1431 std::vector<MagnitudeType> tmp_rRitzValues( curDim_ );
1432 std::vector<MagnitudeType> tmp_iRitzValues( curDim_ );
1433 std::vector<int> bwork( curDim_ );
1434 int info = 0, sdim = 0;
1436 lapack.GEES( jobvs,curDim_, schurH_->values(), schurH_->stride(), &sdim, &tmp_rRitzValues[0],
1437 &tmp_iRitzValues[0], subQ.values(), subQ.stride(), &work[0], lwork,
1438 &rwork[0], &bwork[0], &info );
1440 TEUCHOS_TEST_FOR_EXCEPTION(info != 0, std::logic_error,
1441 "Anasazi::BlockKrylovSchur::computeSchurForm(): GEES(n==" << curDim_ <<
") returned info " << info <<
" != 0.");
1447 bool hermImagDetected =
false;
1448 if (problem_->isHermitian()) {
1449 for (
int i=0; i<curDim_; i++)
1451 if (tmp_iRitzValues[i] != MT_ZERO)
1453 hermImagDetected =
true;
1457 if (hermImagDetected) {
1459 om_->stream(
Warnings) <<
" Eigenproblem is Hermitian and complex eigenvalues have been detected!!!" << std::endl;
1461 Teuchos::SerialDenseMatrix<int,ScalarType> localH( Teuchos::View, *H_, curDim_, curDim_ );
1462 Teuchos::RCP<Teuchos::SerialDenseMatrix<int,ScalarType> > tLocalH;
1463 if (Teuchos::ScalarTraits<ScalarType>::isComplex)
1464 tLocalH = Teuchos::rcp(
new Teuchos::SerialDenseMatrix<int,ScalarType>( localH, Teuchos::CONJ_TRANS ) );
1466 tLocalH = Teuchos::rcp(
new Teuchos::SerialDenseMatrix<int,ScalarType>( localH, Teuchos::TRANS ) );
1467 (*tLocalH) -= localH;
1468 MagnitudeType normF = tLocalH->normFrobenius();
1469 MagnitudeType norm1 = tLocalH->normOne();
1470 om_->stream(
Warnings) <<
" Symmetry error in projected eigenproblem: || S - S' ||_F = " << normF
1471 <<
", || S - S' ||_1 = " << norm1 << std::endl;
1489 Teuchos::SerialDenseMatrix<int,ScalarType> curB(Teuchos::View, *H_,
1490 blockSize_, curDim_, curDim_ );
1493 Teuchos::SerialDenseMatrix<int,ScalarType> subB( blockSize_, curDim_ );
1494 blas.GEMM( Teuchos::NO_TRANS, Teuchos::NO_TRANS, blockSize_, curDim_, curDim_, ST_ONE,
1495 curB.values(), curB.stride(), subQ.values(), subQ.stride(),
1496 ST_ZERO, subB.values(), subB.stride() );
1500 ScalarType* b_ptr = subB.values();
1501 if (problem_->isHermitian() && !hermImagDetected) {
1505 for (
int i=0; i<curDim_ ; i++) {
1506 ritzResiduals_[i] = blas.NRM2(blockSize_, b_ptr + i*blockSize_, 1);
1515 ScalarType vl[ ldvl ];
1516 Teuchos::SerialDenseMatrix<int,ScalarType> S( curDim_, curDim_ );
1517 lapack.TREVC( side, curDim_, schurH_->values(), schurH_->stride(), vl, ldvl,
1518 S.values(), S.stride(), curDim_, &mm, &work[0], &rwork[0], &info );
1520 TEUCHOS_TEST_FOR_EXCEPTION(info != 0, std::logic_error,
1521 "Anasazi::BlockKrylovSchur::computeSchurForm(): TREVC(n==" << curDim_ <<
") returned info " << info <<
" != 0.");
1529 Teuchos::SerialDenseMatrix<int,ScalarType> ritzRes( blockSize_, curDim_ );
1530 blas.GEMM( Teuchos::NO_TRANS, Teuchos::NO_TRANS, blockSize_, curDim_, curDim_, ST_ONE,
1531 subB.values(), subB.stride(), S.values(), S.stride(),
1532 ST_ZERO, ritzRes.values(), ritzRes.stride() );
1566#ifdef ANASAZI_TEUCHOS_TIME_MONITOR
1567 Teuchos::TimeMonitor LocalTimer2(*timerSortRitzVal_);
1570 if (problem_->isHermitian() && !hermImagDetected) {
1573 sm_->sort(tmp_rRitzValues, Teuchos::rcpFromRef(ritzOrder_), curDim_);
1575 while ( i < curDim_ ) {
1577 ritzValues_[i].set(tmp_rRitzValues[i], MT_ZERO);
1578 ritzIndex_.push_back(0);
1585 sm_->sort(tmp_rRitzValues, tmp_iRitzValues, Teuchos::rcpFromRef(ritzOrder_) , curDim_);
1590 std::vector<MagnitudeType> ritz2( curDim_ );
1591 for (i=0; i<curDim_; i++) { ritz2[i] = ritzResiduals_[ ritzOrder_[i] ]; }
1592 blas_mag.COPY( curDim_, &ritz2[0], 1, &ritzResiduals_[0], 1 );
1595 ritzValsCurrent_ =
true;
1611 sortSchurForm( *schurH_, *Q_, ritzOrder_ );
1614 schurCurrent_ =
true;
1625 template <
class ScalarType,
class MV,
class OP>
1627 Teuchos::SerialDenseMatrix<int,ScalarType>& Q,
1628 std::vector<int>& order )
1631#ifdef ANASAZI_TEUCHOS_TIME_MONITOR
1632 Teuchos::TimeMonitor LocalTimer(*timerSortSF_);
1643 int i = 0, nevtemp = 0;
1645 std::vector<int> offset2( curDim_ );
1646 std::vector<int> order2( curDim_ );
1649 Teuchos::LAPACK<int,ScalarType> lapack;
1650 int lwork = 3*curDim_;
1651 std::vector<ScalarType> work( lwork );
1653 while (i < curDim_) {
1654 if ( ritzIndex_[i] != 0 ) {
1655 offset2[nevtemp] = 0;
1656 for (
int j=i; j<curDim_; j++) {
1657 if (order[j] > order[i]) { offset2[nevtemp]++; }
1659 order2[nevtemp] = order[i];
1662 offset2[nevtemp] = 0;
1663 for (
int j=i; j<curDim_; j++) {
1664 if (order[j] > order[i]) { offset2[nevtemp]++; }
1666 order2[nevtemp] = order[i];
1671 ScalarType *ptr_h = H.values();
1672 ScalarType *ptr_q = Q.values();
1673 int ldh = H.stride(), ldq = Q.stride();
1675 for (i=nevtemp-1; i>=0; i--) {
1676 int ifst = order2[i]+1+offset2[i];
1678 lapack.TREXC( compq, curDim_, ptr_h, ldh, ptr_q, ldq, &ifst,
1679 &ilst, &work[0], &info );
1680 TEUCHOS_TEST_FOR_EXCEPTION(info != 0, std::logic_error,
1681 "Anasazi::BlockKrylovSchur::computeSchurForm(): TREXC(n==" << curDim_ <<
") returned info " << info <<
" != 0.");
1687 template <
class ScalarType,
class MV,
class OP>
1692 os.setf(std::ios::scientific, std::ios::floatfield);
1694 os <<
"================================================================================" << endl;
1696 os <<
" BlockKrylovSchur Solver Status" << endl;
1698 os <<
"The solver is "<<(initialized_ ?
"initialized." :
"not initialized.") << endl;
1699 os <<
"The number of iterations performed is " <<iter_<<endl;
1700 os <<
"The block size is " << blockSize_<<endl;
1701 os <<
"The number of blocks is " << numBlocks_<<endl;
1702 os <<
"The current basis size is " << curDim_<<endl;
1703 os <<
"The number of auxiliary vectors is " << numAuxVecs_ << endl;
1704 os <<
"The number of operations Op*x is "<<count_ApplyOp_<<endl;
1706 os.setf(std::ios_base::right, std::ios_base::adjustfield);
1710 os <<
"CURRENT RITZ VALUES "<<endl;
1711 if (ritzIndex_.size() != 0) {
1712 int numPrint = (curDim_ < numRitzPrint_? curDim_: numRitzPrint_);
1713 if (problem_->isHermitian()) {
1714 os << std::setw(20) <<
"Ritz Value"
1715 << std::setw(20) <<
"Ritz Residual"
1717 os <<
"--------------------------------------------------------------------------------"<<endl;
1718 for (
int i=0; i<numPrint; i++) {
1719 os << std::setw(20) << ritzValues_[i].realpart
1720 << std::setw(20) << ritzResiduals_[i]
1724 os << std::setw(24) <<
"Ritz Value"
1725 << std::setw(30) <<
"Ritz Residual"
1727 os <<
"--------------------------------------------------------------------------------"<<endl;
1728 for (
int i=0; i<numPrint; i++) {
1730 os << std::setw(15) << ritzValues_[i].realpart;
1731 if (ritzValues_[i].imagpart < MT_ZERO) {
1732 os <<
" - i" << std::setw(15) << Teuchos::ScalarTraits<MagnitudeType>::magnitude(ritzValues_[i].imagpart);
1734 os <<
" + i" << std::setw(15) << ritzValues_[i].imagpart;
1736 os << std::setw(20) << ritzResiduals_[i] << endl;
1740 os << std::setw(20) <<
"[ NONE COMPUTED ]" << endl;
1744 os <<
"================================================================================" << endl;
Pure virtual base class which describes the basic interface to the iterative eigensolver.
Declaration of basic traits for the multivector type.
Virtual base class which defines basic traits for the operator type.
Templated virtual class for providing orthogonalization/orthonormalization methods.
Types and exceptions used within Anasazi solvers and interfaces.
An exception class parent to all Anasazi exceptions.
BlockKrylovSchurInitFailure is thrown when the BlockKrylovSchur solver is unable to generate an initi...
BlockKrylovSchurOrthoFailure is thrown when the orthogonalization manager is unable to generate ortho...
This class implements the block Krylov-Schur iteration, for solving linear eigenvalue problems.
void resetNumIters()
Reset the iteration count.
const Eigenproblem< ScalarType, MV, OP > & getProblem() const
Get a constant reference to the eigenvalue problem.
void computeSchurForm(const bool sort=true)
Compute the Schur form of the projected eigenproblem from the current Krylov factorization.
void setNumRitzVectors(int numRitzVecs)
Set the number of Ritz vectors to compute.
BlockKrylovSchur(const Teuchos::RCP< Eigenproblem< ScalarType, MV, OP > > &problem, const Teuchos::RCP< SortManager< typename Teuchos::ScalarTraits< ScalarType >::magnitudeType > > &sorter, const Teuchos::RCP< OutputManager< ScalarType > > &printer, const Teuchos::RCP< StatusTest< ScalarType, MV, OP > > &tester, const Teuchos::RCP< OrthoManager< ScalarType, MV > > &ortho, Teuchos::ParameterList ¶ms)
BlockKrylovSchur constructor with eigenproblem, solver utilities, and parameter list of solver option...
BlockKrylovSchurState< ScalarType, MV > getState() const
Get the current state of the eigensolver.
void setAuxVecs(const Teuchos::Array< Teuchos::RCP< const MV > > &auxvecs)
Set the auxiliary vectors for the solver.
bool isInitialized() const
Indicates whether the solver has been initialized or not.
Teuchos::RCP< const MV > getRitzVectors()
Get the Ritz vectors.
void setStepSize(int stepSize)
Set the step size.
int getMaxSubspaceDim() const
Get the maximum dimension allocated for the search subspace.
bool isSchurCurrent() const
Get the status of the Schur form currently stored in the eigensolver.
void iterate()
This method performs Block Krylov-Schur iterations until the status test indicates the need to stop o...
void computeRitzValues()
Compute the Ritz values using the current Krylov factorization.
Teuchos::Array< Teuchos::RCP< const MV > > getAuxVecs() const
Get the auxiliary vectors for the solver.
void setStatusTest(Teuchos::RCP< StatusTest< ScalarType, MV, OP > > test)
Set a new StatusTest for the solver.
void setSize(int blockSize, int numBlocks)
Set the blocksize and number of blocks to be used by the iterative solver in solving this eigenproble...
void initialize()
Initialize the solver with the initial vectors from the eigenproblem or random data.
int getCurSubspaceDim() const
Get the dimension of the search subspace used to generate the current eigenvectors and eigenvalues.
void setBlockSize(int blockSize)
Set the blocksize.
Teuchos::RCP< StatusTest< ScalarType, MV, OP > > getStatusTest() const
Get the current StatusTest used by the solver.
bool isRitzVecsCurrent() const
Get the status of the Ritz vectors currently stored in the eigensolver.
std::vector< typename Teuchos::ScalarTraits< ScalarType >::magnitudeType > getRes2Norms()
Get the current residual 2-norms.
bool isRitzValsCurrent() const
Get the status of the Ritz values currently stored in the eigensolver.
int getNumIters() const
Get the current iteration count.
std::vector< int > getRitzIndex()
Get the Ritz index vector.
std::vector< typename Teuchos::ScalarTraits< ScalarType >::magnitudeType > getRitzRes2Norms()
Get the current Ritz residual 2-norms.
int getStepSize() const
Get the step size.
std::vector< typename Teuchos::ScalarTraits< ScalarType >::magnitudeType > getResNorms()
Get the current residual norms.
std::vector< Value< ScalarType > > getRitzValues()
Get the Ritz values.
void computeRitzVectors()
Compute the Ritz vectors using the current Krylov factorization.
int getNumRitzVectors() const
Get the number of Ritz vectors to compute.
void currentStatus(std::ostream &os)
This method requests that the solver print out its current status to screen.
int getBlockSize() const
Get the blocksize to be used by the iterative solver in solving this eigenproblem.
virtual ~BlockKrylovSchur()
BlockKrylovSchur destructor.
This class defines the interface required by an eigensolver and status test class to compute solution...
The Eigensolver is a templated virtual base class that defines the basic interface that any eigensolv...
static void computeRitzResiduals(const std::vector< typename Teuchos::ScalarTraits< ScalarType >::magnitudeType > &iRV, const Teuchos::SerialDenseMatrix< int, ScalarType > &S, std::vector< typename Teuchos::ScalarTraits< ScalarType >::magnitudeType > *RR)
Helper function for correctly computing the Ritz residuals of the projected eigenproblem.
static void scaleRitzVectors(const std::vector< typename Teuchos::ScalarTraits< ScalarType >::magnitudeType > &iRV, Teuchos::SerialDenseMatrix< int, ScalarType > *S)
Helper function for correctly scaling the eigenvectors of the projected eigenproblem.
static void sortRitzValues(const std::vector< typename Teuchos::ScalarTraits< ScalarType >::magnitudeType > &rRV, const std::vector< typename Teuchos::ScalarTraits< ScalarType >::magnitudeType > &iRV, std::vector< Value< ScalarType > > *RV, std::vector< int > *RO, std::vector< int > *RI)
Helper function for correctly storing the Ritz values when the eigenproblem is non-Hermitian.
Traits class which defines basic operations on multivectors.
Virtual base class which defines basic traits for the operator type.
Anasazi's templated virtual class for providing routines for orthogonalization and orthonormalization...
Output managers remove the need for the eigensolver to know any information about the required output...
Anasazi's templated pure virtual class for managing the sorting of approximate eigenvalues computed b...
Common interface of stopping criteria for Anasazi's solvers.
Namespace Anasazi contains the classes, structs, enums and utilities used by the Anasazi package.
Structure to contain pointers to BlockKrylovSchur state variables.
Teuchos::RCP< const Teuchos::SerialDenseMatrix< int, ScalarType > > S
The current Schur form reduction of the valid part of H.
int curDim
The current dimension of the reduction.
Teuchos::RCP< const Teuchos::SerialDenseMatrix< int, ScalarType > > Q
The current Schur vectors of the valid part of H.
Teuchos::RCP< const Teuchos::SerialDenseMatrix< int, ScalarType > > H
The current Hessenberg matrix.
Teuchos::RCP< const MulVec > V
The current Krylov basis.