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.
Preparations
In the first lines three matrices are initialized. is a general, complex matrix,
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.
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.
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
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
#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
}