10 #ifndef ANASAZI_LOBPCG_SOLMGR_HPP
11 #define ANASAZI_LOBPCG_SOLMGR_HPP
39 #include "Teuchos_FancyOStream.hpp"
141 template<
class ScalarType,
class MV,
class OP>
210 return Teuchos::tuple(_timerSolve, _timerLocking);
270 std::string whch_, ortho_;
272 MagnitudeType convtol_, locktol_;
273 int maxIters_, numIters_;
275 bool relconvtol_, rellocktol_;
283 enum ResType convNorm_, lockNorm_;
297 template<
class ScalarType,
class MV,
class OP>
304 convtol_(
MT::prec()),
313 verbosity_(Anasazi::
Errors),
317 #ifdef ANASAZI_TEUCHOS_TIME_MONITOR
318 , _timerSolve(Teuchos::TimeMonitor::getNewTimer(
"Anasazi: LOBPCGSolMgr::solve()")),
319 _timerLocking(Teuchos::TimeMonitor::getNewTimer(
"Anasazi: LOBPCGSolMgr locking"))
325 TEUCHOS_TEST_FOR_EXCEPTION(problem_->getInitVec() == Teuchos::null,std::invalid_argument,
"Problem does not contain initial vectors to clone from.");
331 whch_ = pl.
get(
"Which",whch_);
333 std::invalid_argument,
"Anasazi::LOBPCGSolMgr: Invalid sorting string.");
336 ortho_ = pl.
get(
"Orthogonalization",ortho_);
337 if (ortho_ !=
"DGKS" && ortho_ !=
"SVQB" && ortho_ !=
"ICGS") {
342 convtol_ = pl.
get(
"Convergence Tolerance",convtol_);
343 relconvtol_ = pl.
get(
"Relative Convergence Tolerance",relconvtol_);
344 strtmp = pl.
get(
"Convergence Norm",std::string(
"2"));
346 convNorm_ = RES_2NORM;
348 else if (strtmp ==
"M") {
349 convNorm_ = RES_ORTH;
353 "Anasazi::LOBPCGSolMgr: Invalid Convergence Norm.");
358 useLocking_ = pl.
get(
"Use Locking",useLocking_);
359 rellocktol_ = pl.
get(
"Relative Locking Tolerance",rellocktol_);
361 locktol_ = convtol_/10;
362 locktol_ = pl.
get(
"Locking Tolerance",locktol_);
363 strtmp = pl.
get(
"Locking Norm",std::string(
"2"));
365 lockNorm_ = RES_2NORM;
367 else if (strtmp ==
"M") {
368 lockNorm_ = RES_ORTH;
372 "Anasazi::LOBPCGSolMgr: Invalid Locking Norm.");
376 maxIters_ = pl.
get(
"Maximum Iterations",maxIters_);
379 blockSize_ = pl.
get(
"Block Size",problem_->getNEV());
381 "Anasazi::LOBPCGSolMgr: \"Block Size\" must be strictly positive.");
385 maxLocked_ = pl.
get(
"Max Locked",problem_->getNEV());
390 if (maxLocked_ == 0) {
394 "Anasazi::LOBPCGSolMgr: \"Max Locked\" must be positive.");
396 std::invalid_argument,
397 "Anasazi::LOBPCGSolMgr: Not enough storage space for requested number of eigenpairs.");
400 lockQuorum_ = pl.
get(
"Locking Quorum",lockQuorum_);
402 std::invalid_argument,
403 "Anasazi::LOBPCGSolMgr: \"Locking Quorum\" must be strictly positive.");
407 fullOrtho_ = pl.
get(
"Full Ortho",fullOrtho_);
411 osProc_ = pl.
get(
"Output Processor", osProc_);
415 osp_ = Teuchos::getParameter<Teuchos::RCP<Teuchos::FancyOStream> >(pl,
"Output Stream");
423 if (Teuchos::isParameterType<int>(pl,
"Verbosity")) {
424 verbosity_ = pl.
get(
"Verbosity", verbosity_);
426 verbosity_ = (int)Teuchos::getParameter<Anasazi::MsgType>(pl,
"Verbosity");
431 recover_ = pl.
get(
"Recover",recover_);
435 state_ = Teuchos::getParameter<Teuchos::RCP<Anasazi::LOBPCGState<ScalarType,MV> > >(pl,
"Init");
441 template<
class ScalarType,
class MV,
class OP>
447 const int nev = problem_->getNEV();
469 if (globalTest_ == Teuchos::null) {
473 convtest = globalTest_;
480 if (lockingTest_ == Teuchos::null) {
484 locktest = lockingTest_;
490 if (locktest != Teuchos::null) alltests.
push_back(locktest);
491 if (debugTest_ != Teuchos::null) alltests.
push_back(debugTest_);
492 if (maxtest != Teuchos::null) alltests.
push_back(maxtest);
497 if ( printer->isVerbosity(
Debug) ) {
507 if (ortho_==
"SVQB") {
509 }
else if (ortho_==
"DGKS") {
511 }
else if (ortho_==
"ICGS") {
514 TEUCHOS_TEST_FOR_EXCEPTION(ortho_!=
"SVQB"&&ortho_!=
"DGKS"&&ortho_!=
"ICGS",std::logic_error,
"Anasazi::LOBPCGSolMgr::solve(): Invalid orthogonalization type.");
520 plist.
set(
"Block Size",blockSize_);
521 plist.
set(
"Full Ortho",fullOrtho_);
529 if (probauxvecs != Teuchos::null) {
537 int curNumLocked = 0;
540 lockvecs = MVT::Clone(*problem_->getInitVec(),maxLocked_);
542 std::vector<MagnitudeType> lockvals;
552 if (fullOrtho_ ==
false && recover_ ==
true) {
553 workMV = MVT::Clone(*problem_->getInitVec(),2*3*blockSize_);
555 else if (useLocking_) {
556 if (problem_->getM() != Teuchos::null) {
557 workMV = MVT::Clone(*problem_->getInitVec(),4*blockSize_);
560 workMV = MVT::Clone(*problem_->getInitVec(),2*blockSize_);
567 problem_->setSolution(sol);
570 if (state_ != Teuchos::null) {
571 lobpcg_solver->initialize(*state_);
576 #ifdef ANASAZI_TEUCHOS_TIME_MONITOR
583 lobpcg_solver->iterate();
590 if (debugTest_ != Teuchos::null && debugTest_->getStatus() ==
Passed) {
591 throw AnasaziError(
"Anasazi::LOBPCGSolMgr::solve(): User-specified debug status test returned Passed.");
598 else if (ordertest->getStatus() ==
Passed || (maxtest != Teuchos::null && maxtest->getStatus() ==
Passed) ) {
609 else if (locktest != Teuchos::null && locktest->getStatus() ==
Passed) {
611 #ifdef ANASAZI_TEUCHOS_TIME_MONITOR
617 "Anasazi::LOBPCGSolMgr::solve(): status test mistake: howMany() non-positive.");
619 "Anasazi::LOBPCGSolMgr::solve(): status test mistake: howMany() not consistent with whichVecs().");
621 "Anasazi::LOBPCGSolMgr::solve(): status test mistake: locking not deactivated.");
623 int numnew = locktest->howMany();
624 std::vector<int> indnew = locktest->whichVecs();
627 if (curNumLocked + numnew > maxLocked_) {
628 numnew = maxLocked_ - curNumLocked;
629 indnew.resize(numnew);
634 bool hadP = lobpcg_solver->hasP();
638 printer->print(
Debug,
"Locking vectors: ");
639 for (
unsigned int i=0; i<indnew.size(); i++) {printer->stream(
Debug) <<
" " << indnew[i];}
640 printer->print(
Debug,
"\n");
642 std::vector<MagnitudeType> newvals(numnew);
647 newvecs = MVT::CloneView(*lobpcg_solver->getRitzVectors(),indnew);
649 std::vector<Value<ScalarType> > allvals = lobpcg_solver->getRitzValues();
650 for (
int i=0; i<numnew; i++) {
651 newvals[i] = allvals[indnew[i]].realpart;
656 std::vector<int> indlock(numnew);
657 for (
int i=0; i<numnew; i++) indlock[i] = curNumLocked+i;
658 MVT::SetBlock(*newvecs,indlock,*lockvecs);
659 newvecs = Teuchos::null;
662 lockvals.insert(lockvals.end(),newvals.begin(),newvals.end());
663 curNumLocked += numnew;
666 std::vector<int> indlock(curNumLocked);
667 for (
int i=0; i<curNumLocked; i++) indlock[i] = i;
669 if (probauxvecs != Teuchos::null) {
677 ordertest->setAuxVals(lockvals);
686 std::vector<int> bsind(blockSize_);
687 for (
int i=0; i<blockSize_; i++) bsind[i] = i;
688 newstateX = MVT::CloneViewNonConst(*workMV,bsind);
689 MVT::SetBlock(*state.
X,bsind,*newstateX);
691 if (state.
MX != Teuchos::null) {
692 std::vector<int> block3(blockSize_);
693 for (
int i=0; i<blockSize_; i++) block3[i] = 2*blockSize_+i;
694 newstateMX = MVT::CloneViewNonConst(*workMV,block3);
695 MVT::SetBlock(*state.
MX,bsind,*newstateMX);
701 MVT::MvRandom(*newX);
703 if (newstateMX != Teuchos::null) {
705 OPT::Apply(*problem_->getM(),*newX,*newMX);
712 ortho->projectAndNormalizeMat(*newstateX,curauxvecs,dummyC,Teuchos::null,newstateMX);
717 std::vector<int> block2(blockSize_);
718 for (
int i=0; i<blockSize_; i++) block2[i] = blockSize_+i;
719 newstateP = MVT::CloneViewNonConst(*workMV,block2);
720 MVT::SetBlock(*state.
P,bsind,*newstateP);
722 if (state.
MP != Teuchos::null) {
723 std::vector<int> block4(blockSize_);
724 for (
int i=0; i<blockSize_; i++) block4[i] = 3*blockSize_+i;
725 newstateMP = MVT::CloneViewNonConst(*workMV,block4);
726 MVT::SetBlock(*state.
MP,bsind,*newstateMP);
732 ortho->projectAndNormalizeMat(*newstateP,curauxvecs,dummyC,Teuchos::null,newstateMP);
736 ortho->projectAndNormalizeMat(*newstateP,curauxvecs,dummyC,Teuchos::null,newstateMP);
741 newstate.
X = newstateX;
742 newstate.
MX = newstateMX;
743 newstate.
P = newstateP;
744 newstate.
MP = newstateMP;
745 lobpcg_solver->initialize(newstate);
748 if (curNumLocked == maxLocked_) {
750 combotest->removeTest(locktest);
754 TEUCHOS_TEST_FOR_EXCEPTION(
true,std::logic_error,
"Anasazi::LOBPCGSolMgr::solve(): Invalid return from lobpcg_solver::iterate().");
763 if (fullOrtho_==
true || recover_==
false) {
767 printer->stream(
Warnings) <<
"Error! Caught LOBPCGRitzFailure at iteration " << lobpcg_solver->getNumIters() << std::endl
768 <<
"Will not try to recover." << std::endl;
771 printer->stream(
Warnings) <<
"Error! Caught LOBPCGRitzFailure at iteration " << lobpcg_solver->getNumIters() << std::endl
772 <<
"Full orthogonalization is off; will try to recover." << std::endl;
779 int localsize = lobpcg_solver->hasP() ? 3*blockSize_ : 2*blockSize_;
780 bool hasM = problem_->getM() != Teuchos::null;
782 std::vector<int> recind(localsize);
783 for (
int i=0; i<localsize; i++) recind[i] = i;
784 restart = MVT::CloneViewNonConst(*workMV,recind);
787 std::vector<int> recind(localsize);
788 for (
int i=0; i<localsize; i++) recind[i] = localsize+i;
789 Krestart = MVT::CloneViewNonConst(*workMV,recind);
802 std::vector<int> blk1(blockSize_);
803 for (
int i=0; i < blockSize_; i++) blk1[i] = i;
804 MVT::SetBlock(*curstate.
X,blk1,*restart);
808 MVT::SetBlock(*curstate.
MX,blk1,*Mrestart);
814 std::vector<int> blk2(blockSize_);
815 for (
int i=0; i < blockSize_; i++) blk2[i] = blockSize_+i;
816 MVT::SetBlock(*curstate.
H,blk2,*restart);
820 MVT::SetBlock(*curstate.
MH,blk2,*Mrestart);
824 if (localsize == 3*blockSize_) {
825 std::vector<int> blk3(blockSize_);
826 for (
int i=0; i < blockSize_; i++) blk3[i] = 2*blockSize_+i;
827 MVT::SetBlock(*curstate.
P,blk3,*restart);
831 MVT::SetBlock(*curstate.
MP,blk3,*Mrestart);
838 if (curNumLocked > 0) {
839 std::vector<int> indlock(curNumLocked);
840 for (
int i=0; i<curNumLocked; i++) indlock[i] = i;
844 if (probauxvecs != Teuchos::null) {
848 int rank = ortho->projectAndNormalizeMat(*restart,Q,dummyC,Teuchos::null,Mrestart);
849 if (rank < blockSize_) {
851 printer->stream(
Errors) <<
"Error! Recovered basis only rank " << rank <<
". Block size is " << blockSize_ <<
".\n"
852 <<
"Recovery failed." << std::endl;
856 if (rank < localsize) {
858 std::vector<int> redind(localsize);
859 for (
int i=0; i<localsize; i++) redind[i] = i;
861 restart = MVT::CloneViewNonConst(*restart,redind);
862 Krestart = MVT::CloneViewNonConst(*Krestart,redind);
871 std::vector<MagnitudeType> theta(localsize);
875 MVT::MvTransMv(1.0,*restart,*Mrestart,MM);
878 OPT::Apply(*problem_->getOperator(),*restart,*Krestart);
881 MVT::MvTransMv(1.0,*restart,*Krestart,KK);
883 msutils::directSolver(localsize,KK,Teuchos::rcpFromRef(MM),S,theta,rank,1);
884 if (rank < blockSize_) {
885 printer->stream(
Errors) <<
"Error! Recovered basis of rank " << rank <<
" produced only " << rank <<
"ritz vectors.\n"
886 <<
"Block size is " << blockSize_ <<
".\n"
887 <<
"Recovery failed." << std::endl;
895 std::vector<int> order(rank);
897 sorter->sort( theta, Teuchos::rcpFromRef(order),rank );
900 msutils::permuteVectors(order,curS);
909 std::vector<int> bsind(blockSize_);
910 for (
int i=0; i<blockSize_; i++) bsind[i] = i;
911 newX = MVT::CloneViewNonConst(*Krestart,bsind);
913 MVT::MvTimesMatAddMv(1.0,*restart,S1,0.0,*newX);
916 theta.resize(blockSize_);
917 newstate.
T = Teuchos::rcpFromRef(theta);
919 lobpcg_solver->initialize(newstate);
923 <<
"Anasazi::LOBPCGSolMgr::solve() caught unexpected exception from Anasazi::LOBPCG::iterate() at iteration " << lobpcg_solver->getNumIters() << std::endl
924 << err.what() << std::endl
925 <<
"Anasazi::LOBPCGSolMgr::solve() returning Unconverged with no solutions." << std::endl;
931 sol.
numVecs = ordertest->howMany();
933 sol.
Evecs = MVT::Clone(*problem_->getInitVec(),sol.
numVecs);
936 std::vector<MagnitudeType> vals(sol.
numVecs);
939 std::vector<int> which = ordertest->whichVecs();
943 std::vector<int> inlocked(0), insolver(0);
944 for (
unsigned int i=0; i<which.size(); i++) {
946 TEUCHOS_TEST_FOR_EXCEPTION(which[i] >= blockSize_,std::logic_error,
"Anasazi::LOBPCGSolMgr::solve(): positive indexing mistake from ordertest.");
947 insolver.push_back(which[i]);
951 TEUCHOS_TEST_FOR_EXCEPTION(which[i] < -curNumLocked,std::logic_error,
"Anasazi::LOBPCGSolMgr::solve(): negative indexing mistake from ordertest.");
952 inlocked.push_back(which[i] + curNumLocked);
959 if (insolver.size() > 0) {
961 int lclnum = insolver.size();
962 std::vector<int> tosol(lclnum);
963 for (
int i=0; i<lclnum; i++) tosol[i] = i;
965 MVT::SetBlock(*v,tosol,*sol.
Evecs);
967 std::vector<Value<ScalarType> > fromsolver = lobpcg_solver->getRitzValues();
968 for (
unsigned int i=0; i<insolver.size(); i++) {
969 vals[i] = fromsolver[insolver[i]].realpart;
974 if (inlocked.size() > 0) {
975 int solnum = insolver.size();
977 int lclnum = inlocked.size();
978 std::vector<int> tosol(lclnum);
979 for (
int i=0; i<lclnum; i++) tosol[i] = solnum + i;
981 MVT::SetBlock(*v,tosol,*sol.
Evecs);
983 for (
unsigned int i=0; i<inlocked.size(); i++) {
984 vals[i+solnum] = lockvals[inlocked[i]];
990 std::vector<int> order(sol.
numVecs);
991 sorter->sort( vals, Teuchos::rcpFromRef(order), sol.
numVecs);
993 for (
int i=0; i<sol.
numVecs; i++) {
994 sol.
Evals[i].realpart = vals[i];
995 sol.
Evals[i].imagpart = MT::zero();
1007 lobpcg_solver->currentStatus(printer->stream(
FinalSummary));
1010 #ifdef ANASAZI_TEUCHOS_TIME_MONITOR
1016 problem_->setSolution(sol);
1017 printer->stream(
Debug) <<
"Returning " << sol.
numVecs <<
" eigenpairs to eigenproblem." << std::endl;
1020 numIters_ = lobpcg_solver->getNumIters();
1029 template <
class ScalarType,
class MV,
class OP>
1034 globalTest_ = global;
1037 template <
class ScalarType,
class MV,
class OP>
1044 template <
class ScalarType,
class MV,
class OP>
1052 template <
class ScalarType,
class MV,
class OP>
1059 template <
class ScalarType,
class MV,
class OP>
1064 lockingTest_ = locking;
1067 template <
class ScalarType,
class MV,
class OP>
1071 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)
#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.
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...
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.