00001 #ifndef ARPACKPP_HH_
00002 #define ARPACKPP_HH_
00003
00004 #include "ARPACK.hh"
00005
00006 #include <arpack++/arscomp.h>
00007 #include <arpack++/argcomp.h>
00008
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
00069
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
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
00124 A_(vec1, vec2);
00125
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
00203
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
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
00275
00276
00277
00278 computed_ = true;
00279 iter_ = arpackSolver_.GetIter();
00280
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
00352
00353
00354
00355
00356
00357
00358
00359
00360
00361
00362
00363
00364
00365
00366
00367
00368
00369
00370
00371
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
00514
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 }
00607
00608 #endif