Reference documentation for deal.II version 9.0.0
slepc_solver.h
1 // ---------------------------------------------------------------------
2 //
3 // Copyright (C) 2009 - 2017 by the deal.II authors
4 //
5 // This file is part of the deal.II library.
6 //
7 // The deal.II library is free software; you can use it, redistribute
8 // it, and/or modify it under the terms of the GNU Lesser General
9 // Public License as published by the Free Software Foundation; either
10 // version 2.1 of the License, or (at your option) any later version.
11 // The full text of the license can be found in the file LICENSE at
12 // the top level of the deal.II distribution.
13 //
14 // ---------------------------------------------------------------------
15 
16 
17 #ifndef dealii_slepc_solver_h
18 #define dealii_slepc_solver_h
19 
20 #include <deal.II/base/config.h>
21 
22 #ifdef DEAL_II_WITH_SLEPC
23 
24 # include <deal.II/lac/solver_control.h>
25 # include <deal.II/lac/petsc_matrix_base.h>
26 # include <deal.II/lac/slepc_spectral_transformation.h>
27 
28 # include <petscconf.h>
29 # include <petscksp.h>
30 # include <slepceps.h>
31 
32 # include <memory>
33 
34 DEAL_II_NAMESPACE_OPEN
35 
130 namespace SLEPcWrappers
131 {
132 
141  {
142  public:
148  const MPI_Comm &mpi_communicator);
149 
153  virtual ~SolverBase ();
154 
173  template <typename OutputVector>
174  void
176  std::vector<PetscScalar> &eigenvalues,
177  std::vector<OutputVector> &eigenvectors,
178  const unsigned int n_eigenpairs = 1);
179 
185  template <typename OutputVector>
186  void
188  const PETScWrappers::MatrixBase &B,
189  std::vector<PetscScalar> &eigenvalues,
190  std::vector<OutputVector> &eigenvectors,
191  const unsigned int n_eigenpairs = 1);
192 
198  template <typename OutputVector>
199  void
201  const PETScWrappers::MatrixBase &B,
202  std::vector<double> &real_eigenvalues,
203  std::vector<double> &imag_eigenvalues,
204  std::vector<OutputVector> &real_eigenvectors,
205  std::vector<OutputVector> &imag_eigenvectors,
206  const unsigned int n_eigenpairs = 1);
207 
211  DEAL_II_DEPRECATED
212  void
214  (const PETScWrappers::VectorBase &this_initial_vector);
215 
222  template <typename Vector>
223  void
225  (const std::vector<Vector> &initial_space);
226 
230  void
232 
237  void
238  set_target_eigenvalue (const PetscScalar &this_target);
239 
246  void
247  set_which_eigenpairs (EPSWhich set_which);
248 
257  void
258  set_problem_type (EPSProblemType set_problem);
259 
265  void
267 
272 
277  int,
278  << " An error with error number " << arg1
279  << " occurred while calling a SLEPc function");
280 
285  int, int,
286  << " The number of converged eigenvectors is " << arg1
287  << " but " << arg2 << " were requested. ");
288 
292  SolverControl &control () const;
293 
294  protected:
295 
301 
305  const MPI_Comm mpi_communicator;
306 
313  void
314  solve (const unsigned int n_eigenpairs,
315  unsigned int *n_converged);
316 
322  void
323  get_eigenpair (const unsigned int index,
324  PetscScalar &eigenvalues,
326 
332  void
333  get_eigenpair (const unsigned int index,
334  double &real_eigenvalues,
335  double &imag_eigenvalues,
336  PETScWrappers::VectorBase &real_eigenvectors,
337  PETScWrappers::VectorBase &imag_eigenvectors);
338 
343  void
345 
350  void
352  const PETScWrappers::MatrixBase &B);
353 
354  protected:
355 
359  EPS eps;
360 
361  private:
365  EPSConvergedReason reason;
366 
367 
374  static
375  int
376  convergence_test (EPS eps,
377  PetscScalar real_eigenvalue,
378  PetscScalar imag_eigenvalue,
379  PetscReal residual_norm,
380  PetscReal *estimated_error,
381  void *solver_control);
382  };
383 
393  {
394  public:
395 
401  {};
402 
409  const MPI_Comm &mpi_communicator = PETSC_COMM_SELF,
410  const AdditionalData &data = AdditionalData());
411 
412  protected:
413 
418  };
419 
428  class SolverArnoldi : public SolverBase
429  {
430  public:
436  {
441  AdditionalData (const bool delayed_reorthogonalization = false);
442 
447  };
448 
455  const MPI_Comm &mpi_communicator = PETSC_COMM_SELF,
456  const AdditionalData &data = AdditionalData());
457 
458  protected:
459 
464  };
465 
474  class SolverLanczos : public SolverBase
475  {
476  public:
482  {
486  EPSLanczosReorthogType reorthog;
487 
492  AdditionalData(const EPSLanczosReorthogType r = EPS_LANCZOS_REORTHOG_FULL);
493  };
494 
501  const MPI_Comm &mpi_communicator = PETSC_COMM_SELF,
502  const AdditionalData &data = AdditionalData());
503 
504  protected:
505 
510  };
511 
520  class SolverPower : public SolverBase
521  {
522  public:
528  {};
529 
536  const MPI_Comm &mpi_communicator = PETSC_COMM_SELF,
537  const AdditionalData &data = AdditionalData());
538 
539  protected:
540 
545  };
546 
556  {
557  public:
563  {
568 
572  AdditionalData(bool double_expansion = false);
573  };
574 
581  const MPI_Comm &mpi_communicator = PETSC_COMM_SELF,
582  const AdditionalData &data = AdditionalData());
583 
584  protected:
585 
590  };
591 
601  {
602  public:
608  {};
609 
616  const MPI_Comm &mpi_communicator = PETSC_COMM_SELF,
617  const AdditionalData &data = AdditionalData());
618 
619  protected:
620 
625  };
626 
627 
636  class SolverLAPACK : public SolverBase
637  {
638  public:
639 
645  {};
646 
653  const MPI_Comm &mpi_communicator = PETSC_COMM_SELF,
654  const AdditionalData &data = AdditionalData());
655 
656  protected:
657 
662  };
663 
664  // --------------------------- inline and template functions -----------
669  // todo: The logic of these functions can be simplified without breaking backward compatibility...
670 
671  template <typename OutputVector>
672  void
674  std::vector<PetscScalar> &eigenvalues,
675  std::vector<OutputVector> &eigenvectors,
676  const unsigned int n_eigenpairs)
677  {
678  // Panic if the number of eigenpairs wanted is out of bounds.
679  AssertThrow ((n_eigenpairs > 0) && (n_eigenpairs <= A.m ()),
681 
682  // Set the matrices of the problem
683  set_matrices (A);
684 
685  // and solve
686  unsigned int n_converged = 0;
687  solve (n_eigenpairs, &n_converged);
688 
689  if (n_converged > n_eigenpairs)
690  n_converged = n_eigenpairs;
691  AssertThrow (n_converged == n_eigenpairs,
692  ExcSLEPcEigenvectorConvergenceMismatchError(n_converged, n_eigenpairs));
693 
695  eigenvectors.resize (n_converged, eigenvectors.front());
696  eigenvalues.resize (n_converged);
697 
698  for (unsigned int index=0; index<n_converged; ++index)
699  get_eigenpair (index, eigenvalues[index], eigenvectors[index]);
700  }
701 
702  template <typename OutputVector>
703  void
705  const PETScWrappers::MatrixBase &B,
706  std::vector<PetscScalar> &eigenvalues,
707  std::vector<OutputVector> &eigenvectors,
708  const unsigned int n_eigenpairs)
709  {
710  // Guard against incompatible matrix sizes:
711  AssertThrow (A.m() == B.m (), ExcDimensionMismatch(A.m(), B.m()));
712  AssertThrow (A.n() == B.n (), ExcDimensionMismatch(A.n(), B.n()));
713 
714  // Panic if the number of eigenpairs wanted is out of bounds.
715  AssertThrow ((n_eigenpairs>0) && (n_eigenpairs<=A.m ()),
717 
718  // Set the matrices of the problem
719  set_matrices (A, B);
720 
721  // and solve
722  unsigned int n_converged = 0;
723  solve (n_eigenpairs, &n_converged);
724 
725  if (n_converged>=n_eigenpairs)
726  n_converged = n_eigenpairs;
727 
728  AssertThrow (n_converged==n_eigenpairs,
729  ExcSLEPcEigenvectorConvergenceMismatchError(n_converged, n_eigenpairs));
731 
732  eigenvectors.resize (n_converged, eigenvectors.front());
733  eigenvalues.resize (n_converged);
734 
735  for (unsigned int index=0; index<n_converged; ++index)
736  get_eigenpair (index, eigenvalues[index], eigenvectors[index]);
737  }
738 
739  template <typename OutputVector>
740  void
742  const PETScWrappers::MatrixBase &B,
743  std::vector<double> &real_eigenvalues,
744  std::vector<double> &imag_eigenvalues,
745  std::vector<OutputVector> &real_eigenvectors,
746  std::vector<OutputVector> &imag_eigenvectors,
747  const unsigned int n_eigenpairs)
748  {
749  // Guard against incompatible matrix sizes:
750  AssertThrow (A.m() == B.m (), ExcDimensionMismatch(A.m(), B.m()));
751  AssertThrow (A.n() == B.n (), ExcDimensionMismatch(A.n(), B.n()));
752 
753  // and incompatible eigenvalue/eigenvector sizes
754  AssertThrow (real_eigenvalues.size() == imag_eigenvalues.size(),
755  ExcDimensionMismatch(real_eigenvalues.size(), imag_eigenvalues.size()));
756  AssertThrow (real_eigenvectors.size() == imag_eigenvectors.size (),
757  ExcDimensionMismatch(real_eigenvectors.size(), imag_eigenvectors.size()));
758 
759  // Panic if the number of eigenpairs wanted is out of bounds.
760  AssertThrow ((n_eigenpairs>0) && (n_eigenpairs<=A.m ()),
762 
763  // Set the matrices of the problem
764  set_matrices (A, B);
765 
766  // and solve
767  unsigned int n_converged = 0;
768  solve (n_eigenpairs, &n_converged);
769 
770  if (n_converged>=n_eigenpairs)
771  n_converged = n_eigenpairs;
772 
773  AssertThrow (n_converged==n_eigenpairs,
774  ExcSLEPcEigenvectorConvergenceMismatchError(n_converged, n_eigenpairs));
775  AssertThrow ((real_eigenvectors.size()!=0) && (imag_eigenvectors.size()!=0),
777 
778  real_eigenvectors.resize (n_converged, real_eigenvectors.front());
779  imag_eigenvectors.resize (n_converged, imag_eigenvectors.front());
780  real_eigenvalues.resize (n_converged);
781  imag_eigenvalues.resize (n_converged);
782 
783  for (unsigned int index=0; index<n_converged; ++index)
784  get_eigenpair (index,
785  real_eigenvalues[index], imag_eigenvalues[index],
786  real_eigenvectors[index], imag_eigenvectors[index]);
787  }
788 
789  template <typename Vector>
790  void
791  SolverBase::set_initial_space(const std::vector<Vector> &this_initial_space)
792  {
793  std::vector<Vec> vecs(this_initial_space.size());
794 
795  for (unsigned int i = 0; i < this_initial_space.size(); i++)
796  {
797  Assert(this_initial_space[i].l2_norm()>0.0,
798  ExcMessage("Initial vectors should be nonzero."));
799  vecs[i] = this_initial_space[i];
800  }
801 
802  // if the eigensolver supports only a single initial vector, but several
803  // guesses are provided, then all except the first one will be discarded.
804  // One could still build a vector that is rich in the directions of all guesses,
805  // by taking a linear combination of them. (TODO: make function virtual?)
806 
807  const PetscErrorCode ierr = EPSSetInitialSpace (eps, vecs.size(), vecs.data());
808  AssertThrow (ierr == 0, ExcSLEPcError(ierr));
809  }
810 
811 }
812 
813 DEAL_II_NAMESPACE_CLOSE
814 
815 #endif // DEAL_II_WITH_SLEPC
816 
817 /*---------------------------- slepc_solver.h ---------------------------*/
818 
819 #endif
820 
821 /*---------------------------- slepc_solver.h ---------------------------*/
static ::ExceptionBase & ExcSLEPcWrappersUsageError()
void set_initial_space(const std::vector< Vector > &initial_space)
Definition: slepc_solver.h:791
#define DeclException2(Exception2, type1, type2, outsequence)
Definition: exceptions.h:358
const AdditionalData additional_data
Definition: slepc_solver.h:544
SolverJacobiDavidson(SolverControl &cn, const MPI_Comm &mpi_communicator=PETSC_COMM_SELF, const AdditionalData &data=AdditionalData())
std::array< std::pair< Number, Tensor< 1, dim, Number > >, std::integral_constant< int, dim >::value > eigenvectors(const SymmetricTensor< 2, dim, Number > &T, const SymmetricTensorEigenvectorMethod method=SymmetricTensorEigenvectorMethod::ql_implicit_shifts)
SolverPower(SolverControl &cn, const MPI_Comm &mpi_communicator=PETSC_COMM_SELF, const AdditionalData &data=AdditionalData())
void set_initial_vector(const PETScWrappers::VectorBase &this_initial_vector)
std::array< Number, 1 > eigenvalues(const SymmetricTensor< 2, 1, Number > &T)
#define AssertThrow(cond, exc)
Definition: exceptions.h:1221
void solve(const PETScWrappers::MatrixBase &A, std::vector< PetscScalar > &eigenvalues, std::vector< OutputVector > &eigenvectors, const unsigned int n_eigenpairs=1)
Definition: slepc_solver.h:673
const MPI_Comm mpi_communicator
Definition: slepc_solver.h:305
SolverKrylovSchur(SolverControl &cn, const MPI_Comm &mpi_communicator=PETSC_COMM_SELF, const AdditionalData &data=AdditionalData())
SolverBase(SolverControl &cn, const MPI_Comm &mpi_communicator)
Definition: slepc_solver.cc:35
AdditionalData(const bool delayed_reorthogonalization=false)
void set_problem_type(EPSProblemType set_problem)
static ::ExceptionBase & ExcMessage(std::string arg1)
#define DeclException1(Exception1, type1, outsequence)
Definition: exceptions.h:346
void set_target_eigenvalue(const PetscScalar &this_target)
void set_matrices(const PETScWrappers::MatrixBase &A)
Definition: slepc_solver.cc:73
void set_which_eigenpairs(EPSWhich set_which)
#define Assert(cond, exc)
Definition: exceptions.h:1142
static ::ExceptionBase & ExcDimensionMismatch(std::size_t arg1, std::size_t arg2)
SolverGeneralizedDavidson(SolverControl &cn, const MPI_Comm &mpi_communicator=PETSC_COMM_SELF, const AdditionalData &data=AdditionalData())
const AdditionalData additional_data
Definition: slepc_solver.h:661
#define DeclException0(Exception0)
Definition: exceptions.h:323
EPSConvergedReason reason
Definition: slepc_solver.h:365
const AdditionalData additional_data
Definition: slepc_solver.h:509
const AdditionalData additional_data
Definition: slepc_solver.h:417
void get_eigenpair(const unsigned int index, PetscScalar &eigenvalues, PETScWrappers::VectorBase &eigenvectors)
static int convergence_test(EPS eps, PetscScalar real_eigenvalue, PetscScalar imag_eigenvalue, PetscReal residual_norm, PetscReal *estimated_error, void *solver_control)
SolverLanczos(SolverControl &cn, const MPI_Comm &mpi_communicator=PETSC_COMM_SELF, const AdditionalData &data=AdditionalData())
static ::ExceptionBase & ExcSLEPcEigenvectorConvergenceMismatchError(int arg1, int arg2)
SolverLAPACK(SolverControl &cn, const MPI_Comm &mpi_communicator=PETSC_COMM_SELF, const AdditionalData &data=AdditionalData())
const AdditionalData additional_data
Definition: slepc_solver.h:624
AdditionalData(const EPSLanczosReorthogType r=EPS_LANCZOS_REORTHOG_FULL)
const AdditionalData additional_data
Definition: slepc_solver.h:463
static ::ExceptionBase & ExcSLEPcError(int arg1)
void set_transformation(SLEPcWrappers::TransformationBase &this_transformation)
Definition: slepc_solver.cc:90
SolverControl & solver_control
Definition: slepc_solver.h:300
SolverArnoldi(SolverControl &cn, const MPI_Comm &mpi_communicator=PETSC_COMM_SELF, const AdditionalData &data=AdditionalData())
SolverControl & control() const
void get_solver_state(const SolverControl::State state)