diff --git a/CMakeLists.txt b/CMakeLists.txt index c45fca3b72..e5c926dda8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -523,10 +523,8 @@ if (BOUT_ENABLE_WARNINGS) ) include(EnableCXXWarningIfSupport) - # Note we explicitly turn off -Wcast-function-type as PETSc *requires* - # we cast a function to the wrong type in MatFDColoringSetFunction target_enable_cxx_warning_if_supported(bout++ - FLAGS -Wnull-dereference -Wno-cast-function-type + FLAGS -Wnull-dereference ) endif() diff --git a/src/solver/impls/imex-bdf2/imex-bdf2.cxx b/src/solver/impls/imex-bdf2/imex-bdf2.cxx index 853d8eaf12..f4096a6b4a 100644 --- a/src/solver/impls/imex-bdf2/imex-bdf2.cxx +++ b/src/solver/impls/imex-bdf2/imex-bdf2.cxx @@ -118,7 +118,25 @@ static PetscErrorCode FormFunctionForColoring(SNES UNUSED(snes), Vec x, Vec f, return static_cast(ctx)->snes_function(x, f, true); } -static PetscErrorCode imexbdf2PCapply(PC pc, Vec x, Vec y) { +// Global context to store IMEXBDF2 instance +static void* imexbdf2_ctx = nullptr; + +#if PETSC_VERSION_GE(3, 24, 0) || PETSC_VERSION_RELEASE == 0 +// Wrapper for PETSc 3.24 and later (signature: PetscErrorCode (*)(void*, Vec, Vec, void*)) +static PetscErrorCode FormFunctionForColoringWrapper(void*, Vec x, Vec y, void* ctx) { + SNES dummy_snes = nullptr; + return FormFunctionForColoring(dummy_snes, x, y, ctx); +} +#else +// Wrapper for PETSc < 3.20 (signature: PetscErrorCode (*)(void)) +static PetscErrorCode FormFunctionForColoringWrapper() { + SNES dummy_snes = nullptr; + Vec dummy_vec = nullptr; + return FormFunctionForColoring(dummy_snes, dummy_vec, dummy_vec, imexbdf2_ctx); +} +#endif + +PetscErrorCode imexbdf2PCapply(PC pc, Vec x, Vec y) { int ierr; // Get the context @@ -651,9 +669,8 @@ void IMEXBDF2::constructSNES(SNES* snesIn) { // Create data structure for SNESComputeJacobianDefaultColor MatFDColoringCreate(Jmf, iscoloring, &fdcoloring); // Set the function to difference - MatFDColoringSetFunction( - fdcoloring, reinterpret_cast(FormFunctionForColoring), - this); + imexbdf2_ctx = this; + MatFDColoringSetFunction(fdcoloring, FormFunctionForColoringWrapper, this); MatFDColoringSetFromOptions(fdcoloring); MatFDColoringSetUp(Jmf, iscoloring, fdcoloring); ISColoringDestroy(&iscoloring); diff --git a/src/solver/impls/petsc/petsc.cxx b/src/solver/impls/petsc/petsc.cxx index 090087d0de..41fe07c03d 100644 --- a/src/solver/impls/petsc/petsc.cxx +++ b/src/solver/impls/petsc/petsc.cxx @@ -61,6 +61,26 @@ extern PetscErrorCode PhysicsPCApply(PC, Vec x, Vec y); extern PetscErrorCode PhysicsJacobianApply(Mat J, Vec x, Vec y); extern PetscErrorCode PhysicsSNESApply(SNES, Vec); +// Global context to store PetscSolver instance +static void* petsc_ctx = nullptr; + +#if PETSC_VERSION_GE(3, 24, 0) || PETSC_VERSION_RELEASE == 0 +// Wrapper for PETSc 3.24 and later (signature: PetscErrorCode (*)(void*, Vec, Vec, void*)) +static PetscErrorCode FormFunctionForColoringWrapper(void*, Vec x, Vec y, void* ctx) { + TS dummy_ts = nullptr; + BoutReal dummy_time = 0.0; + return solver_f(dummy_ts, dummy_time, x, y, ctx); +} +#else +// Wrapper for PETSc < 3.20 (signature: PetscErrorCode (*)(void)) +static PetscErrorCode FormFunctionForColoringWrapper() { + TS dummy_ts = nullptr; + BoutReal dummy_time = 0.0; + Vec dummy_vec = nullptr; + return solver_f(dummy_ts, dummy_time, dummy_vec, dummy_vec, petsc_ctx); +} +#endif + PetscSolver::PetscSolver(Options* opts) : Solver(opts), diagnose( @@ -514,8 +534,8 @@ int PetscSolver::init() { CHKERRQ(ierr); ierr = ISColoringDestroy(&iscoloring); CHKERRQ(ierr); - ierr = MatFDColoringSetFunction(matfdcoloring, - reinterpret_cast(solver_f), this); + petsc_ctx = this; + ierr = MatFDColoringSetFunction(matfdcoloring, FormFunctionForColoringWrapper, this); CHKERRQ(ierr); ierr = SNESSetJacobian(snes, J, J, SNESComputeJacobianDefaultColor, matfdcoloring); CHKERRQ(ierr); diff --git a/src/solver/impls/snes/snes.cxx b/src/solver/impls/snes/snes.cxx index 4dce1e7086..d6dd735fde 100644 --- a/src/solver/impls/snes/snes.cxx +++ b/src/solver/impls/snes/snes.cxx @@ -86,6 +86,24 @@ static PetscErrorCode FormFunctionForColoring(SNES UNUSED(snes), Vec x, Vec f, return static_cast(ctx)->snes_function(x, f, true); } +// Global context to store SNESSolver instance +static void* snes_ctx = nullptr; + +#if PETSC_VERSION_GE(3, 24, 0) || PETSC_VERSION_RELEASE == 0 +// Wrapper for PETSc 3.24 and later (signature: PetscErrorCode (*)(void*, Vec, Vec, void*)) +static PetscErrorCode FormFunctionForColoringWrapper(void*, Vec x, Vec y, void* ctx) { + SNES dummy_snes = nullptr; + return FormFunctionForColoring(dummy_snes, x, y, ctx); +} +#else +// Wrapper for PETSc < 3.20 (signature: PetscErrorCode (*)(void)) +static PetscErrorCode FormFunctionForColoringWrapper() { + SNES dummy_snes = nullptr; + Vec dummy_vec = nullptr; + return FormFunctionForColoring(dummy_snes, dummy_vec, dummy_vec, snes_ctx); +} +#endif + static PetscErrorCode snesPCapply(PC pc, Vec x, Vec y) { int ierr; @@ -1291,8 +1309,8 @@ void SNESSolver::updateColoring() { // Replace the old coloring with the new one MatFDColoringDestroy(&fdcoloring); MatFDColoringCreate(Jfd, iscoloring, &fdcoloring); - MatFDColoringSetFunction( - fdcoloring, reinterpret_cast(FormFunctionForColoring), this); + snes_ctx = this; + MatFDColoringSetFunction(fdcoloring, FormFunctionForColoringWrapper, this); MatFDColoringSetFromOptions(fdcoloring); MatFDColoringSetUp(Jfd, iscoloring, fdcoloring); ISColoringDestroy(&iscoloring);