00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
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
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
00148
00149 RCP<MV> mv = InitTraits<MV, OP>::makeMV(blockSize, KDomain);
00150
00151
00152 MVT::MvRandom( *mv );
00153
00154
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
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
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
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
00221 Anasazi::Eigensolution<Scalar,MV> sol = problem->getSolution();
00222 RCP<MV> evecs_mv = sol.Evecs;
00223 int numev = sol.numVecs;
00224
00225
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
00236
00237
00238
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