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