• Main Page
  • Related Pages
  • Namespaces
  • Classes
  • Files
  • File List
  • File Members

QCAD_GenEigensolver.cpp

Go to the documentation of this file.
00001 //*****************************************************************//
00002 //    Albany 2.0:  Copyright 2012 Sandia Corporation               //
00003 //    This Software is released under the BSD license detailed     //
00004 //    in the file "license.txt" in the top-level Albany directory  //
00005 //*****************************************************************//
00006 
00007 #include "QCAD_GenEigensolver.hpp"
00008 
00009 //#include "Stokhos.hpp"
00010 //#include "Stokhos_Epetra.hpp"
00011 //#include "Sacado_PCE_OrthogPoly.hpp"
00012 
00013 
00014 #include "Teuchos_XMLParameterListHelpers.hpp"
00015 #include "Teuchos_TestForException.hpp"
00016 
00017 //needed?
00018 //#include "Teuchos_RCP.hpp"
00019 //#include "Teuchos_VerboseObject.hpp"
00020 //#include "Teuchos_FancyOStream.hpp"
00021 
00022 //#include "Albany_ModelFactory.hpp"
00023 //#include "Albany_Utils.hpp"
00024 //#include "Albany_SolverFactory.hpp"
00025 //#include "Albany_StateInfoStruct.hpp"
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   // make a copy of the appParams, since we modify them below (e.g. discretization list)
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();   // Number of *vectors* of parameters
00055   model_num_g = model_outArgs.Ng();  // Number of *vectors* of responses
00056 
00057   which = "SM"; //always get smallest eigenvalues
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(); //last response vector is solution (same map as x)
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   //Based on Piro_Epetra_NOXSolver.cpp implementation
00125   OutArgsSetup outArgs;
00126   outArgs.setModelEvalDescription("QCAD Generalized Eigensolver Model Evaluator");
00127 
00128   // Ng is 1 bigger then model's Ng so that the solution vector can be an outarg
00129   outArgs.set_Np_Ng(model_num_p, model_num_g+1);
00130 
00131   //Derivative info 
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   // type definitions
00147   typedef Epetra_MultiVector MV;
00148   typedef Epetra_Operator OP;
00149   typedef Anasazi::MultiVecTraits<double, Epetra_MultiVector> MVT;
00150   
00151   // Get the stiffness and mass matrices
00152   InArgs model_inArgs = model->createInArgs();
00153   OutArgs model_outArgs = model->createOutArgs();
00154 
00155   //input args
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   //output args
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); //compute K matrix
00175 
00176   // reset alpha and beta to compute the mass matrix
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); //compute M matrix
00184 
00185   Teuchos::RCP<Epetra_MultiVector> ivec = Teuchos::rcp( new Epetra_MultiVector(K->OperatorDomainMap(), blockSize) );
00186   ivec->Random();
00187 
00188   // Create the eigenproblem.
00189   Teuchos::RCP<Anasazi::BasicEigenproblem<double, MV, OP> > eigenProblem =
00190     Teuchos::rcp( new Anasazi::BasicEigenproblem<double, MV, OP>(K, M, ivec) );
00191 
00192   // Inform the eigenproblem that the operator A is symmetric
00193   eigenProblem->setHermitian(bHermitian);
00194 
00195   // Set the number of eigenvalues requested
00196   eigenProblem->setNEV( nev );
00197 
00198   // Inform the eigenproblem that you are finishing passing it information
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   // Create parameter list to pass into the solver manager
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   // Create the solver manager
00215   Anasazi::LOBPCGSolMgr<double, MV, OP> eigenSolverMan(eigenProblem, eigenPL);
00216 
00217   // Solve the problem
00218   Anasazi::ReturnType returnCode = eigenSolverMan.solve();
00219 
00220   // Get the eigenvalues and eigenvectors from the eigenproblem
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   // Compute residuals.
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   // Print the results
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   // Package the results in an eigendata structure and "observe" them 
00267   //   (put them into the user-supplied StateManager object)  (see Albany_SaveEigenData.cpp)
00268   Teuchos::RCP<Albany::EigendataStruct> eigenData = Teuchos::rcp( new Albany::EigendataStruct );
00269   eigenData->eigenvalueIm = Teuchos::null;  // eigenvalues are real
00270   eigenData->eigenvectorIm = Teuchos::null; // eigenvectors are real
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       //make eigenvals --> neg_eigenvals to mimic historic LOCA eigensolver (TODO: remove this and switch convention)
00278 
00279   if (sol.numVecs > 0) {
00280     // Store *overlapped* eigenvectors in EigendataStruct
00281     eigenData->eigenvectorRe = 
00282       Teuchos::rcp(new Epetra_MultiVector(*(disc->getOverlapMap()), sol.numVecs));
00283 
00284     // Importer for overlapped data
00285     Teuchos::RCP<Epetra_Import> importer =
00286       Teuchos::rcp(new Epetra_Import(*(disc->getOverlapMap()), *(disc->getMap())));
00287 
00288     // Overlapped eigenstate vectors
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 /*Teuchos::RCP<const Teuchos::ParameterList>
00298 QCAD::GenEigensolver::getValidProblemParameters() const
00299 {
00300   Teuchos::RCP<Teuchos::ParameterList> validPL = Teuchos::createParameterList("ValidPoissonSchrodingerProblemParams");
00301 
00302   validPL->set<std::string>("Name", "", "String to designate Problem Class");
00303   validPL->set<int>("Phalanx Graph Visualization Detail", 0,
00304                     "Flag to select output of Phalanx Graph and level of detail");
00305 
00306   validPL->set<double>("Length Unit In Meters",1e-6,"Length unit in meters");
00307   validPL->set<double>("Energy Unit In Electron Volts",1.0,"Energy (voltage) unit in electron volts");
00308   validPL->set<double>("Temperature",300,"Temperature in Kelvin");
00309   validPL->set<std::string>("MaterialDB Filename","materials.xml","Filename of material database xml file");
00310   validPL->set<int>("Number of Eigenvalues",0,"The number of eigenvalue-eigenvector pairs");
00311   validPL->set<bool>("Verbose Output",false,"Enable detailed output mode");
00312 
00313   validPL->set<bool>("Include exchange-correlation potential",false,"Include exchange-correlation potential in poisson source term");
00314   validPL->set<bool>("Only solve schrodinger in quantum blocks",true,"Limit schrodinger solution to elements blocks labeled as quantum in the materials DB");
00315 
00316   validPL->sublist("Poisson Problem", false, "");
00317   validPL->sublist("Schrodinger Problem", false, "");
00318 
00319   // Candidates for deprecation. Pertain to the solution rather than the problem definition.
00320   validPL->set<std::string>("Solution Method", "Steady", "Flag for Steady, Transient, or Continuation");
00321   
00322   return validPL;
00323 }
00324 */

Generated on Wed Mar 26 2014 18:36:43 for Albany: a Trilinos-based PDE code by  doxygen 1.7.1