10 #ifndef ANASAZI_BLOCK_KRYLOV_SCHUR_SOLMGR_HPP
11 #define ANASAZI_BLOCK_KRYLOV_SCHUR_SOLMGR_HPP
39 #include "Teuchos_FancyOStream.hpp"
124 template<
class ScalarType,
class MV,
class OP>
182 std::vector<Value<ScalarType> > ret( ritzValues_ );
193 return Teuchos::tuple(timerSolve_, timerRestarting_);
239 std::string whch_, ortho_;
240 MagnitudeType ortho_kappa_;
242 MagnitudeType convtol_;
244 bool relconvtol_,conjSplit_;
245 int blockSize_, numBlocks_, stepSize_, nevBlocks_, xtra_nevBlocks_;
248 bool inSituRestart_, dynXtraNev_;
251 std::vector<Value<ScalarType> > ritzValues_;
265 template<
class ScalarType,
class MV,
class OP>
283 verbosity_(Anasazi::
Errors),
284 inSituRestart_(false),
288 #ifdef ANASAZI_TEUCHOS_TIME_MONITOR
289 ,timerSolve_(Teuchos::TimeMonitor::getNewTimer(
"Anasazi: BlockKrylovSchurSolMgr::solve()")),
290 timerRestarting_(Teuchos::TimeMonitor::getNewTimer(
"Anasazi: BlockKrylovSchurSolMgr restarting"))
295 TEUCHOS_TEST_FOR_EXCEPTION(problem_->getInitVec() == Teuchos::null, std::invalid_argument,
"Problem does not contain initial vectors to clone from.");
297 const int nev = problem_->getNEV();
300 convtol_ = pl.
get(
"Convergence Tolerance",
MT::prec());
301 relconvtol_ = pl.
get(
"Relative Convergence Tolerance",relconvtol_);
304 maxRestarts_ = pl.
get(
"Maximum Restarts",maxRestarts_);
307 blockSize_ = pl.
get(
"Block Size",1);
309 "Anasazi::BlockKrylovSchurSolMgr: \"Block Size\" must be strictly positive.");
312 xtra_nevBlocks_ = pl.
get(
"Extra NEV Blocks",0);
313 if (nev%blockSize_) {
314 nevBlocks_ = nev/blockSize_ + 1;
316 nevBlocks_ = nev/blockSize_;
323 if (Teuchos::isParameterType<bool>(pl,
"Dynamic Extra NEV")) {
324 dynXtraNev_ = pl.
get(
"Dynamic Extra NEV",dynXtraNev_);
326 dynXtraNev_ = ( Teuchos::getParameter<int>(pl,
"Dynamic Extra NEV") != 0 );
330 numBlocks_ = pl.
get(
"Num Blocks",3*nevBlocks_);
332 "Anasazi::BlockKrylovSchurSolMgr: \"Num Blocks\" must be strictly positive and large enough to compute the requested eigenvalues.");
335 std::invalid_argument,
336 "Anasazi::BlockKrylovSchurSolMgr: Potentially impossible orthogonality requests. Reduce basis size.");
340 stepSize_ = pl.
get(
"Step Size", (maxRestarts_+1)*(numBlocks_+1));
342 stepSize_ = pl.
get(
"Step Size", numBlocks_+1);
345 "Anasazi::BlockKrylovSchurSolMgr: \"Step Size\" must be strictly positive.");
349 sort_ = Teuchos::getParameter<Teuchos::RCP<Anasazi::SortManager<MagnitudeType> > >(pl,
"Sort Manager");
352 whch_ = pl.
get(
"Which",whch_);
353 TEUCHOS_TEST_FOR_EXCEPTION(whch_ !=
"SM" && whch_ !=
"LM" && whch_ !=
"SR" && whch_ !=
"LR" && whch_ !=
"SI" && whch_ !=
"LI",
354 std::invalid_argument,
"Invalid sorting string.");
359 ortho_ = pl.
get(
"Orthogonalization",ortho_);
360 if (ortho_ !=
"DGKS" && ortho_ !=
"SVQB" && ortho_ !=
"ICGS") {
365 ortho_kappa_ = pl.
get(
"Orthogonalization Constant",ortho_kappa_);
369 osProc_ = pl.
get(
"Output Processor", osProc_);
373 osp_ = Teuchos::getParameter<Teuchos::RCP<Teuchos::FancyOStream> >(pl,
"Output Stream");
381 if (Teuchos::isParameterType<int>(pl,
"Verbosity")) {
382 verbosity_ = pl.
get(
"Verbosity", verbosity_);
384 verbosity_ = (int)Teuchos::getParameter<Anasazi::MsgType>(pl,
"Verbosity");
390 if (Teuchos::isParameterType<bool>(pl,
"In Situ Restarting")) {
391 inSituRestart_ = pl.
get(
"In Situ Restarting",inSituRestart_);
393 inSituRestart_ = ( Teuchos::getParameter<int>(pl,
"In Situ Restarting") != 0 );
397 printNum_ = pl.
get<
int>(
"Print Number of Ritz Values",printNum_);
402 template<
class ScalarType,
class MV,
class OP>
406 const int nev = problem_->getNEV();
422 if (globalTest_ == Teuchos::null) {
426 convtest = globalTest_;
434 if (debugTest_ != Teuchos::null) alltests.
push_back(debugTest_);
440 if ( printer->isVerbosity(
Debug) ) {
450 if (ortho_==
"SVQB") {
452 }
else if (ortho_==
"DGKS") {
453 if (ortho_kappa_ <= 0) {
458 }
else if (ortho_==
"ICGS") {
461 TEUCHOS_TEST_FOR_EXCEPTION(ortho_!=
"SVQB"&&ortho_!=
"DGKS"&&ortho_!=
"ICGS",std::logic_error,
"Anasazi::BlockKrylovSchurSolMgr::solve(): Invalid orthogonalization type.");
467 plist.
set(
"Block Size",blockSize_);
468 plist.
set(
"Num Blocks",numBlocks_);
469 plist.
set(
"Step Size",stepSize_);
470 if (printNum_ == -1) {
471 plist.
set(
"Print Number of Ritz Values",nevBlocks_*blockSize_);
474 plist.
set(
"Print Number of Ritz Values",printNum_);
483 if (probauxvecs != Teuchos::null) {
494 int maxXtraBlocks = 0;
495 if ( dynXtraNev_ ) maxXtraBlocks = ( ( bks_solver->getMaxSubspaceDim() - nev ) / blockSize_ ) / 2;
498 if (maxRestarts_ > 0) {
499 if (inSituRestart_==
true) {
501 workMV = MVT::Clone( *problem_->getInitVec(), 1 );
504 if (problem_->isHermitian()) {
505 workMV = MVT::Clone( *problem_->getInitVec(), (nevBlocks_+maxXtraBlocks)*blockSize_ + blockSize_ );
508 workMV = MVT::Clone( *problem_->getInitVec(), (nevBlocks_+maxXtraBlocks)*blockSize_ + 1 + blockSize_ );
512 workMV = Teuchos::null;
518 problem_->setSolution(sol);
521 int cur_nevBlocks = 0;
525 #ifdef ANASAZI_TEUCHOS_TIME_MONITOR
532 bks_solver->iterate();
539 if ( ordertest->getStatus() ==
Passed ) {
557 else if ( (bks_solver->getCurSubspaceDim() == bks_solver->getMaxSubspaceDim()) ||
558 (!problem_->isHermitian() && !conjSplit_ && (bks_solver->getCurSubspaceDim()+1 == bks_solver->getMaxSubspaceDim())) ) {
561 if (!bks_solver->isSchurCurrent()) {
562 bks_solver->computeSchurForm(
true );
565 outputtest->checkStatus( &*bks_solver );
569 if ( numRestarts >= maxRestarts_ || ordertest->getStatus() ==
Passed) {
574 #ifdef ANASAZI_TEUCHOS_TIME_MONITOR
579 int numConv = ordertest->howMany();
580 cur_nevBlocks = nevBlocks_*blockSize_;
583 int moreNevBlocks = std::min( maxXtraBlocks, std::max( numConv/blockSize_, xtra_nevBlocks_) );
585 cur_nevBlocks += moreNevBlocks * blockSize_;
586 else if ( xtra_nevBlocks_ )
587 cur_nevBlocks += xtra_nevBlocks_ * blockSize_;
595 printer->stream(
Debug) <<
" Performing restart number " << numRestarts <<
" of " << maxRestarts_ << std::endl << std::endl;
596 printer->stream(
Debug) <<
" - Current NEV blocks is " << cur_nevBlocks <<
", the minimum is " << nevBlocks_*blockSize_ << std::endl;
599 ritzValues_ = bks_solver->getRitzValues();
605 int curDim = oldState.
curDim;
608 std::vector<int> ritzIndex = bks_solver->getRitzIndex();
609 if (ritzIndex[cur_nevBlocks-1]==1) {
618 if (problem_->isHermitian() && conjSplit_)
621 <<
" Eigenproblem is Hermitian, complex eigenvalues have been detected, and eigenvalues of interest split a conjugate pair!!!"
623 <<
" Block Krylov-Schur eigensolver cannot guarantee correct behavior in this situation, please turn Hermitian flag off!!!"
633 std::vector<int> curind( curDim );
634 for (
int i=0; i<curDim; i++) { curind[i] = i; }
646 if (inSituRestart_) {
653 std::vector<ScalarType> tau(cur_nevBlocks), work(cur_nevBlocks);
655 lapack.
GEQRF(curDim,cur_nevBlocks,copyQnev.values(),copyQnev.stride(),&tau[0],&work[0],work.size(),&info);
657 "Anasazi::BlockKrylovSchurSolMgr::solve(): error calling GEQRF during restarting.");
659 std::vector<ScalarType> d(cur_nevBlocks);
660 for (
int j=0; j<copyQnev.numCols(); j++) {
661 d[j] = copyQnev(j,j);
663 if (printer->isVerbosity(
Debug)) {
665 for (
int j=0; j<R.
numCols(); j++) {
666 R(j,j) = SCT::magnitude(R(j,j)) - 1.0;
667 for (
int i=j+1; i<R.
numRows(); i++) {
671 printer->stream(
Debug) <<
"||Triangular factor of Su - I||: " << R.
normFrobenius() << std::endl;
677 curind.resize(curDim);
678 for (
int i=0; i<curDim; i++) curind[i] = i;
685 curind.resize(cur_nevBlocks);
686 for (
int i=0; i<cur_nevBlocks; i++) { curind[i] = i; }
689 MVT::MvScale(*newV,d);
692 curind.resize(blockSize_);
693 for (
int i=0; i<blockSize_; i++) { curind[i] = cur_nevBlocks + i; }
694 newF = MVT::CloneViewNonConst( *solverbasis, curind );
698 curind.resize(cur_nevBlocks);
699 for (
int i=0; i<cur_nevBlocks; i++) { curind[i] = i; }
702 MVT::MvTimesMatAddMv( one, *basistemp, Qnev, zero, *tmp_newV );
703 tmp_newV = Teuchos::null;
705 curind.resize(blockSize_);
706 for (
int i=0; i<blockSize_; i++) { curind[i] = cur_nevBlocks + i; }
707 newF = MVT::CloneViewNonConst( *workMV, curind );
711 curind.resize(blockSize_);
712 for (
int i=0; i<blockSize_; i++) { curind[i] = curDim + i; }
714 for (
int i=0; i<blockSize_; i++) { curind[i] = i; }
715 MVT::SetBlock( *oldF, curind, *newF );
716 newF = Teuchos::null;
742 if (inSituRestart_) {
743 newstate.
V = oldState.
V;
748 newstate.
curDim = cur_nevBlocks;
749 bks_solver->initialize(newstate);
759 TEUCHOS_TEST_FOR_EXCEPTION(
true,std::logic_error,
"Anasazi::BlockKrylovSchurSolMgr::solve(): Invalid return from bks_solver::iterate().");
764 <<
"Anasazi::BlockKrylovSchurSolMgr::solve() caught unexpected exception from Anasazi::BlockKrylovSchur::iterate() at iteration " << bks_solver->getNumIters() << std::endl
765 << err.what() << std::endl
766 <<
"Anasazi::BlockKrylovSchurSolMgr::solve() returning Unconverged with no solutions." << std::endl;
773 workMV = Teuchos::null;
776 ritzValues_ = bks_solver->getRitzValues();
778 sol.
numVecs = ordertest->howMany();
779 printer->stream(
Debug) <<
"ordertest->howMany() : " << sol.
numVecs << std::endl;
780 std::vector<int> whichVecs = ordertest->whichVecs();
786 std::vector<int> tmpIndex = bks_solver->getRitzIndex();
787 for (
int i=0; i<(int)ritzValues_.size(); ++i) {
788 printer->stream(
Debug) << ritzValues_[i].realpart <<
" + i " << ritzValues_[i].imagpart <<
", Index = " << tmpIndex[i] << std::endl;
790 printer->stream(
Debug) <<
"Number of converged eigenpairs (before) = " << sol.
numVecs << std::endl;
791 for (
int i=0; i<sol.
numVecs; ++i) {
792 printer->stream(
Debug) <<
"whichVecs[" << i <<
"] = " << whichVecs[i] <<
", tmpIndex[" << whichVecs[i] <<
"] = " << tmpIndex[whichVecs[i]] << std::endl;
794 if (tmpIndex[whichVecs[sol.
numVecs-1]]==1) {
795 printer->stream(
Debug) <<
"There is a conjugate pair on the boundary, resizing sol.numVecs" << std::endl;
796 whichVecs.push_back(whichVecs[sol.
numVecs-1]+1);
798 for (
int i=0; i<sol.
numVecs; ++i) {
799 printer->stream(
Debug) <<
"whichVecs[" << i <<
"] = " << whichVecs[i] <<
", tmpIndex[" << whichVecs[i] <<
"] = " << tmpIndex[whichVecs[i]] << std::endl;
803 bool keepMore =
false;
805 printer->stream(
Debug) <<
"Number of converged eigenpairs (after) = " << sol.
numVecs << std::endl;
806 printer->stream(
Debug) <<
"whichVecs[sol.numVecs-1] > sol.numVecs-1 : " << whichVecs[sol.
numVecs-1] <<
" > " << sol.
numVecs-1 << std::endl;
809 numEvecs = whichVecs[sol.
numVecs-1]+1;
810 printer->stream(
Debug) <<
"keepMore = true; numEvecs = " << numEvecs << std::endl;
814 bks_solver->setNumRitzVectors(numEvecs);
815 bks_solver->computeRitzVectors();
821 sol.
index = bks_solver->getRitzIndex();
822 sol.
Evals = bks_solver->getRitzValues();
823 sol.
Evecs = MVT::CloneCopy( *(bks_solver->getRitzVectors()) );
833 std::vector<Anasazi::Value<ScalarType> > tmpEvals = bks_solver->getRitzValues();
834 for (
int vec_i=0; vec_i<sol.
numVecs; ++vec_i) {
835 sol.
index[vec_i] = tmpIndex[whichVecs[vec_i]];
836 sol.
Evals[vec_i] = tmpEvals[whichVecs[vec_i]];
838 sol.
Evecs = MVT::CloneCopy( *(bks_solver->getRitzVectors()), whichVecs );
847 bks_solver->currentStatus(printer->stream(
FinalSummary));
850 #ifdef ANASAZI_TEUCHOS_TIME_MONITOR
856 problem_->setSolution(sol);
857 printer->stream(
Debug) <<
"Returning " << sol.
numVecs <<
" eigenpairs to eigenproblem." << std::endl;
860 numIters_ = bks_solver->getNumIters();
869 template <
class ScalarType,
class MV,
class OP>
874 globalTest_ = global;
877 template <
class ScalarType,
class MV,
class OP>
884 template <
class ScalarType,
class MV,
class OP>
892 template <
class ScalarType,
class MV,
class OP>
ScalarType * values() const
static ptrdiff_t GetGlobalLength(const MV &mv)
Return the number of rows in the given multivector mv.
Pure virtual base class which describes the basic interface for a solver manager. ...
Teuchos::RCP< const Teuchos::SerialDenseMatrix< int, ScalarType > > H
The current Hessenberg matrix.
std::vector< Value< ScalarType > > Evals
The computed eigenvalues.
A special StatusTest for printing other status tests.
This class defines the interface required by an eigensolver and status test class to compute solution...
An implementation of the Anasazi::SortManager that performs a collection of common sorting techniques...
T & get(const std::string &name, T def_value)
#define TEUCHOS_TEST_FOR_EXCEPTION(throw_exception_test, Exception, msg)
Virtual base class which defines basic traits for the operator type.
Teuchos::RCP< MV > Evecs
The computed eigenvectors.
An implementation of the Anasazi::GenOrthoManager that performs orthogonalization using iterated clas...
ReturnType solve()
This method performs possibly repeated calls to the underlying eigensolver's iterate() routine until ...
Status test for forming logical combinations of other status tests.
The Anasazi::SolverManager is a templated virtual base class that defines the basic interface that an...
void setDebugStatusTest(const Teuchos::RCP< StatusTest< ScalarType, MV, OP > > &debug)
Set the status test for debugging.
ParameterList & set(std::string const &name, T &&value, std::string const &docString="", RCP< const ParameterEntryValidator > const &validator=null)
Basic implementation of the Anasazi::SortManager class.
An implementation of the Anasazi::MatOrthoManager that performs orthogonalization using the SVQB iter...
Structure to contain pointers to BlockKrylovSchur state variables.
virtual ~BlockKrylovSchurSolMgr()
Destructor.
void GEMM(ETransp transa, ETransp transb, const OrdinalType &m, const OrdinalType &n, const OrdinalType &k, const alpha_type alpha, const A_type *A, const OrdinalType &lda, const B_type *B, const OrdinalType &ldb, const beta_type beta, ScalarType *C, const OrdinalType &ldc) const
An exception class parent to all Anasazi exceptions.
Output managers remove the need for the eigensolver to know any information about the required output...
ScalarTraits< ScalarType >::magnitudeType normFrobenius() const
The Anasazi::BlockKrylovSchurSolMgr provides a flexible solver manager over the BlockKrylovSchur eige...
A status test for testing the norm of the eigenvectors residuals along with a set of auxiliary eigenv...
bool isParameter(const std::string &name) const
int numVecs
The number of computed eigenpairs.
std::vector< Value< ScalarType > > getRitzValues() const
Return the Ritz values from the most recent solve.
void setGlobalStatusTest(const Teuchos::RCP< StatusTest< ScalarType, MV, OP > > &global)
Set the status test defining global convergence.
BlockKrylovSchurSolMgr(const Teuchos::RCP< Eigenproblem< ScalarType, MV, OP > > &problem, Teuchos::ParameterList &pl)
Basic constructor for BlockKrylovSchurSolMgr.
Teuchos::RCP< MV > Espace
An orthonormal basis for the computed eigenspace.
Abstract class definition for Anasazi Output Managers.
TEUCHOS_DEPRECATED RCP< T > rcp(T *p, Dealloc_T dealloc, bool owns_mem)
Abstract base class which defines the interface required by an eigensolver and status test class to c...
static void summarize(Ptr< const Comm< int > > comm, std::ostream &out=std::cout, const bool alwaysWriteLocal=false, const bool writeGlobalStats=true, const bool writeZeroTimers=true, const ECounterSetOp setOp=Intersection, const std::string &filter="", const bool ignoreZeroTimers=false)
static magnitudeType prec()
static void applyHouse(int k, MV &V, const Teuchos::SerialDenseMatrix< int, ScalarType > &H, const std::vector< ScalarType > &tau, Teuchos::RCP< MV > workMV=Teuchos::null)
Apply a sequence of Householder reflectors (from GEQRF) to a multivector, using minimal workspace...
ReturnType
Enumerated type used to pass back information from a solver manager.
Output managers remove the need for the eigensolver to know any information about the required output...
A status test for testing the norm of the eigenvectors residuals.
Traits class which defines basic operations on multivectors.
std::vector< int > index
An index into Evecs to allow compressed storage of eigenvectors for real, non-Hermitian problems...
const Eigenproblem< ScalarType, MV, OP > & getProblem() const
Return the eigenvalue problem.
Teuchos::Array< Teuchos::RCP< Teuchos::Time > > getTimers() const
Return the timers for this object.
Anasazi header file which uses auto-configuration information to include necessary C++ headers...
Orthogonalization manager based on the SVQB technique described in "A Block Orthogonalization Procedu...
Struct for storing an eigenproblem solution.
const Teuchos::RCP< StatusTest< ScalarType, MV, OP > > & getGlobalStatusTest() const
Get the status test defining global convergence.
OrdinalType numCols() const
void push_back(const value_type &x)
void GEQRF(const OrdinalType &m, const OrdinalType &n, ScalarType *A, const OrdinalType &lda, ScalarType *TAU, ScalarType *WORK, const OrdinalType &lwork, OrdinalType *info) const
Teuchos::RCP< const MulVec > V
The current Krylov basis.
Special StatusTest for printing status tests.
A status test for testing the norm of the eigenvectors residuals along with a set of auxiliary eigenv...
Status test for forming logical combinations of other status tests.
An implementation of the Anasazi::MatOrthoManager that performs orthogonalization using (potentially)...
Types and exceptions used within Anasazi solvers and interfaces.
Abstract class definition for Anasazi output stream.
Teuchos::RCP< const Teuchos::SerialDenseMatrix< int, ScalarType > > Q
The current Schur vectors of the valid part of H.
Implementation of a block Krylov-Schur eigensolver.
This class implements the block Krylov-Schur iteration, for solving linear eigenvalue problems...
int curDim
The current dimension of the reduction.
Common interface of stopping criteria for Anasazi's solvers.
A status test for testing the norm of the eigenvectors residuals.
Basic implementation of the Anasazi::OrthoManager class.
const Teuchos::RCP< StatusTest< ScalarType, MV, OP > > & getDebugStatusTest() const
Get the status test for debugging.
Basic implementation of the Anasazi::OrthoManager class.
Teuchos::RCP< const Teuchos::SerialDenseMatrix< int, ScalarType > > S
The current Schur form reduction of the valid part of H.
OrdinalType stride() const
int getNumIters() const
Get the iteration count for the most recent call to solve().
OrdinalType numRows() const
Class which provides internal utilities for the Anasazi solvers.