From 58588d4abeb89b6f7f7590f417bdc8406cf02a61 Mon Sep 17 00:00:00 2001 From: tomc271 Date: Wed, 4 Jun 2025 11:25:09 +0100 Subject: [PATCH 1/6] Use a wrapper function to handle FormFunctionForColoring signature mismatch Using reinterpret_cast no longer works. Expected signature is PetscErrorCode (*)() but is PetscErrorCode (*)(SNES, Vec, Vec, void*) on main branch. For the newer version the current solver instance must be passed as the 'cxt' argument, so store 'this' instance in a global variable (before calling MatFDColoringSetFunction). Have to do it this way because the function passed as the (second) argument to MatFDColoringSetFunction must be a free function, so cannot make the function wrapper an instance method and pass 'this' from there. --- src/solver/impls/imex-bdf2/imex-bdf2.cxx | 31 ++++++++++++++++++------ 1 file changed, 24 insertions(+), 7 deletions(-) diff --git a/src/solver/impls/imex-bdf2/imex-bdf2.cxx b/src/solver/impls/imex-bdf2/imex-bdf2.cxx index 853d8eaf12..7587d04aeb 100644 --- a/src/solver/impls/imex-bdf2/imex-bdf2.cxx +++ b/src/solver/impls/imex-bdf2/imex-bdf2.cxx @@ -113,12 +113,30 @@ static PetscErrorCode FormFunctionForDifferencing(void* ctx, Vec x, Vec f) { * * This can be a linearised and simplified form of FormFunction */ -static PetscErrorCode FormFunctionForColoring(SNES UNUSED(snes), Vec x, Vec f, - void* ctx) { - return static_cast(ctx)->snes_function(x, f, true); +static PetscErrorCode FormFunctionForColoring(SNES UNUSED(snes), Vec x, Vec f, void* ctx) { + return static_cast(ctx)->snes_function(x, f, true); +} + +// 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; + imexbdf2_ctx = ctx; // Update context + 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 -static PetscErrorCode imexbdf2PCapply(PC pc, Vec x, Vec y) { +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); From a51fa0fa670b5571f6d6dbacf7998810d489ccee Mon Sep 17 00:00:00 2001 From: tomc271 Date: Wed, 4 Jun 2025 17:00:55 +0100 Subject: [PATCH 2/6] No need to update imexbdf2_ctx in FormFunctionForColoringWrapper(void*, Vec x, Vec y, void* ctx) --- src/solver/impls/imex-bdf2/imex-bdf2.cxx | 1 - 1 file changed, 1 deletion(-) diff --git a/src/solver/impls/imex-bdf2/imex-bdf2.cxx b/src/solver/impls/imex-bdf2/imex-bdf2.cxx index 7587d04aeb..0b78bf7834 100644 --- a/src/solver/impls/imex-bdf2/imex-bdf2.cxx +++ b/src/solver/impls/imex-bdf2/imex-bdf2.cxx @@ -124,7 +124,6 @@ static void* imexbdf2_ctx = nullptr; // 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; - imexbdf2_ctx = ctx; // Update context return FormFunctionForColoring(dummy_snes, x, y, ctx); } #else From fc2e6bddeb5344b30320045c8d52fbfa847aed2a Mon Sep 17 00:00:00 2001 From: tomc271 Date: Wed, 4 Jun 2025 13:10:48 +0100 Subject: [PATCH 3/6] Apply the same fix to PetscSolver Use a wrapper around solver_f for passing as the second argument to MatFDColoringSetFunction. --- src/solver/impls/petsc/petsc.cxx | 24 ++++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/src/solver/impls/petsc/petsc.cxx b/src/solver/impls/petsc/petsc.cxx index 090087d0de..b4fb5f5e3a 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); From 607fffe57697c4b1aea47eecd0aa8341be550c8b Mon Sep 17 00:00:00 2001 From: tomc271 Date: Wed, 4 Jun 2025 17:40:29 +0100 Subject: [PATCH 4/6] Apply the same fix to the SNESSolver --- src/solver/impls/snes/snes.cxx | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/src/solver/impls/snes/snes.cxx b/src/solver/impls/snes/snes.cxx index 4dce1e7086..e5ab207720 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); From fdaeb45538644aea98b19e54b202b732158732e3 Mon Sep 17 00:00:00 2001 From: tomc271 Date: Wed, 4 Jun 2025 18:07:41 +0100 Subject: [PATCH 5/6] No longer any need to disable -Wcast-function-type --- CMakeLists.txt | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) 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() From 6d6be6b64d636031c5ff4522bc035c60ba7b2e23 Mon Sep 17 00:00:00 2001 From: tomc271 <58003025+tomc271@users.noreply.github.com> Date: Wed, 4 Jun 2025 18:29:04 +0000 Subject: [PATCH 6/6] Apply clang-format changes --- src/solver/impls/imex-bdf2/imex-bdf2.cxx | 15 ++++++++------- src/solver/impls/petsc/petsc.cxx | 14 +++++++------- src/solver/impls/snes/snes.cxx | 10 +++++----- 3 files changed, 20 insertions(+), 19 deletions(-) diff --git a/src/solver/impls/imex-bdf2/imex-bdf2.cxx b/src/solver/impls/imex-bdf2/imex-bdf2.cxx index 0b78bf7834..f4096a6b4a 100644 --- a/src/solver/impls/imex-bdf2/imex-bdf2.cxx +++ b/src/solver/impls/imex-bdf2/imex-bdf2.cxx @@ -113,8 +113,9 @@ static PetscErrorCode FormFunctionForDifferencing(void* ctx, Vec x, Vec f) { * * This can be a linearised and simplified form of FormFunction */ -static PetscErrorCode FormFunctionForColoring(SNES UNUSED(snes), Vec x, Vec f, void* ctx) { - return static_cast(ctx)->snes_function(x, f, true); +static PetscErrorCode FormFunctionForColoring(SNES UNUSED(snes), Vec x, Vec f, + void* ctx) { + return static_cast(ctx)->snes_function(x, f, true); } // Global context to store IMEXBDF2 instance @@ -123,15 +124,15 @@ 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); + 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); + SNES dummy_snes = nullptr; + Vec dummy_vec = nullptr; + return FormFunctionForColoring(dummy_snes, dummy_vec, dummy_vec, imexbdf2_ctx); } #endif diff --git a/src/solver/impls/petsc/petsc.cxx b/src/solver/impls/petsc/petsc.cxx index b4fb5f5e3a..41fe07c03d 100644 --- a/src/solver/impls/petsc/petsc.cxx +++ b/src/solver/impls/petsc/petsc.cxx @@ -67,17 +67,17 @@ 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); + 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); + 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 diff --git a/src/solver/impls/snes/snes.cxx b/src/solver/impls/snes/snes.cxx index e5ab207720..d6dd735fde 100644 --- a/src/solver/impls/snes/snes.cxx +++ b/src/solver/impls/snes/snes.cxx @@ -92,15 +92,15 @@ 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); + 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); + SNES dummy_snes = nullptr; + Vec dummy_vec = nullptr; + return FormFunctionForColoring(dummy_snes, dummy_vec, dummy_vec, snes_ctx); } #endif