From: Wolfgang Bangerth Date: Tue, 9 May 2023 15:19:05 +0000 (-0600) Subject: Clean up after ourselves. X-Git-Tag: v9.5.0-rc1~243^2 X-Git-Url: https://gitweb.dealii.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=52df25058906fb892d834571552981b85ebaf480;p=dealii.git Clean up after ourselves. --- 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()