This tutorial shows how to use Arpack++ to solve eigenvalue problems.
Commented program
Preparations
Standard eigenvalue problems
General eigenvalue problems
General, symmetric eigenvalue problems
Complete source code
Commented Program
Include files for eigenvalue solvers.
#include "eigensolver.hh"
Preparations
In the first lines three matrices are initialized. is a general, complex matrix,
std::complex< Real > Cmplx
Type for a complex number. It also depends on the setting of Real.
is real, symmetric and positive definite,
B(0, 0) = 6;
B(0, 1) = 2;
B(0, 2) = 1;
B(0, 3) = 2;
B(1, 0) = 2;
B(1, 1) = 9;
B(1, 2) = 1;
B(1, 3) = 2;
B(2, 0) = 1;
B(2, 1) = 1;
B(2, 2) = 9;
B(2, 3) = 2;
B(3, 0) = 2;
B(3, 1) = 2;
B(3, 2) = 2;
B(3, 3) = 7;
and is real and symmetric.
C(0, 0) = 2;
C(0, 1) = 1;
C(0, 2) = 1;
C(0, 3) = 1;
C(1, 0) = 1;
C(1, 1) = 1;
C(1, 2) = 0;
C(1, 3) = 1;
C(2, 0) = 1;
C(2, 1) = 0;
C(2, 2) = 2;
C(2, 3) = 1;
C(3, 0) = 1;
C(3, 1) = 1;
C(3, 2) = 1;
C(3, 3) = 0;
Standard eigenvalue problems
We solve the standard eigenvalue problem using the class EasyArPackppStd
. First we compute the two eigenvalues closest to zero using the shift and invert mode.
Tool to easily solve standard eigenvalue problems.
We read the computed eigenvalues
and the corresponding eigenvectors.
We test the accuracy of the computed eigenvalues and eigenvectors.
res1 = *eigenvectors[1];
A(res1, res2);
std::cout << "First residuum: " << ((res1 * eigenvalues[1]) - res2).l2() << std::endl;
std::cout << "Eigenvalue with smallest distance to 0.0: " << eigenvalues[1] << std::endl;
Now we compute the two eigenvalues with largest magnitude using the regular mode.
Again we read the computed eigenvalues
eigenvalues = eacs2.getSolver()->getEV();
and the corresponding eigenvectors,
eigenvectors = eacs2.getSolver()->getEF();
and test their accuracy.
res1 = *eigenvectors[1];
A(res1, res2);
std::cout << "Second residuum: " << ((res1 * eigenvalues[1]) - res2).l2() << std::endl;
std::cout << "Eigenvalue with largest magnitude: " << eigenvalues[1] << std::endl;
General eigenvalue problems
Now let us solve the general eigenvalue problem . We use the class EasyArPackppGen
for this purpose. First we compute the two eigenvalues closest to zero using the shift and invert mode.
Tool to easily solve general eigenvalue problems.
Again we read the computed eigenvalues
eigenvalues = eacg.getSolver()->getEV();
and the corresponding eigenvectors,
eigenvectors = eacg.getSolver()->getEF();
and test their accuracy.
A((*eigenvectors[1]), res1);
B((*eigenvectors[1]), res2);
std::cout << "Third residuum: " << (res1 - (res2 * eigenvalues[1])).l2() << std::endl;
std::cout << "Eigenvalue with smallest distance to 0.0: " << eigenvalues[1] << std::endl;
And then we compute the two eigenvalues with largest magnitude using the regular mode.
Again we read the computed eigenvalues
eigenvalues = eacg2.getSolver()->getEV();
and the corresponding eigenvectors,
eigenvectors = eacg2.getSolver()->getEF();
and test their accuracy.
A((*eigenvectors[1]), res1);
B((*eigenvectors[1]), res2);
std::cout << "Fourth residuum: " << (res1 - (res2 * eigenvalues[1])).l2() << std::endl;
std::cout << "Eigenvalue with largest magnitude: " << eigenvalues[1] << std::endl;
General, symmetric eigenvalue problems
In our final example we want to solve the general, symmetric eigenvalue problem , where the matrix is real and symmetric and the matrix is real, symmetric and positive definite. Using Octave we computed the eigenvalues
double eigenvalue1 = -0.1691925951083604;
double eigenvalue2 = 0.0619419844415557;
double eigenvalue3 = 0.3841300911212291;
First we use the so-called Cayley mode of the class EasyArPackppSymGen
to compute the eigenvalue closest to eigenvalue1
Tool to easily solve general eigenvalue problems for symmetric matrices.
and print the difference of the Octave solution and the Arpack++ solution on the screen
std::cout << "Difference of Octave solution and Arpack++ solution using Cayley mode: "
<< (easg1.getSolver()->getEV())[0] - eigenvalue1 << std::endl;
We proceed similarly, when computing the eigenvalue closest to eigenvalue2
using the Buckling mode
std::cout << "Difference of Octave solution and Arpack++ solution using Buckling mode: "
<< (easg2.getSolver()->getEV())[0] - eigenvalue2 << std::endl;
and when computing the eigenvalue closest to eigenvalue3
using the shift and invert mode
std::cout << "Difference of Octave solution and Arpack++ solution using shift and invert mode: "
<< (easg3.getSolver()->getEV())[0] - eigenvalue3 << std::endl;
Complete Source Code
Author Dirk Klindworth 2014
#include "eigensolver.hh"
#ifdef HAS_MPI
#include "mpi.h"
#endif
int main(int argc, char ** argv) {
try {
#ifdef HAS_MPI
MPI_Init(&argc, &argv);
#endif
B(0, 0) = 6;
B(0, 1) = 2;
B(0, 2) = 1;
B(0, 3) = 2;
B(1, 0) = 2;
B(1, 1) = 9;
B(1, 2) = 1;
B(1, 3) = 2;
B(2, 0) = 1;
B(2, 1) = 1;
B(2, 2) = 9;
B(2, 3) = 2;
B(3, 0) = 2;
B(3, 1) = 2;
B(3, 2) = 2;
B(3, 3) = 7;
C(0, 0) = 2;
C(0, 1) = 1;
C(0, 2) = 1;
C(0, 3) = 1;
C(1, 0) = 1;
C(1, 1) = 1;
C(1, 2) = 0;
C(1, 3) = 1;
C(2, 0) = 1;
C(2, 1) = 0;
C(2, 2) = 2;
C(2, 3) = 1;
C(3, 0) = 1;
C(3, 1) = 1;
C(3, 2) = 1;
C(3, 3) = 0;
res1 = *eigenvectors[1];
A(res1, res2);
std::cout << "First residuum: " << ((res1 * eigenvalues[1]) - res2).l2() << std::endl;
std::cout << "Eigenvalue with smallest distance to 0.0: " << eigenvalues[1] << std::endl;
res1 = *eigenvectors[1];
A(res1, res2);
std::cout << "Second residuum: " << ((res1 * eigenvalues[1]) - res2).l2() << std::endl;
std::cout << "Eigenvalue with largest magnitude: " << eigenvalues[1] << std::endl;
A((*eigenvectors[1]), res1);
B((*eigenvectors[1]), res2);
std::cout << "Third residuum: " << (res1 - (res2 * eigenvalues[1])).l2() << std::endl;
std::cout << "Eigenvalue with smallest distance to 0.0: " << eigenvalues[1] << std::endl;
A((*eigenvectors[1]), res1);
B((*eigenvectors[1]), res2);
std::cout << "Fourth residuum: " << (res1 - (res2 * eigenvalues[1])).l2() << std::endl;
std::cout << "Eigenvalue with largest magnitude: " << eigenvalues[1] << std::endl;
double eigenvalue1 = -0.1691925951083604;
double eigenvalue2 = 0.0619419844415557;
double eigenvalue3 = 0.3841300911212291;
std::cout << "Difference of Octave solution and Arpack++ solution using Cayley mode: "
std::cout << "Difference of Octave solution and Arpack++ solution using Buckling mode: "
<< (easg2.getSolver()->getEV())[0] - eigenvalue2 << std::endl;
std::cout << "Difference of Octave solution and Arpack++ solution using shift and invert mode: "
<< (easg3.getSolver()->getEV())[0] - eigenvalue3 << std::endl;
std::cout << e << std::endl;
return 1;
}
#ifdef HAS_MPI
MPI_Barrier(MPI_COMM_WORLD);
MPI_Finalize();
#endif
}
static bool & doit()
If doit is set to false, no stacktrace is printed.
virtual const concepts::Array< Real > & getEV()
virtual ArPackppGen< H, F, concepts::Real > * getSolver()
virtual ArPackppStd< H > * getSolver()
virtual ArPackppSymGen * getSolver()
Getter for the generated solver.