22 #if defined(LIBMESH_HAVE_SLEPC) && defined(LIBMESH_HAVE_PETSC) 67 PetscErrorCode
ierr=0;
69 ierr = LibMeshEPSDestroy(&_eps);
83 PetscErrorCode
ierr=0;
91 ierr = EPSCreate (this->comm().
get(), &_eps);
95 set_slepc_solver_type();
101 template <
typename T>
102 std::pair<unsigned int, unsigned int>
107 const unsigned int m_its)
109 LOG_SCOPE(
"solve_standard()",
"SlepcEigenSolver");
117 libmesh_error_msg(
"Error: input matrix to solve_standard() must be a PetscMatrix.");
120 if (this->_close_matrix_before_solve)
123 return _solve_standard_helper(matrix_A->
mat(), nev, ncv, tol, m_its);
127 template <
typename T>
128 std::pair<unsigned int, unsigned int>
133 const unsigned int m_its)
137 PetscErrorCode
ierr=0;
144 ierr = MatCreateShell(this->comm().
get(),
149 const_cast<void *
>(
static_cast<const void *
>(&shell_matrix)),
151 LIBMESH_CHKERR(
ierr);
153 ierr = MatShellSetOperation(mat,MATOP_MULT,
reinterpret_cast<void(*)(
void)
>(_petsc_shell_matrix_mult));
154 LIBMESH_CHKERR(
ierr);
155 ierr = MatShellSetOperation(mat,MATOP_GET_DIAGONAL,
reinterpret_cast<void(*)(
void)
>(_petsc_shell_matrix_get_diagonal));
156 LIBMESH_CHKERR(
ierr);
158 return _solve_standard_helper(mat, nev, ncv, tol, m_its);
161 template <
typename T>
162 std::pair<unsigned int, unsigned int>
167 const unsigned int m_its)
169 LOG_SCOPE(
"solve_standard()",
"SlepcEigenSolver");
171 PetscErrorCode
ierr=0;
179 PetscReal error, re, im;
186 ierr = EPSSetOperators (_eps, mat, PETSC_NULL);
187 LIBMESH_CHKERR(
ierr);
190 set_slepc_problem_type();
191 set_slepc_position_of_spectrum();
194 #if SLEPC_VERSION_LESS_THAN(3,0,0) 195 ierr = EPSSetDimensions (_eps, nev, ncv);
197 ierr = EPSSetDimensions (_eps, nev, ncv, PETSC_DECIDE);
199 LIBMESH_CHKERR(
ierr);
201 ierr = EPSSetTolerances (_eps, tol, m_its);
202 LIBMESH_CHKERR(
ierr);
209 ierr = EPSSetFromOptions (_eps);
210 LIBMESH_CHKERR(
ierr);
214 if (this->_solver_configuration)
216 this->_solver_configuration->configure_solver();
220 ierr = EPSSolve (_eps);
221 LIBMESH_CHKERR(
ierr);
224 ierr = EPSGetIterationNumber (_eps, &its);
225 LIBMESH_CHKERR(
ierr);
228 ierr = EPSGetConverged(_eps,&nconv);
229 LIBMESH_CHKERR(
ierr);
238 ierr = PetscPrintf(this->comm().
get(),
239 " k ||Ax-kx||/|kx|\n" 240 " ----------------- -----------------\n" );
241 LIBMESH_CHKERR(
ierr);
243 for (PetscInt i=0; i<nconv; i++ )
245 ierr = EPSGetEigenpair(_eps, i, &kr, &ki, PETSC_NULL, PETSC_NULL);
246 LIBMESH_CHKERR(
ierr);
248 #if SLEPC_VERSION_LESS_THAN(3,6,0) 249 ierr = EPSComputeRelativeError(_eps, i, &error);
251 ierr = EPSComputeError(_eps, i, EPS_ERROR_RELATIVE, &error);
253 LIBMESH_CHKERR(
ierr);
255 #ifdef LIBMESH_USE_COMPLEX_NUMBERS 256 re = PetscRealPart(kr);
257 im = PetscImaginaryPart(kr);
265 ierr = PetscPrintf(this->comm().
get(),
" %9f%+9f i %12f\n", re, im, error);
266 LIBMESH_CHKERR(
ierr);
270 ierr = PetscPrintf(this->comm().
get(),
" %12f %12f\n", re, error);
271 LIBMESH_CHKERR(
ierr);
275 ierr = PetscPrintf(this->comm().
get(),
"\n" );
276 LIBMESH_CHKERR(
ierr);
281 return std::make_pair(nconv, its);
288 template <
typename T>
289 std::pair<unsigned int, unsigned int>
295 const unsigned int m_its)
303 if (!matrix_A || !matrix_B)
304 libmesh_error_msg(
"Error: inputs to solve_generalized() must be of type PetscMatrix.");
307 if (this->_close_matrix_before_solve)
313 return _solve_generalized_helper (matrix_A->
mat(), matrix_B->
mat(), nev, ncv, tol, m_its);
316 template <
typename T>
317 std::pair<unsigned int, unsigned int>
323 const unsigned int m_its)
327 PetscErrorCode
ierr=0;
334 ierr = MatCreateShell(this->comm().
get(),
339 const_cast<void *
>(
static_cast<const void *
>(&shell_matrix_A)),
341 LIBMESH_CHKERR(
ierr);
346 libmesh_error_msg(
"Error: inputs to solve_generalized() must be of type PetscMatrix.");
349 if (this->_close_matrix_before_solve)
352 ierr = MatShellSetOperation(mat_A,MATOP_MULT,
reinterpret_cast<void(*)(
void)
>(_petsc_shell_matrix_mult));
353 LIBMESH_CHKERR(
ierr);
354 ierr = MatShellSetOperation(mat_A,MATOP_GET_DIAGONAL,
reinterpret_cast<void(*)(
void)
>(_petsc_shell_matrix_get_diagonal));
355 LIBMESH_CHKERR(
ierr);
357 return _solve_generalized_helper (mat_A, matrix_B->
mat(), nev, ncv, tol, m_its);
360 template <
typename T>
361 std::pair<unsigned int, unsigned int>
367 const unsigned int m_its)
371 PetscErrorCode
ierr=0;
376 libmesh_error_msg(
"Error: inputs to solve_generalized() must be of type PetscMatrix.");
379 if (this->_close_matrix_before_solve)
387 ierr = MatCreateShell(this->comm().
get(),
392 const_cast<void *
>(
static_cast<const void *
>(&shell_matrix_B)),
394 LIBMESH_CHKERR(
ierr);
397 ierr = MatShellSetOperation(mat_B,MATOP_MULT,
reinterpret_cast<void(*)(
void)
>(_petsc_shell_matrix_mult));
398 LIBMESH_CHKERR(
ierr);
399 ierr = MatShellSetOperation(mat_B,MATOP_GET_DIAGONAL,
reinterpret_cast<void(*)(
void)
>(_petsc_shell_matrix_get_diagonal));
400 LIBMESH_CHKERR(
ierr);
402 return _solve_generalized_helper (matrix_A->
mat(), mat_B, nev, ncv, tol, m_its);
405 template <
typename T>
406 std::pair<unsigned int, unsigned int>
412 const unsigned int m_its)
416 PetscErrorCode
ierr=0;
423 ierr = MatCreateShell(this->comm().
get(),
428 const_cast<void *
>(
static_cast<const void *
>(&shell_matrix_A)),
430 LIBMESH_CHKERR(
ierr);
433 ierr = MatCreateShell(this->comm().
get(),
438 const_cast<void *
>(
static_cast<const void *
>(&shell_matrix_B)),
440 LIBMESH_CHKERR(
ierr);
442 ierr = MatShellSetOperation(mat_A,MATOP_MULT,
reinterpret_cast<void(*)(
void)
>(_petsc_shell_matrix_mult));
443 LIBMESH_CHKERR(
ierr);
444 ierr = MatShellSetOperation(mat_A,MATOP_GET_DIAGONAL,
reinterpret_cast<void(*)(
void)
>(_petsc_shell_matrix_get_diagonal));
445 LIBMESH_CHKERR(
ierr);
447 ierr = MatShellSetOperation(mat_B,MATOP_MULT,
reinterpret_cast<void(*)(
void)
>(_petsc_shell_matrix_mult));
448 LIBMESH_CHKERR(
ierr);
449 ierr = MatShellSetOperation(mat_B,MATOP_GET_DIAGONAL,
reinterpret_cast<void(*)(
void)
>(_petsc_shell_matrix_get_diagonal));
450 LIBMESH_CHKERR(
ierr);
452 return _solve_generalized_helper (mat_A, mat_B, nev, ncv, tol, m_its);
457 template <
typename T>
458 std::pair<unsigned int, unsigned int>
464 const unsigned int m_its)
466 LOG_SCOPE(
"solve_generalized()",
"SlepcEigenSolver");
468 PetscErrorCode
ierr=0;
476 PetscReal error, re, im;
483 ierr = EPSSetOperators (_eps, mat_A, mat_B);
484 LIBMESH_CHKERR(
ierr);
487 set_slepc_problem_type();
488 set_slepc_position_of_spectrum();
491 #if SLEPC_VERSION_LESS_THAN(3,0,0) 492 ierr = EPSSetDimensions (_eps, nev, ncv);
494 ierr = EPSSetDimensions (_eps, nev, ncv, PETSC_DECIDE);
496 LIBMESH_CHKERR(
ierr);
500 ierr = EPSSetTolerances (_eps, tol, m_its);
501 LIBMESH_CHKERR(
ierr);
508 ierr = EPSSetFromOptions (_eps);
509 LIBMESH_CHKERR(
ierr);
513 if (this->_solver_configuration)
515 this->_solver_configuration->configure_solver();
519 ierr = EPSSolve (_eps);
520 LIBMESH_CHKERR(
ierr);
523 ierr = EPSGetIterationNumber (_eps, &its);
524 LIBMESH_CHKERR(
ierr);
527 ierr = EPSGetConverged(_eps,&nconv);
528 LIBMESH_CHKERR(
ierr);
537 ierr = PetscPrintf(this->comm().
get(),
538 " k ||Ax-kx||/|kx|\n" 539 " ----------------- -----------------\n" );
540 LIBMESH_CHKERR(
ierr);
542 for (PetscInt i=0; i<nconv; i++ )
544 ierr = EPSGetEigenpair(_eps, i, &kr, &ki, PETSC_NULL, PETSC_NULL);
545 LIBMESH_CHKERR(
ierr);
547 #if SLEPC_VERSION_LESS_THAN(3,6,0) 548 ierr = EPSComputeRelativeError(_eps, i, &error);
550 ierr = EPSComputeError(_eps, i, EPS_ERROR_RELATIVE, &error);
552 LIBMESH_CHKERR(
ierr);
554 #ifdef LIBMESH_USE_COMPLEX_NUMBERS 555 re = PetscRealPart(kr);
556 im = PetscImaginaryPart(kr);
564 ierr = PetscPrintf(this->comm().
get(),
" %9f%+9f i %12f\n", re, im, error);
565 LIBMESH_CHKERR(
ierr);
569 ierr = PetscPrintf(this->comm().
get(),
" %12f %12f\n", re, error);
570 LIBMESH_CHKERR(
ierr);
574 ierr = PetscPrintf(this->comm().
get(),
"\n" );
575 LIBMESH_CHKERR(
ierr);
580 return std::make_pair(nconv, its);
593 template <
typename T>
596 PetscErrorCode
ierr = 0;
598 switch (this->_eigen_solver_type)
601 ierr = EPSSetType (_eps, EPSPOWER); LIBMESH_CHKERR(
ierr);
return;
603 ierr = EPSSetType (_eps, EPSSUBSPACE); LIBMESH_CHKERR(
ierr);
return;
605 ierr = EPSSetType (_eps, EPSLAPACK); LIBMESH_CHKERR(
ierr);
return;
607 ierr = EPSSetType (_eps, EPSARNOLDI); LIBMESH_CHKERR(
ierr);
return;
609 ierr = EPSSetType (_eps, EPSLANCZOS); LIBMESH_CHKERR(
ierr);
return;
611 ierr = EPSSetType (_eps, EPSKRYLOVSCHUR); LIBMESH_CHKERR(
ierr);
return;
616 libMesh::err <<
"ERROR: Unsupported SLEPc Eigen Solver: " 618 <<
"Continuing with SLEPc defaults" << std::endl;
625 template <
typename T>
628 PetscErrorCode
ierr = 0;
630 switch (this->_eigen_problem_type)
633 ierr = EPSSetProblemType (_eps, EPS_NHEP); LIBMESH_CHKERR(
ierr);
return;
635 ierr = EPSSetProblemType (_eps, EPS_GNHEP); LIBMESH_CHKERR(
ierr);
return;
637 ierr = EPSSetProblemType (_eps, EPS_HEP); LIBMESH_CHKERR(
ierr);
return;
639 ierr = EPSSetProblemType (_eps, EPS_GHEP); LIBMESH_CHKERR(
ierr);
return;
640 #if !SLEPC_VERSION_LESS_THAN(3,3,0) 643 ierr = EPSSetProblemType (_eps, EPS_GHIEP); LIBMESH_CHKERR(
ierr);
return;
647 libMesh::err <<
"ERROR: Unsupported SLEPc Eigen Problem: " 648 << this->_eigen_problem_type << std::endl
649 <<
"Continuing with SLEPc defaults" << std::endl;
655 template <
typename T>
658 PetscErrorCode
ierr = 0;
660 switch (this->_position_of_spectrum)
664 ierr = EPSSetWhichEigenpairs (_eps, EPS_LARGEST_MAGNITUDE);
665 LIBMESH_CHKERR(
ierr);
670 ierr = EPSSetWhichEigenpairs (_eps, EPS_SMALLEST_MAGNITUDE);
671 LIBMESH_CHKERR(
ierr);
676 ierr = EPSSetWhichEigenpairs (_eps, EPS_LARGEST_REAL);
677 LIBMESH_CHKERR(
ierr);
682 ierr = EPSSetWhichEigenpairs (_eps, EPS_SMALLEST_REAL);
683 LIBMESH_CHKERR(
ierr);
688 ierr = EPSSetWhichEigenpairs (_eps, EPS_LARGEST_IMAGINARY);
689 LIBMESH_CHKERR(
ierr);
694 ierr = EPSSetWhichEigenpairs (_eps, EPS_SMALLEST_IMAGINARY);
695 LIBMESH_CHKERR(
ierr);
700 #if !SLEPC_VERSION_LESS_THAN(3,1,0) 703 ierr = EPSSetTarget(_eps, this->_target_val);
704 LIBMESH_CHKERR(
ierr);
705 ierr = EPSSetWhichEigenpairs (_eps, EPS_TARGET_MAGNITUDE);
706 LIBMESH_CHKERR(
ierr);
711 ierr = EPSSetTarget(_eps, this->_target_val);
712 LIBMESH_CHKERR(
ierr);
713 ierr = EPSSetWhichEigenpairs (_eps, EPS_TARGET_REAL);
714 LIBMESH_CHKERR(
ierr);
719 ierr = EPSSetTarget(_eps, this->_target_val);
720 LIBMESH_CHKERR(
ierr);
721 ierr = EPSSetWhichEigenpairs (_eps, EPS_TARGET_IMAGINARY);
722 LIBMESH_CHKERR(
ierr);
728 libmesh_error_msg(
"ERROR: Unsupported SLEPc position of spectrum: " << this->_position_of_spectrum);
737 template <
typename T>
741 PetscErrorCode
ierr=0;
749 libmesh_error_msg(
"Error getting eigenvector: input vector must be a PetscVector.");
756 ierr = EPSGetEigenpair(_eps, i, &kr, &ki, solution->
vec(), PETSC_NULL);
757 LIBMESH_CHKERR(
ierr);
759 #ifdef LIBMESH_USE_COMPLEX_NUMBERS 760 re = PetscRealPart(kr);
761 im = PetscImaginaryPart(kr);
767 return std::make_pair(re, im);
771 template <
typename T>
774 PetscErrorCode
ierr=0;
781 ierr = EPSGetEigenvalue(_eps, i, &kr, &ki);
782 LIBMESH_CHKERR(
ierr);
784 #ifdef LIBMESH_USE_COMPLEX_NUMBERS 785 re = PetscRealPart(kr);
786 im = PetscImaginaryPart(kr);
792 return std::make_pair(re, im);
796 template <
typename T>
799 PetscErrorCode
ierr=0;
802 #if SLEPC_VERSION_LESS_THAN(3,6,0) 803 ierr = EPSComputeRelativeError(_eps, i, &error);
805 ierr = EPSComputeError(_eps, i, EPS_ERROR_RELATIVE, &error);
807 LIBMESH_CHKERR(
ierr);
813 template <
typename T>
818 PetscErrorCode
ierr = 0;
824 if (!deflation_vector_petsc_vec)
825 libmesh_error_msg(
"Error attaching deflation space: input vector must be a PetscVector.");
828 Vec deflation_vector = deflation_vector_petsc_vec->
vec();
830 #if SLEPC_VERSION_LESS_THAN(3,1,0) 831 ierr = EPSAttachDeflationSpace(_eps, 1, &deflation_vector, PETSC_FALSE);
833 ierr = EPSSetDeflationSpace(_eps, 1, &deflation_vector);
835 LIBMESH_CHKERR(
ierr);
838 template <
typename T>
841 #if SLEPC_VERSION_LESS_THAN(3,1,0) 842 libmesh_error_msg(
"SLEPc 3.1 is required to call EigenSolver::set_initial_space()");
846 PetscErrorCode
ierr = 0;
852 if (!initial_space_petsc_vec)
853 libmesh_error_msg(
"Error attaching initial space: input vector must be a PetscVector.");
856 Vec initial_vector = initial_space_petsc_vec->
vec();
858 ierr = EPSSetInitialSpace(_eps, 1, &initial_vector);
859 LIBMESH_CHKERR(
ierr);
863 template <
typename T>
867 PetscErrorCode
ierr=0;
869 ierr = MatShellGetContext(mat,&ctx);
872 PetscObjectGetComm((PetscObject)mat,&comm);
873 CHKERRABORT(comm,
ierr);
888 template <
typename T>
892 PetscErrorCode
ierr=0;
894 ierr = MatShellGetContext(mat,&ctx);
897 PetscObjectGetComm((PetscObject)mat,&comm);
898 CHKERRABORT(comm,
ierr);
920 #endif // #ifdef LIBMESH_HAVE_SLEPC std::pair< unsigned int, unsigned int > _solve_generalized_helper(Mat mat_A, Mat mat_B, int nev, int ncv, const double tol, const unsigned int m_its)
NumericVector interface to PETSc Vec.
Real get_relative_error(unsigned int i)
EigenSolver implementation based on SLEPc.
virtual std::pair< Real, Real > get_eigenvalue(dof_id_type i) override
Provides a uniform interface to vector storage schemes for different linear algebra libraries...
const Parallel::Communicator & comm() const
static PetscErrorCode _petsc_shell_matrix_get_diagonal(Mat mat, Vec dest)
void set_slepc_solver_type()
virtual numeric_index_type m() const =0
virtual void set_initial_space(NumericVector< T > &initial_space_in) override
void init(triangulateio &t)
virtual void clear() override
void set_slepc_problem_type()
OStreamProxy err(std::cerr)
virtual numeric_index_type n() const =0
std::string enum_to_string(const T e)
virtual void get_diagonal(NumericVector< T > &dest) const =0
virtual std::pair< unsigned int, unsigned int > solve_standard(SparseMatrix< T > &matrix_A, int nev, int ncv, const double tol, const unsigned int m_its) override
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
static PetscErrorCode _petsc_shell_matrix_mult(Mat mat, Vec arg, Vec dest)
SparseMatrix interface to PETSc Mat.
std::pair< unsigned int, unsigned int > _solve_standard_helper(Mat mat, int nev, int ncv, const double tol, const unsigned int m_its)
SlepcEigenSolver(const Parallel::Communicator &comm_in)
EigenSolverType _eigen_solver_type
void set_slepc_position_of_spectrum()
virtual void init() override
EigenProblemType _eigen_problem_type
virtual void vector_mult(NumericVector< T > &dest, const NumericVector< T > &arg) const =0
virtual void close() override
virtual std::pair< unsigned int, unsigned int > solve_generalized(SparseMatrix< T > &matrix_A, SparseMatrix< T > &matrix_B, int nev, int ncv, const double tol, const unsigned int m_its) override
virtual void attach_deflation_space(NumericVector< T > &deflation_vector) override
virtual void close() override
virtual std::pair< Real, Real > get_eigenpair(dof_id_type i, NumericVector< T > &solution_in) override
Base class which defines the interface for solving eigenproblems.