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 #ifndef ANASAZI_BLOCK_KRYLOV_SCHUR_SOLMGR_HPP
00030 #define ANASAZI_BLOCK_KRYLOV_SCHUR_SOLMGR_HPP
00031
00036 #include "AnasaziConfigDefs.hpp"
00037 #include "AnasaziTypes.hpp"
00038
00039 #include "AnasaziEigenproblem.hpp"
00040 #include "AnasaziSolverManager.hpp"
00041
00042 #include "AnasaziBlockKrylovSchur.hpp"
00043 #include "AnasaziBasicSort.hpp"
00044 #include "AnasaziSVQBOrthoManager.hpp"
00045 #include "AnasaziBasicOrthoManager.hpp"
00046 #include "AnasaziStatusTestMaxIters.hpp"
00047 #include "AnasaziStatusTestResNorm.hpp"
00048 #include "AnasaziStatusTestOrderedResNorm.hpp"
00049 #include "AnasaziStatusTestCombo.hpp"
00050 #include "AnasaziStatusTestOutput.hpp"
00051 #include "AnasaziBasicOutputManager.hpp"
00052 #include "AnasaziSolverUtils.hpp"
00053 #include "Teuchos_BLAS.hpp"
00054 #include "Teuchos_LAPACK.hpp"
00055 #include "Teuchos_TimeMonitor.hpp"
00056
00070 namespace Anasazi {
00071
00072 template<class ScalarType, class MV, class OP>
00073 class BlockKrylovSchurSolMgr : public SolverManager<ScalarType,MV,OP> {
00074
00075 private:
00076 typedef MultiVecTraits<ScalarType,MV> MVT;
00077 typedef OperatorTraits<ScalarType,MV,OP> OPT;
00078 typedef Teuchos::ScalarTraits<ScalarType> SCT;
00079 typedef typename Teuchos::ScalarTraits<ScalarType>::magnitudeType MagnitudeType;
00080 typedef Teuchos::ScalarTraits<MagnitudeType> MT;
00081
00082 public:
00083
00085
00086
00102 BlockKrylovSchurSolMgr( const Teuchos::RCP<Eigenproblem<ScalarType,MV,OP> > &problem,
00103 Teuchos::ParameterList &pl );
00104
00106 virtual ~BlockKrylovSchurSolMgr() {};
00108
00110
00111
00112 const Eigenproblem<ScalarType,MV,OP>& getProblem() const {
00113 return *_problem;
00114 }
00115
00118 std::vector<Value<ScalarType> > getRitzValues() const {
00119 std::vector<Value<ScalarType> > ret( _ritzValues );
00120 return ret;
00121 }
00122
00129 Teuchos::Array<Teuchos::RCP<Teuchos::Time> > getTimers() const {
00130 return tuple(_timerSolve, _timerRestarting);
00131 }
00132
00134
00136
00137
00156 ReturnType solve();
00158
00159 private:
00160 Teuchos::RCP<Eigenproblem<ScalarType,MV,OP> > _problem;
00161 Teuchos::RCP<SortManager<ScalarType,MV,OP> > _sort;
00162
00163 std::string _whch, _ortho;
00164 MagnitudeType _ortho_kappa;
00165
00166 MagnitudeType _convtol;
00167 int _maxRestarts;
00168 bool _relconvtol,_conjSplit;
00169 int _blockSize, _numBlocks, _stepSize, _nevBlocks, _xtra_nevBlocks;
00170 int _verbosity;
00171 bool _inSituRestart;
00172
00173 std::vector<Value<ScalarType> > _ritzValues;
00174
00175 Teuchos::RCP<Teuchos::Time> _timerSolve, _timerRestarting;
00176
00177 };
00178
00179
00180
00181 template<class ScalarType, class MV, class OP>
00182 BlockKrylovSchurSolMgr<ScalarType,MV,OP>::BlockKrylovSchurSolMgr(
00183 const Teuchos::RCP<Eigenproblem<ScalarType,MV,OP> > &problem,
00184 Teuchos::ParameterList &pl ) :
00185 _problem(problem),
00186 _whch("LM"),
00187 _ortho("SVQB"),
00188 _ortho_kappa(-1.0),
00189 _convtol(0),
00190 _maxRestarts(20),
00191 _relconvtol(true),
00192 _conjSplit(false),
00193 _blockSize(0),
00194 _numBlocks(0),
00195 _stepSize(0),
00196 _nevBlocks(0),
00197 _xtra_nevBlocks(0),
00198 _verbosity(Anasazi::Errors),
00199 _inSituRestart(false),
00200 _timerSolve(Teuchos::TimeMonitor::getNewTimer("BKSSolMgr::solve()")),
00201 _timerRestarting(Teuchos::TimeMonitor::getNewTimer("BKSSolMgr restarting"))
00202 {
00203 TEST_FOR_EXCEPTION(_problem == Teuchos::null, std::invalid_argument, "Problem not given to solver manager.");
00204 TEST_FOR_EXCEPTION(!_problem->isProblemSet(), std::invalid_argument, "Problem not set.");
00205 TEST_FOR_EXCEPTION(_problem->getInitVec() == Teuchos::null, std::invalid_argument, "Problem does not contain initial vectors to clone from.");
00206
00207 const int nev = _problem->getNEV();
00208
00209
00210 _convtol = pl.get("Convergence Tolerance",MT::prec());
00211 _relconvtol = pl.get("Relative Convergence Tolerance",_relconvtol);
00212
00213
00214 _maxRestarts = pl.get("Maximum Restarts",_maxRestarts);
00215
00216
00217 _blockSize = pl.get("Block Size",1);
00218 TEST_FOR_EXCEPTION(_blockSize <= 0, std::invalid_argument,
00219 "Anasazi::BlockKrylovSchurSolMgr: \"Block Size\" must be strictly positive.");
00220
00221
00222 _xtra_nevBlocks = pl.get("Extra NEV Blocks",0);
00223 if (nev%_blockSize) {
00224 _nevBlocks = nev/_blockSize + _xtra_nevBlocks + 1;
00225 } else {
00226 _nevBlocks = nev/_blockSize + _xtra_nevBlocks;
00227 }
00228
00229 _numBlocks = pl.get("Num Blocks",3*_nevBlocks);
00230 TEST_FOR_EXCEPTION(_numBlocks <= _nevBlocks, std::invalid_argument,
00231 "Anasazi::BlockKrylovSchurSolMgr: \"Num Blocks\" must be strictly positive and large enough to compute the requested eigenvalues.");
00232
00233 TEST_FOR_EXCEPTION(_numBlocks*_blockSize > MVT::GetVecLength(*_problem->getInitVec()),
00234 std::invalid_argument,
00235 "Anasazi::BlockKrylovSchurSolMgr: Potentially impossible orthogonality requests. Reduce basis size.");
00236
00237
00238 if (_maxRestarts) {
00239 _stepSize = pl.get("Step Size", (_maxRestarts+1)*(_numBlocks+1));
00240 } else {
00241 _stepSize = pl.get("Step Size", _numBlocks+1);
00242 }
00243 TEST_FOR_EXCEPTION(_stepSize < 1, std::invalid_argument,
00244 "Anasazi::BlockKrylovSchurSolMgr: \"Step Size\" must be strictly positive.");
00245
00246
00247 if (pl.isParameter("Sort Manager")) {
00248 _sort = Teuchos::getParameter<Teuchos::RCP<Anasazi::SortManager<ScalarType,MV,OP> > >(pl,"Sort Manager");
00249 } else {
00250
00251 _whch = pl.get("Which",_whch);
00252 TEST_FOR_EXCEPTION(_whch != "SM" && _whch != "LM" && _whch != "SR" && _whch != "LR" && _whch != "SI" && _whch != "LI",
00253 std::invalid_argument, "Invalid sorting string.");
00254 _sort = Teuchos::rcp( new BasicSort<ScalarType,MV,OP>(_whch) );
00255 }
00256
00257
00258 _ortho = pl.get("Orthogonalization",_ortho);
00259 if (_ortho != "DGKS" && _ortho != "SVQB") {
00260 _ortho = "SVQB";
00261 }
00262
00263
00264 _ortho_kappa = pl.get("Orthogonalization Constant",_ortho_kappa);
00265
00266
00267 if (pl.isParameter("Verbosity")) {
00268 if (Teuchos::isParameterType<int>(pl,"Verbosity")) {
00269 _verbosity = pl.get("Verbosity", _verbosity);
00270 } else {
00271 _verbosity = (int)Teuchos::getParameter<Anasazi::MsgType>(pl,"Verbosity");
00272 }
00273 }
00274
00275
00276 if (pl.isParameter("In Situ Restarting")) {
00277 if (Teuchos::isParameterType<bool>(pl,"In Situ Restarting")) {
00278 _inSituRestart = pl.get("In Situ Restarting",_inSituRestart);
00279 } else {
00280 _inSituRestart = (bool)Teuchos::getParameter<int>(pl,"In Situ Restarting");
00281 }
00282 }
00283 }
00284
00285
00286
00287 template<class ScalarType, class MV, class OP>
00288 ReturnType
00289 BlockKrylovSchurSolMgr<ScalarType,MV,OP>::solve() {
00290
00291 const int nev = _problem->getNEV();
00292 ScalarType one = Teuchos::ScalarTraits<ScalarType>::one();
00293 ScalarType zero = Teuchos::ScalarTraits<ScalarType>::zero();
00294
00295 Teuchos::BLAS<int,ScalarType> blas;
00296 Teuchos::LAPACK<int,ScalarType> lapack;
00297 typedef SolverUtils<ScalarType,MV,OP> msutils;
00298
00300
00301 Teuchos::RCP<BasicOutputManager<ScalarType> > printer = Teuchos::rcp( new BasicOutputManager<ScalarType>(_verbosity) );
00302
00304
00305
00306
00307 Teuchos::RCP<StatusTestOrderedResNorm<ScalarType,MV,OP> > convtest
00308 = Teuchos::rcp( new StatusTestOrderedResNorm<ScalarType,MV,OP>(_sort,_convtol,nev,StatusTestOrderedResNorm<ScalarType,MV,OP>::RITZRES_2NORM,_relconvtol) );
00309
00310
00311 Teuchos::RCP<StatusTestOutput<ScalarType,MV,OP> > outputtest
00312 = Teuchos::rcp( new StatusTestOutput<ScalarType,MV,OP>( printer,convtest,1,Passed ) );
00313
00315
00316
00317 Teuchos::RCP<OrthoManager<ScalarType,MV> > ortho;
00318 if (_ortho=="SVQB") {
00319 ortho = Teuchos::rcp( new SVQBOrthoManager<ScalarType,MV,OP>(_problem->getM()) );
00320 } else if (_ortho=="DGKS") {
00321 if (_ortho_kappa <= 0) {
00322 ortho = Teuchos::rcp( new BasicOrthoManager<ScalarType,MV,OP>(_problem->getM()) );
00323 }
00324 else {
00325 ortho = Teuchos::rcp( new BasicOrthoManager<ScalarType,MV,OP>(_problem->getM(),_ortho_kappa) );
00326 }
00327 } else {
00328 TEST_FOR_EXCEPTION(_ortho!="SVQB"&&_ortho!="DGKS",std::logic_error,"Anasazi::BlockKrylovSchurSolMgr::solve(): Invalid orthogonalization type.");
00329 }
00330
00332
00333 Teuchos::ParameterList plist;
00334 plist.set("Block Size",_blockSize);
00335 plist.set("Num Blocks",_numBlocks);
00336 plist.set("Step Size",_stepSize);
00337 plist.set("Print Number of Ritz Values",_nevBlocks*_blockSize);
00338
00340
00341 Teuchos::RCP<BlockKrylovSchur<ScalarType,MV,OP> > bks_solver
00342 = Teuchos::rcp( new BlockKrylovSchur<ScalarType,MV,OP>(_problem,_sort,printer,outputtest,ortho,plist) );
00343
00344 Teuchos::RCP< const MV > probauxvecs = _problem->getAuxVecs();
00345 if (probauxvecs != Teuchos::null) {
00346 bks_solver->setAuxVecs( Teuchos::tuple< Teuchos::RCP<const MV> >(probauxvecs) );
00347 }
00348
00349
00350
00351
00352
00353
00354 Teuchos::RCP<MV> workMV;
00355 if (_maxRestarts > 0) {
00356 if (_inSituRestart==true) {
00357
00358 workMV = MVT::Clone( *_problem->getInitVec(), 1 );
00359 }
00360 else {
00361 if (_problem->isHermitian()) {
00362 workMV = MVT::Clone( *_problem->getInitVec(), _nevBlocks*_blockSize + _blockSize );
00363 } else {
00364 workMV = MVT::Clone( *_problem->getInitVec(), _nevBlocks*_blockSize+1 + _blockSize );
00365 }
00366 }
00367 } else {
00368 workMV = Teuchos::null;
00369 }
00370
00371
00372 Eigensolution<ScalarType,MV> sol;
00373 sol.numVecs = 0;
00374 _problem->setSolution(sol);
00375
00376 int numRestarts = 0;
00377 int cur_nevBlocks = 0;
00378
00379
00380 {
00381 Teuchos::TimeMonitor slvtimer(*_timerSolve);
00382
00383
00384 while (1) {
00385 try {
00386 bks_solver->iterate();
00387
00389
00390
00391
00393 if (convtest->getStatus() == Passed ) {
00394
00395
00396
00397 break;
00398 }
00400
00401
00402
00404
00405
00406
00407
00408
00409
00410
00411 else if ( (bks_solver->getCurSubspaceDim() == bks_solver->getMaxSubspaceDim()) ||
00412 (!_problem->isHermitian() && !_conjSplit && (bks_solver->getCurSubspaceDim()+1 == bks_solver->getMaxSubspaceDim())) ) {
00413
00414 Teuchos::TimeMonitor restimer(*_timerRestarting);
00415
00416 if ( numRestarts >= _maxRestarts ) {
00417 break;
00418 }
00419 numRestarts++;
00420
00421 printer->stream(Debug) << " Performing restart number " << numRestarts << " of " << _maxRestarts << std::endl << std::endl;
00422
00423
00424 if (!bks_solver->isSchurCurrent())
00425 bks_solver->computeSchurForm( true );
00426
00427
00428 _ritzValues = bks_solver->getRitzValues();
00429
00430
00431 BlockKrylovSchurState<ScalarType,MV> oldState = bks_solver->getState();
00432
00433
00434 int curDim = oldState.curDim;
00435
00436
00437 std::vector<int> ritzIndex = bks_solver->getRitzIndex();
00438 if (ritzIndex[_nevBlocks*_blockSize-1]==1) {
00439 _conjSplit = true;
00440 cur_nevBlocks = _nevBlocks*_blockSize+1;
00441 } else {
00442 _conjSplit = false;
00443 cur_nevBlocks = _nevBlocks*_blockSize;
00444 }
00445
00446
00447
00448
00449 Teuchos::SerialDenseMatrix<int,ScalarType> Qnev(Teuchos::View, *(oldState.Q), curDim, cur_nevBlocks);
00450
00451
00452 std::vector<int> curind( curDim );
00453 for (int i=0; i<curDim; i++) { curind[i] = i; }
00454 Teuchos::RCP<const MV> basistemp = MVT::CloneView( *(oldState.V), curind );
00455
00456
00457
00458
00459
00460
00461
00462
00463
00464 Teuchos::RCP<MV> newF;
00465 if (_inSituRestart) {
00466
00467
00468 Teuchos::RCP<MV> solverbasis = Teuchos::rcp_const_cast<MV>(oldState.V);
00469 Teuchos::SerialDenseMatrix<int,ScalarType> copyQnev(Qnev);
00470
00471
00472 std::vector<ScalarType> tau(cur_nevBlocks), work(cur_nevBlocks);
00473 int info;
00474 lapack.GEQRF(curDim,cur_nevBlocks,copyQnev.values(),copyQnev.stride(),&tau[0],&work[0],work.size(),&info);
00475 TEST_FOR_EXCEPTION(info != 0,std::logic_error,
00476 "Anasazi::BlockDavidsonSolMgr::solve(): error calling GEQRF during restarting.");
00477
00478 std::vector<ScalarType> d(cur_nevBlocks);
00479 for (int j=0; j<copyQnev.numCols(); j++) {
00480 d[j] = copyQnev(j,j);
00481 }
00482 if (printer->isVerbosity(Debug)) {
00483 Teuchos::SerialDenseMatrix<int,ScalarType> R(Teuchos::Copy,copyQnev,cur_nevBlocks,cur_nevBlocks);
00484 for (int j=0; j<R.numCols(); j++) {
00485 R(j,j) = SCT::magnitude(R(j,j)) - 1.0;
00486 for (int i=j+1; i<R.numRows(); i++) {
00487 R(i,j) = zero;
00488 }
00489 }
00490 printer->stream(Debug) << "||Triangular factor of Su - I||: " << R.normFrobenius() << std::endl;
00491 }
00492
00493
00494
00495
00496 curind.resize(curDim);
00497 for (int i=0; i<curDim; i++) curind[i] = i;
00498 Teuchos::RCP<MV> oldV = MVT::CloneView(*solverbasis,curind);
00499 msutils::applyHouse(cur_nevBlocks,*oldV,copyQnev,tau,workMV);
00500
00501 oldV = Teuchos::null;
00502
00503
00504 curind.resize(cur_nevBlocks);
00505 for (int i=0; i<cur_nevBlocks; i++) { curind[i] = i; }
00506 oldV = MVT::CloneView( *solverbasis, curind );
00507 MVT::MvScale(*oldV,d);
00508 oldV = Teuchos::null;
00509
00510 curind.resize(_blockSize);
00511 for (int i=0; i<_blockSize; i++) { curind[i] = cur_nevBlocks + i; }
00512 newF = MVT::CloneView( *solverbasis, curind );
00513 }
00514 else {
00515
00516 curind.resize(cur_nevBlocks);
00517 for (int i=0; i<cur_nevBlocks; i++) { curind[i] = i; }
00518 Teuchos::RCP<MV> tmp_newV = MVT::CloneView(*workMV, curind );
00519
00520 MVT::MvTimesMatAddMv( one, *basistemp, Qnev, zero, *tmp_newV );
00521 tmp_newV = Teuchos::null;
00522
00523 curind.resize(_blockSize);
00524 for (int i=0; i<_blockSize; i++) { curind[i] = cur_nevBlocks + i; }
00525 newF = MVT::CloneView( *workMV, curind );
00526 }
00527
00528
00529 curind.resize(_blockSize);
00530 for (int i=0; i<_blockSize; i++) { curind[i] = curDim + i; }
00531 Teuchos::RCP<const MV> oldF = MVT::CloneView( *(oldState.V), curind );
00532 for (int i=0; i<_blockSize; i++) { curind[i] = i; }
00533 MVT::SetBlock( *oldF, curind, *newF );
00534 newF = Teuchos::null;
00535
00536
00537
00538
00539
00540 Teuchos::SerialDenseMatrix<int,ScalarType> oldS(Teuchos::View, *(oldState.S), cur_nevBlocks+_blockSize, cur_nevBlocks);
00541 Teuchos::RCP<Teuchos::SerialDenseMatrix<int,ScalarType> > newH =
00542 Teuchos::rcp( new Teuchos::SerialDenseMatrix<int,ScalarType>( oldS ) );
00543
00544
00545 Teuchos::SerialDenseMatrix<int,ScalarType> oldB(Teuchos::View, *(oldState.H), _blockSize, _blockSize, curDim, curDim-_blockSize);
00546
00547
00548 Teuchos::SerialDenseMatrix<int,ScalarType> subQ(Teuchos::View, *(oldState.Q), _blockSize, cur_nevBlocks, curDim-_blockSize);
00549
00550
00551 Teuchos::SerialDenseMatrix<int,ScalarType> newB(Teuchos::View, *newH, _blockSize, cur_nevBlocks, cur_nevBlocks);
00552
00553
00554 blas.GEMM( Teuchos::NO_TRANS, Teuchos::NO_TRANS, _blockSize, cur_nevBlocks, _blockSize, one,
00555 oldB.values(), oldB.stride(), subQ.values(), subQ.stride(), zero, newB.values(), newB.stride() );
00556
00557
00558
00559
00560 BlockKrylovSchurState<ScalarType,MV> newstate;
00561 if (_inSituRestart) {
00562 newstate.V = oldState.V;
00563 } else {
00564 newstate.V = workMV;
00565 }
00566 newstate.H = newH;
00567 newstate.curDim = cur_nevBlocks;
00568 bks_solver->initialize(newstate);
00569
00570 }
00572
00573
00574
00575
00577 else {
00578 TEST_FOR_EXCEPTION(true,std::logic_error,"Anasazi::BlockKrylovSchurSolMgr::solve(): Invalid return from bks_solver::iterate().");
00579 }
00580 }
00581 catch (std::exception e) {
00582 printer->stream(Errors) << "Error! Caught exception in BlockKrylovSchur::iterate() at iteration " << bks_solver->getNumIters() << std::endl
00583 << e.what() << std::endl;
00584 throw;
00585 }
00586 }
00587
00588
00589
00590 workMV = Teuchos::null;
00591
00592
00593 _ritzValues = bks_solver->getRitzValues();
00594
00595 sol.numVecs = convtest->howMany();
00596 if (sol.numVecs > 0) {
00597 sol.index = bks_solver->getRitzIndex();
00598 sol.Evals = bks_solver->getRitzValues();
00599
00600 if (sol.index[sol.numVecs-1]==1) {
00601 sol.numVecs++;
00602 sol.Evals.resize(sol.numVecs);
00603 sol.index.resize(sol.numVecs);
00604 bks_solver->setNumRitzVectors(sol.numVecs);
00605 } else {
00606 sol.Evals.resize(sol.numVecs);
00607 sol.index.resize(sol.numVecs);
00608 bks_solver->setNumRitzVectors(sol.numVecs);
00609 }
00610 bks_solver->computeRitzVectors();
00611 sol.Evecs = MVT::CloneCopy( *(bks_solver->getRitzVectors()) );
00612 sol.Espace = sol.Evecs;
00613 }
00614 }
00615
00616
00617 bks_solver->currentStatus(printer->stream(FinalSummary));
00618
00619
00620 Teuchos::TimeMonitor::summarize(printer->stream(TimingDetails));
00621
00622 _problem->setSolution(sol);
00623 printer->stream(Debug) << "Returning " << sol.numVecs << " eigenpairs to eigenproblem." << std::endl;
00624
00625 if (sol.numVecs < nev) {
00626 return Unconverged;
00627 }
00628 return Converged;
00629 }
00630
00631
00632 }
00633
00634 #endif