Created
June 18, 2014 10:22
-
-
Save wpoely86/043d0eb92f7e42563e7f to your computer and use it in GitHub Desktop.
arpack usage example
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
double arpackDiagonalize() | |
{ | |
// dimension of the matrix | |
int n = dim; | |
// number of eigenvalues to calculate | |
int nev = 1; | |
// reverse communication parameter, must be zero on first iteration | |
int ido = 0; | |
// standard eigenvalue problem A*x=lambda*x | |
char bmat = 'I'; | |
// calculate the smallest algebraic eigenvalue | |
char which[] = {'S','A'}; | |
// calculate until machine precision | |
double tol = 0; | |
// the residual vector | |
double *resid = new double[n]; | |
// the number of columns in v: the number of lanczos vector | |
// generated at each iteration, ncv <= n | |
// We use the answer to life, the universe and everything, if possible | |
int ncv = 42; | |
if( n < ncv ) | |
ncv = n; | |
// v containts the lanczos basis vectors | |
int ldv = n; | |
double *v = new double[ldv*ncv]; | |
int *iparam = new int[11]; | |
iparam[0] = 1; // Specifies the shift strategy (1->exact) | |
iparam[2] = 3*n; // Maximum number of iterations | |
iparam[6] = 1; /* Sets the mode of dsaupd. | |
1 is exact shifting, | |
2 is user-supplied shifts, | |
3 is shift-invert mode, | |
4 is buckling mode, | |
5 is Cayley mode. */ | |
int *ipntr = new int[11]; /* Indicates the locations in the work array workd | |
where the input and output vectors in the | |
callback routine are located. */ | |
// array used for reverse communication | |
double *workd = new double[3*n]; | |
for(int i=0;i<3*n;i++) | |
workd[i] = 0; | |
int lworkl = ncv*(ncv+8); /* Length of the workl array */ | |
double *workl = new double[lworkl]; | |
// info = 0: random start vector is used | |
int info = 0; /* Passes convergence information out of the iteration | |
routine. */ | |
// rvec == 0 : calculate only eigenvalue | |
// rvec > 0 : calculate eigenvalue and eigenvector | |
int rvec = 0; | |
// how many eigenvectors to calculate: 'A' => nev eigenvectors | |
char howmny = 'A'; | |
int *select; | |
// when howmny == 'A', this is used as workspace to reorder the eigenvectors | |
if( howmny == 'A' ) | |
select = new int[ncv]; | |
// This vector will return the eigenvalues from the second routine, dseupd. | |
double *d = new double[nev]; | |
double *z = 0; | |
if( rvec ) | |
z = new double[n*nev]; | |
// not used if iparam[6] == 1 | |
double sigma; | |
// first iteration | |
dsaupd_(&ido, &bmat, &n, &which[0], &nev, &tol, resid, &ncv, v, &ldv, iparam, ipntr, workd, workl, &lworkl, &info); | |
while( ido != 99 ) | |
{ | |
// matrix-vector multiplication | |
mvprod(workd+ipntr[0]-1, workd+ipntr[1]-1,0); | |
dsaupd_(&ido, &bmat, &n, &which[0], &nev, &tol, resid, &ncv, v, &ldv, iparam, ipntr, workd, workl, &lworkl, &info); | |
} | |
if( info < 0 ) | |
std::cerr << "Error with dsaupd, info = " << info << std::endl; | |
else if ( info == 1 ) | |
std::cerr << "Maximum number of Lanczos iterations reached." << std::endl; | |
else if ( info == 3 ) | |
std::cerr << "No shifts could be applied during implicit Arnoldi update, try increasing NCV." << std::endl; | |
dseupd_(&rvec, &howmny, select, d, z, &ldv, &sigma, &bmat, &n, which, &nev, &tol, resid, &ncv, v, &ldv, iparam, ipntr, workd, workl, &lworkl, &info); | |
if ( info != 0 ) | |
std::cerr << "Error with dseupd, info = " << info << std::endl; | |
// use something to store the result before deleting... | |
sigma = d[0]; | |
delete [] resid; | |
delete [] v; | |
delete [] iparam; | |
delete [] ipntr; | |
delete [] workd; | |
delete [] workl; | |
delete [] d; | |
if( rvec ) | |
delete [] z; | |
if( howmny == 'A' ) | |
delete [] select; | |
return sigma; // lowest eigenvalue | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment