From 52df25058906fb892d834571552981b85ebaf480 Mon Sep 17 00:00:00 2001 From: Wolfgang Bangerth Date: Tue, 9 May 2023 09:19:05 -0600 Subject: [PATCH] Clean up after ourselves. --- source/sundials/kinsol.cc | 56 ++++++++++++++++++++++++--------------- 1 file changed, 34 insertions(+), 22 deletions(-) diff --git a/source/sundials/kinsol.cc b/source/sundials/kinsol.cc index a1db0684e1..a37bbaea0c 100644 --- a/source/sundials/kinsol.cc +++ b/source/sundials/kinsol.cc @@ -21,6 +21,7 @@ #ifdef DEAL_II_WITH_SUNDIALS +# include # include # include @@ -657,9 +658,40 @@ namespace SUNDIALS // recover and we no longer need the exception // - If we have any other exception, rethrow it // - If no exception, test that SUNDIALS really did successfully return + // + // This all creates difficult exit paths from this function. We have to + // do some manual clean ups to get rid of the explicitly created + // temporary objects of this class. To avoid having to repeat the clean-up + // code on each exit path, we package it up and put the code into a + // ScopeExit object that is executed automatically on each such path + // out of this function. Assert(pending_exception == nullptr, ExcInternalError()); status = KINSol(kinsol_mem, solution, data.strategy, u_scale, f_scale); + ScopeExit upon_exit([this, &J, &LS]() mutable { + // Free the vectors which are no longer used. +# ifdef DEAL_II_WITH_MPI + if (is_serial_vector::value == false) + { + N_VDestroy_Parallel(solution); + N_VDestroy_Parallel(u_scale); + N_VDestroy_Parallel(f_scale); + } + else +# endif + { + N_VDestroy_Serial(solution); + N_VDestroy_Serial(u_scale); + N_VDestroy_Serial(f_scale); + } + + if (J != nullptr) + SUNMatDestroy(J); + if (LS != nullptr) + SUNLinSolFree(LS); + KINFree(&kinsol_mem); + }); + if (pending_exception) { try @@ -684,35 +716,15 @@ namespace SUNDIALS internal::copy(initial_guess_and_solution, solution); - // Free the vectors which are no longer used. -# ifdef DEAL_II_WITH_MPI - if (is_serial_vector::value == false) - { - N_VDestroy_Parallel(solution); - N_VDestroy_Parallel(u_scale); - N_VDestroy_Parallel(f_scale); - } - else -# endif - { - N_VDestroy_Serial(solution); - N_VDestroy_Serial(u_scale); - N_VDestroy_Serial(f_scale); - } - long nniters; status = KINGetNumNonlinSolvIters(kinsol_mem, &nniters); AssertKINSOL(status); - if (J != nullptr) - SUNMatDestroy(J); - if (LS != nullptr) - SUNLinSolFree(LS); - KINFree(&kinsol_mem); - return static_cast(nniters); } + + template void KINSOL::set_functions_to_trigger_an_assert() -- 2.39.5