42 #ifndef ANASAZI_LOBPCG_SOLMGR_HPP
43 #define ANASAZI_LOBPCG_SOLMGR_HPP
71 #include "Teuchos_FancyOStream.hpp"
173 template<
class ScalarType,
class MV,
class OP>
242 return Teuchos::tuple(_timerSolve, _timerLocking);
302 std::string whch_, ortho_;
304 MagnitudeType convtol_, locktol_;
305 int maxIters_, numIters_;
307 bool relconvtol_, rellocktol_;
315 enum ResType convNorm_, lockNorm_;
329 template<
class ScalarType,
class MV,
class OP>
336 convtol_(
MT::prec()),
345 verbosity_(Anasazi::
Errors),
349 #ifdef ANASAZI_TEUCHOS_TIME_MONITOR
350 , _timerSolve(Teuchos::TimeMonitor::getNewTimer(
"Anasazi: LOBPCGSolMgr::solve()")),
351 _timerLocking(Teuchos::TimeMonitor::getNewTimer(
"Anasazi: LOBPCGSolMgr locking"))
357 TEUCHOS_TEST_FOR_EXCEPTION(problem_->getInitVec() == Teuchos::null,std::invalid_argument,
"Problem does not contain initial vectors to clone from.");
363 whch_ = pl.
get(
"Which",whch_);
365 std::invalid_argument,
"Anasazi::LOBPCGSolMgr: Invalid sorting string.");
368 ortho_ = pl.
get(
"Orthogonalization",ortho_);
369 if (ortho_ !=
"DGKS" && ortho_ !=
"SVQB" && ortho_ !=
"ICGS") {
374 convtol_ = pl.
get(
"Convergence Tolerance",convtol_);
375 relconvtol_ = pl.
get(
"Relative Convergence Tolerance",relconvtol_);
376 strtmp = pl.
get(
"Convergence Norm",std::string(
"2"));
378 convNorm_ = RES_2NORM;
380 else if (strtmp ==
"M") {
381 convNorm_ = RES_ORTH;
385 "Anasazi::LOBPCGSolMgr: Invalid Convergence Norm.");
390 useLocking_ = pl.
get(
"Use Locking",useLocking_);
391 rellocktol_ = pl.
get(
"Relative Locking Tolerance",rellocktol_);
393 locktol_ = convtol_/10;
394 locktol_ = pl.
get(
"Locking Tolerance",locktol_);
395 strtmp = pl.
get(
"Locking Norm",std::string(
"2"));
397 lockNorm_ = RES_2NORM;
399 else if (strtmp ==
"M") {
400 lockNorm_ = RES_ORTH;
404 "Anasazi::LOBPCGSolMgr: Invalid Locking Norm.");
408 maxIters_ = pl.
get(
"Maximum Iterations",maxIters_);
411 blockSize_ = pl.
get(
"Block Size",problem_->getNEV());
413 "Anasazi::LOBPCGSolMgr: \"Block Size\" must be strictly positive.");
417 maxLocked_ = pl.
get(
"Max Locked",problem_->getNEV());
422 if (maxLocked_ == 0) {
426 "Anasazi::LOBPCGSolMgr: \"Max Locked\" must be positive.");
428 std::invalid_argument,
429 "Anasazi::LOBPCGSolMgr: Not enough storage space for requested number of eigenpairs.");
432 lockQuorum_ = pl.
get(
"Locking Quorum",lockQuorum_);
434 std::invalid_argument,
435 "Anasazi::LOBPCGSolMgr: \"Locking Quorum\" must be strictly positive.");
439 fullOrtho_ = pl.
get(
"Full Ortho",fullOrtho_);
443 osProc_ = pl.
get(
"Output Processor", osProc_);
447 osp_ = Teuchos::getParameter<Teuchos::RCP<Teuchos::FancyOStream> >(pl,
"Output Stream");
455 if (Teuchos::isParameterType<int>(pl,
"Verbosity")) {
456 verbosity_ = pl.
get(
"Verbosity", verbosity_);
458 verbosity_ = (int)Teuchos::getParameter<Anasazi::MsgType>(pl,
"Verbosity");
463 recover_ = pl.
get(
"Recover",recover_);
467 state_ = Teuchos::getParameter<Teuchos::RCP<Anasazi::LOBPCGState<ScalarType,MV> > >(pl,
"Init");
473 template<
class ScalarType,
class MV,
class OP>
479 const int nev = problem_->getNEV();
501 if (globalTest_ == Teuchos::null) {
505 convtest = globalTest_;
512 if (lockingTest_ == Teuchos::null) {
516 locktest = lockingTest_;
522 if (locktest != Teuchos::null) alltests.
push_back(locktest);
523 if (debugTest_ != Teuchos::null) alltests.
push_back(debugTest_);
524 if (maxtest != Teuchos::null) alltests.
push_back(maxtest);
529 if ( printer->isVerbosity(
Debug) ) {
539 if (ortho_==
"SVQB") {
541 }
else if (ortho_==
"DGKS") {
543 }
else if (ortho_==
"ICGS") {
546 TEUCHOS_TEST_FOR_EXCEPTION(ortho_!=
"SVQB"&&ortho_!=
"DGKS"&&ortho_!=
"ICGS",std::logic_error,
"Anasazi::LOBPCGSolMgr::solve(): Invalid orthogonalization type.");
552 plist.
set(
"Block Size",blockSize_);
553 plist.
set(
"Full Ortho",fullOrtho_);
561 if (probauxvecs != Teuchos::null) {
569 int curNumLocked = 0;
572 lockvecs = MVT::Clone(*problem_->getInitVec(),maxLocked_);
574 std::vector<MagnitudeType> lockvals;
584 if (fullOrtho_ ==
false && recover_ ==
true) {
585 workMV = MVT::Clone(*problem_->getInitVec(),2*3*blockSize_);
587 else if (useLocking_) {
588 if (problem_->getM() != Teuchos::null) {
589 workMV = MVT::Clone(*problem_->getInitVec(),4*blockSize_);
592 workMV = MVT::Clone(*problem_->getInitVec(),2*blockSize_);
599 problem_->setSolution(sol);
602 if (state_ != Teuchos::null) {
603 lobpcg_solver->initialize(*state_);
608 #ifdef ANASAZI_TEUCHOS_TIME_MONITOR
615 lobpcg_solver->iterate();
622 if (debugTest_ != Teuchos::null && debugTest_->getStatus() ==
Passed) {
623 throw AnasaziError(
"Anasazi::LOBPCGSolMgr::solve(): User-specified debug status test returned Passed.");
630 else if (ordertest->getStatus() ==
Passed || (maxtest != Teuchos::null && maxtest->getStatus() ==
Passed) ) {
641 else if (locktest != Teuchos::null && locktest->getStatus() ==
Passed) {
643 #ifdef ANASAZI_TEUCHOS_TIME_MONITOR
649 "Anasazi::LOBPCGSolMgr::solve(): status test mistake: howMany() non-positive.");
651 "Anasazi::LOBPCGSolMgr::solve(): status test mistake: howMany() not consistent with whichVecs().");
653 "Anasazi::LOBPCGSolMgr::solve(): status test mistake: locking not deactivated.");
655 int numnew = locktest->howMany();
656 std::vector<int> indnew = locktest->whichVecs();
659 if (curNumLocked + numnew > maxLocked_) {
660 numnew = maxLocked_ - curNumLocked;
661 indnew.resize(numnew);
666 bool hadP = lobpcg_solver->hasP();
670 printer->print(
Debug,
"Locking vectors: ");
671 for (
unsigned int i=0; i<indnew.size(); i++) {printer->stream(
Debug) <<
" " << indnew[i];}
672 printer->print(
Debug,
"\n");
674 std::vector<MagnitudeType> newvals(numnew);
679 newvecs = MVT::CloneView(*lobpcg_solver->getRitzVectors(),indnew);
681 std::vector<Value<ScalarType> > allvals = lobpcg_solver->getRitzValues();
682 for (
int i=0; i<numnew; i++) {
683 newvals[i] = allvals[indnew[i]].realpart;
688 std::vector<int> indlock(numnew);
689 for (
int i=0; i<numnew; i++) indlock[i] = curNumLocked+i;
690 MVT::SetBlock(*newvecs,indlock,*lockvecs);
691 newvecs = Teuchos::null;
694 lockvals.insert(lockvals.end(),newvals.begin(),newvals.end());
695 curNumLocked += numnew;
698 std::vector<int> indlock(curNumLocked);
699 for (
int i=0; i<curNumLocked; i++) indlock[i] = i;
701 if (probauxvecs != Teuchos::null) {
709 ordertest->setAuxVals(lockvals);
718 std::vector<int> bsind(blockSize_);
719 for (
int i=0; i<blockSize_; i++) bsind[i] = i;
720 newstateX = MVT::CloneViewNonConst(*workMV,bsind);
721 MVT::SetBlock(*state.
X,bsind,*newstateX);
723 if (state.
MX != Teuchos::null) {
724 std::vector<int> block3(blockSize_);
725 for (
int i=0; i<blockSize_; i++) block3[i] = 2*blockSize_+i;
726 newstateMX = MVT::CloneViewNonConst(*workMV,block3);
727 MVT::SetBlock(*state.
MX,bsind,*newstateMX);
733 MVT::MvRandom(*newX);
735 if (newstateMX != Teuchos::null) {
737 OPT::Apply(*problem_->getM(),*newX,*newMX);
744 ortho->projectAndNormalizeMat(*newstateX,curauxvecs,dummyC,Teuchos::null,newstateMX);
749 std::vector<int> block2(blockSize_);
750 for (
int i=0; i<blockSize_; i++) block2[i] = blockSize_+i;
751 newstateP = MVT::CloneViewNonConst(*workMV,block2);
752 MVT::SetBlock(*state.
P,bsind,*newstateP);
754 if (state.
MP != Teuchos::null) {
755 std::vector<int> block4(blockSize_);
756 for (
int i=0; i<blockSize_; i++) block4[i] = 3*blockSize_+i;
757 newstateMP = MVT::CloneViewNonConst(*workMV,block4);
758 MVT::SetBlock(*state.
MP,bsind,*newstateMP);
764 ortho->projectAndNormalizeMat(*newstateP,curauxvecs,dummyC,Teuchos::null,newstateMP);
768 ortho->projectAndNormalizeMat(*newstateP,curauxvecs,dummyC,Teuchos::null,newstateMP);
773 newstate.
X = newstateX;
774 newstate.
MX = newstateMX;
775 newstate.
P = newstateP;
776 newstate.
MP = newstateMP;
777 lobpcg_solver->initialize(newstate);
780 if (curNumLocked == maxLocked_) {
782 combotest->removeTest(locktest);
786 TEUCHOS_TEST_FOR_EXCEPTION(
true,std::logic_error,
"Anasazi::LOBPCGSolMgr::solve(): Invalid return from lobpcg_solver::iterate().");
795 if (fullOrtho_==
true || recover_==
false) {
799 printer->stream(
Warnings) <<
"Error! Caught LOBPCGRitzFailure at iteration " << lobpcg_solver->getNumIters() << std::endl
800 <<
"Will not try to recover." << std::endl;
803 printer->stream(
Warnings) <<
"Error! Caught LOBPCGRitzFailure at iteration " << lobpcg_solver->getNumIters() << std::endl
804 <<
"Full orthogonalization is off; will try to recover." << std::endl;
811 int localsize = lobpcg_solver->hasP() ? 3*blockSize_ : 2*blockSize_;
812 bool hasM = problem_->getM() != Teuchos::null;
814 std::vector<int> recind(localsize);
815 for (
int i=0; i<localsize; i++) recind[i] = i;
816 restart = MVT::CloneViewNonConst(*workMV,recind);
819 std::vector<int> recind(localsize);
820 for (
int i=0; i<localsize; i++) recind[i] = localsize+i;
821 Krestart = MVT::CloneViewNonConst(*workMV,recind);
834 std::vector<int> blk1(blockSize_);
835 for (
int i=0; i < blockSize_; i++) blk1[i] = i;
836 MVT::SetBlock(*curstate.
X,blk1,*restart);
840 MVT::SetBlock(*curstate.
MX,blk1,*Mrestart);
846 std::vector<int> blk2(blockSize_);
847 for (
int i=0; i < blockSize_; i++) blk2[i] = blockSize_+i;
848 MVT::SetBlock(*curstate.
H,blk2,*restart);
852 MVT::SetBlock(*curstate.
MH,blk2,*Mrestart);
856 if (localsize == 3*blockSize_) {
857 std::vector<int> blk3(blockSize_);
858 for (
int i=0; i < blockSize_; i++) blk3[i] = 2*blockSize_+i;
859 MVT::SetBlock(*curstate.
P,blk3,*restart);
863 MVT::SetBlock(*curstate.
MP,blk3,*Mrestart);
870 if (curNumLocked > 0) {
871 std::vector<int> indlock(curNumLocked);
872 for (
int i=0; i<curNumLocked; i++) indlock[i] = i;
876 if (probauxvecs != Teuchos::null) {
880 int rank = ortho->projectAndNormalizeMat(*restart,Q,dummyC,Teuchos::null,Mrestart);
881 if (rank < blockSize_) {
883 printer->stream(
Errors) <<
"Error! Recovered basis only rank " << rank <<
". Block size is " << blockSize_ <<
".\n"
884 <<
"Recovery failed." << std::endl;
888 if (rank < localsize) {
890 std::vector<int> redind(localsize);
891 for (
int i=0; i<localsize; i++) redind[i] = i;
893 restart = MVT::CloneViewNonConst(*restart,redind);
894 Krestart = MVT::CloneViewNonConst(*Krestart,redind);
903 std::vector<MagnitudeType> theta(localsize);
907 MVT::MvTransMv(1.0,*restart,*Mrestart,MM);
910 OPT::Apply(*problem_->getOperator(),*restart,*Krestart);
913 MVT::MvTransMv(1.0,*restart,*Krestart,KK);
915 msutils::directSolver(localsize,KK,Teuchos::rcpFromRef(MM),S,theta,rank,1);
916 if (rank < blockSize_) {
917 printer->stream(
Errors) <<
"Error! Recovered basis of rank " << rank <<
" produced only " << rank <<
"ritz vectors.\n"
918 <<
"Block size is " << blockSize_ <<
".\n"
919 <<
"Recovery failed." << std::endl;
927 std::vector<int> order(rank);
929 sorter->sort( theta, Teuchos::rcpFromRef(order),rank );
932 msutils::permuteVectors(order,curS);
941 std::vector<int> bsind(blockSize_);
942 for (
int i=0; i<blockSize_; i++) bsind[i] = i;
943 newX = MVT::CloneViewNonConst(*Krestart,bsind);
945 MVT::MvTimesMatAddMv(1.0,*restart,S1,0.0,*newX);
948 theta.resize(blockSize_);
949 newstate.
T = Teuchos::rcpFromRef(theta);
951 lobpcg_solver->initialize(newstate);
955 <<
"Anasazi::LOBPCGSolMgr::solve() caught unexpected exception from Anasazi::LOBPCG::iterate() at iteration " << lobpcg_solver->getNumIters() << std::endl
956 << err.what() << std::endl
957 <<
"Anasazi::LOBPCGSolMgr::solve() returning Unconverged with no solutions." << std::endl;
963 sol.
numVecs = ordertest->howMany();
965 sol.
Evecs = MVT::Clone(*problem_->getInitVec(),sol.
numVecs);
968 std::vector<MagnitudeType> vals(sol.
numVecs);
971 std::vector<int> which = ordertest->whichVecs();
975 std::vector<int> inlocked(0), insolver(0);
976 for (
unsigned int i=0; i<which.size(); i++) {
978 TEUCHOS_TEST_FOR_EXCEPTION(which[i] >= blockSize_,std::logic_error,
"Anasazi::LOBPCGSolMgr::solve(): positive indexing mistake from ordertest.");
979 insolver.push_back(which[i]);
983 TEUCHOS_TEST_FOR_EXCEPTION(which[i] < -curNumLocked,std::logic_error,
"Anasazi::LOBPCGSolMgr::solve(): negative indexing mistake from ordertest.");
984 inlocked.push_back(which[i] + curNumLocked);
991 if (insolver.size() > 0) {
993 int lclnum = insolver.size();
994 std::vector<int> tosol(lclnum);
995 for (
int i=0; i<lclnum; i++) tosol[i] = i;
997 MVT::SetBlock(*v,tosol,*sol.
Evecs);
999 std::vector<Value<ScalarType> > fromsolver = lobpcg_solver->getRitzValues();
1000 for (
unsigned int i=0; i<insolver.size(); i++) {
1001 vals[i] = fromsolver[insolver[i]].realpart;
1006 if (inlocked.size() > 0) {
1007 int solnum = insolver.size();
1009 int lclnum = inlocked.size();
1010 std::vector<int> tosol(lclnum);
1011 for (
int i=0; i<lclnum; i++) tosol[i] = solnum + i;
1013 MVT::SetBlock(*v,tosol,*sol.
Evecs);
1015 for (
unsigned int i=0; i<inlocked.size(); i++) {
1016 vals[i+solnum] = lockvals[inlocked[i]];
1022 std::vector<int> order(sol.
numVecs);
1023 sorter->sort( vals, Teuchos::rcpFromRef(order), sol.
numVecs);
1025 for (
int i=0; i<sol.
numVecs; i++) {
1026 sol.
Evals[i].realpart = vals[i];
1027 sol.
Evals[i].imagpart = MT::zero();
1039 lobpcg_solver->currentStatus(printer->stream(
FinalSummary));
1042 #ifdef ANASAZI_TEUCHOS_TIME_MONITOR
1048 problem_->setSolution(sol);
1049 printer->stream(
Debug) <<
"Returning " << sol.
numVecs <<
" eigenpairs to eigenproblem." << std::endl;
1052 numIters_ = lobpcg_solver->getNumIters();
1061 template <
class ScalarType,
class MV,
class OP>
1066 globalTest_ = global;
1069 template <
class ScalarType,
class MV,
class OP>
1076 template <
class ScalarType,
class MV,
class OP>
1084 template <
class ScalarType,
class MV,
class OP>
1091 template <
class ScalarType,
class MV,
class OP>
1096 lockingTest_ = locking;
1099 template <
class ScalarType,
class MV,
class OP>
1103 return lockingTest_;
Pure virtual base class which describes the basic interface for a solver manager. ...
std::vector< Value< ScalarType > > Evals
The computed eigenvalues.
const Teuchos::RCP< StatusTest< ScalarType, MV, OP > > & getLockingStatusTest() const
Get the status test defining locking.
ResType
Enumerated type used to specify which residual norm used by residual norm status tests.
A special StatusTest for printing other status tests.
const Teuchos::RCP< StatusTest< ScalarType, MV, OP > > & getDebugStatusTest() const
Get the status test for debugging.
This class defines the interface required by an eigensolver and status test class to compute solution...
LOBPCGSolMgr(const Teuchos::RCP< Eigenproblem< ScalarType, MV, OP > > &problem, Teuchos::ParameterList &pl)
Basic constructor for LOBPCGSolMgr.
An implementation of the Anasazi::SortManager that performs a collection of common sorting techniques...
T & get(const std::string &name, T def_value)
ParameterList & set(std::string const &name, T const &value, std::string const &docString="", RCP< const ParameterEntryValidator > const &validator=null)
#define TEUCHOS_TEST_FOR_EXCEPTION(throw_exception_test, Exception, msg)
This class provides the Locally Optimal Block Preconditioned Conjugate Gradient (LOBPCG) iteration...
Virtual base class which defines basic traits for the operator type.
Teuchos::RCP< MV > Evecs
The computed eigenvectors.
ReturnType solve()
This method performs possibly repeated calls to the underlying eigensolver's iterate() routine until ...
An implementation of the Anasazi::GenOrthoManager that performs orthogonalization using iterated clas...
Status test for forming logical combinations of other status tests.
Teuchos::RCP< const MultiVector > H
The current preconditioned residual vectors.
The Anasazi::SolverManager is a templated virtual base class that defines the basic interface that an...
Teuchos::RCP< const MultiVector > P
The current search direction.
Basic implementation of the Anasazi::SortManager class.
An implementation of the Anasazi::MatOrthoManager that performs orthogonalization using the SVQB iter...
An exception class parent to all Anasazi exceptions.
Output managers remove the need for the eigensolver to know any information about the required output...
Implementation of the locally-optimal block preconditioned conjugate gradient (LOBPCG) method...
Teuchos::RCP< const std::vector< typename Teuchos::ScalarTraits< ScalarType >::magnitudeType > > T
The current Ritz values.
A status test for testing the norm of the eigenvectors residuals along with a set of auxiliary eigenv...
Anasazi's templated, static class providing utilities for the solvers.
bool isParameter(const std::string &name) const
int numVecs
The number of computed eigenpairs.
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)
const Teuchos::RCP< StatusTest< ScalarType, MV, OP > > & getGlobalStatusTest() const
Get the status test defining global convergence.
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)
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...
Teuchos::RCP< const MultiVector > MX
The image of the current eigenvectors under M, or Teuchos::null if M was not specified.
Anasazi header file which uses auto-configuration information to include necessary C++ headers...
void setDebugStatusTest(const Teuchos::RCP< StatusTest< ScalarType, MV, OP > > &debug)
Set the status test for debugging.
Orthogonalization manager based on the SVQB technique described in "A Block Orthogonalization Procedu...
Struct for storing an eigenproblem solution.
void setLockingStatusTest(const Teuchos::RCP< StatusTest< ScalarType, MV, OP > > &locking)
Set the status test defining locking.
Teuchos::RCP< const MultiVector > MH
The image of the current preconditioned residual vectors under M, or Teuchos::null if M was not speci...
A status test for testing the number of iterations.
Status test for testing the number of iterations.
void push_back(const value_type &x)
Special StatusTest for printing status tests.
A status test for testing the norm of the eigenvectors residuals along with a set of auxiliary eigenv...
LOBPCGRitzFailure is thrown when the LOBPCG solver is unable to continue a call to LOBPCG::iterate() ...
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.
void setGlobalStatusTest(const Teuchos::RCP< StatusTest< ScalarType, MV, OP > > &global)
Set the status test defining global convergence.
virtual ~LOBPCGSolMgr()
Destructor.
Teuchos::Array< Teuchos::RCP< Teuchos::Time > > getTimers() const
Return the timers for this object.
Teuchos::RCP< const MultiVector > MP
The image of the current search direction under M, or Teuchos::null if M was not specified.
int getNumIters() const
Get the iteration count for the most recent call to solve().
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.
Basic implementation of the Anasazi::OrthoManager class.
User interface for the LOBPCG eigensolver.
Structure to contain pointers to Anasazi state variables.
Teuchos::RCP< const MultiVector > X
The current eigenvectors.
const Eigenproblem< ScalarType, MV, OP > & getProblem() const
Return the eigenvalue problem.
Class which provides internal utilities for the Anasazi solvers.