Home | Doxygen Documentation | Tutorials | Developer Tools (restricted)

eigensolver/arpackpp.hh
Go to the documentation of this file.
00001 #ifndef ARPACKPP_HH_
00002 #define ARPACKPP_HH_
00003 
00004 #include "ARPACK.hh"
00005 //classes for complex (general) eigenvalue problems
00006 #include <arpack++/arscomp.h>
00007 #include <arpack++/argcomp.h>
00008 //classes for real symmetric (general) eigenvalue problems
00009 #include <arpack++/argsym.h>
00010 #include "operator.hh"
00011 
00012 namespace eigensolver {
00013 
00014   using concepts::Real;
00015   using concepts::Cmplx;
00016 
00020   template<class T>
00021   class ArpackStdOperatorWrapper {
00022   public:
00023 
00028     ArpackStdOperatorWrapper(concepts::Operator<T>& OP) :
00029       OP_(OP) {
00030     }
00031 
00037     template<class F>
00038     void multOPx(F* v, F* w) {
00039       concepts::Vector<F> vec1(OP_.dimX(), v);
00040       concepts::Vector<F> vec2(OP_.dimY());
00041       OP_(vec1, vec2);
00042       for (uint i = 0; i < OP_.dimY(); ++i)
00043         w[i] = vec2[i];
00044     }
00045 
00046   private:
00047     concepts::Operator<T>& OP_;
00048   };
00049 
00053   template<class T, class U, class V>
00054   class ArpackOperatorWrapper {
00055   public:
00056 
00063     ArpackOperatorWrapper(concepts::Operator<T>& OP, concepts::Operator<U>& A,
00064         concepts::Operator<V>& B) :
00065       OP_(OP), A_(A), B_(B) {
00066     }
00067 
00068     //FIXME replace for-loop with memcpy
00069     //TODO what happens if dimensions don't agree? Exception??
00075     template<class S>
00076     void multAxp(S* v, S* w) {
00077       concepts::Vector<S> vec1(A_.dimX(), v);
00078       concepts::Vector<S> vec2(A_.dimY());
00079       A_(vec1, vec2);
00080       for (uint i = 0; i < A_.dimY(); ++i)
00081         w[i] = vec2[i];
00082     }
00083 
00089     template<class S>
00090     void multBxp(S* v, S* w) {
00091       //std::cout << "multBx" << std::endl;
00092       concepts::Vector<S> vec1(B_.dimX(), v);
00093       concepts::Vector<S> vec2(B_.dimY());
00094       B_(vec1, vec2);
00095       for (uint i = 0; i < B_.dimY(); ++i)
00096         w[i] = vec2[i];
00097     }
00098 
00104     template<class S>
00105     void multOPx(S* v, S* w) {
00106       concepts::Vector<S> vec1(OP_.dimX(), v);
00107       concepts::Vector<S> vec2(OP_.dimY());
00108       OP_(vec1, vec2);
00109       for (uint i = 0; i < OP_.dimY(); ++i)
00110         w[i] = vec2[i];
00111     }
00112 
00118     template<class S>
00119     void multOPxRegular(S* v, S* w) {
00120 
00121       concepts::Vector<S> vec1(OP_.dimX(), v);
00122       concepts::Vector<S> vec2(A_.dimY());
00123       //vec2 = A*v
00124       A_(vec1, vec2);
00125       //vec1 = OP * vec2 = OP * A * v
00126       OP_(vec2, vec1);
00127       for (uint i = 0; i < OP_.dimY(); ++i)
00128         w[i] = vec1[i];
00129     }
00130 
00131   private:
00132     concepts::Operator<T>& OP_;
00133     concepts::Operator<U>& A_;
00134     concepts::Operator<V>& B_;
00135   };
00136 
00141   template<class T>
00142   class ArPackppStd: public EigenSolver<concepts::Cmplx> {
00143   public:
00144 
00156     ArPackppStd(concepts::Operator<T>& OP, int kmax, concepts::Cmplx sigma,
00157         Real tol = 0.0, int maxiter = 300,
00158         concepts::Vector<concepts::Cmplx>* start = 0, concepts::Array<
00159             concepts::Cmplx>* resid = 0, bool schur = false) :
00160       whichEV_((char *) "LM"), modus_(ArPack<Real>::SHIFTINV), aow_(OP),
00161           arpackSolver_(OP.dimX(), kmax, &aow_,
00162               &ArpackStdOperatorWrapper<T>::multOPx, sigma, whichEV_, 0, tol,
00163               maxiter), computed_(false) {
00164       if (kmax <= 0 || kmax > (((int)OP.dimX()) - 1))
00165         throw conceptsException(concepts::ExceptionBase("Dimension must be greater than zero and smaller then the dimension of the problem -1"));
00166       ;
00167     }
00168     ;
00169 
00183     ArPackppStd(concepts::Operator<T>& OP, int kmax = 1, char* which = "LM",
00184         Real tol = 0.0, int maxiter = 300,
00185         concepts::Vector<concepts::Cmplx>* start = 0, concepts::Array<
00186             concepts::Cmplx>* resid = 0, bool schur = false) :
00187       whichEV_(which), modus_(ArPack<Real>::SHIFTINV), aow_(OP), arpackSolver_(
00188           OP.dimX(), kmax, &aow_, &ArpackStdOperatorWrapper<T>::multOPx,
00189           whichEV_, 0, tol, maxiter), computed_(false) {
00190       if (kmax <= 0 || kmax > (((int)OP.dimX()) - 1))
00191         throw conceptsException(concepts::ExceptionBase("Dimension must be greater than zero and smaller then the dimension of the problem -1"));
00192       ;
00193     }
00194     ;
00195 
00196     virtual ~ArPackppStd() {
00197       for (uint i = 0; i < this->arpackSolver_.EigenvectorsFound(); ++i)
00198         delete eigenVectors_[i];
00199     }
00200 
00201     /*
00202      * Getter for the computed eigenvalues. Computes Eigenvalus and Eigenvectors if
00203      * they were not computed.
00204      */
00205     virtual const concepts::Array<Cmplx>&
00206     getEV() {
00207       if (!computed_)
00208         compute_();
00209       return eigenValues_;
00210     }
00211 
00216     virtual concepts::Array<concepts::Vector<Cmplx>*>&
00217     getEF() {
00218       if (!computed_)
00219         compute_();
00220       return eigenVectors_;
00221     }
00222 
00224     virtual uint iterations() const {
00225       return iter_;
00226     }
00227 
00229     virtual uint converged() const {
00230       return convEigenvalues_;
00231     }
00232 
00234     inline concepts::Array<Cmplx> getRESID() {
00235       concepts::Array<Cmplx> res(this->arpackSolver_.RawResidualVector(),
00236           this->arpackSolver_.GetN());
00237       return res;
00238     }
00239   protected:
00240     virtual std::ostream&
00241     info(std::ostream& os) const {
00242       os << "ArPackppSymmGen \n";
00243       switch (modus_) {
00244         case ArPack<concepts::Real>::REGINV:
00245           os << "regular inverse mode \n";
00246           break;
00247         case ArPack<concepts::Real>::SHIFTINV:
00248           os << "shift-invert mode \n";
00249           break;
00250         case ArPack<concepts::Real>::NORMAL:
00251           os << "normal mode \n";
00252           break;
00253         case ArPack<concepts::Real>::SHIFTINVIMAG:
00254           os << "shift-invert mode \n";
00255           break;
00256       }
00257       return os;
00258     }
00259   private:
00260     void compute_() {
00261       int numOfVecs = this->arpackSolver_.FindEigenvectors();
00262       //std::cout << numOfVecs << std::endl;
00263       eigenValues_.resize(this->arpackSolver_.ConvergedEigenvalues());
00264 
00265       for (int i = 0; i < this->arpackSolver_.ConvergedEigenvalues(); ++i) {
00266         eigenValues_[i] = this->arpackSolver_.Eigenvalue(i);
00267       }
00268       eigenVectors_.resize(this->arpackSolver_.GetN());
00269       for (int i = 0; i < numOfVecs; ++i)
00270         eigenVectors_[i] = new concepts::Vector<concepts::Cmplx>(
00271             this->arpackSolver_.GetN(), this->arpackSolver_.RawEigenvectors()
00272                 + i * this->arpackSolver_.GetN());
00273 
00274       //for (int i = 0; i < 8; ++i)
00275       //std::cout << "AHA: " << this->arpackSolver_.RawEigenvectors()[i]
00276       //    << std::endl;
00277 
00278       computed_ = true;
00279       iter_ = arpackSolver_.GetIter();
00280       //std::cout << "Num of iterations: " << iter_ << std::endl;
00281       convEigenvalues_ = arpackSolver_.ConvergedEigenvalues();
00282     }
00283     ;
00284     char* whichEV_;
00285     ArPack<Real>::modus modus_;
00286     uint n_;
00287     ArpackStdOperatorWrapper<T> aow_;
00288     ARCompStdEig<Real, ArpackStdOperatorWrapper<T> > arpackSolver_;
00289 
00290     uint iter_;
00291     uint convEigenvalues_;
00292     bool computed_;
00293 
00295     concepts::Array<Cmplx> eigenValues_;
00296     concepts::Array<concepts::Vector<Cmplx>*> eigenVectors_;
00297 
00298   };
00299 
00303   class ArPackppSymGen: public EigenSolver<Real> {
00304 
00305   public:
00306 
00324     ArPackppSymGen(concepts::Operator<Real>& OP, concepts::Operator<Real>& A,
00325         concepts::Operator<Real>& B, int kmax = 1, Real sigma = 0.1, Real tol =
00326             0.0, int maxiter = 300, concepts::Vector<Real>* start = 0,
00327         concepts::Array<Real>* resid = 0, bool schur = false);
00328 
00346     ArPackppSymGen(char invertType, concepts::Operator<Real>& OP,
00347         concepts::Operator<Real>& A, int kmax = 1, Real sigma = 0.1, Real tol =
00348             0.0, int maxiter = 300, concepts::Vector<Real>* start = 0,
00349         concepts::Array<Real>* resid = 0, bool schur = false);
00350 
00351     //    /** Constructor for SHIFTandINVERT mode and Buckling mode
00352     //     @warning B have to be a symmetric positive definite matrix
00353     //     @param OP is the multiplication operator B^-1
00354     //     @param A Stiffness matrix
00355     //     @param B is the Matrix on the right hand side
00356     //     @param kmax Number of eigenpairs to be computed,
00357     //     must be lower then the dimension of the matrices -1
00358     //     @warning kmax have to be lower than the dimension of the matrix -1!
00359     //     @param tol Convergence tolerance for the eigenpairs. The default
00360     //     value 0.0 is replaced by \c DLAMCH('EPS') from LAPACK.
00361     //     @param maxiter Maximum number of Arnoldi iterations allowed
00362     //     @param target What sort of eigenvalues to compute
00363     //     @param sigma Shift for the shift-invert modes
00364     //     @warning In the buckling mode sigma should be a real number that is NOT ZERO!
00365     //     @param start Initial vector for iteration
00366     //     @param schur Calculate Schur vector basis instead of eigenvectors
00367     //     */
00368     //    ArPackppSymGen(concepts::Operator<Real>& OP, concepts::Operator<Real>& A,
00369     //        concepts::Operator<Real>& B, int kmax = 1, char* which = (char*) "LM",
00370     //        Real tol = 0.0, int maxiter = 300, concepts::Vector<Real>* start = 0,
00371     //        concepts::Array<Real>* resid = 0, bool schur = false);
00372 
00374     virtual ~ArPackppSymGen() {
00375       for (uint i = 0; i < this->arpackSolver_.EigenvectorsFound(); ++i)
00376         delete eigenVectors_[i];
00377     }
00378 
00382     virtual const concepts::Array<Real>&
00383     getEV() {
00384       if (!computed_)
00385         compute_();
00386       return eigenValues_;
00387     }
00388 
00392     virtual concepts::Array<concepts::Vector<Real>*>&
00393     getEF() {
00394       if (!computed_)
00395         compute_();
00396       return eigenVectors_;
00397     }
00398 
00400     virtual uint iterations() const {
00401       return iter_;
00402     }
00403 
00405     virtual uint converged() const {
00406       return convEigenvalues_;
00407     }
00408 
00410     inline concepts::Array<Real> getRESID() {
00411       concepts::Array<Real> res(this->arpackSolver_.RawResidualVector(),
00412           this->arpackSolver_.GetN());
00413       return res;
00414     }
00415 
00416   protected:
00417     virtual std::ostream& info(std::ostream& os) const {
00418       os << "ArPackppSymmGen \n";
00419       return os;
00420     }
00421 
00422   private:
00423     void compute_();
00424     char* whichEV_;
00425     ArPack<Real>::modus modus_;
00426     ArpackOperatorWrapper<concepts::Real, concepts::Real, concepts::Real> aow_;
00427     ARSymGenEig<Real, ArpackOperatorWrapper<concepts::Real, concepts::Real,
00428         concepts::Real> , ArpackOperatorWrapper<concepts::Real, concepts::Real,
00429         concepts::Real> > arpackSolver_;
00430 
00431     uint n_;
00432     uint iter_;
00433     uint convEigenvalues_;
00434     bool computed_;
00435 
00437     concepts::Array<Real> eigenValues_;
00438     concepts::Array<concepts::Vector<Real>*> eigenVectors_;
00439 
00440   };
00444   template<class F, class G, class H = concepts::Real>
00445   class ArPackppGen: public EigenSolver<concepts::Cmplx> {
00446   public:
00447 
00461     ArPackppGen(concepts::Operator<F>& OP, concepts::Operator<G>& A,
00462         concepts::Operator<H>& B, int kmax = 1, concepts::Cmplx sigma = 0.0,
00463         Real tol = 0.01, int maxiter = 300,
00464         concepts::Vector<concepts::Cmplx>* start = 0, concepts::Array<
00465             concepts::Cmplx>* resid = 0, bool schur = false) :
00466       whichEV_((char*) "LM"), modus_(ArPack<Real>::SHIFTINV), aow_(OP, A, B),
00467           arpackSolver_(A.dimX(), kmax, &aow_,
00468               &ArpackOperatorWrapper<F, G, H>::multOPx, &aow_,
00469               &ArpackOperatorWrapper<F, G, H>::multBxp, sigma, whichEV_, 0,
00470               tol, maxiter), computed_(false) {
00471       if (kmax <= 0 || kmax > (((int)OP.dimX()) - 1))
00472         throw conceptsException(concepts::ExceptionBase("Dimension must be greater than zero and smaller then the dimension of the problem -1"));
00473       ;
00474     }
00475     ;
00476 
00491     ArPackppGen(concepts::Operator<F>& OP, concepts::Operator<G>& A,
00492         concepts::Operator<H>& B, int kmax = 1, char* which = (char*) "LM",
00493         Real tol = 0.0, int maxiter = 300,
00494         concepts::Vector<concepts::Cmplx>* start = 0, concepts::Array<
00495             concepts::Cmplx>* resid = 0, bool schur = false) :
00496       whichEV_(which), modus_(ArPack<Real>::SHIFTINV), aow_(OP, A, B),
00497           arpackSolver_(A.dimX(), kmax, &aow_,
00498               &ArpackOperatorWrapper<F, G, H>::multOPxRegular, &aow_,
00499               &ArpackOperatorWrapper<F, G, H>::multBxp, whichEV_, 0, tol,
00500               maxiter), computed_(false) {
00501       if (kmax <= 0 || kmax > (((int)OP.dimX()) - 1))
00502         throw conceptsException(concepts::ExceptionBase("Dimension must be greater than zero and smaller then the dimension of the problem -1"));
00503       ;
00504     }
00505     ;
00506 
00507     virtual ~ArPackppGen() {
00508       for (uint i = 0; i < this->arpackSolver_.EigenvectorsFound(); ++i)
00509         delete eigenVectors_[i];
00510     }
00511 
00512     /*
00513      * Getter for the computed eigenvalues. Computes Eigenvalus and Eigenvectors if
00514      * they were not computed.
00515      */
00516     virtual const concepts::Array<Cmplx>&
00517     getEV() {
00518       if (!computed_)
00519         compute_();
00520       return eigenValues_;
00521     }
00522 
00527     virtual concepts::Array<concepts::Vector<Cmplx>*>&
00528     getEF() {
00529       if (!computed_)
00530         compute_();
00531       return eigenVectors_;
00532     }
00533 
00535     virtual uint iterations() const {
00536       return iter_;
00537     }
00538 
00540     virtual uint converged() const {
00541       return convEigenvalues_;
00542     }
00543 
00545     inline concepts::Array<Cmplx> getRESID() {
00546       concepts::Array<Cmplx> res(this->arpackSolver_.RawResidualVector(),
00547           this->arpackSolver_.GetN());
00548       return res;
00549     }
00550   protected:
00551     virtual std::ostream&
00552     info(std::ostream& os) const {
00553       os << "ArPackppSymmGen \n";
00554       switch (modus_) {
00555         case ArPack<concepts::Real>::REGINV:
00556           os << "regular inverse mode \n";
00557           break;
00558         case ArPack<concepts::Real>::SHIFTINV:
00559           os << "shift-invert mode \n";
00560           break;
00561         case ArPack<concepts::Real>::NORMAL:
00562           os << "normal mode \n";
00563           break;
00564         case ArPack<concepts::Real>::SHIFTINVIMAG:
00565           os << "shift-invert mode \n";
00566           break;
00567       }
00568       return os;
00569     }
00570   private:
00571     void compute_() {
00572       int numOfVecs = this->arpackSolver_.FindEigenvectors();
00573       eigenValues_.resize(this->arpackSolver_.ConvergedEigenvalues());
00574 
00575       for (int i = 0; i < this->arpackSolver_.ConvergedEigenvalues(); ++i) {
00576         eigenValues_[i] = this->arpackSolver_.Eigenvalue(i);
00577       }
00578       eigenVectors_.resize(this->arpackSolver_.GetN());
00579       for (int i = 0; i < numOfVecs; ++i)
00580         eigenVectors_[i] = new concepts::Vector<concepts::Cmplx>(
00581             this->arpackSolver_.GetN(), this->arpackSolver_.RawEigenvectors()
00582                 + i * this->arpackSolver_.GetN());
00583 
00584       computed_ = true;
00585       iter_ = arpackSolver_.GetIter();
00586       convEigenvalues_ = arpackSolver_.ConvergedEigenvalues();
00587     }
00588     ;
00589     char* whichEV_;
00590     ArPack<Real>::modus modus_;
00591     uint n_;
00592     ArpackOperatorWrapper<F, G, H> aow_;
00593     ARCompGenEig<Real, ArpackOperatorWrapper<F, G, H> , ArpackOperatorWrapper<
00594         F, G, H> > arpackSolver_;
00595 
00596     uint iter_;
00597     uint convEigenvalues_;
00598     bool computed_;
00599 
00601     concepts::Array<Cmplx> eigenValues_;
00602     concepts::Array<concepts::Vector<Cmplx>*> eigenVectors_;
00603 
00604   };
00605 
00606 } // namespace eigensolver
00607 
00608 #endif /* ARPACKPP_HH_ */

Home | Doxygen Documentation | Tutorials | Developer Tools (restricted)