PlayaAnasaziEigensolverImpl.hpp
Go to the documentation of this file.
00001 /* @HEADER@ */
00002 // ************************************************************************
00003 // 
00004 //                 Playa: Programmable Linear Algebra
00005 //                 Copyright 2012 Sandia Corporation
00006 // 
00007 // Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
00008 // the U.S. Government retains certain rights in this software.
00009 //
00010 // Redistribution and use in source and binary forms, with or without
00011 // modification, are permitted provided that the following conditions are
00012 // met:
00013 //
00014 // 1. Redistributions of source code must retain the above copyright
00015 // notice, this list of conditions and the following disclaimer.
00016 //
00017 // 2. Redistributions in binary form must reproduce the above copyright
00018 // notice, this list of conditions and the following disclaimer in the
00019 // documentation and/or other materials provided with the distribution.
00020 //
00021 // 3. Neither the name of the Corporation nor the names of the
00022 // contributors may be used to endorse or promote products derived from
00023 // this software without specific prior written permission.
00024 //
00025 // THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
00026 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00027 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
00028 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
00029 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
00030 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
00031 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
00032 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
00033 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
00034 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
00035 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00036 //
00037 // Questions? Contact Kevin Long (kevin.long@ttu.edu)
00038 // 
00039 
00040 /* @HEADER@ */
00041 
00042 #ifndef PLAYA_ANASAZIEIGENSOLVER_IMPL_HPP
00043 #define PLAYA_ANASAZIEIGENSOLVER_IMPL_HPP
00044 
00045 #include "PlayaDefs.hpp"
00046 #include "PlayaAnasaziEigensolverDecl.hpp" 
00047 #include "PlayaParameterListPreconditionerFactory.hpp" 
00048 #include "PlayaPreconditionerFactory.hpp" 
00049 #include "AnasaziBlockKrylovSchurSolMgr.hpp"
00050 #include "AnasaziBlockDavidsonSolMgr.hpp"
00051 #include "AnasaziSimpleLOBPCGSolMgr.hpp"
00052 #include "AnasaziLOBPCGSolMgr.hpp"
00053 #include "AnasaziBasicEigenproblem.hpp"
00054 #include "PlayaAnasaziAdapter.hpp"
00055 
00056 
00057 namespace Playa
00058 {
00059 using Teuchos::ParameterList;
00060 using Anasazi::SimpleMV;
00061 /** */
00062 template <class MV, class OP> 
00063 class InitTraits
00064 {
00065 public:
00066   /** */
00067   static RCP<OP> opPtr(const LinearOperator<double>& A);
00068 
00069   /** */
00070   static RCP<MV> makeMV(int numVecs, const VectorSpace<double>& space);
00071 
00072   /** */
00073   static Vector<double> vec(const RCP<MV>& mv, int i);
00074 };
00075 
00076 
00077 /** */
00078 template <> class InitTraits<SimpleMV, LinearOperator<double> >
00079 {
00080 public:
00081   typedef SimpleMV            MV;
00082   typedef LinearOperator<double>            OP;
00083 
00084   /** */
00085   static RCP<OP> opPtr(const LinearOperator<double>& A)
00086     {
00087       if (A.ptr().get() != 0)
00088         return rcp(new LinearOperator<double>(A));
00089       else
00090       {
00091         RCP<LinearOperator<double> > rtn;
00092         return rtn;
00093       }
00094     }
00095 
00096   /** */
00097   static RCP<MV> makeMV(int blockSize, const VectorSpace<double>& space)
00098     {
00099       RCP<MV> mv = rcp(new MV(blockSize));
00100       for (int i=0; i<blockSize; i++) (*mv)[i] = space.createMember();
00101       return mv;
00102     }
00103 
00104   /** */
00105   static Vector<double> vec(const RCP<MV>& mv, int i)
00106     {
00107       return (*mv)[i];
00108     }
00109 
00110   
00111 };
00112 
00113 
00114 
00115 
00116 template <class Scalar>  
00117 inline void AnasaziEigensolver<Scalar>::solve(
00118   const LinearOperator<Scalar>& K,
00119   const LinearOperator<Scalar>& M,
00120   Array<Vector<Scalar> >& evecs,
00121   Array<std::complex<Scalar> >& ew) const 
00122 {
00123   typedef SimpleMV            MV;
00124   typedef LinearOperator<Scalar>            OP;
00125 
00126   typedef Anasazi::MultiVecTraits<Scalar,MV>     MVT;
00127   typedef Anasazi::OperatorTraits<Scalar,MV,OP>  OPT;
00128 
00129   TimeMonitor timer(solveTimer());
00130   VectorSpace<Scalar> KDomain = K.domain();
00131 
00132   RCP<OP> KPtr = InitTraits<MV, OP>::opPtr(K);
00133   RCP<OP> MPtr = InitTraits<MV, OP>::opPtr(M);
00134 
00135 
00136 
00137   
00138   // Eigensolver parameters
00139   std::string method = this->params().template get<string>("Method");
00140   int numEigs = this->params().template get<int>("Number of Eigenvalues");
00141   int blockSize = this->params().template get<int>("Block Size");
00142   bool usePrec = this->params().template get<bool>("Use Preconditioner");
00143   bool hermitian = this->params().template get<bool>("Is Hermitian");
00144 
00145 
00146   
00147   /* Make a multivector with row space = domain of K, column 
00148    * space = multiVec Space*/
00149   RCP<MV> mv = InitTraits<MV, OP>::makeMV(blockSize, KDomain);
00150 
00151   /* Fill the multivector with random values */
00152   MVT::MvRandom( *mv );
00153 
00154   /* Create a preconditioner */
00155   ParameterList precParams = this->params().sublist("Preconditioner");
00156   PreconditionerFactory<double> precFactory 
00157     = new ParameterListPreconditionerFactory(precParams);
00158 
00159   LinearOperator<Scalar> P;
00160   if (usePrec) 
00161   {
00162     TimeMonitor pTimer(precondBuildTimer());
00163     P = precFactory.createPreconditioner(K).right();
00164   }
00165 
00166   /* Create eigenproblem */
00167   RCP<Anasazi::Eigenproblem<Scalar,MV,OP> > problem;
00168 
00169   if (MPtr.get() != 0)
00170   {
00171     problem =
00172       rcp( new Anasazi::BasicEigenproblem<Scalar,MV,OP>(KPtr, MPtr, mv) );
00173   }
00174   else
00175   {
00176     problem =
00177       rcp( new Anasazi::BasicEigenproblem<Scalar,MV,OP>(KPtr, mv) );
00178   }
00179 
00180   ParameterList eigParams = this->params();
00181   problem->setHermitian(hermitian);
00182   problem->setNEV(numEigs);
00183   if (usePrec) problem->setPrec(InitTraits<MV, OP>::opPtr(P));
00184 
00185   bool ret = problem->setProblem();
00186   TEUCHOS_TEST_FOR_EXCEPTION(!ret, std::runtime_error,
00187     "Eigenproblem not setup correctly");
00188   
00189 
00190   // Create the solver manager
00191   RCP<Anasazi::SolverManager<Scalar,MV,OP> > MySolverMan;
00192   if (method=="Block Davidson")
00193   {
00194     MySolverMan = rcp(new Anasazi::BlockDavidsonSolMgr<Scalar,MV,OP>(problem, eigParams));
00195   }
00196   else if (method=="Block Krylov Schur")
00197   {
00198     MySolverMan = rcp(new Anasazi::BlockKrylovSchurSolMgr<Scalar,MV,OP>(problem, eigParams));
00199   }
00200   else if (method=="Simple LOBPCG")
00201   {
00202     MySolverMan = rcp(new Anasazi::SimpleLOBPCGSolMgr<Scalar,MV,OP>(problem, eigParams));
00203   }
00204   else if (method=="LOBPCG")
00205   {
00206     MySolverMan = rcp(new Anasazi::LOBPCGSolMgr<Scalar,MV,OP>(problem, eigParams));
00207   }
00208   else
00209   {
00210     TEUCHOS_TEST_FOR_EXCEPTION(true, std::runtime_error,
00211       "solver method [" << method << "] not recognized");
00212   }
00213 
00214   // Solve the problem to the specified tolerances or length
00215   Anasazi::ReturnType returnCode = MySolverMan->solve();
00216   Out::os() << "return code = " << returnCode << endl;
00217   TEUCHOS_TEST_FOR_EXCEPTION(returnCode != Anasazi::Converged, 
00218     std::runtime_error, "Anasazi did not converge!");
00219   
00220   // Get the eigenvalues and eigenvectors from the eigenproblem
00221   Anasazi::Eigensolution<Scalar,MV> sol = problem->getSolution();
00222   RCP<MV> evecs_mv = sol.Evecs;
00223   int numev = sol.numVecs;
00224   
00225   /* Copy the columns of the eigenvector MV into an array of Playa vectors */
00226   ew.resize(numev);
00227   evecs.resize(numev);
00228 
00229   for (int i=0; i<numev; i++)
00230   {
00231     Vector<Scalar> tmp = InitTraits<MV, OP>::vec(evecs_mv, i);
00232 
00233     evecs[i] = KDomain.createMember();
00234     evecs[i].acceptCopyOf(tmp);
00235     /* record the associated eigenvalue. The matrix is Hermitian so
00236      * we know the eigenvalue is real. */
00237     //evals[i] = sol.Evals[i].realpart;
00238     // if matrix might not be hermitian
00239     ew[i].real(sol.Evals[i].realpart);
00240     ew[i].imag(sol.Evals[i].imagpart);
00241   }
00242 }
00243 
00244 
00245 }
00246 
00247 
00248 #endif

Site Contact