Use LOBPCG with Epetra, with shifted eigenvalue problemThis example computes the eigenvalues of largest magnitude of the discretized 2-D Laplacian operator, using Anasazi's implementation of the LOBPCG method. This problem constructs a shifted eigenproblem that targets the smallest eigenvalues around a certain value (sigma). This operator is discretized using linear finite elements and constructed as an Epetra matrix, then passed shifted using EpetraExt utilities.
#include "Epetra_CrsMatrix.h"
#include "Epetra_LinearProblem.h"
#include "ModeLaplace2DQ2.h"
#include "EpetraExt_MatrixMatrix.h"
#ifdef EPETRA_MPI
#include "Epetra_MpiComm.h"
#else
#include "Epetra_SerialComm.h"
#endif
#include "Epetra_Map.h"
#include "Teuchos_StandardCatchMacros.hpp"
int
main (int argc, char *argv[])
{
#ifdef EPETRA_MPI
MPI_Init(&argc,&argv);
#else
#endif
bool success = false;
try {
int i;
int MyPID = Comm.
MyPID();
int space_dim = 2;
std::vector<double> brick_dim( space_dim );
brick_dim[0] = 1.0;
brick_dim[1] = 1.0;
std::vector<int> elements( space_dim );
elements[0] = 10;
elements[1] = 10;
double sigma = 1.0;
int addErr =
EpetraExt::MatrixMatrix::Add( *M,
false, -sigma, *Kshift, 1.0 );
if (addErr != 0) {
throw -1;
}
const int nev = 10;
const int blockSize = 5;
const int maxIters = 500;
const double tol = 1.0e-8;
std::string which = "SM";
MyPL.
set(
"Verbosity", verbosity );
MyPL.
set(
"Which", which );
MyPL.
set(
"Block Size", blockSize );
MyPL.
set(
"Maximum Iterations", maxIters );
MyPL.
set(
"Convergence Tolerance", tol );
MyPL.
set(
"Full Ortho",
true );
MyPL.
set(
"Use Locking",
true );
MyPL.
set(
"Locking Tolerance", tol/10 );
MVT::MvRandom( *ivec );
MyProblem->setHermitian(true);
MyProblem->setNEV( nev );
bool boolret = MyProblem->setProblem();
if (!boolret) {
throw -1;
}
std::cout << "Anasazi::EigensolverMgr::solve() returned unconverged." << std::endl;
}
std::vector<Anasazi::Value<double> > evals = sol.
Evals;
if (numev > 0) {
std::vector<double> compEvals(numev);
for (i=0; i<numev; ++i) {
compEvals[i] = evals[i].realpart + sigma;
}
std::vector<double> normR(sol.
numVecs);
T(i,i) = compEvals[i];
}
K->
Apply( *evecs, Kvec );
M->
Apply( *evecs, Mvec );
MVT::MvTimesMatAddMv( -1.0, Mvec, T, 1.0, Kvec );
MVT::MvNorm( Kvec, normR );
std::ostringstream os;
os.setf(std::ios_base::right, std::ios_base::adjustfield);
os<<
"Solver manager returned " << (returnCode ==
Anasazi::Converged ?
"converged." :
"unconverged.") << std::endl;
os<<std::endl;
os<<"------------------------------------------------------"<<std::endl;
os<<std::setw(16)<<"Eigenvalue"
<<std::setw(18)<<"Direct Residual"
<<std::endl;
os<<"------------------------------------------------------"<<std::endl;
os<<std::setw(16)<<compEvals[i]
<<std::setw(18)<<normR[i]/compEvals[i]
<<std::endl;
}
os<<"------------------------------------------------------"<<std::endl;
}
success = true;
}
#ifdef EPETRA_MPI
MPI_Finalize();
#endif
return ( success ? EXIT_SUCCESS : EXIT_FAILURE );
}