00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030 #ifndef ANASAZI_LOBPCG_SOLMGR_HPP
00031 #define ANASAZI_LOBPCG_SOLMGR_HPP
00032
00037 #include "AnasaziConfigDefs.hpp"
00038 #include "AnasaziTypes.hpp"
00039
00040 #include "AnasaziEigenproblem.hpp"
00041 #include "AnasaziSolverManager.hpp"
00042
00043 #include "AnasaziSolverUtils.hpp"
00044
00045 #include "AnasaziLOBPCG.hpp"
00046 #include "AnasaziBasicSort.hpp"
00047 #include "AnasaziSVQBOrthoManager.hpp"
00048 #include "AnasaziStatusTestMaxIters.hpp"
00049 #include "AnasaziStatusTestResNorm.hpp"
00050 #include "AnasaziStatusTestOrderedResNorm.hpp"
00051 #include "AnasaziStatusTestCombo.hpp"
00052 #include "AnasaziStatusTestOutput.hpp"
00053 #include "AnasaziBasicOutputManager.hpp"
00054
00055
00083 namespace Anasazi {
00084
00085 template<class ScalarType, class MV, class OP>
00086 class LOBPCGSolMgr : public SolverManager<ScalarType,MV,OP> {
00087
00088 private:
00089 typedef MultiVecTraits<ScalarType,MV> MVT;
00090 typedef OperatorTraits<ScalarType,MV,OP> OPT;
00091 typedef Teuchos::ScalarTraits<ScalarType> SCT;
00092 typedef typename Teuchos::ScalarTraits<ScalarType>::magnitudeType MagnitudeType;
00093 typedef Teuchos::ScalarTraits<MagnitudeType> MT;
00094
00095 public:
00096
00098
00099
00119 LOBPCGSolMgr( const Teuchos::RCP<Eigenproblem<ScalarType,MV,OP> > &problem,
00120 Teuchos::ParameterList &pl );
00121
00123 virtual ~LOBPCGSolMgr() {};
00125
00127
00128
00129 const Eigenproblem<ScalarType,MV,OP>& getProblem() const {
00130 return *problem_;
00131 }
00132
00134
00136
00137
00164 ReturnType solve();
00166
00167 private:
00168 Teuchos::RCP<Eigenproblem<ScalarType,MV,OP> > problem_;
00169
00170 std::string whch_;
00171
00172 MagnitudeType convtol_, locktol_;
00173 int maxIters_;
00174 bool useLocking_;
00175 bool relconvtol_, rellocktol_;
00176 int blockSize_;
00177 bool fullOrtho_;
00178 int maxLocked_;
00179 int verbosity_;
00180 int lockQuorum_;
00181 bool recover_;
00182 Teuchos::RCP<LOBPCGState<ScalarType,MV> > state_;
00183 };
00184
00185
00186
00187 template<class ScalarType, class MV, class OP>
00188 LOBPCGSolMgr<ScalarType,MV,OP>::LOBPCGSolMgr(
00189 const Teuchos::RCP<Eigenproblem<ScalarType,MV,OP> > &problem,
00190 Teuchos::ParameterList &pl ) :
00191 problem_(problem),
00192 whch_("SR"),
00193 convtol_(MT::prec()),
00194 maxIters_(100),
00195 useLocking_(false),
00196 relconvtol_(true),
00197 rellocktol_(true),
00198 blockSize_(0),
00199 fullOrtho_(true),
00200 maxLocked_(0),
00201 verbosity_(Anasazi::Errors),
00202 lockQuorum_(1),
00203 recover_(true)
00204 {
00205 TEST_FOR_EXCEPTION(problem_ == Teuchos::null, std::invalid_argument, "Problem not given to solver manager.");
00206 TEST_FOR_EXCEPTION(!problem_->isProblemSet(), std::invalid_argument, "Problem not set.");
00207 TEST_FOR_EXCEPTION(!problem_->isHermitian(), std::invalid_argument, "Problem not symmetric.");
00208 TEST_FOR_EXCEPTION(problem_->getInitVec() == Teuchos::null,std::invalid_argument, "Problem does not contain initial vectors to clone from.");
00209
00210
00211
00212 whch_ = pl.get("Which",whch_);
00213 TEST_FOR_EXCEPTION(whch_ != "SM" && whch_ != "LM" && whch_ != "SR" && whch_ != "LR",std::invalid_argument, "Invalid sorting string.");
00214
00215
00216 convtol_ = pl.get("Convergence Tolerance",convtol_);
00217 relconvtol_ = pl.get("Relative Convergence Tolerance",relconvtol_);
00218
00219
00220 useLocking_ = pl.get("Use Locking",useLocking_);
00221 rellocktol_ = pl.get("Relative Locking Tolerance",rellocktol_);
00222
00223 locktol_ = convtol_/10;
00224 locktol_ = pl.get("Locking Tolerance",locktol_);
00225
00226
00227 maxIters_ = pl.get("Maximum Iterations",maxIters_);
00228
00229
00230 blockSize_ = pl.get("Block Size",problem_->getNEV());
00231 TEST_FOR_EXCEPTION(blockSize_ <= 0, std::invalid_argument,
00232 "Anasazi::LOBPCGSolMgr: \"Block Size\" must be strictly positive.");
00233
00234
00235 if (useLocking_) {
00236 maxLocked_ = pl.get("Max Locked",problem_->getNEV());
00237 }
00238 else {
00239 maxLocked_ = 0;
00240 }
00241 if (maxLocked_ == 0) {
00242 useLocking_ = false;
00243 }
00244 TEST_FOR_EXCEPTION(maxLocked_ < 0, std::invalid_argument,
00245 "Anasazi::LOBPCGSolMgr: \"Max Locked\" must be positive.");
00246 TEST_FOR_EXCEPTION(maxLocked_ + blockSize_ < problem_->getNEV(),
00247 std::invalid_argument,
00248 "Anasazi::LOBPCGSolMgr: Not enough storage space for requested number of eigenpairs.");
00249
00250 if (useLocking_) {
00251 lockQuorum_ = pl.get("Locking Quorum",lockQuorum_);
00252 TEST_FOR_EXCEPTION(lockQuorum_ <= 0,
00253 std::invalid_argument,
00254 "Anasazi::LOBPCGSolMgr: \"Locking Quorum\" must be strictly positive.");
00255 }
00256
00257
00258 fullOrtho_ = pl.get("Full Ortho",fullOrtho_);
00259
00260
00261 if (pl.isParameter("Verbosity")) {
00262 if (Teuchos::isParameterType<int>(pl,"Verbosity")) {
00263 verbosity_ = pl.get("Verbosity", verbosity_);
00264 } else {
00265 verbosity_ = (int)Teuchos::getParameter<Anasazi::MsgType>(pl,"Verbosity");
00266 }
00267 }
00268
00269
00270 recover_ = pl.get("Recover",recover_);
00271
00272
00273 if (pl.isParameter("Init")) {
00274 state_ = Teuchos::getParameter<Teuchos::RCP<Anasazi::LOBPCGState<ScalarType,MV> > >(pl,"Init");
00275 }
00276 }
00277
00278
00279
00280 template<class ScalarType, class MV, class OP>
00281 ReturnType
00282 LOBPCGSolMgr<ScalarType,MV,OP>::solve() {
00283
00284 const int nev = problem_->getNEV();
00285
00286
00287
00289
00290 Teuchos::RCP<BasicSort<ScalarType,MV,OP> > sorter = Teuchos::rcp( new BasicSort<ScalarType,MV,OP>(whch_) );
00291
00293
00294 Teuchos::RCP<BasicOutputManager<ScalarType> > printer = Teuchos::rcp( new BasicOutputManager<ScalarType>(verbosity_) );
00295
00297
00298
00299
00300 Teuchos::RCP<StatusTestMaxIters<ScalarType,MV,OP> > maxtest;
00301 if (maxIters_ > 0) {
00302 maxtest = Teuchos::rcp( new StatusTestMaxIters<ScalarType,MV,OP>(maxIters_) );
00303 }
00304
00305 Teuchos::RCP<StatusTestOrderedResNorm<ScalarType,MV,OP> > convtest
00306 = Teuchos::rcp( new StatusTestOrderedResNorm<ScalarType,MV,OP>(sorter,convtol_,nev,StatusTestOrderedResNorm<ScalarType,MV,OP>::RES_ORTH,relconvtol_) );
00307
00308 Teuchos::RCP<StatusTestResNorm<ScalarType,MV,OP> > locktest;
00309 if (useLocking_) {
00310 locktest = Teuchos::rcp( new StatusTestResNorm<ScalarType,MV,OP>(locktol_,lockQuorum_,StatusTestResNorm<ScalarType,MV,OP>::RES_ORTH,rellocktol_) );
00311 }
00312 Teuchos::Array<Teuchos::RCP<StatusTest<ScalarType,MV,OP> > > alltests;
00313
00314 alltests.push_back(convtest);
00315 if (maxtest != Teuchos::null) alltests.push_back(maxtest);
00316 if (locktest != Teuchos::null) alltests.push_back(locktest);
00317
00318 Teuchos::RCP<StatusTestCombo<ScalarType,MV,OP> > combotest
00319 = Teuchos::rcp( new StatusTestCombo<ScalarType,MV,OP>( StatusTestCombo<ScalarType,MV,OP>::OR, alltests) );
00320
00321 Teuchos::RCP<StatusTestOutput<ScalarType,MV,OP> > outputtest;
00322 if ( printer->isVerbosity(Debug) ) {
00323 outputtest = Teuchos::rcp( new StatusTestOutput<ScalarType,MV,OP>( printer,combotest,1,Passed+Failed+Undefined ) );
00324 }
00325 else {
00326 outputtest = Teuchos::rcp( new StatusTestOutput<ScalarType,MV,OP>( printer,combotest,1,Passed ) );
00327 }
00328
00330
00331 Teuchos::RCP<SVQBOrthoManager<ScalarType,MV,OP> > ortho
00332 = Teuchos::rcp( new SVQBOrthoManager<ScalarType,MV,OP>(problem_->getM()) );
00333
00335
00336 Teuchos::ParameterList plist;
00337 plist.set("Block Size",blockSize_);
00338 plist.set("Full Ortho",fullOrtho_);
00339
00340
00341 SolverUtils<ScalarType,MV,OP> msutils;
00342
00344
00345 Teuchos::RCP<LOBPCG<ScalarType,MV,OP> > lobpcg_solver
00346 = Teuchos::rcp( new LOBPCG<ScalarType,MV,OP>(problem_,sorter,printer,outputtest,ortho,plist) );
00347
00348 Teuchos::RCP< const MV > probauxvecs = problem_->getAuxVecs();
00349 if (probauxvecs != Teuchos::null) {
00350 lobpcg_solver->setAuxVecs( Teuchos::tuple< Teuchos::RCP<const MV> >(probauxvecs) );
00351 }
00352
00354
00355
00356
00357 int numlocked = 0;
00358 Teuchos::RCP<MV> lockvecs;
00359 if (useLocking_) {
00360 lockvecs = MVT::Clone(*problem_->getInitVec(),maxLocked_);
00361 }
00362 std::vector<MagnitudeType> lockvals;
00363
00364
00365
00366
00367
00368
00369
00370
00371 Teuchos::RCP<MV> workMV;
00372 if (fullOrtho_ == false && recover_ == true) {
00373 workMV = MVT::Clone(*problem_->getInitVec(),2*3*blockSize_);
00374 }
00375 else if (useLocking_) {
00376 if (problem_->getM() != Teuchos::null) {
00377 workMV = MVT::Clone(*problem_->getInitVec(),4*blockSize_);
00378 }
00379 else {
00380 workMV = MVT::Clone(*problem_->getInitVec(),2*blockSize_);
00381 }
00382 }
00383
00384
00385 Eigensolution<ScalarType,MV> sol;
00386 sol.numVecs = 0;
00387 problem_->setSolution(sol);
00388
00389
00390 if (state_ != Teuchos::null) {
00391 lobpcg_solver->initialize(*state_);
00392 }
00393
00394
00395 while (1) {
00396 try {
00397 lobpcg_solver->iterate();
00398
00399
00400 if (convtest->getStatus() == Passed || (maxtest != Teuchos::null && maxtest->getStatus() == Passed) ) {
00401
00402
00403
00404 break;
00405 }
00406
00407 else if (locktest != Teuchos::null && locktest->getStatus() == Passed) {
00408
00409
00410 int numnew = locktest->howMany();
00411 TEST_FOR_EXCEPTION(numnew <= 0,std::logic_error,"Anasazi::LOBPCGSolMgr::solve(): status test mistake.");
00412
00413 std::vector<int> indnew = locktest->whichVecs();
00414
00415
00416 if (numlocked + numnew > maxLocked_) {
00417 numnew = maxLocked_ - numlocked;
00418 indnew.resize(numnew);
00419 }
00420
00421
00422
00423 bool hadP = lobpcg_solver->hasP();
00424
00425 {
00426
00427 printer->print(Debug,"Locking vectors: ");
00428 for (unsigned int i=0; i<indnew.size(); i++) {printer->stream(Debug) << " " << indnew[i];}
00429 printer->print(Debug,"\n");
00430 }
00431 std::vector<MagnitudeType> newvals(numnew);
00432 Teuchos::RCP<const MV> newvecs;
00433 {
00434
00435
00436 newvecs = MVT::CloneView(*lobpcg_solver->getRitzVectors(),indnew);
00437
00438 std::vector<Value<ScalarType> > allvals = lobpcg_solver->getRitzValues();
00439 for (int i=0; i<numnew; i++) {
00440 newvals[i] = allvals[indnew[i]].realpart;
00441 }
00442 }
00443
00444 {
00445 std::vector<int> indlock(numnew);
00446 for (int i=0; i<numnew; i++) indlock[i] = numlocked+i;
00447 MVT::SetBlock(*newvecs,indlock,*lockvecs);
00448 newvecs = Teuchos::null;
00449 }
00450
00451 lockvals.insert(lockvals.end(),newvals.begin(),newvals.end());
00452 numlocked += numnew;
00453
00454 {
00455 std::vector<int> indlock(numlocked);
00456 for (int i=0; i<numlocked; i++) indlock[i] = i;
00457 Teuchos::RCP<const MV> curlocked = MVT::CloneView(*lockvecs,indlock);
00458 if (probauxvecs != Teuchos::null) {
00459 lobpcg_solver->setAuxVecs( Teuchos::tuple< Teuchos::RCP<const MV> >(probauxvecs,curlocked) );
00460 }
00461 else {
00462 lobpcg_solver->setAuxVecs( Teuchos::tuple< Teuchos::RCP<const MV> >(curlocked) );
00463 }
00464 }
00465
00466 convtest->setAuxVals(lockvals);
00467
00468 {
00469 LOBPCGState<ScalarType,MV> state = lobpcg_solver->getState();
00470 Teuchos::RCP<MV> newstateX, newstateMX, newstateP, newstateMP;
00471
00472
00473
00474
00475 std::vector<int> bsind(blockSize_);
00476 for (int i=0; i<blockSize_; i++) bsind[i] = i;
00477 newstateX = MVT::CloneView(*workMV,bsind);
00478 MVT::SetBlock(*state.X,bsind,*newstateX);
00479
00480 if (state.MX != Teuchos::null) {
00481 std::vector<int> block3(blockSize_);
00482 for (int i=0; i<blockSize_; i++) block3[i] = 2*blockSize_+i;
00483 newstateMX = MVT::CloneView(*workMV,block3);
00484 MVT::SetBlock(*state.MX,bsind,*newstateMX);
00485 }
00486
00487
00488 {
00489 Teuchos::RCP<MV> newX = MVT::CloneView(*newstateX,indnew);
00490 MVT::MvRandom(*newX);
00491
00492 if (newstateMX != Teuchos::null) {
00493 Teuchos::RCP<MV> newMX = MVT::CloneView(*newstateMX,indnew);
00494 OPT::Apply(*problem_->getM(),*newX,*newMX);
00495 }
00496 }
00497
00498 Teuchos::Array<Teuchos::RCP<const MV> > curauxvecs = lobpcg_solver->getAuxVecs();
00499 Teuchos::Array<Teuchos::RCP<Teuchos::SerialDenseMatrix<int,ScalarType> > > dummy;
00500
00501 ortho->projectAndNormalizeMat(*newstateX,newstateMX,dummy,Teuchos::null,curauxvecs);
00502
00503 if (hadP) {
00504
00505
00506 std::vector<int> block2(blockSize_);
00507 for (int i=0; i<blockSize_; i++) block2[i] = blockSize_+i;
00508 newstateP = MVT::CloneView(*workMV,block2);
00509 MVT::SetBlock(*state.P,bsind,*newstateP);
00510
00511 if (state.MP != Teuchos::null) {
00512 std::vector<int> block4(blockSize_);
00513 for (int i=0; i<blockSize_; i++) block4[i] = 3*blockSize_+i;
00514 newstateMP = MVT::CloneView(*workMV,block4);
00515 MVT::SetBlock(*state.MP,bsind,*newstateMP);
00516 }
00517
00518 if (fullOrtho_) {
00519
00520 curauxvecs.push_back(newstateX);
00521 ortho->projectAndNormalizeMat(*newstateP,newstateMP,dummy,Teuchos::null,curauxvecs);
00522 }
00523 else {
00524
00525 ortho->projectAndNormalizeMat(*newstateP,newstateMP,dummy,Teuchos::null,curauxvecs);
00526 }
00527 }
00528
00529 LOBPCGState<ScalarType,MV> newstate;
00530 newstate.X = newstateX;
00531 newstate.MX = newstateMX;
00532 newstate.P = newstateP;
00533 newstate.MP = newstateMP;
00534 lobpcg_solver->initialize(newstate);
00535 }
00536
00537 if (numlocked == maxLocked_) {
00538
00539 locktest->setQuorum(blockSize_+1);
00540 }
00541 }
00542 else {
00543 TEST_FOR_EXCEPTION(true,std::logic_error,"Anasazi::LOBPCGSolMgr::solve(): Invalid return from lobpcg_solver::iterate().");
00544 }
00545 }
00546 catch (LOBPCGRitzFailure re) {
00547 if (fullOrtho_==true || recover_==false) {
00548
00549
00550
00551 printer->stream(Warnings) << "Error! Caught LOBPCGRitzFailure at iteration " << lobpcg_solver->getNumIters() << std::endl
00552 << "Will not try to recover." << std::endl;
00553 break;
00554 }
00555 printer->stream(Warnings) << "Error! Caught LOBPCGRitzFailure at iteration " << lobpcg_solver->getNumIters() << std::endl
00556 << "Full orthogonalization is off; will try to recover." << std::endl;
00557
00558
00559
00560
00561 LOBPCGState<ScalarType,MV> curstate = lobpcg_solver->getState();
00562 Teuchos::RCP<MV> restart, Krestart, Mrestart;
00563 int localsize = lobpcg_solver->hasP() ? 3*blockSize_ : 2*blockSize_;
00564 bool hasM = problem_->getM() != Teuchos::null;
00565 {
00566 std::vector<int> recind(localsize);
00567 for (int i=0; i<localsize; i++) recind[i] = i;
00568 restart = MVT::CloneView(*workMV,recind);
00569 }
00570 {
00571 std::vector<int> recind(localsize);
00572 for (int i=0; i<localsize; i++) recind[i] = localsize+i;
00573 Krestart = MVT::CloneView(*workMV,recind);
00574 }
00575 if (hasM) {
00576 Mrestart = Krestart;
00577 }
00578 else {
00579 Mrestart = restart;
00580 }
00581
00582
00583
00584
00585 {
00586 std::vector<int> blk1(blockSize_);
00587 for (int i=0; i < blockSize_; i++) blk1[i] = i;
00588 MVT::SetBlock(*curstate.X,blk1,*restart);
00589
00590
00591 if (hasM) {
00592 MVT::SetBlock(*curstate.MX,blk1,*Mrestart);
00593 }
00594 }
00595
00596
00597 {
00598 std::vector<int> blk2(blockSize_);
00599 for (int i=0; i < blockSize_; i++) blk2[i] = blockSize_+i;
00600 MVT::SetBlock(*curstate.H,blk2,*restart);
00601
00602
00603 if (hasM) {
00604 MVT::SetBlock(*curstate.MH,blk2,*Mrestart);
00605 }
00606 }
00607
00608 if (localsize == 3*blockSize_) {
00609 std::vector<int> blk3(blockSize_);
00610 for (int i=0; i < blockSize_; i++) blk3[i] = 2*blockSize_+i;
00611 MVT::SetBlock(*curstate.P,blk3,*restart);
00612
00613
00614 if (hasM) {
00615 MVT::SetBlock(*curstate.MP,blk3,*Mrestart);
00616 }
00617 }
00618
00619 Teuchos::Array<Teuchos::RCP<Teuchos::SerialDenseMatrix<int,ScalarType> > > dummy;
00620 Teuchos::Array<Teuchos::RCP<const MV> > Q;
00621 {
00622 if (numlocked > 0) {
00623 std::vector<int> indlock(numlocked);
00624 for (int i=0; i<numlocked; i++) indlock[i] = i;
00625 Teuchos::RCP<const MV> curlocked = MVT::CloneView(*lockvecs,indlock);
00626 Q.push_back(curlocked);
00627 }
00628 if (probauxvecs != Teuchos::null) {
00629 Q.push_back(probauxvecs);
00630 }
00631 }
00632 int rank = ortho->projectAndNormalizeMat(*restart,Mrestart,dummy,Teuchos::null,Q);
00633 if (rank < blockSize_) {
00634
00635 printer->stream(Errors) << "Error! Recovered basis only rank " << rank << ". Block size is " << blockSize_ << ".\n"
00636 << "Recovery failed." << std::endl;
00637 break;
00638 }
00639
00640 if (rank < localsize) {
00641 localsize = rank;
00642 std::vector<int> redind(localsize);
00643 for (int i=0; i<localsize; i++) redind[i] = i;
00644
00645 restart = MVT::CloneView(*restart,redind);
00646 Krestart = MVT::CloneView(*Krestart,redind);
00647 if (hasM) {
00648 Mrestart = Krestart;
00649 }
00650 else {
00651 Mrestart = restart;
00652 }
00653 }
00654 Teuchos::SerialDenseMatrix<int,ScalarType> KK(localsize,localsize), MM(localsize,localsize), S(localsize,localsize);
00655 std::vector<MagnitudeType> theta(localsize);
00656
00657
00658
00659 MVT::MvTransMv(1.0,*restart,*Mrestart,MM);
00660
00661
00662 OPT::Apply(*problem_->getOperator(),*restart,*Krestart);
00663
00664
00665 MVT::MvTransMv(1.0,*restart,*Krestart,KK);
00666 rank = localsize;
00667 msutils.directSolver(localsize,KK,Teuchos::rcp(&MM,false),S,theta,rank,1);
00668 if (rank < blockSize_) {
00669 printer->stream(Errors) << "Error! Recovered basis of rank " << rank << " produced only " << rank << "ritz vectors.\n"
00670 << "Block size is " << blockSize_ << ".\n"
00671 << "Recovery failed." << std::endl;
00672 break;
00673 }
00674 theta.resize(rank);
00675
00676
00677 {
00678 Teuchos::BLAS<int,ScalarType> blas;
00679 std::vector<int> order(rank);
00680
00681 sorter->sort( lobpcg_solver.get(), rank, theta, &order );
00682
00683 Teuchos::SerialDenseMatrix<int,ScalarType> curS(Teuchos::View,S,rank,rank);
00684 msutils.permuteVectors(order,curS);
00685 }
00686
00687 Teuchos::SerialDenseMatrix<int,ScalarType> S1(Teuchos::View,S,localsize,blockSize_);
00688
00689
00690 LOBPCGState<ScalarType,MV> newstate;
00691 Teuchos::RCP<MV> newX;
00692 {
00693 std::vector<int> bsind(blockSize_);
00694 for (int i=0; i<blockSize_; i++) bsind[i] = i;
00695 newX = MVT::CloneView(*Krestart,bsind);
00696 }
00697 MVT::MvTimesMatAddMv(1.0,*restart,S1,0.0,*newX);
00698
00699 newstate.X = newX;
00700 theta.resize(blockSize_);
00701 newstate.T = Teuchos::rcp( &theta, false );
00702
00703 lobpcg_solver->initialize(newstate);
00704 }
00705
00706 }
00707
00708 sol.numVecs = convtest->howMany();
00709 if (sol.numVecs > 0) {
00710 sol.Evecs = MVT::Clone(*problem_->getInitVec(),sol.numVecs);
00711 sol.Espace = sol.Evecs;
00712 sol.Evals.resize(sol.numVecs);
00713 std::vector<MagnitudeType> vals(sol.numVecs);
00714
00715
00716 std::vector<int> which = convtest->whichVecs();
00717
00718
00719
00720 std::vector<int> inlocked(0), insolver(0);
00721 for (unsigned int i=0; i<which.size(); i++) {
00722 if (which[i] < blockSize_) {
00723 insolver.push_back(which[i]);
00724 }
00725 else {
00726
00727 TEST_FOR_EXCEPTION(which[i] >= numlocked+blockSize_,std::logic_error,"Anasazi::LOBPCGSolMgr::solve(): indexing mistake.");
00728 inlocked.push_back(which[i] - blockSize_);
00729 }
00730 }
00731
00732 TEST_FOR_EXCEPTION(insolver.size() + inlocked.size() != (unsigned int)sol.numVecs,std::logic_error,"Anasazi::LOBPCGSolMgr::solve(): indexing mistake.");
00733
00734
00735 if (insolver.size() > 0) {
00736
00737 int lclnum = insolver.size();
00738 std::vector<int> tosol(lclnum);
00739 for (int i=0; i<lclnum; i++) tosol[i] = i;
00740 Teuchos::RCP<const MV> v = MVT::CloneView(*lobpcg_solver->getRitzVectors(),insolver);
00741 MVT::SetBlock(*v,tosol,*sol.Evecs);
00742
00743 std::vector<Value<ScalarType> > fromsolver = lobpcg_solver->getRitzValues();
00744 for (unsigned int i=0; i<insolver.size(); i++) {
00745 vals[i] = fromsolver[insolver[i]].realpart;
00746 }
00747 }
00748
00749
00750 if (inlocked.size() > 0) {
00751 int solnum = insolver.size();
00752
00753 int lclnum = inlocked.size();
00754 std::vector<int> tosol(lclnum);
00755 for (int i=0; i<lclnum; i++) tosol[i] = solnum + i;
00756 Teuchos::RCP<const MV> v = MVT::CloneView(*lockvecs,inlocked);
00757 MVT::SetBlock(*v,tosol,*sol.Evecs);
00758
00759 for (unsigned int i=0; i<inlocked.size(); i++) {
00760 vals[i+solnum] = lockvals[inlocked[i]];
00761 }
00762 }
00763
00764
00765 {
00766 std::vector<int> order(sol.numVecs);
00767 sorter->sort( lobpcg_solver.get(), sol.numVecs, vals, &order );
00768
00769 for (int i=0; i<sol.numVecs; i++) {
00770 sol.Evals[i].realpart = vals[i];
00771 sol.Evals[i].imagpart = MT::zero();
00772 }
00773
00774 msutils.permuteVectors(sol.numVecs,order,*sol.Evecs);
00775 }
00776
00777
00778 sol.index.resize(sol.numVecs,0);
00779 }
00780
00781
00782 lobpcg_solver->currentStatus(printer->stream(FinalSummary));
00783
00784
00785 Teuchos::TimeMonitor::summarize(printer->stream(TimingDetails));
00786
00787 problem_->setSolution(sol);
00788 printer->stream(Debug) << "Returning " << sol.numVecs << " eigenpairs to eigenproblem." << std::endl;
00789
00790 if (sol.numVecs < nev) return Unconverged;
00791 return Converged;
00792 }
00793
00794
00795 }
00796
00797 #endif