$extrastylesheet
slepc_eigen_solver.C
Go to the documentation of this file.
00001 // The libMesh Finite Element Library.
00002 // Copyright (C) 2002-2014 Benjamin S. Kirk, John W. Peterson, Roy H. Stogner
00003 
00004 // This library is free software; you can redistribute it and/or
00005 // modify it under the terms of the GNU Lesser General Public
00006 // License as published by the Free Software Foundation; either
00007 // version 2.1 of the License, or (at your option) any later version.
00008 
00009 // This library is distributed in the hope that it will be useful,
00010 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00011 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00012 // Lesser General Public License for more details.
00013 
00014 // You should have received a copy of the GNU Lesser General Public
00015 // License along with this library; if not, write to the Free Software
00016 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00017 
00018 
00019 
00020 #include "libmesh/libmesh_common.h"
00021 
00022 #if defined(LIBMESH_HAVE_SLEPC) && defined(LIBMESH_HAVE_PETSC)
00023 
00024 
00025 // C++ includes
00026 
00027 // Local Includes
00028 #include "libmesh/libmesh_logging.h"
00029 #include "libmesh/petsc_matrix.h"
00030 #include "libmesh/petsc_vector.h"
00031 #include "libmesh/slepc_eigen_solver.h"
00032 #include "libmesh/shell_matrix.h"
00033 #include "libmesh/string_to_enum.h"
00034 
00035 namespace libMesh
00036 {
00037 
00038 extern "C"
00039 {
00040   // Older versions of PETSc do not have the different int typedefs.
00041   // On 64-bit machines, PetscInt may actually be a long long int.
00042   // This change occurred in Petsc-2.2.1.
00043 #if PETSC_VERSION_LESS_THAN(2,2,1)
00044   typedef int PetscErrorCode;
00045   typedef int PetscInt;
00046 #endif
00047 }
00048 
00049 
00050 /*----------------------- functions ----------------------------------*/
00051 template <typename T>
00052 void SlepcEigenSolver<T>::clear ()
00053 {
00054   if (this->initialized())
00055     {
00056       this->_is_initialized = false;
00057 
00058       PetscErrorCode ierr=0;
00059 
00060       ierr = LibMeshEPSDestroy(&_eps);
00061       LIBMESH_CHKERRABORT(ierr);
00062 
00063       // SLEPc default eigenproblem solver
00064 #if SLEPC_VERSION_LESS_THAN(2,3,2)
00065       this->_eigen_solver_type = ARNOLDI;
00066 #else
00067       // Krylov-Schur showed up as of Slepc 2.3.2
00068       this->_eigen_solver_type = KRYLOVSCHUR;
00069 #endif
00070     }
00071 }
00072 
00073 
00074 
00075 template <typename T>
00076 void SlepcEigenSolver<T>::init ()
00077 {
00078 
00079   PetscErrorCode ierr=0;
00080 
00081   // Initialize the data structures if not done so already.
00082   if (!this->initialized())
00083     {
00084       this->_is_initialized = true;
00085 
00086       // Create the eigenproblem solver context
00087       ierr = EPSCreate (this->comm().get(), &_eps);
00088       LIBMESH_CHKERRABORT(ierr);
00089 
00090       // Set user-specified  solver
00091       set_slepc_solver_type();
00092     }
00093 }
00094 
00095 
00096 
00097 template <typename T>
00098 std::pair<unsigned int, unsigned int>
00099 SlepcEigenSolver<T>::solve_standard (SparseMatrix<T> &matrix_A_in,
00100                                      int nev,                  // number of requested eigenpairs
00101                                      int ncv,                  // number of basis vectors
00102                                      const double tol,         // solver tolerance
00103                                      const unsigned int m_its) // maximum number of iterations
00104 {
00105   //   START_LOG("solve_standard()", "SlepcEigenSolver");
00106 
00107   this->init ();
00108 
00109   // Make sure the SparseMatrix passed in is really a PetscMatrix
00110   PetscMatrix<T>* matrix_A   = cast_ptr<PetscMatrix<T>*>(&matrix_A_in);
00111 
00112   // Close the matrix and vectors in case this wasn't already done.
00113   matrix_A->close ();
00114 
00115   // just for debugging, remove this
00116   //   char mat_file[] = "matA.petsc";
00117   //   PetscViewer petsc_viewer;
00118   //   ierr = PetscViewerBinaryOpen(this->comm().get(), mat_file, PETSC_FILE_CREATE, &petsc_viewer);
00119   //          LIBMESH_CHKERRABORT(ierr);
00120   //   ierr = MatView(matrix_A->mat(),petsc_viewer);
00121   //          LIBMESH_CHKERRABORT(ierr);
00122 
00123   return _solve_standard_helper(matrix_A->mat(), nev, ncv, tol, m_its);
00124 }
00125 
00126 
00127 template <typename T>
00128 std::pair<unsigned int, unsigned int>
00129 SlepcEigenSolver<T>::solve_standard (ShellMatrix<T> &shell_matrix,
00130                                      int nev,                  // number of requested eigenpairs
00131                                      int ncv,                  // number of basis vectors
00132                                      const double tol,         // solver tolerance
00133                                      const unsigned int m_its) // maximum number of iterations
00134 {
00135   this->init ();
00136 
00137   PetscErrorCode ierr=0;
00138 
00139   // Prepare the matrix.
00140   Mat mat;
00141   ierr = MatCreateShell(this->comm().get(),
00142                         shell_matrix.m(), // Specify the number of local rows
00143                         shell_matrix.n(), // Specify the number of local columns
00144                         PETSC_DETERMINE,
00145                         PETSC_DETERMINE,
00146                         const_cast<void*>(static_cast<const void*>(&shell_matrix)),
00147                         &mat);
00148   LIBMESH_CHKERRABORT(ierr);
00149 
00150   /* Note that the const_cast above is only necessary because PETSc
00151      does not accept a const void*.  Inside the member function
00152      _petsc_shell_matrix() below, the pointer is casted back to a
00153      const ShellMatrix<T>*.  */
00154 
00155   ierr = MatShellSetOperation(mat,MATOP_MULT,reinterpret_cast<void(*)(void)>(_petsc_shell_matrix_mult));
00156   LIBMESH_CHKERRABORT(ierr);
00157   ierr = MatShellSetOperation(mat,MATOP_GET_DIAGONAL,reinterpret_cast<void(*)(void)>(_petsc_shell_matrix_get_diagonal));
00158   LIBMESH_CHKERRABORT(ierr);
00159 
00160 
00161   return _solve_standard_helper(mat, nev, ncv, tol, m_its);
00162 }
00163 
00164 template <typename T>
00165 std::pair<unsigned int, unsigned int>
00166 SlepcEigenSolver<T>::_solve_standard_helper
00167 (Mat mat,
00168  int nev,                  // number of requested eigenpairs
00169  int ncv,                  // number of basis vectors
00170  const double tol,         // solver tolerance
00171  const unsigned int m_its) // maximum number of iterations
00172 {
00173   START_LOG("solve_standard()", "SlepcEigenSolver");
00174 
00175   PetscErrorCode ierr=0;
00176 
00177   // converged eigen pairs and number of iterations
00178   PetscInt nconv=0;
00179   PetscInt its=0;
00180 
00181 #ifdef  DEBUG
00182   // The relative error.
00183   PetscReal error, re, im;
00184 
00185   // Pointer to vectors of the real parts, imaginary parts.
00186   PetscScalar kr, ki;
00187 #endif
00188 
00189   // Set operators.
00190   ierr = EPSSetOperators (_eps, mat, PETSC_NULL);
00191   LIBMESH_CHKERRABORT(ierr);
00192 
00193   //set the problem type and the position of the spectrum
00194   set_slepc_problem_type();
00195   set_slepc_position_of_spectrum();
00196 
00197   // Set eigenvalues to be computed.
00198 #if SLEPC_VERSION_LESS_THAN(3,0,0)
00199   ierr = EPSSetDimensions (_eps, nev, ncv);
00200 #else
00201   ierr = EPSSetDimensions (_eps, nev, ncv, PETSC_DECIDE);
00202 #endif
00203   LIBMESH_CHKERRABORT(ierr);
00204   // Set the tolerance and maximum iterations.
00205   ierr = EPSSetTolerances (_eps, tol, m_its);
00206   LIBMESH_CHKERRABORT(ierr);
00207 
00208   // Set runtime options, e.g.,
00209   //      -eps_type <type>, -eps_nev <nev>, -eps_ncv <ncv>
00210   // Similar to PETSc, these options will override those specified
00211   // above as long as EPSSetFromOptions() is called _after_ any
00212   // other customization routines.
00213   ierr = EPSSetFromOptions (_eps);
00214   LIBMESH_CHKERRABORT(ierr);
00215 
00216   // Solve the eigenproblem.
00217   ierr = EPSSolve (_eps);
00218   LIBMESH_CHKERRABORT(ierr);
00219 
00220   // Get the number of iterations.
00221   ierr = EPSGetIterationNumber (_eps, &its);
00222   LIBMESH_CHKERRABORT(ierr);
00223 
00224   // Get number of converged eigenpairs.
00225   ierr = EPSGetConverged(_eps,&nconv);
00226   LIBMESH_CHKERRABORT(ierr);
00227 
00228 
00229 #ifdef DEBUG
00230   // ierr = PetscPrintf(this->comm().get(),
00231   //         "\n Number of iterations: %d\n"
00232   //         " Number of converged eigenpairs: %d\n\n", its, nconv);
00233 
00234   // Display eigenvalues and relative errors.
00235   ierr = PetscPrintf(this->comm().get(),
00236                      "           k           ||Ax-kx||/|kx|\n"
00237                      "   ----------------- -----------------\n" );
00238   LIBMESH_CHKERRABORT(ierr);
00239 
00240   for(PetscInt i=0; i<nconv; i++ )
00241     {
00242       ierr = EPSGetEigenpair(_eps, i, &kr, &ki, PETSC_NULL, PETSC_NULL);
00243       LIBMESH_CHKERRABORT(ierr);
00244 
00245       ierr = EPSComputeRelativeError(_eps, i, &error);
00246       LIBMESH_CHKERRABORT(ierr);
00247 
00248 #ifdef LIBMESH_USE_COMPLEX_NUMBERS
00249       re = PetscRealPart(kr);
00250       im = PetscImaginaryPart(kr);
00251 #else
00252       re = kr;
00253       im = ki;
00254 #endif
00255 
00256       if (im != .0)
00257         {
00258           ierr = PetscPrintf(this->comm().get()," %9f%+9f i %12f\n", re, im, error);
00259           LIBMESH_CHKERRABORT(ierr);
00260         }
00261       else
00262         {
00263           ierr = PetscPrintf(this->comm().get(),"   %12f       %12f\n", re, error);
00264           LIBMESH_CHKERRABORT(ierr);
00265         }
00266     }
00267 
00268   ierr = PetscPrintf(this->comm().get(),"\n" );
00269   LIBMESH_CHKERRABORT(ierr);
00270 #endif // DEBUG
00271 
00272 
00273   STOP_LOG("solve_standard()", "SlepcEigenSolver");
00274 
00275   // return the number of converged eigenpairs
00276   // and the number of iterations
00277   return std::make_pair(nconv, its);
00278 
00279 }
00280 
00281 
00282 
00283 
00284 
00285 template <typename T>
00286 std::pair<unsigned int, unsigned int>
00287 SlepcEigenSolver<T>::solve_generalized (SparseMatrix<T> &matrix_A_in,
00288                                         SparseMatrix<T> &matrix_B_in,
00289                                         int nev,                  // number of requested eigenpairs
00290                                         int ncv,                  // number of basis vectors
00291                                         const double tol,         // solver tolerance
00292                                         const unsigned int m_its) // maximum number of iterations
00293 {
00294   this->init ();
00295 
00296   // Make sure the data passed in are really of Petsc types
00297   PetscMatrix<T>* matrix_A   = cast_ptr<PetscMatrix<T>*>(&matrix_A_in);
00298   PetscMatrix<T>* matrix_B   = cast_ptr<PetscMatrix<T>*>(&matrix_B_in);
00299 
00300   // Close the matrix and vectors in case this wasn't already done.
00301   matrix_A->close ();
00302   matrix_B->close ();
00303 
00304 
00305   return _solve_generalized_helper (matrix_A->mat(), matrix_B->mat(), nev, ncv, tol, m_its);
00306 }
00307 
00308 template <typename T>
00309 std::pair<unsigned int, unsigned int>
00310 SlepcEigenSolver<T>::solve_generalized (ShellMatrix<T> &shell_matrix_A,
00311                                         SparseMatrix<T> &matrix_B_in,
00312                                         int nev,                  // number of requested eigenpairs
00313                                         int ncv,                  // number of basis vectors
00314                                         const double tol,         // solver tolerance
00315                                         const unsigned int m_its) // maximum number of iterations
00316 {
00317   this->init ();
00318 
00319   PetscErrorCode ierr=0;
00320 
00321   // Prepare the matrix.
00322   Mat mat_A;
00323   ierr = MatCreateShell(this->comm().get(),
00324                         shell_matrix_A.m(), // Specify the number of local rows
00325                         shell_matrix_A.n(), // Specify the number of local columns
00326                         PETSC_DETERMINE,
00327                         PETSC_DETERMINE,
00328                         const_cast<void*>(static_cast<const void*>(&shell_matrix_A)),
00329                         &mat_A);
00330   LIBMESH_CHKERRABORT(ierr);
00331 
00332   PetscMatrix<T>* matrix_B   = cast_ptr<PetscMatrix<T>*>(&matrix_B_in);
00333 
00334   // Close the matrix and vectors in case this wasn't already done.
00335   matrix_B->close ();
00336 
00337   /* Note that the const_cast above is only necessary because PETSc
00338      does not accept a const void*.  Inside the member function
00339      _petsc_shell_matrix() below, the pointer is casted back to a
00340      const ShellMatrix<T>*.  */
00341 
00342   ierr = MatShellSetOperation(mat_A,MATOP_MULT,reinterpret_cast<void(*)(void)>(_petsc_shell_matrix_mult));
00343   LIBMESH_CHKERRABORT(ierr);
00344   ierr = MatShellSetOperation(mat_A,MATOP_GET_DIAGONAL,reinterpret_cast<void(*)(void)>(_petsc_shell_matrix_get_diagonal));
00345   LIBMESH_CHKERRABORT(ierr);
00346 
00347   return _solve_generalized_helper (mat_A, matrix_B->mat(), nev, ncv, tol, m_its);
00348 }
00349 
00350 template <typename T>
00351 std::pair<unsigned int, unsigned int>
00352 SlepcEigenSolver<T>::solve_generalized (SparseMatrix<T> &matrix_A_in,
00353                                         ShellMatrix<T> &shell_matrix_B,
00354                                         int nev,                  // number of requested eigenpairs
00355                                         int ncv,                  // number of basis vectors
00356                                         const double tol,         // solver tolerance
00357                                         const unsigned int m_its) // maximum number of iterations
00358 {
00359   this->init ();
00360 
00361   PetscErrorCode ierr=0;
00362 
00363   PetscMatrix<T>* matrix_A = cast_ptr<PetscMatrix<T>*>(&matrix_A_in);
00364 
00365   // Close the matrix and vectors in case this wasn't already done.
00366   matrix_A->close ();
00367 
00368   // Prepare the matrix.
00369   Mat mat_B;
00370   ierr = MatCreateShell(this->comm().get(),
00371                         shell_matrix_B.m(), // Specify the number of local rows
00372                         shell_matrix_B.n(), // Specify the number of local columns
00373                         PETSC_DETERMINE,
00374                         PETSC_DETERMINE,
00375                         const_cast<void*>(static_cast<const void*>(&shell_matrix_B)),
00376                         &mat_B);
00377   LIBMESH_CHKERRABORT(ierr);
00378 
00379   /* Note that the const_cast above is only necessary because PETSc
00380      does not accept a const void*.  Inside the member function
00381      _petsc_shell_matrix() below, the pointer is casted back to a
00382      const ShellMatrix<T>*.  */
00383 
00384   ierr = MatShellSetOperation(mat_B,MATOP_MULT,reinterpret_cast<void(*)(void)>(_petsc_shell_matrix_mult));
00385   LIBMESH_CHKERRABORT(ierr);
00386   ierr = MatShellSetOperation(mat_B,MATOP_GET_DIAGONAL,reinterpret_cast<void(*)(void)>(_petsc_shell_matrix_get_diagonal));
00387   LIBMESH_CHKERRABORT(ierr);
00388 
00389   return _solve_generalized_helper (matrix_A->mat(), mat_B, nev, ncv, tol, m_its);
00390 }
00391 
00392 template <typename T>
00393 std::pair<unsigned int, unsigned int>
00394 SlepcEigenSolver<T>::solve_generalized (ShellMatrix<T> &shell_matrix_A,
00395                                         ShellMatrix<T> &shell_matrix_B,
00396                                         int nev,                  // number of requested eigenpairs
00397                                         int ncv,                  // number of basis vectors
00398                                         const double tol,         // solver tolerance
00399                                         const unsigned int m_its) // maximum number of iterations
00400 {
00401   this->init ();
00402 
00403   PetscErrorCode ierr=0;
00404 
00405   // Prepare the matrix.
00406   Mat mat_A;
00407   ierr = MatCreateShell(this->comm().get(),
00408                         shell_matrix_A.m(), // Specify the number of local rows
00409                         shell_matrix_A.n(), // Specify the number of local columns
00410                         PETSC_DETERMINE,
00411                         PETSC_DETERMINE,
00412                         const_cast<void*>(static_cast<const void*>(&shell_matrix_A)),
00413                         &mat_A);
00414   LIBMESH_CHKERRABORT(ierr);
00415 
00416   Mat mat_B;
00417   ierr = MatCreateShell(this->comm().get(),
00418                         shell_matrix_B.m(), // Specify the number of local rows
00419                         shell_matrix_B.n(), // Specify the number of local columns
00420                         PETSC_DETERMINE,
00421                         PETSC_DETERMINE,
00422                         const_cast<void*>(static_cast<const void*>(&shell_matrix_B)),
00423                         &mat_B);
00424   LIBMESH_CHKERRABORT(ierr);
00425 
00426   /* Note that the const_cast above is only necessary because PETSc
00427      does not accept a const void*.  Inside the member function
00428      _petsc_shell_matrix() below, the pointer is casted back to a
00429      const ShellMatrix<T>*.  */
00430 
00431   ierr = MatShellSetOperation(mat_A,MATOP_MULT,reinterpret_cast<void(*)(void)>(_petsc_shell_matrix_mult));
00432   LIBMESH_CHKERRABORT(ierr);
00433   ierr = MatShellSetOperation(mat_A,MATOP_GET_DIAGONAL,reinterpret_cast<void(*)(void)>(_petsc_shell_matrix_get_diagonal));
00434   LIBMESH_CHKERRABORT(ierr);
00435 
00436   ierr = MatShellSetOperation(mat_B,MATOP_MULT,reinterpret_cast<void(*)(void)>(_petsc_shell_matrix_mult));
00437   LIBMESH_CHKERRABORT(ierr);
00438   ierr = MatShellSetOperation(mat_B,MATOP_GET_DIAGONAL,reinterpret_cast<void(*)(void)>(_petsc_shell_matrix_get_diagonal));
00439   LIBMESH_CHKERRABORT(ierr);
00440 
00441   return _solve_generalized_helper (mat_A, mat_B, nev, ncv, tol, m_its);
00442 }
00443 
00444 
00445 
00446 template <typename T>
00447 std::pair<unsigned int, unsigned int>
00448 SlepcEigenSolver<T>::_solve_generalized_helper (Mat mat_A,
00449                                                 Mat mat_B,
00450                                                 int nev,                  // number of requested eigenpairs
00451                                                 int ncv,                  // number of basis vectors
00452                                                 const double tol,         // solver tolerance
00453                                                 const unsigned int m_its) // maximum number of iterations
00454 {
00455   START_LOG("solve_generalized()", "SlepcEigenSolver");
00456 
00457   PetscErrorCode ierr=0;
00458 
00459   // converged eigen pairs and number of iterations
00460   PetscInt nconv=0;
00461   PetscInt its=0;
00462 
00463 #ifdef  DEBUG
00464   // The relative error.
00465   PetscReal error, re, im;
00466 
00467   // Pointer to vectors of the real parts, imaginary parts.
00468   PetscScalar kr, ki;
00469 #endif
00470 
00471   // Set operators.
00472   ierr = EPSSetOperators (_eps, mat_A, mat_B);
00473   LIBMESH_CHKERRABORT(ierr);
00474 
00475   //set the problem type and the position of the spectrum
00476   set_slepc_problem_type();
00477   set_slepc_position_of_spectrum();
00478 
00479   // Set eigenvalues to be computed.
00480 #if SLEPC_VERSION_LESS_THAN(3,0,0)
00481   ierr = EPSSetDimensions (_eps, nev, ncv);
00482 #else
00483   ierr = EPSSetDimensions (_eps, nev, ncv, PETSC_DECIDE);
00484 #endif
00485   LIBMESH_CHKERRABORT(ierr);
00486 
00487 
00488   // Set the tolerance and maximum iterations.
00489   ierr = EPSSetTolerances (_eps, tol, m_its);
00490   LIBMESH_CHKERRABORT(ierr);
00491 
00492   // Set runtime options, e.g.,
00493   //      -eps_type <type>, -eps_nev <nev>, -eps_ncv <ncv>
00494   // Similar to PETSc, these options will override those specified
00495   // above as long as EPSSetFromOptions() is called _after_ any
00496   // other customization routines.
00497   ierr = EPSSetFromOptions (_eps);
00498   LIBMESH_CHKERRABORT(ierr);
00499 
00500   // Solve the eigenproblem.
00501   ierr = EPSSolve (_eps);
00502   LIBMESH_CHKERRABORT(ierr);
00503 
00504   // Get the number of iterations.
00505   ierr = EPSGetIterationNumber (_eps, &its);
00506   LIBMESH_CHKERRABORT(ierr);
00507 
00508   // Get number of converged eigenpairs.
00509   ierr = EPSGetConverged(_eps,&nconv);
00510   LIBMESH_CHKERRABORT(ierr);
00511 
00512 
00513 #ifdef DEBUG
00514   // ierr = PetscPrintf(this->comm().get(),
00515   //         "\n Number of iterations: %d\n"
00516   //         " Number of converged eigenpairs: %d\n\n", its, nconv);
00517 
00518   // Display eigenvalues and relative errors.
00519   ierr = PetscPrintf(this->comm().get(),
00520                      "           k           ||Ax-kx||/|kx|\n"
00521                      "   ----------------- -----------------\n" );
00522   LIBMESH_CHKERRABORT(ierr);
00523 
00524   for(PetscInt i=0; i<nconv; i++ )
00525     {
00526       ierr = EPSGetEigenpair(_eps, i, &kr, &ki, PETSC_NULL, PETSC_NULL);
00527       LIBMESH_CHKERRABORT(ierr);
00528 
00529       ierr = EPSComputeRelativeError(_eps, i, &error);
00530       LIBMESH_CHKERRABORT(ierr);
00531 
00532 #ifdef LIBMESH_USE_COMPLEX_NUMBERS
00533       re = PetscRealPart(kr);
00534       im = PetscImaginaryPart(kr);
00535 #else
00536       re = kr;
00537       im = ki;
00538 #endif
00539 
00540       if (im != .0)
00541         {
00542           ierr = PetscPrintf(this->comm().get()," %9f%+9f i %12f\n", re, im, error);
00543           LIBMESH_CHKERRABORT(ierr);
00544         }
00545       else
00546         {
00547           ierr = PetscPrintf(this->comm().get(),"   %12f       %12f\n", re, error);
00548           LIBMESH_CHKERRABORT(ierr);
00549         }
00550     }
00551 
00552   ierr = PetscPrintf(this->comm().get(),"\n" );
00553   LIBMESH_CHKERRABORT(ierr);
00554 #endif // DEBUG
00555 
00556   STOP_LOG("solve_generalized()", "SlepcEigenSolver");
00557 
00558   // return the number of converged eigenpairs
00559   // and the number of iterations
00560   return std::make_pair(nconv, its);
00561 
00562 }
00563 
00564 
00565 
00566 
00567 
00568 
00569 
00570 
00571 
00572 
00573 
00574 template <typename T>
00575 void SlepcEigenSolver<T>::set_slepc_solver_type()
00576 {
00577   PetscErrorCode ierr = 0;
00578 
00579   switch (this->_eigen_solver_type)
00580     {
00581     case POWER:
00582       ierr = EPSSetType (_eps, (char*) EPSPOWER);    LIBMESH_CHKERRABORT(ierr); return;
00583     case SUBSPACE:
00584       ierr = EPSSetType (_eps, (char*) EPSSUBSPACE); LIBMESH_CHKERRABORT(ierr); return;
00585     case LAPACK:
00586       ierr = EPSSetType (_eps, (char*) EPSLAPACK);   LIBMESH_CHKERRABORT(ierr); return;
00587     case ARNOLDI:
00588       ierr = EPSSetType (_eps, (char*) EPSARNOLDI);  LIBMESH_CHKERRABORT(ierr); return;
00589     case LANCZOS:
00590       ierr = EPSSetType (_eps, (char*) EPSLANCZOS);  LIBMESH_CHKERRABORT(ierr); return;
00591 #if !SLEPC_VERSION_LESS_THAN(2,3,2)
00592       // EPSKRYLOVSCHUR added in 2.3.2
00593     case KRYLOVSCHUR:
00594       ierr = EPSSetType (_eps, (char*) EPSKRYLOVSCHUR);  LIBMESH_CHKERRABORT(ierr); return;
00595 #endif
00596       // case ARPACK:
00597       // ierr = EPSSetType (_eps, (char*) EPSARPACK);   LIBMESH_CHKERRABORT(ierr); return;
00598 
00599     default:
00600       libMesh::err << "ERROR:  Unsupported SLEPc Eigen Solver: "
00601                    << Utility::enum_to_string(this->_eigen_solver_type) << std::endl
00602                    << "Continuing with SLEPc defaults" << std::endl;
00603     }
00604 }
00605 
00606 
00607 
00608 
00609 template <typename T>
00610 void SlepcEigenSolver<T>:: set_slepc_problem_type()
00611 {
00612   PetscErrorCode ierr = 0;
00613 
00614   switch (this->_eigen_problem_type)
00615     {
00616     case NHEP:
00617       ierr = EPSSetProblemType (_eps, EPS_NHEP);  LIBMESH_CHKERRABORT(ierr); return;
00618     case GNHEP:
00619       ierr = EPSSetProblemType (_eps, EPS_GNHEP); LIBMESH_CHKERRABORT(ierr); return;
00620     case HEP:
00621       ierr = EPSSetProblemType (_eps, EPS_HEP);   LIBMESH_CHKERRABORT(ierr); return;
00622     case GHEP:
00623       ierr = EPSSetProblemType (_eps, EPS_GHEP);  LIBMESH_CHKERRABORT(ierr); return;
00624 #if !SLEPC_VERSION_LESS_THAN(3,3,0)
00625       // EPS_GHIEP added in 3.3.0
00626     case GHIEP:
00627       ierr = EPSSetProblemType (_eps, EPS_GHIEP);  LIBMESH_CHKERRABORT(ierr); return;
00628 #endif
00629 
00630     default:
00631       libMesh::err << "ERROR:  Unsupported SLEPc Eigen Problem: "
00632                    << this->_eigen_problem_type        << std::endl
00633                    << "Continuing with SLEPc defaults" << std::endl;
00634     }
00635 }
00636 
00637 
00638 
00639 template <typename T>
00640 void SlepcEigenSolver<T>:: set_slepc_position_of_spectrum()
00641 {
00642   PetscErrorCode ierr = 0;
00643 
00644   switch (this->_position_of_spectrum)
00645     {
00646     case LARGEST_MAGNITUDE:
00647       ierr = EPSSetWhichEigenpairs (_eps, EPS_LARGEST_MAGNITUDE);  LIBMESH_CHKERRABORT(ierr); return;
00648     case SMALLEST_MAGNITUDE:
00649       ierr = EPSSetWhichEigenpairs (_eps, EPS_SMALLEST_MAGNITUDE); LIBMESH_CHKERRABORT(ierr); return;
00650     case LARGEST_REAL:
00651       ierr = EPSSetWhichEigenpairs (_eps, EPS_LARGEST_REAL);       LIBMESH_CHKERRABORT(ierr); return;
00652     case SMALLEST_REAL:
00653       ierr = EPSSetWhichEigenpairs (_eps, EPS_SMALLEST_REAL);      LIBMESH_CHKERRABORT(ierr); return;
00654     case LARGEST_IMAGINARY:
00655       ierr = EPSSetWhichEigenpairs (_eps, EPS_LARGEST_IMAGINARY);  LIBMESH_CHKERRABORT(ierr); return;
00656     case SMALLEST_IMAGINARY:
00657       ierr = EPSSetWhichEigenpairs (_eps, EPS_SMALLEST_IMAGINARY); LIBMESH_CHKERRABORT(ierr); return;
00658 
00659 
00660     default:
00661       libmesh_error_msg("ERROR:  Unsupported SLEPc position of spectrum: " << this->_position_of_spectrum);
00662     }
00663 }
00664 
00665 
00666 
00667 
00668 
00669 
00670 template <typename T>
00671 std::pair<Real, Real> SlepcEigenSolver<T>::get_eigenpair(unsigned int i,
00672                                                          NumericVector<T> &solution_in)
00673 {
00674   PetscErrorCode ierr=0;
00675 
00676   PetscReal re, im;
00677 
00678   // Make sure the NumericVector passed in is really a PetscVector
00679   PetscVector<T>* solution = cast_ptr<PetscVector<T>*>(&solution_in);
00680 
00681   // real and imaginary part of the ith eigenvalue.
00682   PetscScalar kr, ki;
00683 
00684   solution->close();
00685 
00686   ierr = EPSGetEigenpair(_eps, i, &kr, &ki, solution->vec(), PETSC_NULL);
00687   LIBMESH_CHKERRABORT(ierr);
00688 
00689 #ifdef LIBMESH_USE_COMPLEX_NUMBERS
00690   re = PetscRealPart(kr);
00691   im = PetscImaginaryPart(kr);
00692 #else
00693   re = kr;
00694   im = ki;
00695 #endif
00696 
00697   return std::make_pair(re, im);
00698 }
00699 
00700 
00701 template <typename T>
00702 std::pair<Real, Real> SlepcEigenSolver<T>::get_eigenvalue(unsigned int i)
00703 {
00704   PetscErrorCode ierr=0;
00705 
00706   PetscReal re, im;
00707 
00708   // real and imaginary part of the ith eigenvalue.
00709   PetscScalar kr, ki;
00710 
00711   ierr = EPSGetEigenvalue(_eps, i, &kr, &ki);
00712   LIBMESH_CHKERRABORT(ierr);
00713 
00714 #ifdef LIBMESH_USE_COMPLEX_NUMBERS
00715   re = PetscRealPart(kr);
00716   im = PetscImaginaryPart(kr);
00717 #else
00718   re = kr;
00719   im = ki;
00720 #endif
00721 
00722   return std::make_pair(re, im);
00723 }
00724 
00725 
00726 template <typename T>
00727 Real SlepcEigenSolver<T>::get_relative_error(unsigned int i)
00728 {
00729   PetscErrorCode ierr=0;
00730   PetscReal error;
00731 
00732   ierr = EPSComputeRelativeError(_eps, i, &error);
00733   LIBMESH_CHKERRABORT(ierr);
00734 
00735   return error;
00736 }
00737 
00738 
00739 template <typename T>
00740 void SlepcEigenSolver<T>::attach_deflation_space(NumericVector<T>& deflation_vector_in)
00741 {
00742   this->init();
00743 
00744   PetscErrorCode ierr = 0;
00745   Vec deflation_vector = (cast_ptr<PetscVector<T>*>(&deflation_vector_in))->vec();
00746   Vec* deflation_space = &deflation_vector;
00747 #if SLEPC_VERSION_LESS_THAN(3,1,0)
00748   ierr = EPSAttachDeflationSpace(_eps, 1, deflation_space, PETSC_FALSE);
00749 #else
00750   ierr = EPSSetDeflationSpace(_eps, 1, deflation_space);
00751 #endif
00752   LIBMESH_CHKERRABORT(ierr);
00753 }
00754 
00755 template <typename T>
00756 PetscErrorCode SlepcEigenSolver<T>::_petsc_shell_matrix_mult(Mat mat, Vec arg, Vec dest)
00757 {
00758   /* Get the matrix context.  */
00759   PetscErrorCode ierr=0;
00760   void* ctx;
00761   ierr = MatShellGetContext(mat,&ctx);
00762 
00763   Parallel::communicator comm;
00764   PetscObjectGetComm((PetscObject)mat,&comm);
00765   CHKERRABORT(comm,ierr);
00766 
00767   /* Get user shell matrix object.  */
00768   const ShellMatrix<T>& shell_matrix = *static_cast<const ShellMatrix<T>*>(ctx);
00769 
00770   /* Make \p NumericVector instances around the vectors.  */
00771   PetscVector<T> arg_global(arg,   shell_matrix.comm());
00772   PetscVector<T> dest_global(dest, shell_matrix.comm());
00773 
00774   /* Call the user function.  */
00775   shell_matrix.vector_mult(dest_global,arg_global);
00776 
00777   return ierr;
00778 }
00779 
00780 template <typename T>
00781 PetscErrorCode SlepcEigenSolver<T>::_petsc_shell_matrix_get_diagonal(Mat mat, Vec dest)
00782 {
00783   /* Get the matrix context.  */
00784   PetscErrorCode ierr=0;
00785   void* ctx;
00786   ierr = MatShellGetContext(mat,&ctx);
00787 
00788   Parallel::communicator comm;
00789   PetscObjectGetComm((PetscObject)mat,&comm);
00790   CHKERRABORT(comm,ierr);
00791 
00792   /* Get user shell matrix object.  */
00793   const ShellMatrix<T>& shell_matrix = *static_cast<const ShellMatrix<T>*>(ctx);
00794 
00795   /* Make \p NumericVector instances around the vector.  */
00796   PetscVector<T> dest_global(dest, shell_matrix.comm());
00797 
00798   /* Call the user function.  */
00799   shell_matrix.get_diagonal(dest_global);
00800 
00801   return ierr;
00802 }
00803 
00804 //------------------------------------------------------------------
00805 // Explicit instantiations
00806 template class SlepcEigenSolver<Number>;
00807 
00808 } // namespace libMesh
00809 
00810 
00811 
00812 #endif // #ifdef LIBMESH_HAVE_SLEPC