deal.II version GIT relicensing-6834-g5b78e6bcdf 2026-10-01 11:20:01+00:00
\(\newcommand{\dealvcentcolon}{\mathrel{\mathop{:}}}\) \(\newcommand{\dealcoloneq}{\dealvcentcolon\mathrel{\mkern-1.2mu}=}\) \(\newcommand{\jump}[1]{\left[\!\left[ #1 \right]\!\right]}\) \(\newcommand{\average}[1]{\left\{\!\left\{ #1 \right\}\!\right\}}\)
Loading...
Searching...
No Matches
slepc_solver.h
Go to the documentation of this file.
1// -----------------------------------------------------------------------------
2//
3// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception OR LGPL-2.1-or-later
4// Copyright (C) 2009 - 2026 by the deal.II authors
5//
6// This file is part of the deal.II library.
7//
8// Detailed license information governing the source code and contributions
9// can be found in LICENSE.md and CONTRIBUTING.md at the top level directory.
10//
11// -----------------------------------------------------------------------------
12
13
14#ifndef dealii_slepc_solver_h
15# define dealii_slepc_solver_h
16
17# include <deal.II/base/config.h>
18
19# ifdef DEAL_II_WITH_SLEPC
20
24
25# include <petscconf.h>
26# include <petscksp.h>
27
28# include <slepceps.h>
29
30# include <memory>
31
32# endif // DEAL_II_WITH_SLEPC
33
35
36# ifdef DEAL_II_WITH_SLEPC
132{
147 {
148 public:
154
158 virtual ~SolverBase();
159
178 template <typename OutputVector>
179 void
181 std::vector<PetscScalar> &eigenvalues,
182 std::vector<OutputVector> &eigenvectors,
183 const unsigned int n_eigenpairs = 1);
184
190 template <typename OutputVector>
191 void
194 std::vector<PetscScalar> &eigenvalues,
195 std::vector<OutputVector> &eigenvectors,
196 const unsigned int n_eigenpairs = 1);
197
203 template <typename OutputVector>
204 void
207 std::vector<double> &real_eigenvalues,
208 std::vector<double> &imag_eigenvalues,
209 std::vector<OutputVector> &real_eigenvectors,
210 std::vector<OutputVector> &imag_eigenvectors,
211 const unsigned int n_eigenpairs = 1);
212
219 template <typename Vector>
220 void
221 set_initial_space(const std::vector<Vector> &initial_space);
222
226 void
228
233 void
234 set_target_eigenvalue(const PetscScalar &this_target);
235
242 void
243 set_which_eigenpairs(EPSWhich set_which);
244
253 void
254 set_problem_type(EPSProblemType set_problem);
255
261 void
263
268
273 int,
274 << " An error with error number " << arg1
275 << " occurred while calling a SLEPc function");
276
281 int,
282 int,
283 << " The number of converged eigenvectors is " << arg1
284 << " but " << arg2 << " were requested. ");
285
290 control() const;
291
292 protected:
298
303
310 void
311 solve(const unsigned int n_eigenpairs, unsigned int *n_converged);
312
318 void
319 get_eigenpair(const unsigned int index,
320 PetscScalar &eigenvalues,
322
328 void
329 get_eigenpair(const unsigned int index,
330 double &real_eigenvalues,
331 double &imag_eigenvalues,
332 PETScWrappers::VectorBase &real_eigenvectors,
333 PETScWrappers::VectorBase &imag_eigenvectors);
334
339 void
341
346 void
349
350 protected:
354 EPS eps;
355
356 private:
360 EPSConvergedReason reason;
361
362
369 static int
371 PetscScalar real_eigenvalue,
372 PetscScalar imag_eigenvalue,
373 PetscReal residual_norm,
374 PetscReal *estimated_error,
375 void *solver_control);
376 };
377
378
379
393 {
394 public:
400 {};
401
407 explicit SolverKrylovSchur(
408 SolverControl &cn,
409 const MPI_Comm mpi_communicator = PETSC_COMM_SELF,
411
412 protected:
417 };
418
419
420
434 {
435 public:
441 {
446 explicit AdditionalData(const bool delayed_reorthogonalization = false);
447
452 };
453
459 explicit SolverArnoldi(SolverControl &cn,
460 const MPI_Comm mpi_communicator = PETSC_COMM_SELF,
462
463 protected:
468 };
469
470
471
485 {
486 public:
492 {
496 EPSLanczosReorthogType reorthog;
497
502 explicit AdditionalData(
503 const EPSLanczosReorthogType r = EPS_LANCZOS_REORTHOG_FULL);
504 };
505
511 explicit SolverLanczos(SolverControl &cn,
512 const MPI_Comm mpi_communicator = PETSC_COMM_SELF,
514
515 protected:
520 };
521
522
523
536 class SolverPower : public SolverBase
537 {
538 public:
544 {};
545
551 explicit SolverPower(SolverControl &cn,
552 const MPI_Comm mpi_communicator = PETSC_COMM_SELF,
554
555 protected:
560 };
561
562
563
577 {
578 public:
584 {
589
593 explicit AdditionalData(bool double_expansion = false);
594 };
595
602 SolverControl &cn,
603 const MPI_Comm mpi_communicator = PETSC_COMM_SELF,
605
606 protected:
611 };
612
613
614
628 {
629 public:
635 {};
636
642 explicit SolverJacobiDavidson(
643 SolverControl &cn,
644 const MPI_Comm mpi_communicator = PETSC_COMM_SELF,
646
647 protected:
652 };
653
654
655
669 {
670 public:
676 {};
677
683 explicit SolverLAPACK(SolverControl &cn,
684 const MPI_Comm mpi_communicator = PETSC_COMM_SELF,
686
687 protected:
692 };
693
694
695
696 // --------------------------- inline and template functions -----------
701 // todo: The logic of these functions can be simplified without breaking
702 // backward compatibility...
703
704 template <typename OutputVector>
705 void
707 std::vector<PetscScalar> &eigenvalues,
708 std::vector<OutputVector> &eigenvectors,
709 const unsigned int n_eigenpairs)
710 {
711 // Panic if the number of eigenpairs wanted is out of bounds.
712 AssertThrow((n_eigenpairs > 0) && (n_eigenpairs <= A.m()),
714
715 // Set the matrices of the problem
716 set_matrices(A);
717
718 // and solve
719 unsigned int n_converged = 0;
720 solve(n_eigenpairs, &n_converged);
721
722 if (n_converged > n_eigenpairs)
723 n_converged = n_eigenpairs;
724 AssertThrow(n_converged == n_eigenpairs,
726 n_eigenpairs));
727
729 eigenvectors.resize(n_converged, eigenvectors.front());
730 eigenvalues.resize(n_converged);
731
732 for (unsigned int index = 0; index < n_converged; ++index)
733 get_eigenpair(index, eigenvalues[index], eigenvectors[index]);
734 }
735
736 template <typename OutputVector>
737 void
740 std::vector<PetscScalar> &eigenvalues,
741 std::vector<OutputVector> &eigenvectors,
742 const unsigned int n_eigenpairs)
743 {
744 // Guard against incompatible matrix sizes:
745 AssertThrow(A.m() == B.m(), ExcDimensionMismatch(A.m(), B.m()));
746 AssertThrow(A.n() == B.n(), ExcDimensionMismatch(A.n(), B.n()));
747
748 // Panic if the number of eigenpairs wanted is out of bounds.
749 AssertThrow((n_eigenpairs > 0) && (n_eigenpairs <= A.m()),
751
752 // Set the matrices of the problem
753 set_matrices(A, B);
754
755 // and solve
756 unsigned int n_converged = 0;
757 solve(n_eigenpairs, &n_converged);
758
759 if (n_converged >= n_eigenpairs)
760 n_converged = n_eigenpairs;
761
762 AssertThrow(n_converged == n_eigenpairs,
764 n_eigenpairs));
766
767 eigenvectors.resize(n_converged, eigenvectors.front());
768 eigenvalues.resize(n_converged);
769
770 for (unsigned int index = 0; index < n_converged; ++index)
771 get_eigenpair(index, eigenvalues[index], eigenvectors[index]);
772 }
773
774 template <typename OutputVector>
775 void
778 std::vector<double> &real_eigenvalues,
779 std::vector<double> &imag_eigenvalues,
780 std::vector<OutputVector> &real_eigenvectors,
781 std::vector<OutputVector> &imag_eigenvectors,
782 const unsigned int n_eigenpairs)
783 {
784 // Guard against incompatible matrix sizes:
785 AssertThrow(A.m() == B.m(), ExcDimensionMismatch(A.m(), B.m()));
786 AssertThrow(A.n() == B.n(), ExcDimensionMismatch(A.n(), B.n()));
787
788 // and incompatible eigenvalue/eigenvector sizes
789 AssertThrow(real_eigenvalues.size() == imag_eigenvalues.size(),
790 ExcDimensionMismatch(real_eigenvalues.size(),
791 imag_eigenvalues.size()));
792 AssertThrow(real_eigenvectors.size() == imag_eigenvectors.size(),
793 ExcDimensionMismatch(real_eigenvectors.size(),
794 imag_eigenvectors.size()));
795
796 // Panic if the number of eigenpairs wanted is out of bounds.
797 AssertThrow((n_eigenpairs > 0) && (n_eigenpairs <= A.m()),
799
800 // Set the matrices of the problem
801 set_matrices(A, B);
802
803 // and solve
804 unsigned int n_converged = 0;
805 solve(n_eigenpairs, &n_converged);
806
807 if (n_converged >= n_eigenpairs)
808 n_converged = n_eigenpairs;
809
810 AssertThrow(n_converged == n_eigenpairs,
812 n_eigenpairs));
813 AssertThrow((real_eigenvectors.size() != 0) &&
814 (imag_eigenvectors.size() != 0),
816
817 real_eigenvectors.resize(n_converged, real_eigenvectors.front());
818 imag_eigenvectors.resize(n_converged, imag_eigenvectors.front());
819 real_eigenvalues.resize(n_converged);
820 imag_eigenvalues.resize(n_converged);
821
822 for (unsigned int index = 0; index < n_converged; ++index)
823 get_eigenpair(index,
824 real_eigenvalues[index],
825 imag_eigenvalues[index],
826 real_eigenvectors[index],
827 imag_eigenvectors[index]);
828 }
829
830 template <typename VectorType>
831 void
833 const std::vector<VectorType> &this_initial_space)
834 {
835 std::vector<Vec> vecs(this_initial_space.size());
836
837 for (unsigned int i = 0; i < this_initial_space.size(); ++i)
838 {
839 Assert(this_initial_space[i].l2_norm() > 0.0,
840 ExcMessage("Initial vectors should be nonzero."));
841 vecs[i] = this_initial_space[i];
842 }
843
844 // if the eigensolver supports only a single initial vector, but several
845 // guesses are provided, then all except the first one will be discarded.
846 // One could still build a vector that is rich in the directions of all
847 // guesses, by taking a linear combination of them. (TODO: make function
848 // virtual?)
849
850 const PetscErrorCode ierr =
851 EPSSetInitialSpace(eps, vecs.size(), vecs.data());
852 AssertThrow(ierr == 0, ExcSLEPcError(ierr));
853 }
854
855} // namespace SLEPcWrappers
856
857# endif // DEAL_II_WITH_SLEPC
858
860
861/*---------------------------- slepc_solver.h ---------------------------*/
862
863#endif
864
865/*---------------------------- slepc_solver.h ---------------------------*/
const AdditionalData additional_data
SolverControl & control() const
EPSConvergedReason reason
void set_target_eigenvalue(const PetscScalar &this_target)
const MPI_Comm mpi_communicator
void set_matrices(const PETScWrappers::MatrixBase &A)
void get_solver_state(const SolverControl::State state)
void set_initial_space(const std::vector< Vector > &initial_space)
void set_problem_type(EPSProblemType set_problem)
SolverControl & solver_control
void solve(const PETScWrappers::MatrixBase &A, std::vector< PetscScalar > &eigenvalues, std::vector< OutputVector > &eigenvectors, const unsigned int n_eigenpairs=1)
void get_eigenpair(const unsigned int index, PetscScalar &eigenvalues, PETScWrappers::VectorBase &eigenvectors)
void set_transformation(SLEPcWrappers::TransformationBase &this_transformation)
static int convergence_test(EPS eps, PetscScalar real_eigenvalue, PetscScalar imag_eigenvalue, PetscReal residual_norm, PetscReal *estimated_error, void *solver_control)
void set_which_eigenpairs(EPSWhich set_which)
const AdditionalData additional_data
const AdditionalData additional_data
const AdditionalData additional_data
const AdditionalData additional_data
const AdditionalData additional_data
#define DEAL_II_NAMESPACE_OPEN
Definition config.h:38
#define DEAL_II_NAMESPACE_CLOSE
Definition config.h:39
#define DeclException0(Exception0)
static ::ExceptionBase & ExcSLEPcEigenvectorConvergenceMismatchError(int arg1, int arg2)
static ::ExceptionBase & ExcSLEPcError(int arg1)
#define Assert(cond, exc)
#define DeclException2(Exception2, type1, type2, outsequence)
static ::ExceptionBase & ExcDimensionMismatch(std::size_t arg1, std::size_t arg2)
#define DeclException1(Exception1, type1, outsequence)
static ::ExceptionBase & ExcSLEPcWrappersUsageError()
static ::ExceptionBase & ExcMessage(std::string arg1)
#define AssertThrow(cond, exc)
std::vector< index_type > data
Definition mpi.cc:734
std::array< Number, 1 > eigenvalues(const SymmetricTensor< 2, 1, Number > &T)
std::array< std::pair< Number, Tensor< 1, dim, Number > >, dim > eigenvectors(const SymmetricTensor< 2, dim, Number > &T, const SymmetricTensorEigenvectorMethod method=SymmetricTensorEigenvectorMethod::ql_implicit_shifts)