arpack/arpack.hpp

Go to the documentation of this file.
00001 #ifndef _ARPACK_HPP
00002 #define _ARPACK_HPP
00003 
00004 
00005 //
00006 // Copyright (c) 2009 Simen Kvaal
00007 //
00008 // This file is part of OpenFCI.
00009 //
00010 // OpenFCI is free software: you can redistribute it and/or modify
00011 // it under the terms of the GNU General Public License as published by
00012 // the Free Software Foundation, either version 3 of the License, or
00013 // (at your option) any later version.
00014 //
00015 // OpenFCI is distributed in the hope that it will be useful,
00016 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00017 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00018 // GNU General Public License for more details.
00019 //
00020 // You should have received a copy of the GNU General Public License
00021 // along with OpenFCI. If not, see <http://www.gnu.org/licenses/>.
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); // initial vector if info != 0.
00152         info = 0; // use random initial vector.
00153         V.resize(ncv*n+1);
00154         ldv = n;
00155         iparam.resize(12); // set them!
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++; // increase iteration counter
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 } // namespace arpack
00248 
00249 
00250 #endif

Generated on Wed Jun 17 11:44:02 2009 for OpenFCI by  doxygen 1.4.7