Anasazi Version of the Day

Classes  
class  Anasazi::BlockDavidson< ScalarType, MV, OP > 
This class implements a Block Davidson iteration, a preconditioned iteration for solving linear Hermitian eigenproblems. More...  
class  Anasazi::BlockDavidsonSolMgr< ScalarType, MV, OP > 
The BlockDavidsonSolMgr provides a powerful solver manager over the BlockDavidson eigensolver. More...  
class  Anasazi::BlockKrylovSchur< ScalarType, MV, OP > 
This class implements the block KrylovSchur iteration, for solving linear eigenvalue problems. More...  
class  Anasazi::BlockKrylovSchurSolMgr< ScalarType, MV, OP > 
The Anasazi::BlockKrylovSchurSolMgr provides a flexible solver manager over the BlockKrylovSchur eigensolver. More...  
class  Anasazi::IRTR< ScalarType, MV, OP > 
class  Anasazi::LOBPCG< ScalarType, MV, OP > 
This class provides the Locally Optimal Block Preconditioned Conjugate Gradient (LOBPCG) iteration, a preconditioned iteration for solving linear Hermitian eigenproblems. More...  
class  Anasazi::LOBPCGSolMgr< ScalarType, MV, OP > 
The LOBPCGSolMgr provides a powerful solver manager over the LOBPCG eigensolver. More...  
class  Anasazi::RTRBase< ScalarType, MV, OP > 
This class is an abstract base class for Implicit Riemannian TrustRegion based eigensolvers. The class provides the interfaces shared by the IRTR solvers (e.g., getState() and initialize()) as well as the shared implementations (e.g., inner products). More...  
class  Anasazi::RTRSolMgr< ScalarType, MV, OP > 
The Anasazi::RTRSolMgr provides a simple solver manager over the RTR eigensolver. For more information, see the discussion for RTRBase. More...  
class  Anasazi::SimpleLOBPCGSolMgr< ScalarType, MV, OP > 
The Anasazi::SimpleLOBPCGSolMgr provides a simple solver manager over the LOBPCG eigensolver. More...  
class  Anasazi::SIRTR< ScalarType, MV, OP > 
Anasazi is a framework for developing largescale iterative eigensolvers. When developing such a framework, or even a collection of different solvers, one will notice a large amount of overlap among different implementations. For example, two separate eigensolvers may utilize the same orthogonalization methods, whereas two different implementations of a particular eigensolver may utilize different orthogonalization routines. Dividing the different tasks associated with an iterative eigensolver into multiple routines enables increased code reuse and eases code maintenance. The question arises: how does one distill the essence of a particular eigensolver, with the end goal of separating this code from the supporting code?
To illustrate this dilemma, consider the block Davidson iteration. The essence of the algorithm can be distilled as follows: a preconditioner is applied to the current residual vectors, and the resulting vectors are used to expand a subspace from which the next eigenvector approximations (and their residuals) are computed. However, a multitude of choices abound in implementing this simple iteration: the size of the computed basis, whether and how the method is restarted, the convergence criterion for the algorithm, and the use of deflation (locking) mechanisms, etc.
Many of these decisions are separate from the actual iteration. Extracting the essential nature of an iteration results in a simpler piece of code to develop, debug and maintain. The Anasazi iterative eigensolver framework encourages this by providing three distinct entities to fulfill the roles needed by an eigensolver: Anasazi::Eigensolver, Anasazi::StatusTest and Anasazi::SolverManager:
Returning to the block Davidson example, let's examine how these different pieces come into play. The Anasazi::BlockDavidson class contains both the state and mechanism of the block Davidson iteration. The state consists of the current test basis, the eigenvector estimates, the residual vectors, and other support data. The eigensolver iteration is described above, and is implemented inside the Anasazi::BlockDavidson::iterate() method. On a call to Anasazi::BlockDavidson::iterate(), the iteration persists until one of two things happens: either the basis becomes full or the Anasazi::StatusTest provided to the solver indicates that the iteration should be terminated. This is summarized in the following code snippet:
void Anasazi::BlockDavidson::iterate() { while ( statustest.checkStatus(this) != Anasazi::Passed && getCurSubspaceDim() < getMaxSubspaceDim() ) { // perform block Davidson iterations } }
The Anasazi::StatusTest::checkStatus() routine takes an Anasazi::Eigensolver object as an argument. For a status test to examine the status of an arbitrary iteration, we must have some abstract interface defining the status of the iteration. This interface is defined by the Anasazi::Eigensolver abstract base class, the class from which all eigensolvers in Anasazi derive. The following are some example of the methods provided by Anasazi::Eigensolver for use by Anasazi::StatusTest objects:
// Get the current residual norms std::vector<MagnitudeType> getResNorms(); // Get the Ritz values from the previous iteration. std::vector<Value<ScalarType> > getRitzValues(); // Get the current iteration count. int getNumIters() const; // and many more!!!
The termination of Anasazi::Eigensolver::iterate() is partially controlled by the status test. In one example, a user wishing to limit the number of iterations might utilize Anasazi::StatusTestMaxIters. In another example, a user wishing to halt Anasazi::Eigensolver::iterate() when the residual norms satisfy a certain tolerance might utilize Anasazi::StatusTestResNorm. Arbitrary combinations of status tests can be created using a Anasazi::StatusTestCombo class, so that the stopping criterion can now be affected without modifying the iteration. Furthermore, these decisions can be made at runtime. See Anasazi::StatusTest for a list of status tests provided by Anasazi.
Recalling again the block Davidson example, we know that after filling the allocated basis in the iterate() routine, the eigensolver must be restarted with a new subspace. A user wishing to perform a particular type of restarting needs access to the entire state of the eigensolver and must be able to set this state. Each of the Anasazi eigensolvers provides getState() and initialize() methods for retrieving and setting the internal state of the eigensolver. In the case of Anasazi::BlockDavidson, this method can be used to access the current test basis, which can be used for performing a restart. The user may produce a new state for the eigensolver and then pass it to the eigensolver via the Anasazi::BlockDavidson::initialize() method. In this way, the user has great flexibility in dictating the behavior of the algorithm.
However, the code for performing restarting and locking and similar features is tedious. Furthermore, much research has been conducted into robust and efficient methods for performing these operations. The Anasazi::SolverManager exists as a way to encapsulate this functionality in an accessible package, suitable for use in other codes. The goal of a solver manager is to perform all of the communication with a particular eigensolver, providing advanced functionality, on behalf of the user. Algorithmic parameters of a particular solver manager are set via a Teuchos::ParameterList. The only other input provided to the solver manager is the Anasazi::Eigenproblem to be solved. Consider the following example:
// create an eigenproblem Anasazi::Eigenproblem prob = ... // create a parameter list for the Anasazi::BlockDavidsonSolMgr solver manager Teuchos::ParameterList pl; pl.set("Block Size",5); pl.set("Num Blocks",10); pl.set("Maximum Restarts",20); // create a Block Davidson solver manager Anasazi::BlockDavidsonSolMgr manager(prob,pl); // solve the eigenproblem Anasazi::ReturnType ret = manager.solve(); // retrieve the answer Anasazi::Eigensolution sltn = prob.getSolution();
The Anasazi::BlockDavidsonSolMgr solver manager is responsible for
The division between eigensolver and solver manager enables the following functionality in Anasazi: