46 #ifndef ANASAZI_BLOCK_KRYLOV_SCHUR_HPP 47 #define ANASAZI_BLOCK_KRYLOV_SCHUR_HPP 54 #include "Teuchos_ScalarTraits.hpp" 55 #include "AnasaziHelperTraits.hpp" 59 #include "Teuchos_LAPACK.hpp" 60 #include "Teuchos_BLAS.hpp" 61 #include "Teuchos_SerialDenseMatrix.hpp" 62 #include "Teuchos_ParameterList.hpp" 63 #include "Teuchos_TimeMonitor.hpp" 88 template <
class ScalarType,
class MulVec>
96 Teuchos::RCP<const MulVec>
V;
102 Teuchos::RCP<const Teuchos::SerialDenseMatrix<int,ScalarType> >
H;
104 Teuchos::RCP<const Teuchos::SerialDenseMatrix<int,ScalarType> >
S;
106 Teuchos::RCP<const Teuchos::SerialDenseMatrix<int,ScalarType> >
Q;
108 H(Teuchos::null), S(Teuchos::null),
146 template <
class ScalarType,
class MV,
class OP>
164 const Teuchos::RCP<
SortManager<
typename Teuchos::ScalarTraits<ScalarType>::magnitudeType> > &sorter,
168 Teuchos::ParameterList ¶ms
286 std::vector<Value<ScalarType> > ret = ritzValues_;
287 ret.resize(ritzIndex_.size());
302 std::vector<typename Teuchos::ScalarTraits<ScalarType>::magnitudeType>
getResNorms() {
303 std::vector<typename Teuchos::ScalarTraits<ScalarType>::magnitudeType> ret(0);
311 std::vector<typename Teuchos::ScalarTraits<ScalarType>::magnitudeType>
getRes2Norms() {
312 std::vector<typename Teuchos::ScalarTraits<ScalarType>::magnitudeType> ret(0);
320 std::vector<typename Teuchos::ScalarTraits<ScalarType>::magnitudeType>
getRitzRes2Norms() {
321 std::vector<typename Teuchos::ScalarTraits<ScalarType>::magnitudeType> ret = ritzResiduals_;
322 ret.resize(ritzIndex_.size());
335 Teuchos::RCP<StatusTest<ScalarType,MV,OP> > getStatusTest()
const;
346 void setSize(
int blockSize,
int numBlocks);
349 void setBlockSize(
int blockSize);
352 void setStepSize(
int stepSize);
355 void setNumRitzVectors(
int numRitzVecs);
372 if (!initialized_)
return 0;
377 int getMaxSubspaceDim()
const {
return (problem_->isHermitian()?blockSize_*numBlocks_:blockSize_*numBlocks_+1); }
392 void setAuxVecs(
const Teuchos::Array<Teuchos::RCP<const MV> > &auxvecs);
395 Teuchos::Array<Teuchos::RCP<const MV> >
getAuxVecs()
const {
return auxVecs_;}
403 void currentStatus(std::ostream &os);
425 void computeRitzVectors();
428 void computeRitzValues();
431 void computeSchurForm(
const bool sort =
true );
441 typedef Teuchos::ScalarTraits<ScalarType> SCT;
442 typedef typename SCT::magnitudeType MagnitudeType;
443 typedef typename std::vector<ScalarType>::iterator STiter;
444 typedef typename std::vector<MagnitudeType>::iterator MTiter;
445 const MagnitudeType MT_ONE;
446 const MagnitudeType MT_ZERO;
447 const MagnitudeType NANVAL;
448 const ScalarType ST_ONE;
449 const ScalarType ST_ZERO;
457 CheckList() : checkV(
false), checkArn(
false), checkAux(
false) {};
462 std::string accuracyCheck(
const CheckList &chk,
const std::string &where)
const;
463 void sortSchurForm( Teuchos::SerialDenseMatrix<int,ScalarType>&
H,
464 Teuchos::SerialDenseMatrix<int,ScalarType>&
Q,
465 std::vector<int>& order );
469 const Teuchos::RCP<Eigenproblem<ScalarType,MV,OP> > problem_;
470 const Teuchos::RCP<SortManager<typename Teuchos::ScalarTraits<ScalarType>::magnitudeType> > sm_;
471 const Teuchos::RCP<OutputManager<ScalarType> > om_;
472 Teuchos::RCP<StatusTest<ScalarType,MV,OP> > tester_;
473 const Teuchos::RCP<OrthoManager<ScalarType,MV> > orthman_;
477 Teuchos::RCP<const OP> Op_;
481 Teuchos::RCP<Teuchos::Time> timerOp_, timerSortRitzVal_,
482 timerCompSF_, timerSortSF_,
483 timerCompRitzVec_, timerOrtho_;
517 Teuchos::RCP<MV> ritzVectors_, V_;
523 Teuchos::RCP<Teuchos::SerialDenseMatrix<int,ScalarType> > H_;
528 Teuchos::RCP<Teuchos::SerialDenseMatrix<int,ScalarType> > schurH_;
529 Teuchos::RCP<Teuchos::SerialDenseMatrix<int,ScalarType> > Q_;
532 Teuchos::Array<Teuchos::RCP<const MV> > auxVecs_;
539 bool ritzVecsCurrent_, ritzValsCurrent_, schurCurrent_;
542 std::vector<Value<ScalarType> > ritzValues_;
543 std::vector<MagnitudeType> ritzResiduals_;
546 std::vector<int> ritzIndex_;
547 std::vector<int> ritzOrder_;
556 template <
class ScalarType,
class MV,
class OP>
559 const Teuchos::RCP<
SortManager<
typename Teuchos::ScalarTraits<ScalarType>::magnitudeType> > &sorter,
563 Teuchos::ParameterList ¶ms
565 MT_ONE(Teuchos::ScalarTraits<MagnitudeType>::one()),
566 MT_ZERO(Teuchos::ScalarTraits<MagnitudeType>::zero()),
567 NANVAL(Teuchos::ScalarTraits<MagnitudeType>::nan()),
568 ST_ONE(Teuchos::ScalarTraits<ScalarType>::one()),
569 ST_ZERO(Teuchos::ScalarTraits<ScalarType>::zero()),
577 #ifdef ANASAZI_TEUCHOS_TIME_MONITOR
578 timerOp_(Teuchos::TimeMonitor::getNewTimer(
"Anasazi: BlockKrylovSchur::Operation Op*x")),
579 timerSortRitzVal_(Teuchos::TimeMonitor::getNewTimer(
"Anasazi: BlockKrylovSchur::Sorting Ritz values")),
580 timerCompSF_(Teuchos::TimeMonitor::getNewTimer(
"Anasazi: BlockKrylovSchur::Computing Schur form")),
581 timerSortSF_(Teuchos::TimeMonitor::getNewTimer(
"Anasazi: BlockKrylovSchur::Sorting Schur form")),
582 timerCompRitzVec_(Teuchos::TimeMonitor::getNewTimer(
"Anasazi: BlockKrylovSchur::Computing Ritz vectors")),
583 timerOrtho_(Teuchos::TimeMonitor::getNewTimer(
"Anasazi: BlockKrylovSchur::Orthogonalization")),
593 auxVecs_( Teuchos::Array<Teuchos::RCP<const MV> >(0) ),
596 ritzVecsCurrent_(false),
597 ritzValsCurrent_(false),
598 schurCurrent_(false),
601 TEUCHOS_TEST_FOR_EXCEPTION(problem_ == Teuchos::null,std::invalid_argument,
602 "Anasazi::BlockKrylovSchur::constructor: user specified null problem pointer.");
603 TEUCHOS_TEST_FOR_EXCEPTION(sm_ == Teuchos::null,std::invalid_argument,
604 "Anasazi::BlockKrylovSchur::constructor: user passed null sort manager pointer.");
605 TEUCHOS_TEST_FOR_EXCEPTION(om_ == Teuchos::null,std::invalid_argument,
606 "Anasazi::BlockKrylovSchur::constructor: user passed null output manager pointer.");
607 TEUCHOS_TEST_FOR_EXCEPTION(tester_ == Teuchos::null,std::invalid_argument,
608 "Anasazi::BlockKrylovSchur::constructor: user passed null status test pointer.");
609 TEUCHOS_TEST_FOR_EXCEPTION(orthman_ == Teuchos::null,std::invalid_argument,
610 "Anasazi::BlockKrylovSchur::constructor: user passed null orthogonalization manager pointer.");
611 TEUCHOS_TEST_FOR_EXCEPTION(problem_->isProblemSet() ==
false, std::invalid_argument,
612 "Anasazi::BlockKrylovSchur::constructor: user specified problem is not set.");
613 TEUCHOS_TEST_FOR_EXCEPTION(sorter == Teuchos::null,std::invalid_argument,
614 "Anasazi::BlockKrylovSchur::constructor: user specified null sort manager pointer.");
615 TEUCHOS_TEST_FOR_EXCEPTION(printer == Teuchos::null,std::invalid_argument,
616 "Anasazi::BlockKrylovSchur::constructor: user specified null output manager pointer.");
617 TEUCHOS_TEST_FOR_EXCEPTION(tester == Teuchos::null,std::invalid_argument,
618 "Anasazi::BlockKrylovSchur::constructor: user specified null status test pointer.");
619 TEUCHOS_TEST_FOR_EXCEPTION(ortho == Teuchos::null,std::invalid_argument,
620 "Anasazi::BlockKrylovSchur::constructor: user specified null ortho manager pointer.");
623 Op_ = problem_->getOperator();
626 TEUCHOS_TEST_FOR_EXCEPTION(!params.isParameter(
"Step Size"), std::invalid_argument,
627 "Anasazi::BlockKrylovSchur::constructor: mandatory parameter 'Step Size' is not specified.");
628 int ss = params.get(
"Step Size",numBlocks_);
632 int bs = params.get(
"Block Size", 1);
633 int nb = params.get(
"Num Blocks", 3*problem_->getNEV());
638 int numRitzVecs = params.get(
"Number of Ritz Vectors", 0);
642 numRitzPrint_ = params.get(
"Print Number of Ritz Values", bs);
649 template <
class ScalarType,
class MV,
class OP>
658 template <
class ScalarType,
class MV,
class OP>
661 TEUCHOS_TEST_FOR_EXCEPTION(stepSize <= 0, std::invalid_argument,
"Anasazi::BlockKrylovSchur::setStepSize(): new step size must be positive and non-zero.");
662 stepSize_ = stepSize;
667 template <
class ScalarType,
class MV,
class OP>
673 TEUCHOS_TEST_FOR_EXCEPTION(numRitzVecs < 0, std::invalid_argument,
"Anasazi::BlockKrylovSchur::setNumRitzVectors(): number of Ritz vectors to compute must be positive.");
676 if (numRitzVecs != numRitzVecs_) {
678 ritzVectors_ = Teuchos::null;
681 ritzVectors_ = Teuchos::null;
683 numRitzVecs_ = numRitzVecs;
684 ritzVecsCurrent_ =
false;
690 template <
class ScalarType,
class MV,
class OP>
696 TEUCHOS_TEST_FOR_EXCEPTION(numBlocks <= 0 || blockSize <= 0, std::invalid_argument,
"Anasazi::BlockKrylovSchur::setSize was passed a non-positive argument.");
697 TEUCHOS_TEST_FOR_EXCEPTION(numBlocks < 3, std::invalid_argument,
"Anasazi::BlockKrylovSchur::setSize(): numBlocks must be at least three.");
698 if (blockSize == blockSize_ && numBlocks == numBlocks_) {
703 blockSize_ = blockSize;
704 numBlocks_ = numBlocks;
706 Teuchos::RCP<const MV> tmp;
712 if (problem_->getInitVec() != Teuchos::null) {
713 tmp = problem_->getInitVec();
717 TEUCHOS_TEST_FOR_EXCEPTION(tmp == Teuchos::null,std::invalid_argument,
718 "Anasazi::BlockKrylovSchur::setSize(): eigenproblem did not specify initial vectors to clone from.");
726 if (problem_->isHermitian()) {
727 newsd = blockSize_*numBlocks_;
729 newsd = blockSize_*numBlocks_+1;
732 TEUCHOS_TEST_FOR_EXCEPTION(static_cast<ptrdiff_t>(newsd) >
MVT::GetGlobalLength(*tmp),std::invalid_argument,
733 "Anasazi::BlockKrylovSchur::setSize(): maximum basis size is larger than problem dimension.");
735 ritzValues_.resize(newsd);
736 ritzResiduals_.resize(newsd,MT_ONE);
737 ritzOrder_.resize(newsd);
740 H_ = Teuchos::rcp(
new Teuchos::SerialDenseMatrix<int,ScalarType>(newsd+blockSize_,newsd) );
741 Q_ = Teuchos::rcp(
new Teuchos::SerialDenseMatrix<int,ScalarType>(newsd,newsd) );
743 initialized_ =
false;
750 template <
class ScalarType,
class MV,
class OP>
752 typedef typename Teuchos::Array<Teuchos::RCP<const MV> >::iterator tarcpmv;
757 if (om_->isVerbosity(
Debug ) ) {
761 om_->print(
Debug, accuracyCheck(chk,
": in setAuxVecs()") );
765 for (tarcpmv i=auxVecs_.begin(); i != auxVecs_.end(); i++) {
770 if (numAuxVecs_ > 0 && initialized_) {
771 initialized_ =
false;
784 template <
class ScalarType,
class MV,
class OP>
789 std::vector<int> bsind(blockSize_);
790 for (
int i=0; i<blockSize_; i++) bsind[i] = i;
798 std::string errstr(
"Anasazi::BlockKrylovSchur::initialize(): specified multivectors must have a consistent length and width.");
802 if (newstate.
V != Teuchos::null && newstate.
H != Teuchos::null) {
807 std::invalid_argument, errstr );
808 if (newstate.
V != V_) {
810 std::invalid_argument, errstr );
812 std::invalid_argument, errstr );
815 std::invalid_argument, errstr );
817 curDim_ = newstate.
curDim;
821 TEUCHOS_TEST_FOR_EXCEPTION(newstate.
H->numRows() < curDim_ || newstate.
H->numCols() < curDim_, std::invalid_argument, errstr);
823 if (curDim_ == 0 && lclDim > blockSize_) {
824 om_->stream(
Warnings) <<
"Anasazi::BlockKrylovSchur::initialize(): the solver was initialized with a kernel of " << lclDim << std::endl
825 <<
"The block size however is only " << blockSize_ << std::endl
826 <<
"The last " << lclDim - blockSize_ <<
" vectors of the kernel will be overwritten on the first call to iterate()." << std::endl;
831 if (newstate.
V != V_) {
832 std::vector<int> nevind(lclDim);
833 for (
int i=0; i<lclDim; i++) nevind[i] = i;
838 if (newstate.
H != H_) {
839 H_->putScalar( ST_ZERO );
840 Teuchos::SerialDenseMatrix<int,ScalarType> newH(Teuchos::View,*newstate.
H,curDim_+blockSize_,curDim_);
841 Teuchos::RCP<Teuchos::SerialDenseMatrix<int,ScalarType> > lclH;
842 lclH = Teuchos::rcp(
new Teuchos::SerialDenseMatrix<int,ScalarType>(Teuchos::View,*H_,curDim_+blockSize_,curDim_) );
846 lclH = Teuchos::null;
853 Teuchos::RCP<const MV> ivec = problem_->getInitVec();
854 TEUCHOS_TEST_FOR_EXCEPTION(ivec == Teuchos::null,std::invalid_argument,
855 "Anasazi::BlockKrylovSchur::initialize(): eigenproblem did not specify initial vectors to clone from.");
858 bool userand =
false;
859 if (lclDim < blockSize_) {
867 std::vector<int> dimind2(lclDim);
868 for (
int i=0; i<lclDim; i++) { dimind2[i] = i; }
877 dimind2.resize(blockSize_-lclDim);
878 for (
int i=0; i<blockSize_-lclDim; i++) { dimind2[i] = lclDim + i; }
899 if (auxVecs_.size() > 0) {
900 #ifdef ANASAZI_TEUCHOS_TIME_MONITOR 901 Teuchos::TimeMonitor lcltimer( *timerOrtho_ );
904 Teuchos::Array<Teuchos::RCP<Teuchos::SerialDenseMatrix<int,ScalarType> > > dummy;
905 int rank = orthman_->projectAndNormalize(*newV,auxVecs_);
907 "Anasazi::BlockKrylovSchur::initialize(): couldn't generate initial basis of full rank." );
910 #ifdef ANASAZI_TEUCHOS_TIME_MONITOR 911 Teuchos::TimeMonitor lcltimer( *timerOrtho_ );
914 int rank = orthman_->normalize(*newV);
916 "Anasazi::BlockKrylovSchur::initialize(): couldn't generate initial basis of full rank." );
923 newV = Teuchos::null;
927 ritzVecsCurrent_ =
false;
928 ritzValsCurrent_ =
false;
929 schurCurrent_ =
false;
934 if (om_->isVerbosity(
Debug ) ) {
940 om_->print(
Debug, accuracyCheck(chk,
": after initialize()") );
944 if (om_->isVerbosity(
Debug)) {
955 template <
class ScalarType,
class MV,
class OP>
965 template <
class ScalarType,
class MV,
class OP>
971 if (initialized_ ==
false) {
977 int searchDim = blockSize_*numBlocks_;
978 if (problem_->isHermitian() ==
false) {
987 while (tester_->checkStatus(
this) !=
Passed && curDim_+blockSize_ <= searchDim) {
992 int lclDim = curDim_ + blockSize_;
995 std::vector<int> curind(blockSize_);
996 for (
int i=0; i<blockSize_; i++) { curind[i] = lclDim + i; }
1001 for (
int i=0; i<blockSize_; i++) { curind[i] = curDim_ + i; }
1008 #ifdef ANASAZI_TEUCHOS_TIME_MONITOR 1009 Teuchos::TimeMonitor lcltimer( *timerOp_ );
1012 count_ApplyOp_ += blockSize_;
1016 Vprev = Teuchos::null;
1020 #ifdef ANASAZI_TEUCHOS_TIME_MONITOR 1021 Teuchos::TimeMonitor lcltimer( *timerOrtho_ );
1025 std::vector<int> prevind(lclDim);
1026 for (
int i=0; i<lclDim; i++) { prevind[i] = i; }
1028 Teuchos::Array<Teuchos::RCP<const MV> > AVprev(1, Vprev);
1031 Teuchos::RCP<Teuchos::SerialDenseMatrix<int,ScalarType> >
1032 subH = Teuchos::rcp(
new Teuchos::SerialDenseMatrix<int,ScalarType>
1033 ( Teuchos::View,*H_,lclDim,blockSize_,0,curDim_ ) );
1034 Teuchos::Array<Teuchos::RCP<Teuchos::SerialDenseMatrix<int,ScalarType> > > AsubH;
1035 AsubH.append( subH );
1038 if (auxVecs_.size() > 0) {
1039 for (Array_size_type i=0; i<auxVecs_.size(); i++) {
1040 AVprev.append( auxVecs_[i] );
1041 AsubH.append( Teuchos::null );
1048 Teuchos::RCP<Teuchos::SerialDenseMatrix<int,ScalarType> >
1049 subR = Teuchos::rcp(
new Teuchos::SerialDenseMatrix<int,ScalarType>
1050 ( Teuchos::View,*H_,blockSize_,blockSize_,lclDim,curDim_ ) );
1051 int rank = orthman_->projectAndNormalize(*Vnext,AVprev,AsubH,subR);
1058 "Anasazi::BlockKrylovSchur::iterate(): couldn't generate basis of full rank.");
1064 Vnext = Teuchos::null;
1065 curDim_ += blockSize_;
1067 ritzVecsCurrent_ =
false;
1068 ritzValsCurrent_ =
false;
1069 schurCurrent_ =
false;
1072 if (!(iter_%stepSize_)) {
1077 if (om_->isVerbosity(
Debug ) ) {
1081 chk.checkArn =
true;
1082 om_->print(
Debug, accuracyCheck(chk,
": after local update") );
1087 om_->print(
OrthoDetails, accuracyCheck(chk,
": after local update") );
1091 if (om_->isVerbosity(
Debug)) {
1116 template <
class ScalarType,
class MV,
class OP>
1119 std::stringstream os;
1121 os.setf(std::ios::scientific, std::ios::floatfield);
1124 os <<
" Debugging checks: iteration " << iter_ << where << std::endl;
1127 std::vector<int> lclind(curDim_);
1128 for (
int i=0; i<curDim_; i++) lclind[i] = i;
1129 std::vector<int> bsind(blockSize_);
1130 for (
int i=0; i<blockSize_; i++) { bsind[i] = curDim_ + i; }
1132 Teuchos::RCP<const MV> lclV,lclF;
1133 Teuchos::RCP<MV> lclAV;
1140 tmp = orthman_->orthonormError(*lclV);
1141 os <<
" >> Error in V^H M V == I : " << tmp << std::endl;
1143 tmp = orthman_->orthonormError(*lclF);
1144 os <<
" >> Error in F^H M F == I : " << tmp << std::endl;
1146 tmp = orthman_->orthogError(*lclV,*lclF);
1147 os <<
" >> Error in V^H M F == 0 : " << tmp << std::endl;
1149 for (Array_size_type i=0; i<auxVecs_.size(); i++) {
1151 tmp = orthman_->orthogError(*lclV,*auxVecs_[i]);
1152 os <<
" >> Error in V^H M Aux[" << i <<
"] == 0 : " << tmp << std::endl;
1154 tmp = orthman_->orthogError(*lclF,*auxVecs_[i]);
1155 os <<
" >> Error in F^H M Aux[" << i <<
"] == 0 : " << tmp << std::endl;
1165 #ifdef ANASAZI_TEUCHOS_TIME_MONITOR 1166 Teuchos::TimeMonitor lcltimer( *timerOp_ );
1172 Teuchos::SerialDenseMatrix<int,ScalarType> subH(Teuchos::View,*H_,curDim_,curDim_);
1176 Teuchos::SerialDenseMatrix<int,ScalarType> curB(Teuchos::View,*H_,
1177 blockSize_,curDim_, curDim_ );
1181 std::vector<MagnitudeType> arnNorms( curDim_ );
1182 orthman_->norm( *lclAV, arnNorms );
1184 for (
int i=0; i<curDim_; i++) {
1185 os <<
" >> Error in Krylov-Schur factorization (R = AV-VS-FB^H), ||R[" << i <<
"]|| : " << arnNorms[i] << std::endl;
1191 for (Array_size_type i=0; i<auxVecs_.size(); i++) {
1192 tmp = orthman_->orthonormError(*auxVecs_[i]);
1193 os <<
" >> Error in Aux[" << i <<
"]^H M Aux[" << i <<
"] == I : " << tmp << std::endl;
1194 for (Array_size_type j=i+1; j<auxVecs_.size(); j++) {
1195 tmp = orthman_->orthogError(*auxVecs_[i],*auxVecs_[j]);
1196 os <<
" >> Error in Aux[" << i <<
"]^H M Aux[" << j <<
"] == 0 : " << tmp << std::endl;
1217 template <
class ScalarType,
class MV,
class OP>
1225 if (!ritzValsCurrent_) {
1245 template <
class ScalarType,
class MV,
class OP>
1248 #ifdef ANASAZI_TEUCHOS_TIME_MONITOR 1249 Teuchos::TimeMonitor LocalTimer(*timerCompRitzVec_);
1252 TEUCHOS_TEST_FOR_EXCEPTION(numRitzVecs_==0, std::invalid_argument,
1253 "Anasazi::BlockKrylovSchur::computeRitzVectors(): no Ritz vectors were required from this solver.");
1255 TEUCHOS_TEST_FOR_EXCEPTION(curDim_ < numRitzVecs_, std::invalid_argument,
1256 "Anasazi::BlockKrylovSchur::computeRitzVectors(): the current subspace is not large enough to compute the number of requested Ritz vectors.");
1260 if (curDim_ && initialized_) {
1263 if (!ritzVecsCurrent_) {
1266 if (!schurCurrent_) {
1274 TEUCHOS_TEST_FOR_EXCEPTION(ritzIndex_[numRitzVecs_-1]==1, std::logic_error,
1275 "Anasazi::BlockKrylovSchur::computeRitzVectors(): the number of required Ritz vectors splits a complex conjugate pair.");
1277 Teuchos::LAPACK<int,ScalarType> lapack;
1278 Teuchos::LAPACK<int,MagnitudeType> lapack_mag;
1288 std::vector<int> curind( curDim_ );
1289 for (
int i=0; i<curDim_; i++) { curind[i] = i; }
1291 if (problem_->isHermitian()) {
1293 Teuchos::SerialDenseMatrix<int,ScalarType> subQ( Teuchos::View, *Q_, curDim_, numRitzVecs_ );
1299 bool complexRitzVals =
false;
1300 for (
int i=0; i<numRitzVecs_; i++) {
1301 if (ritzIndex_[i] != 0) {
1302 complexRitzVals =
true;
1306 if (complexRitzVals)
1307 om_->stream(
Warnings) <<
" Eigenproblem is Hermitian and complex eigenvalues have converged, corresponding eigenvectors will be incorrect!!!" 1312 Teuchos::SerialDenseMatrix<int,ScalarType> subQ( Teuchos::View, *Q_, curDim_, curDim_ );
1315 Teuchos::RCP<MV> tmpritzVectors_ =
MVT::Clone( *V_, curDim_ );
1326 int lwork = 3*curDim_;
1327 std::vector<ScalarType> work( lwork );
1328 std::vector<MagnitudeType> rwork( curDim_ );
1332 ScalarType vl[ ldvl ];
1333 Teuchos::SerialDenseMatrix<int,ScalarType> copyQ( Teuchos::Copy, *Q_, curDim_, curDim_ );
1334 lapack.TREVC( side, curDim_, schurH_->values(), schurH_->stride(), vl, ldvl,
1335 copyQ.values(), copyQ.stride(), curDim_, &mm, &work[0], &rwork[0], &info );
1336 TEUCHOS_TEST_FOR_EXCEPTION(info != 0, std::logic_error,
1337 "Anasazi::BlockKrylovSchur::computeRitzVectors(): TREVC(n==" << curDim_ <<
") returned info " << info <<
" != 0.");
1340 Teuchos::SerialDenseMatrix<int,ScalarType> subCopyQ( Teuchos::View, copyQ, curDim_, numRitzVecs_ );
1343 curind.resize( numRitzVecs_ );
1348 std::vector<MagnitudeType> ritzNrm( numRitzVecs_ );
1352 tmpritzVectors_ = Teuchos::null;
1353 view_ritzVectors = Teuchos::null;
1356 ScalarType ritzScale = ST_ONE;
1357 for (
int i=0; i<numRitzVecs_; i++) {
1360 if (ritzIndex_[i] == 1 ) {
1361 ritzScale = ST_ONE/lapack_mag.LAPY2(ritzNrm[i],ritzNrm[i+1]);
1362 std::vector<int> newind(2);
1363 newind[0] = i; newind[1] = i+1;
1366 MVT::MvAddMv( ritzScale, *tmpritzVectors_, ST_ZERO, *tmpritzVectors_, *view_ritzVectors );
1373 std::vector<int> newind(1);
1377 MVT::MvAddMv( ST_ONE/ritzNrm[i], *tmpritzVectors_, ST_ZERO, *tmpritzVectors_, *view_ritzVectors );
1384 ritzVecsCurrent_ =
true;
1393 template <
class ScalarType,
class MV,
class OP>
1395 TEUCHOS_TEST_FOR_EXCEPTION(test == Teuchos::null,std::invalid_argument,
1396 "Anasazi::BlockKrylovSchur::setStatusTest() was passed a null StatusTest.");
1402 template <
class ScalarType,
class MV,
class OP>
1420 template <
class ScalarType,
class MV,
class OP>
1424 #ifdef ANASAZI_TEUCHOS_TIME_MONITOR 1425 Teuchos::TimeMonitor LocalTimer(*timerCompSF_);
1432 if (!schurCurrent_) {
1436 if (!ritzValsCurrent_) {
1437 Teuchos::LAPACK<int,ScalarType> lapack;
1438 Teuchos::LAPACK<int,MagnitudeType> lapack_mag;
1439 Teuchos::BLAS<int,ScalarType> blas;
1440 Teuchos::BLAS<int,MagnitudeType> blas_mag;
1443 Teuchos::SerialDenseMatrix<int,ScalarType> subQ( Teuchos::View, *Q_, curDim_, curDim_ );
1446 schurH_ = Teuchos::rcp(
new Teuchos::SerialDenseMatrix<int,ScalarType>( Teuchos::Copy, *H_, curDim_, curDim_ ) );
1460 int lwork = 3*curDim_;
1461 std::vector<ScalarType> work( lwork );
1462 std::vector<MagnitudeType> rwork( curDim_ );
1463 std::vector<MagnitudeType> tmp_rRitzValues( curDim_ );
1464 std::vector<MagnitudeType> tmp_iRitzValues( curDim_ );
1465 std::vector<int> bwork( curDim_ );
1466 int info = 0, sdim = 0;
1468 lapack.GEES( jobvs,curDim_, schurH_->values(), schurH_->stride(), &sdim, &tmp_rRitzValues[0],
1469 &tmp_iRitzValues[0], subQ.values(), subQ.stride(), &work[0], lwork,
1470 &rwork[0], &bwork[0], &info );
1472 TEUCHOS_TEST_FOR_EXCEPTION(info != 0, std::logic_error,
1473 "Anasazi::BlockKrylovSchur::computeSchurForm(): GEES(n==" << curDim_ <<
") returned info " << info <<
" != 0.");
1479 bool hermImagDetected =
false;
1480 if (problem_->isHermitian()) {
1481 for (
int i=0; i<curDim_; i++)
1483 if (tmp_iRitzValues[i] != MT_ZERO)
1485 hermImagDetected =
true;
1489 if (hermImagDetected) {
1491 om_->stream(
Warnings) <<
" Eigenproblem is Hermitian and complex eigenvalues have been detected!!!" << std::endl;
1493 Teuchos::SerialDenseMatrix<int,ScalarType> localH( Teuchos::View, *H_, curDim_, curDim_ );
1494 Teuchos::RCP<Teuchos::SerialDenseMatrix<int,ScalarType> > tLocalH;
1495 if (Teuchos::ScalarTraits<ScalarType>::isComplex)
1496 tLocalH = Teuchos::rcp(
new Teuchos::SerialDenseMatrix<int,ScalarType>( localH, Teuchos::CONJ_TRANS ) );
1498 tLocalH = Teuchos::rcp(
new Teuchos::SerialDenseMatrix<int,ScalarType>( localH, Teuchos::TRANS ) );
1499 (*tLocalH) -= localH;
1500 MagnitudeType normF = tLocalH->normFrobenius();
1501 MagnitudeType norm1 = tLocalH->normOne();
1502 om_->stream(
Warnings) <<
" Symmetry error in projected eigenproblem: || S - S' ||_F = " << normF
1503 <<
", || S - S' ||_1 = " << norm1 << std::endl;
1521 Teuchos::SerialDenseMatrix<int,ScalarType> curB(Teuchos::View, *H_,
1522 blockSize_, curDim_, curDim_ );
1525 Teuchos::SerialDenseMatrix<int,ScalarType> subB( blockSize_, curDim_ );
1526 blas.GEMM( Teuchos::NO_TRANS, Teuchos::NO_TRANS, blockSize_, curDim_, curDim_, ST_ONE,
1527 curB.values(), curB.stride(), subQ.values(), subQ.stride(),
1528 ST_ZERO, subB.values(), subB.stride() );
1532 ScalarType* b_ptr = subB.values();
1533 if (problem_->isHermitian() && !hermImagDetected) {
1537 for (
int i=0; i<curDim_ ; i++) {
1538 ritzResiduals_[i] = blas.NRM2(blockSize_, b_ptr + i*blockSize_, 1);
1547 ScalarType vl[ ldvl ];
1548 Teuchos::SerialDenseMatrix<int,ScalarType> S( curDim_, curDim_ );
1549 lapack.TREVC( side, curDim_, schurH_->values(), schurH_->stride(), vl, ldvl,
1550 S.values(), S.stride(), curDim_, &mm, &work[0], &rwork[0], &info );
1552 TEUCHOS_TEST_FOR_EXCEPTION(info != 0, std::logic_error,
1553 "Anasazi::BlockKrylovSchur::computeSchurForm(): TREVC(n==" << curDim_ <<
") returned info " << info <<
" != 0.");
1561 Teuchos::SerialDenseMatrix<int,ScalarType> ritzRes( blockSize_, curDim_ );
1562 blas.GEMM( Teuchos::NO_TRANS, Teuchos::NO_TRANS, blockSize_, curDim_, curDim_, ST_ONE,
1563 subB.values(), subB.stride(), S.values(), S.stride(),
1564 ST_ZERO, ritzRes.values(), ritzRes.stride() );
1598 #ifdef ANASAZI_TEUCHOS_TIME_MONITOR 1599 Teuchos::TimeMonitor LocalTimer2(*timerSortRitzVal_);
1602 if (problem_->isHermitian() && !hermImagDetected) {
1605 sm_->sort(tmp_rRitzValues, Teuchos::rcpFromRef(ritzOrder_), curDim_);
1607 while ( i < curDim_ ) {
1609 ritzValues_[i].set(tmp_rRitzValues[i], MT_ZERO);
1610 ritzIndex_.push_back(0);
1617 sm_->sort(tmp_rRitzValues, tmp_iRitzValues, Teuchos::rcpFromRef(ritzOrder_) , curDim_);
1622 std::vector<MagnitudeType> ritz2( curDim_ );
1623 for (i=0; i<curDim_; i++) { ritz2[i] = ritzResiduals_[ ritzOrder_[i] ]; }
1624 blas_mag.COPY( curDim_, &ritz2[0], 1, &ritzResiduals_[0], 1 );
1627 ritzValsCurrent_ =
true;
1643 sortSchurForm( *schurH_, *Q_, ritzOrder_ );
1646 schurCurrent_ =
true;
1657 template <
class ScalarType,
class MV,
class OP>
1659 Teuchos::SerialDenseMatrix<int,ScalarType>& Q,
1660 std::vector<int>& order )
1663 #ifdef ANASAZI_TEUCHOS_TIME_MONITOR 1664 Teuchos::TimeMonitor LocalTimer(*timerSortSF_);
1675 int i = 0, nevtemp = 0;
1677 std::vector<int> offset2( curDim_ );
1678 std::vector<int> order2( curDim_ );
1681 Teuchos::LAPACK<int,ScalarType> lapack;
1682 int lwork = 3*curDim_;
1683 std::vector<ScalarType> work( lwork );
1685 while (i < curDim_) {
1686 if ( ritzIndex_[i] != 0 ) {
1687 offset2[nevtemp] = 0;
1688 for (
int j=i; j<curDim_; j++) {
1689 if (order[j] > order[i]) { offset2[nevtemp]++; }
1691 order2[nevtemp] = order[i];
1694 offset2[nevtemp] = 0;
1695 for (
int j=i; j<curDim_; j++) {
1696 if (order[j] > order[i]) { offset2[nevtemp]++; }
1698 order2[nevtemp] = order[i];
1703 ScalarType *ptr_h = H.values();
1704 ScalarType *ptr_q = Q.values();
1705 int ldh = H.stride(), ldq = Q.stride();
1707 for (i=nevtemp-1; i>=0; i--) {
1708 int ifst = order2[i]+1+offset2[i];
1710 lapack.TREXC( compq, curDim_, ptr_h, ldh, ptr_q, ldq, &ifst,
1711 &ilst, &work[0], &info );
1712 TEUCHOS_TEST_FOR_EXCEPTION(info != 0, std::logic_error,
1713 "Anasazi::BlockKrylovSchur::computeSchurForm(): TREXC(n==" << curDim_ <<
") returned info " << info <<
" != 0.");
1719 template <
class ScalarType,
class MV,
class OP>
1724 os.setf(std::ios::scientific, std::ios::floatfield);
1726 os <<
"================================================================================" << endl;
1728 os <<
" BlockKrylovSchur Solver Status" << endl;
1730 os <<
"The solver is "<<(initialized_ ?
"initialized." :
"not initialized.") << endl;
1731 os <<
"The number of iterations performed is " <<iter_<<endl;
1732 os <<
"The block size is " << blockSize_<<endl;
1733 os <<
"The number of blocks is " << numBlocks_<<endl;
1734 os <<
"The current basis size is " << curDim_<<endl;
1735 os <<
"The number of auxiliary vectors is " << numAuxVecs_ << endl;
1736 os <<
"The number of operations Op*x is "<<count_ApplyOp_<<endl;
1738 os.setf(std::ios_base::right, std::ios_base::adjustfield);
1742 os <<
"CURRENT RITZ VALUES "<<endl;
1743 if (ritzIndex_.size() != 0) {
1744 int numPrint = (curDim_ < numRitzPrint_? curDim_: numRitzPrint_);
1745 if (problem_->isHermitian()) {
1746 os << std::setw(20) <<
"Ritz Value" 1747 << std::setw(20) <<
"Ritz Residual" 1749 os <<
"--------------------------------------------------------------------------------"<<endl;
1750 for (
int i=0; i<numPrint; i++) {
1751 os << std::setw(20) << ritzValues_[i].realpart
1752 << std::setw(20) << ritzResiduals_[i]
1756 os << std::setw(24) <<
"Ritz Value" 1757 << std::setw(30) <<
"Ritz Residual" 1759 os <<
"--------------------------------------------------------------------------------"<<endl;
1760 for (
int i=0; i<numPrint; i++) {
1762 os << std::setw(15) << ritzValues_[i].realpart;
1763 if (ritzValues_[i].imagpart < MT_ZERO) {
1764 os <<
" - i" << std::setw(15) << Teuchos::ScalarTraits<MagnitudeType>::magnitude(ritzValues_[i].imagpart);
1766 os <<
" + i" << std::setw(15) << ritzValues_[i].imagpart;
1768 os << std::setw(20) << ritzResiduals_[i] << endl;
1772 os << std::setw(20) <<
"[ NONE COMPUTED ]" << endl;
1776 os <<
"================================================================================" << endl;
static ptrdiff_t GetGlobalLength(const MV &mv)
Return the number of rows in the given multivector mv.
void computeRitzValues()
Compute the Ritz values using the current Krylov factorization.
BlockKrylovSchurOrthoFailure is thrown when the orthogonalization manager is unable to generate ortho...
Teuchos::RCP< const Teuchos::SerialDenseMatrix< int, ScalarType > > H
The current Hessenberg matrix.
static void MvRandom(MV &mv)
Replace the vectors in mv with random vectors.
static void MvTimesMatAddMv(const ScalarType alpha, const MV &A, const Teuchos::SerialDenseMatrix< int, ScalarType > &B, const ScalarType beta, MV &mv)
Update mv with .
void setStepSize(int stepSize)
Set the step size.
std::vector< typename Teuchos::ScalarTraits< ScalarType >::magnitudeType > getRitzRes2Norms()
Get the current Ritz residual 2-norms.
Teuchos::RCP< const MV > getRitzVectors()
Get the Ritz vectors.
This class defines the interface required by an eigensolver and status test class to compute solution...
bool isRitzVecsCurrent() const
Get the status of the Ritz vectors currently stored in the eigensolver.
virtual ~BlockKrylovSchur()
BlockKrylovSchur destructor.
Declaration of basic traits for the multivector type.
std::vector< typename Teuchos::ScalarTraits< ScalarType >::magnitudeType > getResNorms()
Get the current residual norms.
void setAuxVecs(const Teuchos::Array< Teuchos::RCP< const MV > > &auxvecs)
Set the auxiliary vectors for the solver.
void iterate()
This method performs Block Krylov-Schur iterations until the status test indicates the need to stop o...
Virtual base class which defines basic traits for the operator type.
static void Apply(const OP &Op, const MV &x, MV &y)
Application method which performs operation y = Op*x. An OperatorError exception is thrown if there i...
Teuchos::Array< Teuchos::RCP< const MV > > getAuxVecs() const
Get the auxiliary vectors for the solver.
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.
Structure to contain pointers to BlockKrylovSchur state variables.
An exception class parent to all Anasazi exceptions.
void setStatusTest(Teuchos::RCP< StatusTest< ScalarType, MV, OP > > test)
Set a new StatusTest for the solver.
Pure virtual base class which describes the basic interface to the iterative eigensolver.
Namespace Anasazi contains the classes, structs, enums and utilities used by the Anasazi package...
void initialize()
Initialize the solver with the initial vectors from the eigenproblem or random data.
void computeRitzVectors()
Compute the Ritz vectors using the current Krylov factorization.
int getBlockSize() const
Get the blocksize to be used by the iterative solver in solving this eigenproblem.
int getNumIters() const
Get the current iteration count.
void setNumRitzVectors(int numRitzVecs)
Set the number of Ritz vectors to compute.
void computeSchurForm(const bool sort=true)
Compute the Schur form of the projected eigenproblem from the current Krylov factorization.
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.
bool isInitialized() const
Indicates whether the solver has been initialized or not.
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...
Output managers remove the need for the eigensolver to know any information about the required output...
void resetNumIters()
Reset the iteration count.
Templated virtual class for providing orthogonalization/orthonormalization methods.
Traits class which defines basic operations on multivectors.
static Teuchos::RCP< MV > CloneCopy(const MV &mv)
Creates a new MV and copies contents of mv into the new vector (deep copy).
Virtual base class which defines basic traits for the operator type.
int getStepSize() const
Get the step size.
static Teuchos::RCP< MV > CloneViewNonConst(MV &mv, const std::vector< int > &index)
Creates a new MV that shares the selected contents of mv (shallow copy).
static void MvNorm(const MV &mv, std::vector< typename Teuchos::ScalarTraits< ScalarType >::magnitudeType > &normvec)
Compute the 2-norm of each individual vector of mv. Upon return, normvec[i] holds the value of ...
static Teuchos::RCP< const MV > CloneView(const MV &mv, const std::vector< int > &index)
Creates a new const MV that shares the selected contents of mv (shallow copy).
static void SetBlock(const MV &A, const std::vector< int > &index, MV &mv)
Copy the vectors in A to a set of vectors in mv indicated by the indices given in index...
std::vector< Value< ScalarType > > getRitzValues()
Get the Ritz values.
std::vector< int > getRitzIndex()
Get the Ritz index vector.
static int GetNumberVecs(const MV &mv)
Obtain the number of vectors in mv.
Teuchos::RCP< StatusTest< ScalarType, MV, OP > > getStatusTest() const
Get the current StatusTest used by the solver.
static void MvAddMv(const ScalarType alpha, const MV &A, const ScalarType beta, const MV &B, MV &mv)
Replace mv with .
std::vector< typename Teuchos::ScalarTraits< ScalarType >::magnitudeType > getRes2Norms()
Get the current residual 2-norms.
Teuchos::RCP< const MulVec > V
The current Krylov basis.
BlockKrylovSchurInitFailure is thrown when the BlockKrylovSchur solver is unable to generate an initi...
BlockKrylovSchurState< ScalarType, MV > getState() const
Get the current state of the eigensolver.
bool isSchurCurrent() const
Get the status of the Schur form currently stored in the eigensolver.
bool isRitzValsCurrent() const
Get the status of the Ritz values currently stored in the eigensolver.
Types and exceptions used within Anasazi solvers and interfaces.
void currentStatus(std::ostream &os)
This method requests that the solver print out its current status to screen.
Anasazi's templated virtual class for providing routines for orthogonalization and orthonormalization...
int getCurSubspaceDim() const
Get the dimension of the search subspace used to generate the current eigenvectors and eigenvalues...
Teuchos::RCP< const Teuchos::SerialDenseMatrix< int, ScalarType > > Q
The current Schur vectors of the valid part of H.
int getNumRitzVectors() const
Get the number of Ritz vectors to compute.
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.
void setBlockSize(int blockSize)
Set the blocksize.
This class implements the block Krylov-Schur iteration, for solving linear eigenvalue problems...
Anasazi's templated pure virtual class for managing the sorting of approximate eigenvalues computed b...
void setSize(int blockSize, int numBlocks)
Set the blocksize and number of blocks to be used by the iterative solver in solving this eigenproble...
int curDim
The current dimension of the reduction.
int getMaxSubspaceDim() const
Get the maximum dimension allocated for the search subspace.
Common interface of stopping criteria for Anasazi's solvers.
The Eigensolver is a templated virtual base class that defines the basic interface that any eigensolv...
Teuchos::RCP< const Teuchos::SerialDenseMatrix< int, ScalarType > > S
The current Schur form reduction of the valid part of H.
static Teuchos::RCP< MV > Clone(const MV &mv, const int numvecs)
Creates a new empty MV containing numvecs columns.
const Eigenproblem< ScalarType, MV, OP > & getProblem() const
Get a constant reference to the eigenvalue problem.