00001 #ifndef _ARPACK_HPP
00002 #define _ARPACK_HPP
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00040 #include "saupp.h"
00041 #include "seupp.h"
00042 #include <cassert>
00043 #include <iostream>
00044
00045 namespace arpack
00046 {
00047
00053 template<class matrix_t>
00054 class symmetric_eigensolver
00055 {
00056 private:
00058 typedef void (matrix_t::* operation_func_t)(double*, double*);
00059
00060 bool debug;
00061
00062 matrix_t *mat;
00063 operation_func_t matrix_op;
00064
00065 ARint n;
00066 ARint nev;
00067 ARint ncv;
00068 double tol;
00069
00070 ARint ido;
00071 char bmat;
00072 char which[3];
00073
00074 std::vector<double> resid;
00075 std::vector<double> V;
00076 ARint ldv;
00077 std::vector<ARint> iparam;
00078 std::vector<ARint> ipntr;
00079 std::vector<double> workd;
00080 std::vector<double> workl;
00081 ARint lworkl;
00082 ARint info;
00083
00084 ARint maxit;
00085
00086 ARint nconv;
00087 std::vector<double> d;
00088 std::vector<double> Z;
00089
00090 public:
00092 void set_matrix_op(matrix_t *the_mat, void (matrix_t::* the_matrix_op)(double*, double*))
00093 {
00094 mat = the_mat;
00095 matrix_op = the_matrix_op;
00096 }
00097
00099 void set_parameters(ARint the_n, ARint the_nev, double the_tol, ARint the_ncv = 0)
00100 {
00101 assert(the_n > 0);
00102 assert(the_nev > 0);
00103 assert(the_nev < the_n);
00104
00105 n = the_n;
00106 nev = the_nev;
00107 tol = the_tol;
00108 if (the_ncv == 0)
00109 {
00110 ncv = min(2*nev+1,n);
00111 }
00112 else
00113 ncv = the_ncv;
00114
00115 }
00116
00117
00119 symmetric_eigensolver()
00120 {
00121 maxit = 1000;
00122 debug = true;
00123 }
00124
00126 symmetric_eigensolver(matrix_t *the_mat, void (matrix_t::* the_matrix_op)(double*, double*))
00127 {
00128 debug = true;
00129 maxit = 1000;
00130 set_matrix_op(the_mat, the_matrix_op);
00131 }
00132
00134 void set_debug(bool d) { debug = d; }
00135
00136
00137
00139 ARint solve()
00140 {
00141
00142
00143 bool finished;
00144
00145 finished = false;
00146
00147 ido = 0;
00148 bmat = 'I';
00149 strcpy(which,"SM");
00150 tol = 1e-8;
00151 resid.resize(n);
00152 info = 0;
00153 V.resize(ncv*n+1);
00154 ldv = n;
00155 iparam.resize(12);
00156 iparam[1] = 1;
00157 iparam[3] = maxit;
00158 iparam[4] = 1;
00159 iparam[7] = 1;
00160 ipntr.resize(12);
00161
00162 workd.resize(3*n + 1);
00163 lworkl = ncv*(ncv+8);
00164 workl.resize(lworkl + 1);
00165
00166
00167 int it = 1;
00168
00169 while (finished == false)
00170 {
00171 it++;
00172 if (debug)
00173 {
00174 std::cerr << "Iteration number " << it << " commencing." << endl;
00175 }
00176 saupp(ido, bmat, n, which, nev, tol, &resid[0],
00177 ncv, &V[0], ldv, &iparam[0], &ipntr[0], &workd[0], &workl[0], lworkl, info);
00178
00179 if (debug)
00180 std::cerr << "(ido, info) == " << ido << ", " << info << std::endl;
00181
00182 if ((ido == -1) || (ido == 1))
00183 {
00184 (mat->*matrix_op)(&workd[ipntr[1]], &workd[ipntr[2]]);
00185 }
00186 else
00187 finished = true;
00188
00189
00190 }
00191
00192 if (info != 0)
00193 {
00194 std::cerr << "Warning! Exit status of ARPACK was info == " << info << "." << std::endl;
00195 }
00196
00197
00198 nconv = iparam[5];
00199 bool rvec = true;
00200 double sigma = 0;
00201
00202 if (debug)
00203 {
00204 std::cerr << "Found nconv == " << nconv << " out of nev == " << nev << " eigenvalues." << std::endl;
00205 }
00206
00207 d.resize(n);
00208 Z.resize(nconv*n);
00209
00210 seupp(rvec, 'A', &d[0], &Z[0],
00211 n, sigma, bmat, n,
00212 which, nev, tol, &resid[0],
00213 ncv, &V[0], ldv, &iparam[0],
00214 &ipntr[0], &workd[0], &workl[0],
00215 lworkl, info);
00216
00217
00218 return nconv;
00219
00220 }
00221
00222
00224 void eigenvalues(std::vector<double>& evals)
00225 {
00226 evals.resize(nconv);
00227 for (size_t k = 0; k<(size_t)nconv; ++k)
00228 evals[k] = d[k];
00229
00230 }
00231
00233 double get_eigenvalue(size_t k)
00234 {
00235 return d[k];
00236 }
00237
00239 double get_eigenvector(size_t j, size_t k)
00240 {
00241 return Z[n*j + k];
00242 }
00243
00244 };
00245
00246
00247 }
00248
00249
00250 #endif