From c654e1b361732ec1159e798aa7c7c2abdf61752d Mon Sep 17 00:00:00 2001 From: Denis Davydov Date: Sat, 12 Dec 2015 20:51:22 +0100 Subject: [PATCH] allow initialisation of PETSc solvers with preconditioners; make SLEPc::Transformation a friend --- include/deal.II/lac/petsc_solver.h | 25 +++++++++++++++-- source/lac/petsc_solver.cc | 45 +++++++++++++++++++++++++++--- 2 files changed, 64 insertions(+), 6 deletions(-) diff --git a/include/deal.II/lac/petsc_solver.h b/include/deal.II/lac/petsc_solver.h index d0a1e1aed1..55a18791e3 100644 --- a/include/deal.II/lac/petsc_solver.h +++ b/include/deal.II/lac/petsc_solver.h @@ -27,8 +27,19 @@ # include +#ifdef DEAL_II_WITH_SLEPC +#include +#endif + DEAL_II_NAMESPACE_OPEN +#ifdef DEAL_II_WITH_SLEPC +namespace SLEPcWrappers +{ + // forward declarations + class TransformationBase; +} +#endif namespace PETScWrappers { @@ -145,6 +156,12 @@ namespace PETScWrappers */ SolverControl &control() const; + /** + * Initialise the solver with the preconditioner. + * This function is intended for use with SLEPc spectral transformation class. + */ + void initialise(const PreconditionerBase &preconditioner); + /** * Exception */ @@ -221,10 +238,9 @@ namespace PETScWrappers ~SolverData (); /** - * Objects for Krylov subspace solvers and preconditioners. + * Object for Krylov subspace solvers. */ KSP ksp; - PC pc; }; /** @@ -232,6 +248,11 @@ namespace PETScWrappers * in the main solver routine if necessary. */ std_cxx11::shared_ptr solver_data; + + /** + * Make the transformation class a friend, since it needs to set the solver. + */ + friend SLEPcWrappers::TransformationBase; }; diff --git a/source/lac/petsc_solver.cc b/source/lac/petsc_solver.cc index 4f810cdfad..4e702f4bce 100644 --- a/source/lac/petsc_solver.cc +++ b/source/lac/petsc_solver.cc @@ -33,14 +33,17 @@ namespace PETScWrappers SolverBase::SolverData::~SolverData () { - // destroy the solver object + if (ksp != NULL) + { + // destroy the solver object #if DEAL_II_PETSC_VERSION_LT(3,2,0) - int ierr = KSPDestroy (ksp); + int ierr = KSPDestroy (ksp); #else - int ierr = KSPDestroy (&ksp); + int ierr = KSPDestroy (&ksp); #endif - AssertThrow (ierr == 0, ExcPETScError(ierr)); + AssertThrow (ierr == 0, ExcPETScError(ierr)); + } } @@ -202,6 +205,40 @@ namespace PETScWrappers return 0; } + void + SolverBase::initialise(const PreconditionerBase &preconditioner) + { + int ierr; + + solver_data.reset (new SolverData()); + + ierr = KSPCreate (mpi_communicator, &solver_data->ksp); + AssertThrow (ierr == 0, ExcPETScError(ierr)); + + // let derived classes set the solver + // type, and the preconditioning + // object set the type of + // preconditioner + set_solver_type (solver_data->ksp); + + ierr = KSPSetPC (solver_data->ksp, preconditioner.get_pc()); + AssertThrow (ierr == 0, ExcPETScError(ierr)); + + // then a convergence monitor + // function. that function simply + // checks with the solver_control + // object we have in this object for + // convergence + KSPSetConvergenceTest (solver_data->ksp, &convergence_test, + reinterpret_cast(&solver_control), + PETSC_NULL); + + // set the command line options provided + // by the user to override the defaults + ierr = KSPSetFromOptions (solver_data->ksp); + AssertThrow (ierr == 0, ExcPETScError(ierr)); + } + /* ---------------------- SolverRichardson ------------------------ */ -- 2.39.5