00001
00002
00003
00004
00005
00006
00007 #include "QCAD_GenEigensolver.hpp"
00008
00009
00010
00011
00012
00013
00014 #include "Teuchos_XMLParameterListHelpers.hpp"
00015 #include "Teuchos_TestForException.hpp"
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 #include "Albany_EigendataInfoStruct.hpp"
00027 #include "Epetra_Import.h"
00028
00029 #include "AnasaziConfigDefs.hpp"
00030 #include "AnasaziBasicEigenproblem.hpp"
00031 #include "AnasaziLOBPCGSolMgr.hpp"
00032 #include "AnasaziBasicOutputManager.hpp"
00033 #include "AnasaziEpetraAdapter.hpp"
00034 #include "Epetra_CrsMatrix.h"
00035
00036
00037
00038 QCAD::GenEigensolver::
00039 GenEigensolver(const Teuchos::RCP<Teuchos::ParameterList>& eigensolveParams,
00040 const Teuchos::RCP<EpetraExt::ModelEvaluator>& model,
00041 const Teuchos::RCP<Albany::StateManager>& observer,
00042 Teuchos::RCP<const Epetra_Comm> comm)
00043 {
00044 using std::string;
00045
00046
00047 Teuchos::RCP<Teuchos::ParameterList> myParams = Teuchos::rcp( new Teuchos::ParameterList(*eigensolveParams) );
00048
00049 this->model = model;
00050 this->observer = observer;
00051
00052 EpetraExt::ModelEvaluator::InArgs model_inArgs = model->createInArgs();
00053 EpetraExt::ModelEvaluator::OutArgs model_outArgs = model->createOutArgs();
00054 model_num_p = model_inArgs.Np();
00055 model_num_g = model_outArgs.Ng();
00056
00057 which = "SM";
00058 bHermitian = myParams->get<bool>("Symmetric",true);
00059 nev = myParams->get<int>("Num Eigenvalues",10);
00060 blockSize = myParams->get<int>("Block Size",5);
00061 maxIters = myParams->get<int>("Maximum Iterations",500);
00062 conv_tol = myParams->get<double>("Convergece Tolerance",1.0e-8);
00063
00064 myComm = comm;
00065 }
00066
00067 QCAD::GenEigensolver::~GenEigensolver()
00068 {
00069 }
00070
00071
00072 Teuchos::RCP<const Epetra_Map> QCAD::GenEigensolver::get_x_map() const
00073 {
00074 Teuchos::RCP<const Epetra_Map> neverused;
00075 return neverused;
00076 }
00077
00078 Teuchos::RCP<const Epetra_Map> QCAD::GenEigensolver::get_f_map() const
00079 {
00080 Teuchos::RCP<const Epetra_Map> neverused;
00081 return neverused;
00082 }
00083
00084 Teuchos::RCP<const Epetra_Map> QCAD::GenEigensolver::get_p_map(int l) const
00085 {
00086 return model->get_p_map(l);
00087 }
00088
00089 Teuchos::RCP<const Epetra_Map> QCAD::GenEigensolver::get_g_map(int j) const
00090 {
00091 if (j == model_num_g) return model->get_x_map();
00092 else return model->get_g_map(j);
00093 }
00094
00095 Teuchos::RCP<const Epetra_Vector> QCAD::GenEigensolver::get_x_init() const
00096 {
00097 Teuchos::RCP<const Epetra_Vector> neverused;
00098 return neverused;
00099 }
00100
00101 Teuchos::RCP<const Epetra_Vector> QCAD::GenEigensolver::get_x_dot_init() const
00102 {
00103 Teuchos::RCP<const Epetra_Vector> neverused;
00104 return neverused;
00105 }
00106
00107
00108 Teuchos::RCP<const Epetra_Vector> QCAD::GenEigensolver::get_p_init(int l) const
00109 {
00110 return model->get_p_init(l);
00111 }
00112
00113
00114 EpetraExt::ModelEvaluator::InArgs QCAD::GenEigensolver::createInArgs() const
00115 {
00116 InArgsSetup inArgs;
00117 inArgs.setModelEvalDescription("QCAD Generalized Eigensolver Model Evaluator");
00118 inArgs.set_Np(model_num_p);
00119 return inArgs;
00120 }
00121
00122 EpetraExt::ModelEvaluator::OutArgs QCAD::GenEigensolver::createOutArgs() const
00123 {
00124
00125 OutArgsSetup outArgs;
00126 outArgs.setModelEvalDescription("QCAD Generalized Eigensolver Model Evaluator");
00127
00128
00129 outArgs.set_Np_Ng(model_num_p, model_num_g+1);
00130
00131
00132 EpetraExt::ModelEvaluator::OutArgs model_outArgs = model->createOutArgs();
00133 for (int i=0; i<model_num_g; i++) {
00134 for (int j=0; j<model_num_p; j++)
00135 outArgs.setSupports(OUT_ARG_DgDp, i, j, model_outArgs.supports(OUT_ARG_DgDp, i, j));
00136 }
00137
00138 return outArgs;
00139 }
00140
00141
00142 void
00143 QCAD::GenEigensolver::evalModel(const InArgs& inArgs,
00144 const OutArgs& outArgs ) const
00145 {
00146
00147 typedef Epetra_MultiVector MV;
00148 typedef Epetra_Operator OP;
00149 typedef Anasazi::MultiVecTraits<double, Epetra_MultiVector> MVT;
00150
00151
00152 InArgs model_inArgs = model->createInArgs();
00153 OutArgs model_outArgs = model->createOutArgs();
00154
00155
00156 model_inArgs.set_t(0.0);
00157
00158 Teuchos::RCP<const Epetra_Vector> x = model->get_x_init();
00159 Teuchos::RCP<const Epetra_Vector> x_dot = model->get_x_dot_init();
00160 model_inArgs.set_x(x);
00161 model_inArgs.set_x_dot(x_dot);
00162
00163 model_inArgs.set_alpha(0.0);
00164 model_inArgs.set_beta(1.0);
00165
00166 for(int i=0; i<model_num_p; i++)
00167 model_inArgs.set_p(i, inArgs.get_p(i));
00168
00169
00170 Teuchos::RCP<Epetra_CrsMatrix> K =
00171 Teuchos::rcp_dynamic_cast<Epetra_CrsMatrix>(model->create_W(), true);
00172 model_outArgs.set_W(K);
00173
00174 model->evalModel(model_inArgs, model_outArgs);
00175
00176
00177 model_inArgs.set_alpha(1.0);
00178 model_inArgs.set_beta(0.0);
00179 Teuchos::RCP<Epetra_CrsMatrix> M =
00180 Teuchos::rcp_dynamic_cast<Epetra_CrsMatrix>(model->create_W(), true);
00181 model_outArgs.set_W(M);
00182
00183 model->evalModel(model_inArgs, model_outArgs);
00184
00185 Teuchos::RCP<Epetra_MultiVector> ivec = Teuchos::rcp( new Epetra_MultiVector(K->OperatorDomainMap(), blockSize) );
00186 ivec->Random();
00187
00188
00189 Teuchos::RCP<Anasazi::BasicEigenproblem<double, MV, OP> > eigenProblem =
00190 Teuchos::rcp( new Anasazi::BasicEigenproblem<double, MV, OP>(K, M, ivec) );
00191
00192
00193 eigenProblem->setHermitian(bHermitian);
00194
00195
00196 eigenProblem->setNEV( nev );
00197
00198
00199 bool bSuccess = eigenProblem->setProblem();
00200 TEUCHOS_TEST_FOR_EXCEPTION(!bSuccess, Teuchos::Exceptions::InvalidParameter,
00201 "Anasazi::BasicEigenproblem::setProblem() returned an error.\n" << std::endl);
00202
00203
00204
00205 Teuchos::ParameterList eigenPL;
00206 eigenPL.set( "Which", which );
00207 eigenPL.set( "Block Size", blockSize );
00208 eigenPL.set( "Maximum Iterations", maxIters );
00209 eigenPL.set( "Convergence Tolerance", conv_tol );
00210 eigenPL.set( "Full Ortho", true );
00211 eigenPL.set( "Use Locking", true );
00212 eigenPL.set( "Verbosity", Anasazi::IterationDetails );
00213
00214
00215 Anasazi::LOBPCGSolMgr<double, MV, OP> eigenSolverMan(eigenProblem, eigenPL);
00216
00217
00218 Anasazi::ReturnType returnCode = eigenSolverMan.solve();
00219
00220
00221 Anasazi::Eigensolution<double,MV> sol = eigenProblem->getSolution();
00222 std::vector<Anasazi::Value<double> > evals = sol.Evals;
00223 Teuchos::RCP<MV> evecs = sol.Evecs;
00224
00225 std::vector<double> evals_real(sol.numVecs);
00226 for(int i=0; i<sol.numVecs; i++) evals_real[i] = evals[i].realpart;
00227
00228
00229 std::vector<double> normR(sol.numVecs);
00230 if (sol.numVecs > 0) {
00231 Teuchos::SerialDenseMatrix<int,double> T(sol.numVecs, sol.numVecs);
00232 Epetra_MultiVector Kvec( K->OperatorDomainMap(), evecs->NumVectors() );
00233 Epetra_MultiVector Mvec( M->OperatorDomainMap(), evecs->NumVectors() );
00234 T.putScalar(0.0);
00235 for (int i=0; i<sol.numVecs; i++) {
00236 T(i,i) = evals_real[i];
00237 }
00238 K->Apply( *evecs, Kvec );
00239 M->Apply( *evecs, Mvec );
00240 MVT::MvTimesMatAddMv( -1.0, Mvec, T, 1.0, Kvec );
00241 MVT::MvNorm( Kvec, normR );
00242 }
00243
00244
00245 std::ostringstream os;
00246 os.setf(std::ios_base::right, std::ios_base::adjustfield);
00247 os<<"Solver manager returned " << (returnCode == Anasazi::Converged ? "converged." : "unconverged.") << std::endl;
00248 os<<std::endl;
00249 os<<"------------------------------------------------------"<<std::endl;
00250 os<<std::setw(16)<<"Eigenvalue"
00251 <<std::setw(18)<<"Direct Residual"
00252 <<std::endl;
00253 os<<"------------------------------------------------------"<<std::endl;
00254 for (int i=0; i<sol.numVecs; i++) {
00255 os<<std::setw(16)<<evals_real[i]
00256 <<std::setw(18)<<normR[i]/evals_real[i]
00257 <<std::endl;
00258 }
00259 os<<"------------------------------------------------------"<<std::endl;
00260
00261 std::cout << Anasazi::Anasazi_Version() << std::endl << std::endl;
00262 std::cout << os.str();
00263
00264
00265
00266
00267
00268 Teuchos::RCP<Albany::EigendataStruct> eigenData = Teuchos::rcp( new Albany::EigendataStruct );
00269 eigenData->eigenvalueIm = Teuchos::null;
00270 eigenData->eigenvectorIm = Teuchos::null;
00271
00272 Teuchos::RCP<Albany::AbstractDiscretization> disc =
00273 observer->getDiscretization();
00274
00275 eigenData->eigenvalueRe = Teuchos::rcp( new std::vector<double>(evals_real) );
00276 for(int i=0; i<sol.numVecs; i++) (*(eigenData->eigenvalueRe))[i] *= -1;
00277
00278
00279 if (sol.numVecs > 0) {
00280
00281 eigenData->eigenvectorRe =
00282 Teuchos::rcp(new Epetra_MultiVector(*(disc->getOverlapMap()), sol.numVecs));
00283
00284
00285 Teuchos::RCP<Epetra_Import> importer =
00286 Teuchos::rcp(new Epetra_Import(*(disc->getOverlapMap()), *(disc->getMap())));
00287
00288
00289 for(int i=0; i<sol.numVecs; i++)
00290 (*(eigenData->eigenvectorRe))(i)->Import( *((*evecs)(i)), *importer, Insert );
00291 }
00292
00293 observer->setEigenData(eigenData);
00294
00295 }
00296
00297
00298
00299
00300
00301
00302
00303
00304
00305
00306
00307
00308
00309
00310
00311
00312
00313
00314
00315
00316
00317
00318
00319
00320
00321
00322
00323
00324