# include <deal.II/lac/petsc_precondition.h>
# include <deal.II/lac/petsc_vector_base.h>
-# include <petscversion.h>
-
-# include <cmath>
-# include <memory>
+// Shorthand notation for PETSc error codes.
+# define AssertPETSc(code) \
+ do \
+ { \
+ PetscErrorCode ierr = (code); \
+ AssertThrow(ierr == 0, ExcPETScError(ierr)); \
+ } \
+ while (0)
DEAL_II_NAMESPACE_OPEN
namespace PETScWrappers
{
- SolverBase::SolverData::~SolverData()
+ SolverBase::SolverBase()
+ : ksp(nullptr)
+ , solver_control(nullptr)
+ {}
+
+
+ SolverBase::SolverBase(SolverControl &cn)
+ : ksp(nullptr)
+ , solver_control(&cn)
+ {}
+
+
+
+ void
+ SolverBase::set_solver_type(KSP &) const
+ {}
+
+
+
+ SolverBase::~SolverBase()
{
- destroy_krylov_solver(ksp);
+ AssertPETSc(KSPDestroy(&ksp));
}
- SolverBase::SolverBase(SolverControl &cn)
- : solver_control(cn)
- {}
+ KSP
+ SolverBase::petsc_ksp()
+ {
+ return ksp;
+ }
+
+
+
+ SolverBase::operator KSP() const
+ {
+ return ksp;
+ }
const VectorBase & b,
const PreconditionBase &preconditioner)
{
- /*
- TODO: PETSc duplicates communicators, so this does not work (you put
- MPI_COMM_SELF in, but get something other out when you ask PETSc for the
- communicator. This mainly fails due to the MatrixFree classes, that can not
- ask PETSc for a communicator. //Timo Heister
- Assert(A.get_mpi_communicator()==mpi_communicator, ExcMessage("PETSc Solver
- and Matrix need to use the same MPI_Comm."));
- Assert(x.get_mpi_communicator()==mpi_communicator, ExcMessage("PETSc Solver
- and Vector need to use the same MPI_Comm."));
- Assert(b.get_mpi_communicator()==mpi_communicator, ExcMessage("PETSc Solver
- and Vector need to use the same MPI_Comm."));
- */
-
// first create a solver object if this
// is necessary
- if (solver_data.get() == nullptr)
+ if (ksp == nullptr)
{
- solver_data = std::make_unique<SolverData>();
-
- PetscErrorCode ierr =
- KSPCreate(A.get_mpi_communicator(), &solver_data->ksp);
- AssertThrow(ierr == 0, ExcPETScError(ierr));
+ initialize_ksp_with_comm(A.get_mpi_communicator());
// 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));
-
- // setting the preconditioner overwrites the used matrices.
- // hence, we need to set the matrices after the preconditioner.
- Mat B;
- ierr = PCGetOperators(preconditioner.get_pc(), nullptr, &B);
- AssertThrow(ierr == 0, ExcPETScError(ierr));
- ierr = KSPSetOperators(solver_data->ksp, A, B);
- 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
- ierr = KSPSetConvergenceTest(solver_data->ksp,
- &convergence_test,
- reinterpret_cast<void *>(&solver_control),
- nullptr);
- AssertThrow(ierr == 0, ExcPETScError(ierr));
+ set_solver_type(ksp);
+
+ AssertPETSc(KSPSetPC(ksp, preconditioner.get_pc()));
+
+ /*
+ * by default we set up the preconditioner only once.
+ * this can be overriden by command line.
+ */
+ AssertPETSc(KSPSetReusePreconditioner(ksp, PETSC_TRUE));
}
+ // setting the preconditioner overwrites the used matrices.
+ // hence, we need to set the matrices after the preconditioner.
+ Mat B;
+ AssertPETSc(KSPGetOperators(ksp, nullptr, &B));
+ AssertPETSc(KSPSetOperators(ksp, A, B));
+
// set the command line option prefix name
- PetscErrorCode ierr =
- KSPSetOptionsPrefix(solver_data->ksp, prefix_name.c_str());
- AssertThrow(ierr == 0, ExcPETScError(ierr));
+ AssertPETSc(KSPSetOptionsPrefix(ksp, prefix_name.c_str()));
// set the command line options provided
// by the user to override the defaults
- ierr = KSPSetFromOptions(solver_data->ksp);
- AssertThrow(ierr == 0, ExcPETScError(ierr));
+ AssertPETSc(KSPSetFromOptions(ksp));
// then do the real work: set up solver
// internal data and solve the
// system.
- ierr = KSPSetUp(solver_data->ksp);
- AssertThrow(ierr == 0, ExcPETScError(ierr));
-
- ierr = KSPSolve(solver_data->ksp, b, x);
- AssertThrow(ierr == 0, ExcPETScError(ierr));
+ AssertPETSc(KSPSetUp(ksp));
- // do not destroy solver object
- // solver_data.reset ();
+ AssertPETSc(KSPSolve(ksp, b, x));
// in case of failure: throw
// exception
- if (solver_control.last_check() != SolverControl::success)
+ if (solver_control &&
+ solver_control->last_check() != SolverControl::success)
AssertThrow(false,
- SolverControl::NoConvergence(solver_control.last_step(),
- solver_control.last_value()));
+ SolverControl::NoConvergence(solver_control->last_step(),
+ solver_control->last_value()));
// otherwise exit as normal
}
void
SolverBase::reset()
{
- solver_data.reset();
+ AssertPETSc(KSPDestroy(&ksp));
}
SolverControl &
SolverBase::control() const
{
- return solver_control;
+ AssertThrow(
+ solver_control,
+ ExcMessage(
+ "You need to create the solver with a SolverControl object if you want to call the function that returns it."));
+ return *solver_control;
}
break;
case ::dealii::SolverControl::success:
- *reason = static_cast<KSPConvergedReason>(1);
+ *reason = KSP_CONVERGED_RTOL;
break;
case ::dealii::SolverControl::failure:
void
- SolverBase::initialize(const PreconditionBase &preconditioner)
+ SolverBase::initialize_ksp_with_comm(const MPI_Comm &comm)
+ {
+ // Create the PETSc KSP object
+ AssertPETSc(KSPCreate(comm, &ksp));
+
+ // then a convergence monitor
+ // function that simply
+ // checks with the solver_control
+ // object we have in this object for
+ // convergence
+ perhaps_set_convergence_test();
+ }
+
+
+
+ void
+ SolverBase::perhaps_set_convergence_test() const
{
- PetscErrorCode ierr;
+ if (ksp && solver_control)
+ AssertPETSc(
+ KSPSetConvergenceTest(ksp, &convergence_test, solver_control, nullptr));
+ }
- solver_data = std::make_unique<SolverData>();
- ierr = KSPCreate(preconditioner.get_mpi_communicator(), &solver_data->ksp);
- AssertThrow(ierr == 0, ExcPETScError(ierr));
+ void
+ SolverBase::initialize(const PreconditionBase &preconditioner)
+ {
+ initialize_ksp_with_comm(preconditioner.get_mpi_communicator());
// 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
- ierr = KSPSetConvergenceTest(solver_data->ksp,
- &convergence_test,
- reinterpret_cast<void *>(&solver_control),
- nullptr);
- AssertThrow(ierr == 0, ExcPETScError(ierr));
+ set_solver_type(ksp);
// set the command line options provided
// by the user to override the defaults
- ierr = KSPSetFromOptions(solver_data->ksp);
- AssertThrow(ierr == 0, ExcPETScError(ierr));
+ AssertPETSc(KSPSetFromOptions(ksp));
}
void
SolverRichardson::set_solver_type(KSP &ksp) const
{
- PetscErrorCode ierr = KSPSetType(ksp, KSPRICHARDSON);
- AssertThrow(ierr == 0, ExcPETScError(ierr));
+ AssertPETSc(KSPSetType(ksp, KSPRICHARDSON));
// set the damping factor from the data
- ierr = KSPRichardsonSetScale(ksp, additional_data.omega);
- AssertThrow(ierr == 0, ExcPETScError(ierr));
+ AssertPETSc(KSPRichardsonSetScale(ksp, additional_data.omega));
// in the deal.II solvers, we always
// honor the initial guess in the
// solution vector. do so here as well:
- ierr = KSPSetInitialGuessNonzero(ksp, PETSC_TRUE);
- AssertThrow(ierr == 0, ExcPETScError(ierr));
+ AssertPETSc(KSPSetInitialGuessNonzero(ksp, PETSC_TRUE));
// Hand over the absolute
// tolerance and the maximum
// the Richardson iteration,
// where no residual is
// available.
- ierr = KSPSetTolerances(ksp,
- PETSC_DEFAULT,
- this->solver_control.tolerance(),
- PETSC_DEFAULT,
- this->solver_control.max_steps() + 1);
- AssertThrow(ierr == 0, ExcPETScError(ierr));
+ AssertPETSc(KSPSetTolerances(ksp,
+ PETSC_DEFAULT,
+ this->solver_control->tolerance(),
+ PETSC_DEFAULT,
+ this->solver_control->max_steps() + 1));
}
void
SolverChebychev::set_solver_type(KSP &ksp) const
{
- PetscErrorCode ierr = KSPSetType(ksp, KSPCHEBYSHEV);
- AssertThrow(ierr == 0, ExcPETScError(ierr));
+ AssertPETSc(KSPSetType(ksp, KSPCHEBYSHEV));
// in the deal.II solvers, we always
// honor the initial guess in the
// solution vector. do so here as well:
- ierr = KSPSetInitialGuessNonzero(ksp, PETSC_TRUE);
- AssertThrow(ierr == 0, ExcPETScError(ierr));
+ AssertPETSc(KSPSetInitialGuessNonzero(ksp, PETSC_TRUE));
}
void
SolverCG::set_solver_type(KSP &ksp) const
{
- PetscErrorCode ierr = KSPSetType(ksp, KSPCG);
- AssertThrow(ierr == 0, ExcPETScError(ierr));
+ AssertPETSc(KSPSetType(ksp, KSPCG));
// in the deal.II solvers, we always
// honor the initial guess in the
// solution vector. do so here as well:
- ierr = KSPSetInitialGuessNonzero(ksp, PETSC_TRUE);
- AssertThrow(ierr == 0, ExcPETScError(ierr));
+ AssertPETSc(KSPSetInitialGuessNonzero(ksp, PETSC_TRUE));
}
void
SolverBiCG::set_solver_type(KSP &ksp) const
{
- PetscErrorCode ierr = KSPSetType(ksp, KSPBICG);
- AssertThrow(ierr == 0, ExcPETScError(ierr));
+ AssertPETSc(KSPSetType(ksp, KSPBICG));
// in the deal.II solvers, we always
// honor the initial guess in the
// solution vector. do so here as well:
- ierr = KSPSetInitialGuessNonzero(ksp, PETSC_TRUE);
- AssertThrow(ierr == 0, ExcPETScError(ierr));
+ AssertPETSc(KSPSetInitialGuessNonzero(ksp, PETSC_TRUE));
}
void
SolverGMRES::set_solver_type(KSP &ksp) const
{
- PetscErrorCode ierr = KSPSetType(ksp, KSPGMRES);
- AssertThrow(ierr == 0, ExcPETScError(ierr));
+ AssertPETSc(KSPSetType(ksp, KSPGMRES));
- ierr = KSPGMRESSetRestart(ksp, additional_data.restart_parameter);
- AssertThrow(ierr == 0, ExcPETScError(ierr));
+ AssertPETSc(KSPGMRESSetRestart(ksp, additional_data.restart_parameter));
// Set preconditioning side to right
if (additional_data.right_preconditioning)
{
- ierr = KSPSetPCSide(ksp, PC_RIGHT);
- AssertThrow(ierr == 0, ExcPETScError(ierr));
+ AssertPETSc(KSPSetPCSide(ksp, PC_RIGHT));
}
// in the deal.II solvers, we always
// honor the initial guess in the
// solution vector. do so here as well:
- ierr = KSPSetInitialGuessNonzero(ksp, PETSC_TRUE);
- AssertThrow(ierr == 0, ExcPETScError(ierr));
+ AssertPETSc(KSPSetInitialGuessNonzero(ksp, PETSC_TRUE));
}
void
SolverBicgstab::set_solver_type(KSP &ksp) const
{
- PetscErrorCode ierr = KSPSetType(ksp, KSPBCGS);
- AssertThrow(ierr == 0, ExcPETScError(ierr));
+ AssertPETSc(KSPSetType(ksp, KSPBCGS));
// in the deal.II solvers, we always
// honor the initial guess in the
// solution vector. do so here as well:
- ierr = KSPSetInitialGuessNonzero(ksp, PETSC_TRUE);
- AssertThrow(ierr == 0, ExcPETScError(ierr));
+ AssertPETSc(KSPSetInitialGuessNonzero(ksp, PETSC_TRUE));
}
void
SolverCGS::set_solver_type(KSP &ksp) const
{
- PetscErrorCode ierr = KSPSetType(ksp, KSPCGS);
- AssertThrow(ierr == 0, ExcPETScError(ierr));
+ AssertPETSc(KSPSetType(ksp, KSPCGS));
// in the deal.II solvers, we always
// honor the initial guess in the
// solution vector. do so here as well:
- ierr = KSPSetInitialGuessNonzero(ksp, PETSC_TRUE);
- AssertThrow(ierr == 0, ExcPETScError(ierr));
+ AssertPETSc(KSPSetInitialGuessNonzero(ksp, PETSC_TRUE));
}
void
SolverTFQMR::set_solver_type(KSP &ksp) const
{
- PetscErrorCode ierr = KSPSetType(ksp, KSPTFQMR);
- AssertThrow(ierr == 0, ExcPETScError(ierr));
+ AssertPETSc(KSPSetType(ksp, KSPTFQMR));
// in the deal.II solvers, we always
// honor the initial guess in the
// solution vector. do so here as well:
- ierr = KSPSetInitialGuessNonzero(ksp, PETSC_TRUE);
- AssertThrow(ierr == 0, ExcPETScError(ierr));
+ AssertPETSc(KSPSetInitialGuessNonzero(ksp, PETSC_TRUE));
}
void
SolverTCQMR::set_solver_type(KSP &ksp) const
{
- PetscErrorCode ierr = KSPSetType(ksp, KSPTCQMR);
- AssertThrow(ierr == 0, ExcPETScError(ierr));
+ AssertPETSc(KSPSetType(ksp, KSPTCQMR));
// in the deal.II solvers, we always
// honor the initial guess in the
// solution vector. do so here as well:
- ierr = KSPSetInitialGuessNonzero(ksp, PETSC_TRUE);
- AssertThrow(ierr == 0, ExcPETScError(ierr));
+ AssertPETSc(KSPSetInitialGuessNonzero(ksp, PETSC_TRUE));
}
void
SolverCR::set_solver_type(KSP &ksp) const
{
- PetscErrorCode ierr = KSPSetType(ksp, KSPCR);
- AssertThrow(ierr == 0, ExcPETScError(ierr));
+ AssertPETSc(KSPSetType(ksp, KSPCR));
// in the deal.II solvers, we always
// honor the initial guess in the
// solution vector. do so here as well:
- ierr = KSPSetInitialGuessNonzero(ksp, PETSC_TRUE);
- AssertThrow(ierr == 0, ExcPETScError(ierr));
+ AssertPETSc(KSPSetInitialGuessNonzero(ksp, PETSC_TRUE));
}
void
SolverLSQR::set_solver_type(KSP &ksp) const
{
- PetscErrorCode ierr = KSPSetType(ksp, KSPLSQR);
- AssertThrow(ierr == 0, ExcPETScError(ierr));
+ AssertPETSc(KSPSetType(ksp, KSPLSQR));
// in the deal.II solvers, we always
// honor the initial guess in the
// solution vector. do so here as well:
- ierr = KSPSetInitialGuessNonzero(ksp, PETSC_TRUE);
- AssertThrow(ierr == 0, ExcPETScError(ierr));
+ AssertPETSc(KSPSetInitialGuessNonzero(ksp, PETSC_TRUE));
+
+ // The KSPLSQR implementation overwrites the user-defined
+ // convergence test at creation (i.e. KSPSetType) time.
+ // This is probably a bad design decision in PETSc.
+ // Anyway, here we make sure we use our own convergence
+ // test.
+ perhaps_set_convergence_test();
}
void
SolverPreOnly::set_solver_type(KSP &ksp) const
{
- PetscErrorCode ierr = KSPSetType(ksp, KSPPREONLY);
- AssertThrow(ierr == 0, ExcPETScError(ierr));
+ AssertPETSc(KSPSetType(ksp, KSPPREONLY));
// The KSPPREONLY solver of
// PETSc never calls the convergence
// is set to some nice values, which
// guarantee a nice result at the end
// of the solution process.
- solver_control.check(1, 0.0);
+ solver_control->check(1, 0.0);
// Using the PREONLY solver with
// a nonzero initial guess leads
// PETSc to produce some error messages.
- ierr = KSPSetInitialGuessNonzero(ksp, PETSC_FALSE);
- AssertThrow(ierr == 0, ExcPETScError(ierr));
+ AssertPETSc(KSPSetInitialGuessNonzero(ksp, PETSC_FALSE));
}
- SparseDirectMUMPS::SolverDataMUMPS::~SolverDataMUMPS()
- {
- destroy_krylov_solver(ksp);
- // the 'pc' object is owned by the 'ksp' object, and consequently
- // does not have to be destroyed explicitly here
- }
-
-
void
SparseDirectMUMPS::set_solver_type(KSP &ksp) const
{
* preconditioner. Its use is due to SparseDirectMUMPS being a direct
* (rather than iterative) solver
*/
- PetscErrorCode ierr = KSPSetType(ksp, KSPPREONLY);
- AssertThrow(ierr == 0, ExcPETScError(ierr));
+ AssertPETSc(KSPSetType(ksp, KSPPREONLY));
/*
* The KSPPREONLY solver of PETSc never calls the convergence monitor,
* SolverControl status is set to some nice values, which guarantee a
* nice result at the end of the solution process.
*/
- solver_control.check(1, 0.0);
+ solver_control->check(1, 0.0);
/*
* Using a PREONLY solver with a nonzero initial guess leads PETSc to
* produce some error messages.
*/
- ierr = KSPSetInitialGuessNonzero(ksp, PETSC_FALSE);
- AssertThrow(ierr == 0, ExcPETScError(ierr));
+ AssertPETSc(KSPSetInitialGuessNonzero(ksp, PETSC_FALSE));
}
void
const VectorBase &b)
{
# ifdef DEAL_II_PETSC_WITH_MUMPS
- /*
- * factorization matrix to be obtained from MUMPS
- */
- Mat F;
-
- /*
- * setting MUMPS integer control parameters ICNTL to be passed to
- * MUMPS. Setting entry 7 of MUMPS ICNTL array (of size 40) to a value
- * of 2. This sets use of Approximate Minimum Fill (AMF)
- */
- PetscInt ival = 2, icntl = 7;
- /*
- * number of iterations to solution (should be 1) for a direct solver
- */
- PetscInt its;
- /*
- * norm of residual
- */
- PetscReal rnorm;
-
/*
* creating a solver object if this is necessary
*/
- if (solver_data == nullptr)
+ if (ksp == nullptr)
{
- solver_data = std::make_unique<SolverDataMUMPS>();
+ initialize_ksp_with_comm(A.get_mpi_communicator());
/*
- * creates the default KSP context and puts it in the location
- * solver_data->ksp
+ * setting the solver type
*/
- PetscErrorCode ierr =
- KSPCreate(A.get_mpi_communicator(), &solver_data->ksp);
- AssertThrow(ierr == 0, ExcPETScError(ierr));
+ set_solver_type(ksp);
/*
* set the matrices involved. the last argument is irrelevant here,
* since we use the solver only once anyway
*/
- ierr = KSPSetOperators(solver_data->ksp, A, A);
- AssertThrow(ierr == 0, ExcPETScError(ierr));
-
- /*
- * setting the solver type
- */
- set_solver_type(solver_data->ksp);
+ AssertPETSc(KSPSetOperators(ksp, A, A));
/*
* getting the associated preconditioner context
*/
- ierr = KSPGetPC(solver_data->ksp, &solver_data->pc);
- AssertThrow(ierr == 0, ExcPETScError(ierr));
+ PC pc;
+ AssertPETSc(KSPGetPC(ksp, &pc));
/*
* build PETSc PC for particular PCLU or PCCHOLESKY preconditioner
* depending on whether the symmetric mode has been set
*/
if (symmetric_mode)
- ierr = PCSetType(solver_data->pc, PCCHOLESKY);
+ AssertPETSc(PCSetType(pc, PCCHOLESKY));
else
- ierr = PCSetType(solver_data->pc, PCLU);
- AssertThrow(ierr == 0, ExcPETScError(ierr));
-
- /*
- * convergence monitor function that checks with the solver_control
- * object for convergence
- */
- ierr = KSPSetConvergenceTest(solver_data->ksp,
- &convergence_test,
- reinterpret_cast<void *>(&solver_control),
- nullptr);
- AssertThrow(ierr == 0, ExcPETScError(ierr));
+ AssertPETSc(PCSetType(pc, PCLU));
- /*
- * set the software that is to be used to perform the lu
- * factorization here we start to see differences with the base
- * class solve function
- */
+ /*
+ * set the software that is to be used to perform the lu
+ * factorization here we start to see differences with the base
+ * class solve function
+ */
# if DEAL_II_PETSC_VERSION_LT(3, 9, 0)
- ierr = PCFactorSetMatSolverPackage(solver_data->pc, MATSOLVERMUMPS);
+ AssertPETSc(PCFactorSetMatSolverPackage(pc, MATSOLVERMUMPS));
# else
- ierr = PCFactorSetMatSolverType(solver_data->pc, MATSOLVERMUMPS);
+ AssertPETSc(PCFactorSetMatSolverType(pc, MATSOLVERMUMPS));
# endif
- AssertThrow(ierr == 0, ExcPETScError(ierr));
/*
* set up the package to call for the factorization
*/
# if DEAL_II_PETSC_VERSION_LT(3, 9, 0)
- ierr = PCFactorSetUpMatSolverPackage(solver_data->pc);
+ AssertPETSc(PCFactorSetUpMatSolverPackage(pc));
# else
- ierr = PCFactorSetUpMatSolverType(solver_data->pc);
+ AssertPETSc(PCFactorSetUpMatSolverType(pc));
# endif
- AssertThrow(ierr == 0, ExcPETScError(ierr));
-
- /*
- * get the factored matrix F from the preconditioner context. This
- * routine is valid only for LU, ILU, Cholesky, and incomplete
- * Cholesky
- */
- ierr = PCFactorGetMatrix(solver_data->pc, &F);
- AssertThrow(ierr == 0, ExcPETScError(ierr));
/*
- * Passing the control parameters to MUMPS
+ * get the factored matrix F from the preconditioner context.
*/
- ierr = MatMumpsSetIcntl(F, icntl, ival);
- AssertThrow(ierr == 0, ExcPETScError(ierr));
+ Mat F;
+ AssertPETSc(PCFactorGetMatrix(pc, &F));
/*
- * set the command line option prefix name
+ * pass control parameters to MUMPS.
+ * Setting entry 7 of MUMPS ICNTL array to a value
+ * of 2. This sets use of Approximate Minimum Fill (AMF)
*/
- ierr = KSPSetOptionsPrefix(solver_data->ksp, prefix_name.c_str());
- AssertThrow(ierr == 0, ExcPETScError(ierr));
+ AssertPETSc(MatMumpsSetIcntl(F, 7, 2));
/*
- * set the command line options provided by the user to override
- * the defaults
+ * by default we set up the preconditioner only once.
+ * this can be overriden by command line.
*/
- ierr = KSPSetFromOptions(solver_data->ksp);
- AssertThrow(ierr == 0, ExcPETScError(ierr));
+ AssertPETSc(KSPSetReusePreconditioner(ksp, PETSC_TRUE));
}
+ /*
+ * set the matrices involved. the last argument is irrelevant here,
+ * since we use the solver only once anyway
+ */
+ AssertPETSc(KSPSetOperators(ksp, A, A));
+
+ /*
+ * set the command line option prefix name
+ */
+ AssertPETSc(KSPSetOptionsPrefix(ksp, prefix_name.c_str()));
+
+ /*
+ * set the command line options provided by the user to override
+ * the defaults
+ */
+ AssertPETSc(KSPSetFromOptions(ksp));
+
/*
* solve the linear system
*/
- PetscErrorCode ierr = KSPSolve(solver_data->ksp, b, x);
- AssertThrow(ierr == 0, ExcPETScError(ierr));
+ AssertPETSc(KSPSolve(ksp, b, x));
/*
* in case of failure throw exception
*/
- if (solver_control.last_check() != SolverControl::success)
+ if (solver_control &&
+ solver_control->last_check() != SolverControl::success)
{
AssertThrow(false,
- SolverControl::NoConvergence(solver_control.last_step(),
- solver_control.last_value()));
- }
- else
- {
- /*
- * obtain convergence information. obtain the number of iterations
- * and residual norm
- */
- ierr = KSPGetIterationNumber(solver_data->ksp, &its);
- AssertThrow(ierr == 0, ExcPETScError(ierr));
- ierr = KSPGetResidualNorm(solver_data->ksp, &rnorm);
- AssertThrow(ierr == 0, ExcPETScError(ierr));
+ SolverControl::NoConvergence(solver_control->last_step(),
+ solver_control->last_value()));
}
# else // DEAL_II_PETSC_WITH_MUMPS
- PetscErrorCode
- SparseDirectMUMPS::convergence_test(KSP /*ksp*/,
- const PetscInt iteration,
- const PetscReal residual_norm,
- KSPConvergedReason *reason,
- void * solver_control_x)
- {
- SolverControl &solver_control =
- *reinterpret_cast<SolverControl *>(solver_control_x);
-
- const SolverControl::State state =
- solver_control.check(iteration, residual_norm);
-
- switch (state)
- {
- case ::dealii::SolverControl::iterate:
- *reason = KSP_CONVERGED_ITERATING;
- break;
-
- case ::dealii::SolverControl::success:
- *reason = static_cast<KSPConvergedReason>(1);
- break;
-
- case ::dealii::SolverControl::failure:
- if (solver_control.last_step() > solver_control.max_steps())
- *reason = KSP_DIVERGED_ITS;
- else
- *reason = KSP_DIVERGED_DTOL;
- break;
-
- default:
- Assert(false, ExcNotImplemented());
- }
-
- return 0;
- }
-
-
-
void
SparseDirectMUMPS::set_symmetric_mode(const bool flag)
{