From 3db449370dae023c6284fd9e5d14e3f43925d58f Mon Sep 17 00:00:00 2001 From: Stefano Zampini Date: Fri, 16 Jun 2023 01:26:28 +0300 Subject: [PATCH] PETSc: Fix backward compatibility --- include/deal.II/lac/petsc_compatibility.h | 39 ++++++++++++++++++++++ include/deal.II/lac/petsc_snes.templates.h | 6 ++-- include/deal.II/lac/petsc_ts.templates.h | 9 ++--- source/lac/petsc_compatibility.cc | 28 +++++++++++++++- source/lac/petsc_precondition.cc | 6 ++-- tests/petsc/vector_wrap_01.cc | 4 --- tests/petsc_complex/17.cc | 4 --- tests/petsc_complex/vector_wrap_01.cc | 4 --- tests/tests.h | 2 -- 9 files changed, 78 insertions(+), 24 deletions(-) diff --git a/include/deal.II/lac/petsc_compatibility.h b/include/deal.II/lac/petsc_compatibility.h index 1b94af4903..bd061ea8fb 100644 --- a/include/deal.II/lac/petsc_compatibility.h +++ b/include/deal.II/lac/petsc_compatibility.h @@ -16,6 +16,12 @@ /* * Rather than using ifdefs everywhere, try to wrap older versions of PETSc * functions in one place. + * + * Functions that are not inlined are: + * - Functions returning PetscErrorCode that are supposed to be called within + * PETSc callbacks. + * - Functions that need access to internal PETSc headers that we don't want + * to expose to deal.II users */ #ifndef dealii_petsc_compatibility_h #define dealii_petsc_compatibility_h @@ -98,24 +104,47 @@ namespace PETScWrappers set_matrix_option(matrix, MAT_KEEP_NONZERO_PATTERN, PETSC_TRUE); } + + /** * Tell PETSc that the status of the vector has changed. */ void petsc_increment_state_counter(Vec v); + + /** * Tell PETSc that the status of the matrix has changed. */ void petsc_increment_state_counter(Mat A); + + /** + * Set the failed reason for the preconditioner. + */ + PetscErrorCode + pc_set_failed_reason(PC pc, PCFailedReason reason); + + + /** * Resets internal domain error flags in the SNES object. */ void snes_reset_domain_flags(SNES snes); + + + /** + * Resets internal domain error flags in the SNES object. + */ + void + snes_set_jacobian_domain_error(SNES snes); + + + /** * Tell PETSc nonlinear solver to use matrix free finite differencing (MFFD). * @@ -128,6 +157,8 @@ namespace PETScWrappers void set_use_matrix_free(SNES snes, const bool mf_operator, const bool mf); + + /** * Tell PETSc ODE solver to use matrix free finite differencing (MFFD). * @@ -140,24 +171,32 @@ namespace PETScWrappers void set_use_matrix_free(TS ts, const bool mf_operator, const bool mf); + + /** * Set final time for ODE integration. */ void ts_set_max_time(TS ts, const PetscReal maxtime); + + /** * Set maximum number of steps for ODE integration. */ void ts_set_max_steps(TS ts, const PetscInt maxsteps); + + /** * Return current step number. */ unsigned int ts_get_step_number(TS ts); + + /** * Return true if the TS has a SNES object. */ diff --git a/include/deal.II/lac/petsc_snes.templates.h b/include/deal.II/lac/petsc_snes.templates.h index cf5af01c4d..f9dbfb674e 100644 --- a/include/deal.II/lac/petsc_snes.templates.h +++ b/include/deal.II/lac/petsc_snes.templates.h @@ -226,7 +226,9 @@ namespace PETScWrappers AssertPETSc(SNESReset(snes)); // By default PETSc does not check for Jacobian errors in optimized // mode. Here we do it unconditionally. +# if DEAL_II_PETSC_VERSION_GTE(3, 11, 0) AssertPETSc(SNESSetCheckJacobianDomainError(snes, PETSC_TRUE)); +# endif } @@ -378,7 +380,7 @@ namespace PETScWrappers const int err = call_and_possibly_capture_snes_exception( user->jacobian, user->pending_exception, - [snes]() -> void { AssertPETSc(SNESSetJacobianDomainError(snes)); }, + [snes]() -> void { snes_set_jacobian_domain_error(snes); }, xdealii, Adealii, Pdealii); @@ -424,7 +426,7 @@ namespace PETScWrappers const int err = call_and_possibly_capture_snes_exception( user->setup_jacobian, user->pending_exception, - [snes]() -> void { AssertPETSc(SNESSetJacobianDomainError(snes)); }, + [snes]() -> void { snes_set_jacobian_domain_error(snes); }, xdealii); if (err) return PetscError( diff --git a/include/deal.II/lac/petsc_ts.templates.h b/include/deal.II/lac/petsc_ts.templates.h index 3061a17764..f071222ad9 100644 --- a/include/deal.II/lac/petsc_ts.templates.h +++ b/include/deal.II/lac/petsc_ts.templates.h @@ -492,7 +492,7 @@ namespace PETScWrappers [ts]() -> void { SNES snes; AssertPETSc(TSGetSNES(ts, &snes)); - AssertPETSc(SNESSetJacobianDomainError(snes)); + snes_set_jacobian_domain_error(snes); }, t, xdealii, @@ -553,7 +553,7 @@ namespace PETScWrappers [ts]() -> void { SNES snes; AssertPETSc(TSGetSNES(ts, &snes)); - AssertPETSc(SNESSetJacobianDomainError(snes)); + snes_set_jacobian_domain_error(snes); }, t, xdealii, @@ -653,7 +653,7 @@ namespace PETScWrappers [ts]() -> void { SNES snes; AssertPETSc(TSGetSNES(ts, &snes)); - AssertPETSc(SNESSetJacobianDomainError(snes)); + snes_set_jacobian_domain_error(snes); }, t, xdealii, @@ -869,13 +869,14 @@ namespace PETScWrappers // By default PETSc does not check for Jacobian errors in optimized // mode. Here we do it unconditionally. +# if DEAL_II_PETSC_VERSION_GTE(3, 11, 0) if (ts_has_snes(ts)) { SNES snes; AssertPETSc(TSGetSNES(ts, &snes)); AssertPETSc(SNESSetCheckJacobianDomainError(snes, PETSC_TRUE)); } - +# endif // Having set everything up, now do the actual work // and let PETSc do the time stepping. If there is // a pending exception, then one of the user callbacks diff --git a/source/lac/petsc_compatibility.cc b/source/lac/petsc_compatibility.cc index ad702fce50..b787052001 100644 --- a/source/lac/petsc_compatibility.cc +++ b/source/lac/petsc_compatibility.cc @@ -22,6 +22,7 @@ #ifdef DEAL_II_WITH_PETSC +# include # include # include # include @@ -52,11 +53,36 @@ namespace PETScWrappers AssertPETSc(PetscObjectStateIncrease(reinterpret_cast(A))); } + PetscErrorCode + pc_set_failed_reason(PC pc, PCFailedReason reason) + { +# if DEAL_II_PETSC_VERSION_GTE(3, 14, 0) + return PCSetFailedReason(pc, reason); +# else + pc->failedreason = reason; + return 0; +# endif + } + void snes_reset_domain_flags(SNES snes) { +# if DEAL_II_PETSC_VERSION_GTE(3, 11, 0) snes->jacobiandomainerror = PETSC_FALSE; - snes->domainerror = PETSC_FALSE; +# endif + snes->domainerror = PETSC_FALSE; + } + + void + snes_set_jacobian_domain_error(SNES snes) + { +# if DEAL_II_PETSC_VERSION_GTE(3, 11, 0) + snes->jacobiandomainerror = PETSC_TRUE; +# else + // There is no equivalent, and since this used to stop + // computations, we opt to set the converged reason + snes->reason = SNES_DIVERGED_FUNCTION_DOMAIN; +# endif } void diff --git a/source/lac/petsc_precondition.cc b/source/lac/petsc_precondition.cc index 94f1122572..f018a7bdc0 100644 --- a/source/lac/petsc_precondition.cc +++ b/source/lac/petsc_precondition.cc @@ -1113,7 +1113,7 @@ namespace PETScWrappers // Failed reason is not reset uniformly within the // interface code of PCSetUp in PETSc. // We handle it here. - PetscCall(PCSetFailedReason(ppc, PC_NOERROR)); + PetscCall(pc_set_failed_reason(ppc, PC_NOERROR)); PetscFunctionReturn(0); } @@ -1141,7 +1141,7 @@ namespace PETScWrappers } catch (const RecoverableUserCallbackError &) { - PetscCall(PCSetFailedReason(ppc, PC_SUBPC_ERROR)); + PetscCall(pc_set_failed_reason(ppc, PC_SUBPC_ERROR)); } catch (...) { @@ -1182,7 +1182,7 @@ namespace PETScWrappers } catch (const RecoverableUserCallbackError &) { - PetscCall(PCSetFailedReason(ppc, PC_SUBPC_ERROR)); + PetscCall(pc_set_failed_reason(ppc, PC_SUBPC_ERROR)); } catch (...) { diff --git a/tests/petsc/vector_wrap_01.cc b/tests/petsc/vector_wrap_01.cc index dff5c14c73..2dc83293b4 100644 --- a/tests/petsc/vector_wrap_01.cc +++ b/tests/petsc/vector_wrap_01.cc @@ -61,11 +61,7 @@ main(int argc, char **argv) test(v, w); } -#if DEAL_II_PETSC_VERSION_LT(3, 2, 0) - ierr = VecDestroy(vpetsc); -#else ierr = VecDestroy(&vpetsc); -#endif AssertThrow(ierr == 0, ExcPETScError(ierr)); } diff --git a/tests/petsc_complex/17.cc b/tests/petsc_complex/17.cc index fb15449229..17653fbaa0 100644 --- a/tests/petsc_complex/17.cc +++ b/tests/petsc_complex/17.cc @@ -34,11 +34,7 @@ test(PETScWrappers::MPI::Vector &v) { const PetscScalar s(1. * k, 2. * k); v(k) = s; -#if DEAL_II_PETSC_VERSION_LT(3, 7, 0) - norm += std::fabs(1. * k) + std::fabs(2. * k); -#else norm += std::abs(s); -#endif } v.compress(VectorOperation::insert); diff --git a/tests/petsc_complex/vector_wrap_01.cc b/tests/petsc_complex/vector_wrap_01.cc index 7acb96b363..044cde359b 100644 --- a/tests/petsc_complex/vector_wrap_01.cc +++ b/tests/petsc_complex/vector_wrap_01.cc @@ -61,11 +61,7 @@ main(int argc, char **argv) test(v, w); } -#if DEAL_II_PETSC_VERSION_LT(3, 2, 0) - ierr = VecDestroy(vpetsc); -#else ierr = VecDestroy(&vpetsc); -#endif AssertThrow(ierr == 0, ExcPETScError(ierr)); } diff --git a/tests/tests.h b/tests/tests.h index 16185387d9..d5c6250d5f 100644 --- a/tests/tests.h +++ b/tests/tests.h @@ -461,7 +461,6 @@ namespace void check_petsc_allocations() { -# if DEAL_II_PETSC_VERSION_GTE(3, 2, 0) PetscStageLog stageLog; PetscLogGetStageLog(&stageLog); @@ -492,7 +491,6 @@ namespace if (errors) throw dealii::ExcMessage("PETSc memory leak"); -# endif } } // namespace #endif -- 2.39.5