Anasazi  Version of the Day
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
AnasaziRandomizedSolMgr.hpp
Go to the documentation of this file.
1 // @HEADER
2 // ***********************************************************************
3 //
4 // Anasazi: Block Eigensolvers Package
5 // Copyright 2004 Sandia Corporation
6 //
7 // Under terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
8 // the U.S. Government retains certain rights in this software.
9 //
10 // Redistribution and use in source and binary forms, with or without
11 // modification, are permitted provided that the following conditions are
12 // met:
13 //
14 // 1. Redistributions of source code must retain the above copyright
15 // notice, this list of conditions and the following disclaimer.
16 //
17 // 2. Redistributions in binary form must reproduce the above copyright
18 // notice, this list of conditions and the following disclaimer in the
19 // documentation and/or other materials provided with the distribution.
20 //
21 // 3. Neither the name of the Corporation nor the names of the
22 // contributors may be used to endorse or promote products derived from
23 // this software without specific prior written permission.
24 //
25 // THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
26 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
28 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
29 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
30 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
31 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
32 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
33 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
34 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
35 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36 //
37 // Questions? Contact Michael A. Heroux (maherou@sandia.gov)
38 //
39 // ***********************************************************************
40 // @HEADER
41 
42 #ifndef ANASAZI_RANDOMIZED_SOLMGR_HPP
43 #define ANASAZI_RANDOMIZED_SOLMGR_HPP
44 
50 #include "AnasaziConfigDefs.hpp"
51 #include "AnasaziTypes.hpp"
52 
53 #include "AnasaziEigenproblem.hpp"
54 #include "AnasaziSolverManager.hpp"
55 
56 #include "AnasaziBasicSort.hpp"
60 
65 #include "AnasaziOutputManager.hpp"
67 #include "AnasaziSolverUtils.hpp"
68 
69 #include "Teuchos_TimeMonitor.hpp"
70 #include "Teuchos_FancyOStream.hpp"
71 #include "Teuchos_LAPACK.hpp"
72 
88 namespace Anasazi {
89 
90  namespace Experimental {
91 
92  template<class ScalarType, class MV, class OP>
93  class RandomizedSolMgr : public SolverManager<ScalarType,MV,OP> {
94 
95  private:
96  typedef int OT;
97  typedef MultiVecTraits<ScalarType,MV> MVT;
98  typedef OperatorTraits<ScalarType,MV,OP> OPT;
101  const ScalarType ONE = SCT::one();
102 
103  public:
104 
106 
107 
124  RandomizedSolMgr( const Teuchos::RCP<Eigenproblem<ScalarType,MV,OP> > &problem,
126 
128  virtual ~RandomizedSolMgr() {};
130 
132 
133 
134  const Eigenproblem<ScalarType,MV,OP>& getProblem() const {
135  return *problem_;
136  }
137 
138  int getNumIters() const {
139  return numIters_;
140  }
141 
142  int getNumFailed() const {
143  return numFailed_;
144  }
145 
147 
149 
150 
159  ReturnType solve();
161 
162  private:
165  std::string whch_;
166  MT tol_;
167  int osProc_;
168  int verb_;
169  Teuchos::RCP<Teuchos::Time> timerOrtho_;
170  Teuchos::RCP<Teuchos::Time> timerSolve_;
172  std::string ortho_;
173  int orthoFreq_;
174  int resFreq_;
175  int blockSize_;
176  int maxIters_;
177  int numIters_;
178  bool trackResNorms_;
179  int numFailed_;
180  };
181 
182 
184  template<class ScalarType, class MV, class OP>
185  RandomizedSolMgr<ScalarType,MV,OP>::RandomizedSolMgr(
186  const Teuchos::RCP<Eigenproblem<ScalarType,MV,OP> > &problem,
187  Teuchos::ParameterList &pl ) :
188  problem_(problem),
189  whch_("LM"),
190  tol_(1e-6),
191  osProc_(0),
192  verb_(Anasazi::Errors),
193 #ifdef ANASAZI_TEUCHOS_TIME_MONITOR
194  timerOrtho_(Teuchos::TimeMonitor::getNewTimer("Anasazi: Randomized::Orthogonalization")),
195  timerSolve_(Teuchos::TimeMonitor::getNewTimer("Anasazi: Randomized::solve()")),
196  timerOp_(Teuchos::TimeMonitor::getNewTimer("Anasazi: Randomized::Operation Op*x")),
197 #endif
198  ortho_("SVQB"),
199  orthoFreq_(0),
200  resFreq_(0),
201  blockSize_(0),
202  maxIters_(5),
203  numIters_(0),
204  trackResNorms_(true)
205  {
206  TEUCHOS_TEST_FOR_EXCEPTION(problem_ == Teuchos::null, std::invalid_argument, "Problem not given to solver manager.");
207  TEUCHOS_TEST_FOR_EXCEPTION(!problem_->isProblemSet(), std::invalid_argument, "Problem not set.");
208  TEUCHOS_TEST_FOR_EXCEPTION(problem_->getInitVec() == Teuchos::null,std::invalid_argument, "Problem does not contain initial vectors to clone from.");
209 
210  whch_ = pl.get("Which",whch_);
211  TEUCHOS_TEST_FOR_EXCEPTION(whch_ != "LM" && whch_ != "LR",
212  AnasaziError,
213  "RandomizedSolMgr: \"Which\" parameter must be LM or LR. Other options not available.");
214 
215  tol_ = pl.get("Convergence Tolerance",tol_);
216  TEUCHOS_TEST_FOR_EXCEPTION(tol_ <= 0,
217  AnasaziError,
218  "RandomizedSolMgr: \"Tolerance\" parameter must be strictly positive.");
219 
220  // Create a formatted output stream to print to.
221  // See if user requests output processor.
222  osProc_ = pl.get("Output Processor", osProc_);
223 
224  // If not passed in by user, it will be chosen based upon operator type.
225  if (pl.isParameter("Output Stream")) {
226  osp_ = Teuchos::getParameter<Teuchos::RCP<Teuchos::FancyOStream> >(pl,"Output Stream");
227  }
228  else {
229  osp_ = OutputStreamTraits<OP>::getOutputStream (*problem_->getOperator(), osProc_);
230  }
231 
232  // verbosity level
233  if (pl.isParameter("Verbosity")) {
234  if (Teuchos::isParameterType<int>(pl,"Verbosity")) {
235  verb_ = pl.get("Verbosity", verb_);
236  } else {
237  verb_ = (int)Teuchos::getParameter<Anasazi::MsgType>(pl,"Verbosity");
238  }
239  }
240 
241  // Orthogonalization type
242  ortho_ = pl.get("Orthogonalization","SVQB");
243 
244  blockSize_= pl.get("Block Size",problem_->getNEV());
245  TEUCHOS_TEST_FOR_EXCEPTION(blockSize_ <= 0,
246  AnasaziError,
247  "RandomizedSolMgr: \"Block Size\" parameter must be strictly positive.");
248 
249  maxIters_ = pl.get("Maximum Iterations",maxIters_);
250  trackResNorms_ = pl.get("Track Residuals",true);
251 
252  // How many iterations between orthogonalizations
253  if (pl.isParameter("Orthogonalization Frequency")) {
254  if (Teuchos::isParameterType<int>(pl,"Orthogonalization Frequency")) {
255  orthoFreq_ = pl.get("Orthogonalization Frequency", orthoFreq_);
256  } else {
257  orthoFreq_ = (int)Teuchos::getParameter<Anasazi::MsgType>(pl,"Orthogonalization Frequency");
258  }
259  }
260 
261  // How many iterations between checking the residuals
262  if (pl.isParameter("Residual Frequency")) {
263  if (Teuchos::isParameterType<int>(pl,"Residual Frequency")) {
264  resFreq_ = pl.get("Residual Frequency", resFreq_);
265  } else {
266  resFreq_ = (int)Teuchos::getParameter<Anasazi::MsgType>(pl,"Residual Frequency");
267  }
268  }
269  }
270 
272  template<class ScalarType, class MV, class OP>
273  ReturnType
274  RandomizedSolMgr<ScalarType,MV,OP>::solve() {
275 
276  // Sort manager
277  Teuchos::RCP<BasicSort<MT> > sorter = Teuchos::rcp( new BasicSort<MT> );
278  sorter->setSortType(whch_);
279  std::vector<int> order(blockSize_); /* Permutation array for sorting the eigenvectors */
280  SolverUtils<ScalarType,MV,OP> msutils;
281 
282  // Output manager
283  Teuchos::RCP<OutputManager<ScalarType> > printer = Teuchos::rcp( new OutputManager<ScalarType>(verb_,osp_) );
284 
285  // Eigensolution manager
286  Eigensolution<ScalarType,MV> sol;
287  sol.numVecs = 0;
288  problem_->setSolution(sol); /* In case there is an exception thrown */
289 
290  // ortho manager
292  int rank;
293  if (ortho_=="SVQB") {
295  } else if (ortho_=="DGKS") {
297  } else if (ortho_=="ICGS") {
299  } else {
300  TEUCHOS_TEST_FOR_EXCEPTION(ortho_!="SVQB"&&ortho_!="DGKS"&&ortho_!="ICGS",std::logic_error,"Anasazi::RandomSolver Invalid orthogonalization type.");
301  }
302 
303  if(blockSize_ < problem_->getNEV()){
304  printer->stream(Warnings) << "Warning! Block size smaller than number evals. Increasing Block Size to num evals." << std::endl;
305  blockSize_ = problem_->getNEV();
306  }
307 
308  /* Grab some Multivector to Clone
309  * in practice, getInitVec() should always provide this, but it is possible to use a
310  * Eigenproblem with nothing in getInitVec() by manually initializing with initialize();
311  * in case of that strange scenario, we will try to Clone from V_; first resort to getInitVec(),
312  * because we would like to clear the storage associated with V_ so we have room for the new V_ */
313  Teuchos::RCP<MV> randVecs;
314  TEUCHOS_TEST_FOR_EXCEPTION(problem_->getInitVec() == Teuchos::null,std::invalid_argument,
315  "Anasazi::Randomized: eigenproblem did not specify initial vectors to clone from.");
316  if(MVT::GetNumberVecs(*(problem_->getInitVec()))==blockSize_){
317  randVecs = MVT::CloneCopy(*(problem_->getInitVec()));
318  } else {
319  randVecs = MVT::Clone(*(problem_->getInitVec()),blockSize_);
320  MVT::MvRandom(*randVecs);
321  }
322 
323  { /* Ortho Timer */
324 #ifdef ANASAZI_TEUCHOS_TIME_MONITOR
325  Teuchos::TimeMonitor lcltimer( *timerOrtho_ );
326 #endif
327  rank = orthoMgr->normalize(*randVecs);
328  if( rank < blockSize_ ) printer->stream(Warnings) << "Warning! Anasazi::RandomSolver Random vectors did not have full rank!" << std::endl;
329  } /* End Ortho Timer */
330 
331  /* Set up variables for residual computation ------------------------------ */
332  int i, j; // Loop variables
333 
334  /* For computing H = Q^TAQ. (RR projection) */
335  Teuchos::RCP<MV> TmpVecs = MVT::Clone(*randVecs,blockSize_);
336  Teuchos::SerialDenseMatrix<OT,ScalarType> H (blockSize_, blockSize_);
337 
338  /* For solving the projected eigenvalue problem. */
340  Teuchos::SerialDenseMatrix<OT,ScalarType> evects (blockSize_, blockSize_);
341  std::vector<MT> evals_real(blockSize_);
342  std::vector<MT> evals_imag(blockSize_);
343 
344  /* Size of workspace and workspace for DGEEV */
345  int info = -1000;
346  ScalarType* vlr = 0;
347  const int ldv = 1;
348  int lwork = -1;
349  std::vector<ScalarType> work(1);
350  std::vector<MT> rwork(2*blockSize_);
351  numIters_ = 0;
352 
353  /* For computing the residuals of the eigenproblem */
354  int numev;
355  std::vector<Value<ScalarType>> EigenVals(blockSize_);
356  Teuchos::RCP<MV> Avecs, evecs;
357  Teuchos::SerialDenseMatrix<OT,ScalarType> T (blockSize_, blockSize_ );
358  std::vector<MT> normV( blockSize_ );
359  bool converged = false;
360 
361  { // Solve Timer
362 #ifdef ANASAZI_TEUCHOS_TIME_MONITOR
363  Teuchos::TimeMonitor slvtimer(*timerSolve_);
364 #endif
365  sol.numVecs = blockSize_;
366  sol.Evals.resize(sol.numVecs);
367 
368  // Perform multiplies by A and Rayleigh-Ritz
369  for( i = 0; i < maxIters_; i++ ){
370  if (converged == true) {
371  numFailed_ = 0;
372  numIters_ = i-1;
373  break;
374  }
375 
376  { /* Begin Operator Timer */
377 #ifdef ANASAZI_TEUCHOS_TIME_MONITOR
378  Teuchos::TimeMonitor lcltimer( *timerOp_ );
379 #endif
380  OPT::Apply( *(problem_->getOperator()), *randVecs, *randVecs );
381  } /* End Operator Timer */
382 
383  if ((orthoFreq_ > 0 && i % orthoFreq_ == 0) || (resFreq_ > 0 && i % resFreq_ == 0)) {
384  { /* Start Ortho Timer */
385 #ifdef ANASAZI_TEUCHOS_TIME_MONITOR
386  Teuchos::TimeMonitor lcltimer( *timerOrtho_ );
387 #endif
388  rank = orthoMgr->normalize(*randVecs);
389  if( rank < blockSize_ ) printer->stream(Warnings) << "Warning! Anasazi::RandomSolver Random vectors did not have full rank!" << std::endl;
390  } /* End Ortho Timer */
391  } /* End Ortho */
392 
393  if (resFreq_ > 0 && i % resFreq_ == 0) {
394 
395  // Build the H matrix to run Rayleigh-Ritz on
396  OPT::Apply( *(problem_->getOperator()), *randVecs, *TmpVecs );
397  MVT::MvTransMv(ONE, *randVecs, *TmpVecs, H);
398 
399  // Run GEEV once to find the correct size for rwork
400  lapack.GEEV('N','V',blockSize_,H.values(),H.stride(),evals_real.data(),evals_imag.data(),vlr, ldv, evects.values(), evects.stride(), &work[0], lwork, &rwork[0], &info);
401  lwork = std::abs (static_cast<int> (Teuchos::ScalarTraits<ScalarType>::real (work[0])));
402  work.resize( lwork );
403 
404  // Run GEEV a second time to solve for Harmonic Ritz Values:
405  lapack.GEEV('N','V',blockSize_,H.values(),H.stride(),evals_real.data(),evals_imag.data(),vlr, ldv, evects.values(), evects.stride(), &work[0], lwork, &rwork[0], &info);
406  if(info != 0) printer->stream(Warnings) << "Warning! Anasazi::RandomSolver GEEV solve possible failure: info = " << info << std::endl;
407  lwork = -1;
408 
409  // sort the eigenvalues and permute the eigenvectors appropriately
410  sorter->sort(evals_real,evals_imag,Teuchos::rcpFromRef(order),blockSize_);
411  msutils.permuteVectors(order, evects);
412 
413  for( j = 0; j < blockSize_; j++){
414  EigenVals[j].realpart = evals_real[j];
415  EigenVals[j].imagpart = evals_imag[j];
416  }
417 
418  // Project Evects back up to large problem.
419  MVT::MvTimesMatAddMv(ONE, *randVecs, evects, 0.0, *TmpVecs);
420 
421  // Copy only the eigenvectors we asked for to soln.
422  sol.Evecs = MVT::CloneCopy(*TmpVecs, Teuchos::Range1D(0,sol.numVecs-1));
423  sol.numVecs = blockSize_;
424  sol.Evals = EigenVals;
425 
426  // Extract evects/evals from solution
427  evecs = sol.Evecs;
428  numev = sol.numVecs;
429 
430  // Check residuals for convergence
431  if (numev > 0 ) {
432  for ( j = 0; j < numev; ++j ) T(j, j) = sol.Evals[j].realpart;
433 
434  Avecs = MVT::Clone(*evecs, numev);
435  OPT::Apply(*(problem_->getOperator()), *evecs, *Avecs);
436 
437  MVT::MvTimesMatAddMv(-ONE, *evecs, T, ONE, *Avecs); /* Residuals = A*evecs - evecs*lambda */
438  MVT::MvNorm(*Avecs, normV);
439 
440  numFailed_ = 0;
441  converged = true;
442  for ( j = 0; j < numev; ++j )
443  {
444  if ( SCT::magnitude(sol.Evals[j].realpart) != SCT::zero() ) normV[j] = SCT::magnitude(normV[j]/sol.Evals[j].realpart);
445  if (normV[j] > tol_) {
446  numFailed_++;
447  converged = false;
448  break;
449  }
450  }
451  } // End residual computation
452  } // End Rayleigh-Ritz solve
453  } // End subspace iterations
454 
455  if(converged == false)
456  {
457  { /* Begin Ortho Timer */
458 #ifdef ANASAZI_TEUCHOS_TIME_MONITOR
459  Teuchos::TimeMonitor lcltimer( *timerOrtho_ );
460 #endif
461  rank = orthoMgr->normalize(*randVecs);
462  if( rank < blockSize_ ) printer->stream(Warnings) << "Warning! Anasazi::RandomSolver Random vectors did not have full rank!" << std::endl;
463  } /* End Ortho Timer */
464 
465  OPT::Apply( *(problem_->getOperator()), *randVecs, *TmpVecs );
466  MVT::MvTransMv(ONE, *randVecs, *TmpVecs, H);
467 
468  /* --------------------------------------------------------------------------
469  * Parameters for DGEEV:
470  * 'N' = Don't compute left eigenvectors.
471  * 'V' = Compute right eigenvectors.
472  * blockSize = Dimension of H (numEvals)
473  * H.values = H matrix (Q'AQ)
474  * H.stride = Leading dimension of H (numEvals)
475  * evals_real.data() = Array to store evals, real parts
476  * evals_imag.data() = Array to store evals, imag parts
477  * vlr = Stores left evects, so don't need this
478  * ldv = Leading dimension of vlr
479  * evects = Array to store right evects
480  * evects.stride = Leading dimension of evects
481  * work = Work array
482  * lwork = -1 means to query for array size
483  * rwork = Not referenced because ST is not complex
484  * -------------------------------------------------------------------------- */
485  //Find workspace size for DGEEV:
486  lapack.GEEV('N','V',blockSize_,H.values(),H.stride(),evals_real.data(),evals_imag.data(),vlr, ldv, evects.values(), evects.stride(), &work[0], lwork, &rwork[0], &info);
487  if(info != 0) printer->stream(IterationDetails) << "Warning!! Anasazi::RandomSolver GEEV solve possible failure: info = " << info << std::endl;
488 
489  lwork = std::abs (static_cast<int> (Teuchos::ScalarTraits<ScalarType>::real (work[0])));
490  work.resize( lwork );
491 
492  // Solve for Harmonic Ritz Values:
493  lapack.GEEV('N','V',blockSize_,H.values(),H.stride(),evals_real.data(),evals_imag.data(),vlr, ldv, evects.values(), evects.stride(), &work[0], lwork, &rwork[0], &info);
494  if(info != 0) printer->stream(IterationDetails) << "Warning!! Anasazi::RandomSolver GEEV solve possible failure: info = " << info << std::endl;
495 
496  // Sort the eigenvalues and permute the eigenvectors appropriately
497  sorter->sort(evals_real,evals_imag,Teuchos::rcpFromRef(order),blockSize_);
498  msutils.permuteVectors(order, evects);
499 
500  for( j = 0; j < blockSize_; j++){
501  EigenVals[j].realpart = evals_real[j];
502  EigenVals[j].imagpart = evals_imag[j];
503  }
504  sol.Evals = EigenVals;
505 
506  // Project Evects back up to large problem and permute
507  MVT::MvTimesMatAddMv(ONE,*randVecs,evects, 0.0,*TmpVecs);
508 
509  //------Post-Solve Processing----------------------------
510  //Copy only the eigenvectors we asked for to soln.
511  sol.numVecs = blockSize_;
512  sol.Evecs = MVT::CloneCopy(*TmpVecs, Teuchos::Range1D(0,sol.numVecs-1));
513  numIters_ = maxIters_;
514 
515  } // End converged == false
516  } // End solve timer
517 
518  // Send the solution to the eigenproblem
519  problem_->setSolution(sol);
520  printer->stream(Debug) << "Returning " << sol.numVecs << " eigenpairs to eigenproblem." << std::endl;
521 
522  // print timing information
523 #ifdef ANASAZI_TEUCHOS_TIME_MONITOR
524  if ( printer->isVerbosity( TimingDetails ) ) Teuchos::TimeMonitor::summarize( printer->stream( TimingDetails ) );
525 #endif
526 
527  if (converged) return Converged; // Return from RandomizedSolMgr::solve()
528  return Unconverged; // Return from RandomizedSolMgr::solve()
529 
530  } // End Solve function
531  } // end Experimental namespace
532 } // end Anasazi namespace
533 
534 #endif /* ANASAZI_RANDOMIZED_SOLMGR_HPP */
Pure virtual base class which describes the basic interface for a solver manager. ...
T & get(const std::string &name, T def_value)
#define TEUCHOS_TEST_FOR_EXCEPTION(throw_exception_test, Exception, msg)
An implementation of the Anasazi::GenOrthoManager that performs orthogonalization using iterated clas...
Basic implementation of the Anasazi::SortManager class.
An implementation of the Anasazi::MatOrthoManager that performs orthogonalization using the SVQB iter...
bool isParameter(const std::string &name) const
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)
ReturnType
Enumerated type used to pass back information from a solver manager.
A status test for testing the norm of the eigenvectors residuals.
Anasazi header file which uses auto-configuration information to include necessary C++ headers...
Orthogonalization manager based on the SVQB technique described in &quot;A Block Orthogonalization Procedu...
Status test for testing the number of iterations.
Special StatusTest for printing status tests.
void GEEV(const char &JOBVL, const char &JOBVR, const OrdinalType &n, ScalarType *A, const OrdinalType &lda, MagnitudeType *WR, MagnitudeType *WI, ScalarType *VL, const OrdinalType &ldvl, ScalarType *VR, const OrdinalType &ldvr, ScalarType *WORK, const OrdinalType &lwork, MagnitudeType *RWORK, OrdinalType *info) const
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.
Basic implementation of the Anasazi::OrthoManager class.
Basic implementation of the Anasazi::OrthoManager class.
Class which provides internal utilities for the Anasazi solvers.