Anasazi  Version of the Day
AnasaziSimpleLOBPCGSolMgr.hpp
Go to the documentation of this file.
1 
2 // @HEADER
3 // ***********************************************************************
4 //
5 // Anasazi: Block Eigensolvers Package
6 // Copyright 2004 Sandia Corporation
7 //
8 // Under terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
9 // the U.S. Government retains certain rights in this software.
10 //
11 // Redistribution and use in source and binary forms, with or without
12 // modification, are permitted provided that the following conditions are
13 // met:
14 //
15 // 1. Redistributions of source code must retain the above copyright
16 // notice, this list of conditions and the following disclaimer.
17 //
18 // 2. Redistributions in binary form must reproduce the above copyright
19 // notice, this list of conditions and the following disclaimer in the
20 // documentation and/or other materials provided with the distribution.
21 //
22 // 3. Neither the name of the Corporation nor the names of the
23 // contributors may be used to endorse or promote products derived from
24 // this software without specific prior written permission.
25 //
26 // THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
27 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
29 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
30 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
31 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
32 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
33 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
34 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
35 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
36 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
37 //
38 // Questions? Contact Michael A. Heroux (maherou@sandia.gov)
39 //
40 // ***********************************************************************
41 // @HEADER
42 
43 #ifndef ANASAZI_SIMPLE_LOBPCG_SOLMGR_HPP
44 #define ANASAZI_SIMPLE_LOBPCG_SOLMGR_HPP
45 
51 #include "AnasaziConfigDefs.hpp"
52 #include "AnasaziTypes.hpp"
53 
54 #include "AnasaziEigenproblem.hpp"
55 #include "AnasaziSolverManager.hpp"
56 
57 #include "AnasaziLOBPCG.hpp"
58 #include "AnasaziBasicSort.hpp"
65 #include "AnasaziSolverUtils.hpp"
66 
67 #include "Teuchos_TimeMonitor.hpp"
68 
76 
100 namespace Anasazi {
101 
102 template<class ScalarType, class MV, class OP>
103 class SimpleLOBPCGSolMgr : public SolverManager<ScalarType,MV,OP> {
104 
105  private:
107  typedef Teuchos::ScalarTraits<ScalarType> SCT;
108  typedef typename Teuchos::ScalarTraits<ScalarType>::magnitudeType MagnitudeType;
109  typedef Teuchos::ScalarTraits<MagnitudeType> MT;
110 
111  public:
112 
114 
115 
126  SimpleLOBPCGSolMgr( const Teuchos::RCP<Eigenproblem<ScalarType,MV,OP> > &problem,
127  Teuchos::ParameterList &pl );
128 
130  virtual ~SimpleLOBPCGSolMgr() {};
132 
134 
135 
137  return *problem_;
138  }
139 
140  int getNumIters() const {
141  return numIters_;
142  }
143 
145 
147 
148 
157  ReturnType solve();
159 
160  private:
161  Teuchos::RCP<Eigenproblem<ScalarType,MV,OP> > problem_;
162  std::string whch_;
163  MagnitudeType tol_;
164  int verb_;
165  int blockSize_;
166  int maxIters_;
167  int numIters_;
168 };
169 
170 
172 template<class ScalarType, class MV, class OP>
174  const Teuchos::RCP<Eigenproblem<ScalarType,MV,OP> > &problem,
175  Teuchos::ParameterList &pl ) :
176  problem_(problem),
177  whch_("LM"),
178  tol_(1e-6),
179  verb_(Anasazi::Errors),
180  blockSize_(0),
181  maxIters_(100),
182  numIters_(0)
183 {
184  TEUCHOS_TEST_FOR_EXCEPTION(problem_ == Teuchos::null, std::invalid_argument, "Problem not given to solver manager.");
185  TEUCHOS_TEST_FOR_EXCEPTION(!problem_->isProblemSet(), std::invalid_argument, "Problem not set.");
186  TEUCHOS_TEST_FOR_EXCEPTION(!problem_->isHermitian(), std::invalid_argument, "Problem not symmetric.");
187  TEUCHOS_TEST_FOR_EXCEPTION(problem_->getInitVec() == Teuchos::null,std::invalid_argument, "Problem does not contain initial vectors to clone from.");
188 
189  whch_ = pl.get("Which","SR");
190  TEUCHOS_TEST_FOR_EXCEPTION(whch_ != "SM" && whch_ != "LM" && whch_ != "SR" && whch_ != "LR",
191  AnasaziError,
192  "SimpleLOBPCGSolMgr: \"Which\" parameter must be SM, LM, SR or LR.");
193 
194  tol_ = pl.get("Convergence Tolerance",tol_);
195  TEUCHOS_TEST_FOR_EXCEPTION(tol_ <= 0,
196  AnasaziError,
197  "SimpleLOBPCGSolMgr: \"Tolerance\" parameter must be strictly postiive.");
198 
199  // verbosity level
200  if (pl.isParameter("Verbosity")) {
201  if (Teuchos::isParameterType<int>(pl,"Verbosity")) {
202  verb_ = pl.get("Verbosity", verb_);
203  } else {
204  verb_ = (int)Teuchos::getParameter<Anasazi::MsgType>(pl,"Verbosity");
205  }
206  }
207 
208 
209  blockSize_= pl.get("Block Size",problem_->getNEV());
210  TEUCHOS_TEST_FOR_EXCEPTION(blockSize_ <= 0,
211  AnasaziError,
212  "SimpleLOBPCGSolMgr: \"Block Size\" parameter must be strictly positive.");
213 
214  maxIters_ = pl.get("Maximum Iterations",maxIters_);
215 }
216 
217 
218 
220 template<class ScalarType, class MV, class OP>
223 
224  // sort manager
225  Teuchos::RCP<BasicSort<MagnitudeType> > sorter = Teuchos::rcp( new BasicSort<MagnitudeType>(whch_) );
226  // output manager
227  Teuchos::RCP<BasicOutputManager<ScalarType> > printer = Teuchos::rcp( new BasicOutputManager<ScalarType>(verb_) );
228  // status tests
229  Teuchos::RCP<StatusTestMaxIters<ScalarType,MV,OP> > max;
230  if (maxIters_ > 0) {
231  max = Teuchos::rcp( new StatusTestMaxIters<ScalarType,MV,OP>(maxIters_) );
232  }
233  else {
234  max = Teuchos::null;
235  }
236  Teuchos::RCP<StatusTestResNorm<ScalarType,MV,OP> > norm
237  = Teuchos::rcp( new StatusTestResNorm<ScalarType,MV,OP>(tol_) );
238  Teuchos::Array< Teuchos::RCP<StatusTest<ScalarType,MV,OP> > > alltests;
239  alltests.push_back(norm);
240  if (max != Teuchos::null) alltests.push_back(max);
241  Teuchos::RCP<StatusTestCombo<ScalarType,MV,OP> > combo
242  = Teuchos::rcp( new StatusTestCombo<ScalarType,MV,OP>(
244  ));
245  // printing StatusTest
246  Teuchos::RCP<StatusTestOutput<ScalarType,MV,OP> > outputtest
247  = Teuchos::rcp( new StatusTestOutput<ScalarType,MV,OP>( printer,combo,1,Passed ) );
248  // orthomanager
249  Teuchos::RCP<SVQBOrthoManager<ScalarType,MV,OP> > ortho
250  = Teuchos::rcp( new SVQBOrthoManager<ScalarType,MV,OP>(problem_->getM()) );
251  // parameter list
252  Teuchos::ParameterList plist;
253  plist.set("Block Size",blockSize_);
254  plist.set("Full Ortho",true);
255 
256  // create an LOBPCG solver
257  Teuchos::RCP<LOBPCG<ScalarType,MV,OP> > lobpcg_solver
258  = Teuchos::rcp( new LOBPCG<ScalarType,MV,OP>(problem_,sorter,printer,outputtest,ortho,plist) );
259  // add the auxillary vecs from the eigenproblem to the solver
260  if (problem_->getAuxVecs() != Teuchos::null) {
261  lobpcg_solver->setAuxVecs( Teuchos::tuple<Teuchos::RCP<const MV> >(problem_->getAuxVecs()) );
262  }
263 
264  int numfound = 0;
265  int nev = problem_->getNEV();
266  Teuchos::Array< Teuchos::RCP<MV> > foundvecs;
267  Teuchos::Array< Teuchos::RCP< std::vector<MagnitudeType> > > foundvals;
268  while (numfound < nev) {
269  // reduce the strain on norm test, if we are almost done
270  if (nev - numfound < blockSize_) {
271  norm->setQuorum(nev-numfound);
272  }
273 
274  // tell the solver to iterate
275  try {
276  lobpcg_solver->iterate();
277  }
278  catch (const std::exception &e) {
279  // we are a simple solver manager. we don't catch exceptions. set solution empty, then rethrow.
280  printer->stream(Anasazi::Errors) << "Exception: " << e.what() << std::endl;
282  sol.numVecs = 0;
283  problem_->setSolution(sol);
284  throw;
285  }
286 
287  // check the status tests
288  if (norm->getStatus() == Passed) {
289 
290  int num = norm->howMany();
291  // if num < blockSize_, it is because we are on the last iteration: num+numfound>=nev
292  TEUCHOS_TEST_FOR_EXCEPTION(num < blockSize_ && num+numfound < nev,
293  std::logic_error,
294  "Anasazi::SimpleLOBPCGSolMgr::solve(): logic error.");
295  std::vector<int> ind = norm->whichVecs();
296  // just grab the ones that we need
297  if (num + numfound > nev) {
298  num = nev - numfound;
299  ind.resize(num);
300  }
301 
302  // copy the converged eigenvectors
303  Teuchos::RCP<MV> newvecs = MVT::CloneCopy(*lobpcg_solver->getRitzVectors(),ind);
304  // store them
305  foundvecs.push_back(newvecs);
306  // add them as auxiliary vectors
307  Teuchos::Array<Teuchos::RCP<const MV> > auxvecs = lobpcg_solver->getAuxVecs();
308  auxvecs.push_back(newvecs);
309  // setAuxVecs() will reset the solver to uninitialized, without messing with numIters()
310  lobpcg_solver->setAuxVecs(auxvecs);
311 
312  // copy the converged eigenvalues
313  Teuchos::RCP<std::vector<MagnitudeType> > newvals = Teuchos::rcp( new std::vector<MagnitudeType>(num) );
314  std::vector<Value<ScalarType> > all = lobpcg_solver->getRitzValues();
315  for (int i=0; i<num; i++) {
316  (*newvals)[i] = all[ind[i]].realpart;
317  }
318  foundvals.push_back(newvals);
319 
320  numfound += num;
321  }
322  else if (max != Teuchos::null && max->getStatus() == Passed) {
323 
324  int num = norm->howMany();
325  std::vector<int> ind = norm->whichVecs();
326 
327  if (num > 0) {
328  // copy the converged eigenvectors
329  Teuchos::RCP<MV> newvecs = MVT::CloneCopy(*lobpcg_solver->getRitzVectors(),ind);
330  // store them
331  foundvecs.push_back(newvecs);
332  // don't bother adding them as auxiliary vectors; we have reached maxiters and are going to quit
333 
334  // copy the converged eigenvalues
335  Teuchos::RCP<std::vector<MagnitudeType> > newvals = Teuchos::rcp( new std::vector<MagnitudeType>(num) );
336  std::vector<Value<ScalarType> > all = lobpcg_solver->getRitzValues();
337  for (int i=0; i<num; i++) {
338  (*newvals)[i] = all[ind[i]].realpart;
339  }
340  foundvals.push_back(newvals);
341 
342  numfound += num;
343  }
344  break; // while(numfound < nev)
345  }
346  else {
347  TEUCHOS_TEST_FOR_EXCEPTION(true,std::logic_error,"Anasazi::SimpleLOBPCGSolMgr::solve(): solver returned without satisfy status test.");
348  }
349  } // end of while(numfound < nev)
350 
351  TEUCHOS_TEST_FOR_EXCEPTION(foundvecs.size() != foundvals.size(),std::logic_error,"Anasazi::SimpleLOBPCGSolMgr::solve(): inconsistent array sizes");
352 
353  // create contiguous storage for all eigenvectors, eigenvalues
355  sol.numVecs = numfound;
356  if (numfound > 0) {
357  // allocate space for eigenvectors
358  sol.Evecs = MVT::Clone(*problem_->getInitVec(),numfound);
359  }
360  else {
361  sol.Evecs = Teuchos::null;
362  }
363  sol.Espace = sol.Evecs;
364  // allocate space for eigenvalues
365  std::vector<MagnitudeType> vals(numfound);
366  sol.Evals.resize(numfound);
367  // all real eigenvalues: set index vectors [0,...,numfound-1]
368  sol.index.resize(numfound,0);
369  // store eigenvectors, eigenvalues
370  int curttl = 0;
371  for (unsigned int i=0; i<foundvals.size(); i++) {
372  TEUCHOS_TEST_FOR_EXCEPTION((signed int)(foundvals[i]->size()) != MVT::GetNumberVecs(*foundvecs[i]), std::logic_error, "Anasazi::SimpleLOBPCGSolMgr::solve(): inconsistent sizes");
373  unsigned int lclnum = foundvals[i]->size();
374  std::vector<int> lclind(lclnum);
375  for (unsigned int j=0; j<lclnum; j++) lclind[j] = curttl+j;
376  // put the eigenvectors
377  MVT::SetBlock(*foundvecs[i],lclind,*sol.Evecs);
378  // put the eigenvalues
379  std::copy( foundvals[i]->begin(), foundvals[i]->end(), vals.begin()+curttl );
380 
381  curttl += lclnum;
382  }
383  TEUCHOS_TEST_FOR_EXCEPTION( curttl != sol.numVecs, std::logic_error, "Anasazi::SimpleLOBPCGSolMgr::solve(): inconsistent sizes");
384 
385  // sort the eigenvalues and permute the eigenvectors appropriately
386  if (numfound > 0) {
387  std::vector<int> order(sol.numVecs);
388  sorter->sort(vals,Teuchos::rcpFromRef(order),sol.numVecs);
389  // store the values in the Eigensolution
390  for (int i=0; i<sol.numVecs; i++) {
391  sol.Evals[i].realpart = vals[i];
392  sol.Evals[i].imagpart = MT::zero();
393  }
394  // now permute the eigenvectors according to order
396  msutils.permuteVectors(sol.numVecs,order,*sol.Evecs);
397  }
398 
399  // print final summary
400  lobpcg_solver->currentStatus(printer->stream(FinalSummary));
401 
402  // print timing information
403 #ifdef ANASAZI_TEUCHOS_TIME_MONITOR
404  if ( printer->isVerbosity( TimingDetails ) ) {
405  Teuchos::TimeMonitor::summarize( printer->stream( TimingDetails ) );
406  }
407 #endif
408 
409  // send the solution to the eigenproblem
410  problem_->setSolution(sol);
411  printer->stream(Debug) << "Returning " << sol.numVecs << " eigenpairs to eigenproblem." << std::endl;
412 
413  // get the number of iterations performed for this solve.
414  numIters_ = lobpcg_solver->getNumIters();
415 
416  // return from SolMgr::solve()
417  if (sol.numVecs < nev) return Unconverged;
418  return Converged;
419 }
420 
421 
422 
423 
424 } // end Anasazi namespace
425 
426 #endif /* ANASAZI_SIMPLE_LOBPCG_SOLMGR_HPP */
Pure virtual base class which describes the basic interface for a solver manager. ...
A special StatusTest for printing other status tests.
This class defines the interface required by an eigensolver and status test class to compute solution...
An implementation of the Anasazi::SortManager that performs a collection of common sorting techniques...
This class provides the Locally Optimal Block Preconditioned Conjugate Gradient (LOBPCG) iteration...
Status test for forming logical combinations of other status tests.
The Anasazi::SolverManager is a templated virtual base class that defines the basic interface that an...
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.
Implementation of the locally-optimal block preconditioned conjugate gradient (LOBPCG) method...
Namespace Anasazi contains the classes, structs, enums and utilities used by the Anasazi package...
Anasazi&#39;s templated, static class providing utilities for the solvers.
int numVecs
The number of computed eigenpairs.
Basic output manager for sending information of select verbosity levels to the appropriate output str...
int getNumIters() const
Get the iteration count for the most recent call to solve().
Anasazi&#39;s basic output manager for sending information of select verbosity levels to the appropriate ...
Abstract base class which defines the interface required by an eigensolver and status test class to c...
ReturnType
Enumerated type used to pass back information from a solver manager.
A status test for testing the norm of the eigenvectors residuals.
Traits class which defines basic operations on multivectors.
static Teuchos::RCP< MV > CloneCopy(const MV &mv)
Creates a new MV and copies contents of mv into the new vector (deep copy).
The Anasazi::SimpleLOBPCGSolMgr provides a simple solver manager over the LOBPCG eigensolver.
Anasazi header file which uses auto-configuration information to include necessary C++ headers...
Orthogonalization manager based on the SVQB technique described in "A Block Orthogonalization Procedu...
Struct for storing an eigenproblem solution.
const Eigenproblem< ScalarType, MV, OP > & getProblem() const
Return the eigenvalue problem.
ReturnType solve()
This method performs possibly repeated calls to the underlying eigensolver&#39;s iterate() routine until ...
static void SetBlock(const MV &A, const std::vector< int > &index, MV &mv)
Copy the vectors in A to a set of vectors in mv indicated by the indices given in index...
A status test for testing the number of iterations.
static int GetNumberVecs(const MV &mv)
Obtain the number of vectors in mv.
Status test for testing the number of iterations.
static void permuteVectors(const int n, const std::vector< int > &perm, MV &Q, std::vector< typename Teuchos::ScalarTraits< ScalarType >::magnitudeType > *resids=0)
Permute the vectors in a multivector according to the permutation vector perm, and optionally the res...
Special StatusTest for printing status tests.
Status test for forming logical combinations of other status tests.
Types and exceptions used within Anasazi solvers and interfaces.
A status test for testing the norm of the eigenvectors residuals.
static Teuchos::RCP< MV > Clone(const MV &mv, const int numvecs)
Creates a new empty MV containing numvecs columns.
SimpleLOBPCGSolMgr(const Teuchos::RCP< Eigenproblem< ScalarType, MV, OP > > &problem, Teuchos::ParameterList &pl)
Basic constructor for SimpleLOBPCGSolMgr.
Class which provides internal utilities for the Anasazi solvers.