TSFAnasaziEigensolverImpl.hpp
Go to the documentation of this file.
00001 /* @HEADER@ */
00002 /* ***********************************************************************
00003 // 
00004 //           TSFExtended: Trilinos Solver Framework Extended
00005 //                 Copyright (2004) Sandia Corporation
00006 // 
00007 // Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive
00008 // license for use of this work by or on behalf of the U.S. Government.
00009 // 
00010 // This library is free software; you can redistribute it and/or modify
00011 // it under the terms of the GNU Lesser General Public License as
00012 // published by the Free Software Foundation; either version 2.1 of the
00013 // License, or (at your option) any later version.
00014 //  
00015 // This library is distributed in the hope that it will be useful, but
00016 // WITHOUT ANY WARRANTY; without even the implied warranty of
00017 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00018 // Lesser General Public License for more details.
00019 //  
00020 // You should have received a copy of the GNU Lesser General Public
00021 // License along with this library; if not, write to the Free Software
00022 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
00023 // USA
00024 // Questions? Contact Michael A. Heroux (maherou@sandia.gov) 
00025 // 
00026 // **********************************************************************/
00027 /* @HEADER@ */
00028 
00029 #ifndef TSFANASAZIEIGENSOLVER_IMPL_HPP
00030 #define TSFANASAZIEIGENSOLVER_IMPL_HPP
00031 
00032 #include "SundanceDefs.hpp"
00033 #include "TSFAnasaziEigensolverDecl.hpp" 
00034 #include "TSFParameterListPreconditionerFactory.hpp" 
00035 #include "TSFPreconditionerFactory.hpp" 
00036 #include "AnasaziBlockKrylovSchurSolMgr.hpp"
00037 #include "AnasaziBlockDavidsonSolMgr.hpp"
00038 #include "AnasaziSimpleLOBPCGSolMgr.hpp"
00039 #include "AnasaziLOBPCGSolMgr.hpp"
00040 #include "AnasaziBasicEigenproblem.hpp"
00041 #include "AnasaziThyraAdapter.hpp"
00042 #include "TSFAnasaziAdapter.hpp"
00043 
00044 
00045 namespace TSFExtended
00046 {
00047 using Teuchos::ParameterList;
00048 using Anasazi::SimpleMV;
00049 /** */
00050 template <class MV, class OP> 
00051 class InitTraits
00052 {
00053 public:
00054   /** */
00055   static RCP<OP> opPtr(const LinearOperator<double>& A);
00056 
00057   /** */
00058   static RCP<MV> makeMV(int numVecs, const VectorSpace<double>& space);
00059 
00060   /** */
00061   static Vector<double> vec(const RCP<MV>& mv, int i);
00062 };
00063 
00064 
00065 /** */
00066 template <> class InitTraits<SimpleMV, LinearOperator<double> >
00067 {
00068 public:
00069   typedef SimpleMV            MV;
00070   typedef LinearOperator<double>            OP;
00071 
00072   /** */
00073   static RCP<OP> opPtr(const LinearOperator<double>& A)
00074     {
00075       if (A.ptr().get() != 0)
00076         return rcp(new LinearOperator<double>(A));
00077       else
00078       {
00079         RCP<LinearOperator<double> > rtn;
00080         return rtn;
00081       }
00082     }
00083 
00084   /** */
00085   static RCP<MV> makeMV(int blockSize, const VectorSpace<double>& space)
00086     {
00087       RCP<MV> mv = rcp(new MV(blockSize));
00088       for (int i=0; i<blockSize; i++) (*mv)[i] = space.createMember();
00089       return mv;
00090     }
00091 
00092   /** */
00093   static Vector<double> vec(const RCP<MV>& mv, int i)
00094     {
00095       return (*mv)[i];
00096     }
00097 
00098   
00099 };
00100 
00101 
00102 /** */
00103 template <> class InitTraits<MultiVectorBase<double>, LinearOpBase<double> >
00104 {
00105 public:
00106   typedef Thyra::MultiVectorBase<double>         MV;
00107   typedef Thyra::LinearOpBase<double>            OP;
00108 
00109   /** */
00110   static RCP<OP> opPtr(const LinearOperator<double>& A)
00111     {
00112       return A.ptr();
00113     }
00114 
00115   /** */
00116   static RCP<MV> makeMV(int blockSize, const VectorSpace<double>& space)
00117     {
00118       RCP<const Thyra::VectorSpaceBase<double> > mvSpace = space.ptr();
00119       return Thyra::createMembers( *mvSpace, blockSize );
00120     }
00121 
00122   /** */
00123   static Vector<double> vec(const RCP<MV>& mv, int i)
00124     {
00125       return mv->col(i);
00126     }
00127 };
00128 
00129 
00130 
00131 
00132 
00133 template <class Scalar>  
00134 inline void AnasaziEigensolver<Scalar>::solve(
00135   const LinearOperator<Scalar>& K,
00136   const LinearOperator<Scalar>& M,
00137   Array<Vector<Scalar> >& evecs,
00138   Array<std::complex<Scalar> >& ew) const 
00139 {
00140 //#define USE_THYRA_MV
00141 
00142 #ifdef USE_THYRA_MV
00143   typedef Thyra::MultiVectorBase<Scalar>         MV;
00144   typedef Thyra::LinearOpBase<Scalar>            OP;
00145 #else
00146   typedef SimpleMV            MV;
00147   typedef LinearOperator<Scalar>            OP;
00148 #endif
00149   typedef Anasazi::MultiVecTraits<Scalar,MV>     MVT;
00150   typedef Anasazi::OperatorTraits<Scalar,MV,OP>  OPT;
00151 
00152   TimeMonitor timer(solveTimer());
00153   VectorSpace<Scalar> KDomain = K.domain();
00154 
00155   RCP<OP> KPtr = InitTraits<MV, OP>::opPtr(K);
00156   RCP<OP> MPtr = InitTraits<MV, OP>::opPtr(M);
00157 
00158 
00159 
00160   
00161   // Eigensolver parameters
00162   std::string method = this->params().get<string>("Method");
00163   int numEigs = this->params().get<int>("Number of Eigenvalues");
00164   int blockSize = this->params().get<int>("Block Size");
00165   bool usePrec = this->params().get<bool>("Use Preconditioner");
00166   bool hermitian = this->params().get<bool>("Is Hermitian");
00167 
00168 
00169   
00170   /* Make a multivector with row space = domain of K, column 
00171    * space = multiVec Space*/
00172   RCP<MV> mv = InitTraits<MV, OP>::makeMV(blockSize, KDomain);
00173 
00174   /* Fill the multivector with random values */
00175   MVT::MvRandom( *mv );
00176 
00177   /* Create a preconditioner */
00178   ParameterList precParams = this->params().sublist("Preconditioner");
00179   PreconditionerFactory<double> precFactory 
00180     = new ParameterListPreconditionerFactory(precParams);
00181 
00182   LinearOperator<Scalar> P;
00183   if (usePrec) 
00184   {
00185     TimeMonitor pTimer(precondBuildTimer());
00186     P = precFactory.createPreconditioner(K).right();
00187   }
00188 
00189   /* Create eigenproblem */
00190   RCP<Anasazi::Eigenproblem<Scalar,MV,OP> > problem;
00191 
00192   if (MPtr.get() != 0)
00193   {
00194     problem =
00195       rcp( new Anasazi::BasicEigenproblem<Scalar,MV,OP>(KPtr, MPtr, mv) );
00196   }
00197   else
00198   {
00199     problem =
00200       rcp( new Anasazi::BasicEigenproblem<Scalar,MV,OP>(KPtr, mv) );
00201   }
00202 
00203   ParameterList eigParams = this->params();
00204   problem->setHermitian(hermitian);
00205   problem->setNEV(numEigs);
00206   if (usePrec) problem->setPrec(InitTraits<MV, OP>::opPtr(P));
00207 
00208   bool ret = problem->setProblem();
00209   TEST_FOR_EXCEPTION(!ret, std::runtime_error,
00210     "Eigenproblem not setup correctly");
00211   
00212 
00213   // Create the solver manager
00214   RCP<Anasazi::SolverManager<Scalar,MV,OP> > MySolverMan;
00215   if (method=="Block Davidson")
00216   {
00217     MySolverMan = rcp(new Anasazi::BlockDavidsonSolMgr<Scalar,MV,OP>(problem, eigParams));
00218   }
00219   else if (method=="Block Krylov Schur")
00220   {
00221     MySolverMan = rcp(new Anasazi::BlockKrylovSchurSolMgr<Scalar,MV,OP>(problem, eigParams));
00222   }
00223   else if (method=="Simple LOBPCG")
00224   {
00225     MySolverMan = rcp(new Anasazi::SimpleLOBPCGSolMgr<Scalar,MV,OP>(problem, eigParams));
00226   }
00227   else if (method=="LOBPCG")
00228   {
00229     MySolverMan = rcp(new Anasazi::LOBPCGSolMgr<Scalar,MV,OP>(problem, eigParams));
00230   }
00231   else
00232   {
00233     TEST_FOR_EXCEPTION(true, std::runtime_error,
00234       "solver method [" << method << "] not recognized");
00235   }
00236 
00237   // Solve the problem to the specified tolerances or length
00238   Anasazi::ReturnType returnCode = MySolverMan->solve();
00239   Out::os() << "return code = " << returnCode << endl;
00240   TEST_FOR_EXCEPTION(returnCode != Anasazi::Converged, 
00241     std::runtime_error, "Anasazi did not converge!");
00242   
00243   // Get the eigenvalues and eigenvectors from the eigenproblem
00244   Anasazi::Eigensolution<Scalar,MV> sol = problem->getSolution();
00245   RCP<MV> evecs_mv = sol.Evecs;
00246   int numev = sol.numVecs;
00247   
00248   /* Copy the columns of the eigenvector MV into an array of TSF vectors */
00249   ew.resize(numev);
00250   evecs.resize(numev);
00251 
00252   for (int i=0; i<numev; i++)
00253   {
00254     Vector<Scalar> tmp = InitTraits<MV, OP>::vec(evecs_mv, i);
00255 
00256     evecs[i] = KDomain.createMember();
00257     evecs[i].acceptCopyOf(tmp);
00258     /* record the associated eigenvalue. The matrix is Hermitian so
00259      * we know the eigenvalue is real. */
00260     //evals[i] = sol.Evals[i].realpart;
00261     // if matrix might not be hermitian
00262     ew[i].real() = sol.Evals[i].realpart;
00263     ew[i].imag() = sol.Evals[i].imagpart;
00264   }
00265 }
00266 
00267 
00268 }
00269 
00270 
00271 #endif

Site Contact