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 #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
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
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
00171
00172 RCP<MV> mv = InitTraits<MV, OP>::makeMV(blockSize, KDomain);
00173
00174
00175 MVT::MvRandom( *mv );
00176
00177
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
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
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
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
00244 Anasazi::Eigensolution<Scalar,MV> sol = problem->getSolution();
00245 RCP<MV> evecs_mv = sol.Evecs;
00246 int numev = sol.numVecs;
00247
00248
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
00259
00260
00261
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