]> https://gitweb.dealii.org/ - dealii.git/commitdiff
Unify multiple copies of the same function. 15295/head
authorWolfgang Bangerth <bangerth@colostate.edu>
Thu, 1 Jun 2023 21:36:37 +0000 (15:36 -0600)
committerWolfgang Bangerth <bangerth@colostate.edu>
Thu, 1 Jun 2023 21:36:37 +0000 (15:36 -0600)
include/deal.II/sundials/utilities.h [new file with mode: 0644]
source/sundials/arkode.cc
source/sundials/ida.cc
source/sundials/kinsol.cc

diff --git a/include/deal.II/sundials/utilities.h b/include/deal.II/sundials/utilities.h
new file mode 100644 (file)
index 0000000..7a509bb
--- /dev/null
@@ -0,0 +1,106 @@
+// ---------------------------------------------------------------------
+//
+// Copyright (C) 2023 by the deal.II authors
+//
+// This file is part of the deal.II library.
+//
+// The deal.II library is free software; you can use it, redistribute
+// it, and/or modify it under the terms of the GNU Lesser General
+// Public License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+// The full text of the license can be found in the file LICENSE.md at
+// the top level directory of deal.II.
+//
+// ---------------------------------------------------------------------
+
+
+#ifndef dealii_sundials_utilities_h
+#define dealii_sundials_utilities_h
+
+#include <deal.II/base/config.h>
+
+#ifdef DEAL_II_WITH_SUNDIALS
+#  include <exception>
+
+
+DEAL_II_NAMESPACE_OPEN
+
+namespace SUNDIALS
+{
+  namespace Utilities
+  {
+    /**
+     * A function that calls the function object given by its first argument
+     * with the set of arguments following at the end. If the call returns
+     * regularly, the current function returns zero to indicate success. If the
+     * call fails with an exception of type RecoverableUserCallbackError, then
+     * the current function returns 1 to indicate that the called function
+     * object thought the error it encountered is recoverable. If the call fails
+     * with any other exception, then the current function returns with an error
+     * code of -1. In each of the last two cases, the exception thrown by `f`
+     * is captured and `eptr` is set to the exception. In case of success,
+     * `eptr` is set to `nullptr`.
+     */
+    template <typename F, typename... Args>
+    int
+    call_and_possibly_capture_exception(const F &           f,
+                                        std::exception_ptr &eptr,
+                                        Args &&...args)
+    {
+      // See whether there is already something in the exception pointer
+      // variable. This can only happen if we had previously had
+      // a recoverable exception, and the underlying library actually
+      // did recover successfully. In that case, we can abandon the
+      // exception previously thrown. If eptr contains anything other,
+      // then we really don't know how that could have happened, and
+      // should probably bail out:
+      if (eptr)
+        {
+          try
+            {
+              std::rethrow_exception(eptr);
+            }
+          catch (const RecoverableUserCallbackError &)
+            {
+              // ok, ignore, but reset the pointer
+              eptr = nullptr;
+            }
+          catch (...)
+            {
+              // uh oh:
+              AssertThrow(false, ExcInternalError());
+            }
+        }
+
+      // Call the function and if that succeeds, return zero:
+      try
+        {
+          f(std::forward<Args>(args)...);
+          eptr = nullptr;
+          return 0;
+        }
+      // If the call failed with a recoverable error, then
+      // ignore the exception for now (but store a pointer to it)
+      // and return a positive return value (+1). If the underlying
+      // implementation manages to recover
+      catch (const RecoverableUserCallbackError &)
+        {
+          eptr = std::current_exception();
+          return 1;
+        }
+      // For any other exception, capture the exception and
+      // return -1:
+      catch (const std::exception &)
+        {
+          eptr = std::current_exception();
+          return -1;
+        }
+    }
+  } // namespace Utilities
+} // namespace SUNDIALS
+
+DEAL_II_NAMESPACE_CLOSE
+
+#endif // DEAL_II_WITH_SUNDIALS
+
+#endif
index dd29cf218810aade7117917f2dc8f7a0550c6779..fdbd600b96566f59e933a87521d2d74175672af2 100644 (file)
@@ -38,6 +38,7 @@
 
 #  include <deal.II/sundials/n_vector.h>
 #  include <deal.II/sundials/sunlinsol_wrapper.h>
+#  include <deal.II/sundials/utilities.h>
 
 #  include <arkode/arkode_arkstep.h>
 #  include <sunlinsol/sunlinsol_spgmr.h>
@@ -49,79 +50,6 @@ DEAL_II_NAMESPACE_OPEN
 
 namespace SUNDIALS
 {
-  namespace
-  {
-    /**
-     * A function that calls the function object given by its first argument
-     * with the set of arguments following at the end. If the call returns
-     * regularly, the current function returns zero to indicate success. If the
-     * call fails with an exception of type RecoverableUserCallbackError, then
-     * the current function returns 1 to indicate that the called function
-     * object thought the error it encountered is recoverable. If the call fails
-     * with any other exception, then the current function returns with an error
-     * code of -1. In each of the last two cases, the exception thrown by `f`
-     * is captured and `eptr` is set to the exception. In case of success,
-     * `eptr` is set to `nullptr`.
-     */
-    template <typename F, typename... Args>
-    int
-    call_and_possibly_capture_exception(const F &           f,
-                                        std::exception_ptr &eptr,
-                                        Args &&...args)
-    {
-      // See whether there is already something in the exception pointer
-      // variable. This can only happen if we had previously had
-      // a recoverable exception, and the underlying library actually
-      // did recover successfully. In that case, we can abandon the
-      // exception previously thrown. If eptr contains anything other,
-      // then we really don't know how that could have happened, and
-      // should probably bail out:
-      if (eptr)
-        {
-          try
-            {
-              std::rethrow_exception(eptr);
-            }
-          catch (const RecoverableUserCallbackError &)
-            {
-              // ok, ignore, but reset the pointer
-              eptr = nullptr;
-            }
-          catch (...)
-            {
-              // uh oh:
-              AssertThrow(false, ExcInternalError());
-            }
-        }
-
-      // Call the function and if that succeeds, return zero:
-      try
-        {
-          f(std::forward<Args>(args)...);
-          eptr = nullptr;
-          return 0;
-        }
-      // If the call failed with a recoverable error, then
-      // ignore the exception for now (but store a pointer to it)
-      // and return a positive return value (+1). If the underlying
-      // implementation manages to recover
-      catch (const RecoverableUserCallbackError &)
-        {
-          eptr = std::current_exception();
-          return 1;
-        }
-      // For any other exception, capture the exception and
-      // return -1:
-      catch (const std::exception &)
-        {
-          eptr = std::current_exception();
-          return -1;
-        }
-    }
-  } // namespace
-
-
-
   template <typename VectorType>
   ARKode<VectorType>::ARKode(const AdditionalData &data)
     : ARKode(data, MPI_COMM_SELF)
@@ -350,11 +278,12 @@ namespace SUNDIALS
       auto *src_yy = internal::unwrap_nvector_const<VectorType>(yy);
       auto *dst_yp = internal::unwrap_nvector<VectorType>(yp);
 
-      return call_and_possibly_capture_exception(solver.explicit_function,
-                                                 solver.pending_exception,
-                                                 tt,
-                                                 *src_yy,
-                                                 *dst_yp);
+      return Utilities::call_and_possibly_capture_exception(
+        solver.explicit_function,
+        solver.pending_exception,
+        tt,
+        *src_yy,
+        *dst_yp);
     };
 
 
@@ -367,11 +296,12 @@ namespace SUNDIALS
       auto *src_yy = internal::unwrap_nvector_const<VectorType>(yy);
       auto *dst_yp = internal::unwrap_nvector<VectorType>(yp);
 
-      return call_and_possibly_capture_exception(solver.implicit_function,
-                                                 solver.pending_exception,
-                                                 tt,
-                                                 *src_yy,
-                                                 *dst_yp);
+      return Utilities::call_and_possibly_capture_exception(
+        solver.implicit_function,
+        solver.pending_exception,
+        tt,
+        *src_yy,
+        *dst_yp);
     };
 
     arkode_mem = ARKStepCreate(explicit_function ? explicit_function_callback :
@@ -501,7 +431,7 @@ namespace SUNDIALS
 
           auto *dst_Jv = internal::unwrap_nvector<VectorType>(Jv);
 
-          return call_and_possibly_capture_exception(
+          return Utilities::call_and_possibly_capture_exception(
             solver.jacobian_times_vector,
             solver.pending_exception,
             *src_v,
@@ -520,7 +450,7 @@ namespace SUNDIALS
           auto *src_y  = internal::unwrap_nvector_const<VectorType>(y);
           auto *src_fy = internal::unwrap_nvector_const<VectorType>(fy);
 
-          return call_and_possibly_capture_exception(
+          return Utilities::call_and_possibly_capture_exception(
             solver.jacobian_times_setup,
             solver.pending_exception,
             t,
@@ -554,7 +484,7 @@ namespace SUNDIALS
 
               auto *dst_z = internal::unwrap_nvector<VectorType>(z);
 
-              return call_and_possibly_capture_exception(
+              return Utilities::call_and_possibly_capture_exception(
                 solver.jacobian_preconditioner_solve,
                 solver.pending_exception,
                 t,
@@ -581,7 +511,7 @@ namespace SUNDIALS
               auto *src_y  = internal::unwrap_nvector_const<VectorType>(y);
               auto *src_fy = internal::unwrap_nvector_const<VectorType>(fy);
 
-              return call_and_possibly_capture_exception(
+              return Utilities::call_and_possibly_capture_exception(
                 solver.jacobian_preconditioner_setup,
                 solver.pending_exception,
                 t,
@@ -696,9 +626,8 @@ namespace SUNDIALS
           ARKode<VectorType> &solver =
             *static_cast<ARKode<VectorType> *>(mtimes_data);
 
-          return call_and_possibly_capture_exception(solver.mass_times_setup,
-                                                     solver.pending_exception,
-                                                     t);
+          return Utilities::call_and_possibly_capture_exception(
+            solver.mass_times_setup, solver.pending_exception, t);
         };
 
         auto mass_matrix_times_vector_callback =
@@ -710,11 +639,12 @@ namespace SUNDIALS
           auto *src_v  = internal::unwrap_nvector_const<VectorType>(v);
           auto *dst_Mv = internal::unwrap_nvector<VectorType>(Mv);
 
-          return call_and_possibly_capture_exception(solver.mass_times_vector,
-                                                     solver.pending_exception,
-                                                     t,
-                                                     *src_v,
-                                                     *dst_Mv);
+          return Utilities::call_and_possibly_capture_exception(
+            solver.mass_times_vector,
+            solver.pending_exception,
+            t,
+            *src_v,
+            *dst_Mv);
         };
 
         status = ARKStepSetMassTimes(arkode_mem,
@@ -733,7 +663,7 @@ namespace SUNDIALS
               ARKode<VectorType> &solver =
                 *static_cast<ARKode<VectorType> *>(user_data);
 
-              return call_and_possibly_capture_exception(
+              return Utilities::call_and_possibly_capture_exception(
                 solver.mass_preconditioner_setup, solver.pending_exception, t);
             };
 
@@ -750,7 +680,7 @@ namespace SUNDIALS
               auto *src_r = internal::unwrap_nvector_const<VectorType>(r);
               auto *dst_z = internal::unwrap_nvector<VectorType>(z);
 
-              return call_and_possibly_capture_exception(
+              return Utilities::call_and_possibly_capture_exception(
                 solver.mass_preconditioner_solve,
                 solver.pending_exception,
                 t,
index 8b8597a477b1f25b4841d2862546a38865fef875..ec4a3e6f5ab4e5bac21b90f446b8e1600a10c854 100644 (file)
@@ -36,6 +36,7 @@
 #  endif
 
 #  include <deal.II/sundials/n_vector.h>
+#  include <deal.II/sundials/utilities.h>
 
 #  include <iomanip>
 #  include <iostream>
@@ -44,78 +45,6 @@ DEAL_II_NAMESPACE_OPEN
 
 namespace SUNDIALS
 {
-  namespace
-  {
-    /**
-     * A function that calls the function object given by its first argument
-     * with the set of arguments following at the end. If the call returns
-     * regularly, the current function returns zero to indicate success. If the
-     * call fails with an exception of type RecoverableUserCallbackError, then
-     * the current function returns 1 to indicate that the called function
-     * object thought the error it encountered is recoverable. If the call fails
-     * with any other exception, then the current function returns with an error
-     * code of -1. In each of the last two cases, the exception thrown by `f`
-     * is captured and `eptr` is set to the exception. In case of success,
-     * `eptr` is set to `nullptr`.
-     */
-    template <typename F, typename... Args>
-    int
-    call_and_possibly_capture_exception(const F &           f,
-                                        std::exception_ptr &eptr,
-                                        Args &&...args)
-    {
-      // See whether there is already something in the exception pointer
-      // variable. This can only happen if we had previously had
-      // a recoverable exception, and the underlying library actually
-      // did recover successfully. In that case, we can abandon the
-      // exception previously thrown. If eptr contains anything other,
-      // then we really don't know how that could have happened, and
-      // should probably bail out:
-      if (eptr)
-        {
-          try
-            {
-              std::rethrow_exception(eptr);
-            }
-          catch (const RecoverableUserCallbackError &)
-            {
-              // ok, ignore, but reset the pointer
-              eptr = nullptr;
-            }
-          catch (...)
-            {
-              // uh oh:
-              AssertThrow(false, ExcInternalError());
-            }
-        }
-
-      // Call the function and if that succeeds, return zero:
-      try
-        {
-          f(std::forward<Args>(args)...);
-          eptr = nullptr;
-          return 0;
-        }
-      // If the call failed with a recoverable error, then
-      // ignore the exception for now (but store a pointer to it)
-      // and return a positive return value (+1). If the underlying
-      // implementation manages to recover
-      catch (const RecoverableUserCallbackError &)
-        {
-          eptr = std::current_exception();
-          return 1;
-        }
-      // For any other exception, capture the exception and
-      // return -1:
-      catch (const std::exception &)
-        {
-          eptr = std::current_exception();
-          return -1;
-        }
-    }
-  } // namespace
-
-
   template <typename VectorType>
   IDA<VectorType>::IDA(const AdditionalData &data)
     : IDA(data, MPI_COMM_SELF)
@@ -306,12 +235,13 @@ namespace SUNDIALS
         auto *src_yp   = internal::unwrap_nvector_const<VectorType>(yp);
         auto *residual = internal::unwrap_nvector<VectorType>(rr);
 
-        return call_and_possibly_capture_exception(solver.residual,
-                                                   solver.pending_exception,
-                                                   tt,
-                                                   *src_yy,
-                                                   *src_yp,
-                                                   *residual);
+        return Utilities::call_and_possibly_capture_exception(
+          solver.residual,
+          solver.pending_exception,
+          tt,
+          *src_yy,
+          *src_yp,
+          *residual);
       },
       current_time,
       yy,
@@ -421,16 +351,18 @@ namespace SUNDIALS
       auto *src_b = internal::unwrap_nvector_const<VectorType>(b);
       auto *dst_x = internal::unwrap_nvector<VectorType>(x);
       if (solver.solve_with_jacobian)
-        return call_and_possibly_capture_exception(solver.solve_with_jacobian,
-                                                   solver.pending_exception,
-                                                   *src_b,
-                                                   *dst_x,
-                                                   tol);
+        return Utilities::call_and_possibly_capture_exception(
+          solver.solve_with_jacobian,
+          solver.pending_exception,
+          *src_b,
+          *dst_x,
+          tol);
       else if (solver.solve_jacobian_system)
-        return call_and_possibly_capture_exception(solver.solve_jacobian_system,
-                                                   solver.pending_exception,
-                                                   *src_b,
-                                                   *dst_x);
+        return Utilities::call_and_possibly_capture_exception(
+          solver.solve_jacobian_system,
+          solver.pending_exception,
+          *src_b,
+          *dst_x);
       else
         {
           // We have already checked this outside, so we should never get here.
@@ -510,12 +442,13 @@ namespace SUNDIALS
         auto *src_yy = internal::unwrap_nvector_const<VectorType>(yy);
         auto *src_yp = internal::unwrap_nvector_const<VectorType>(yp);
 
-        return call_and_possibly_capture_exception(solver.setup_jacobian,
-                                                   solver.pending_exception,
-                                                   tt,
-                                                   *src_yy,
-                                                   *src_yp,
-                                                   cj);
+        return Utilities::call_and_possibly_capture_exception(
+          solver.setup_jacobian,
+          solver.pending_exception,
+          tt,
+          *src_yy,
+          *src_yp,
+          cj);
       });
     AssertIDA(status);
     status = IDASetMaxOrd(ida_mem, data.maximum_order);
index a2bd709493b999e9ee201c052188175cfdaf1084..aaaa7c0103f8a7e4030578c14c460551575c2aae 100644 (file)
@@ -37,6 +37,7 @@
 #  endif
 
 #  include <deal.II/sundials/n_vector.h>
+#  include <deal.II/sundials/utilities.h>
 
 // Make sure we #include the SUNDIALS config file...
 #  include <sundials/sundials_config.h>
@@ -52,77 +53,6 @@ DEAL_II_NAMESPACE_OPEN
 
 namespace SUNDIALS
 {
-  namespace
-  {
-    /**
-     * A function that calls the function object given by its first argument
-     * with the set of arguments following at the end. If the call returns
-     * regularly, the current function returns zero to indicate success. If the
-     * call fails with an exception of type RecoverableUserCallbackError, then
-     * the current function returns 1 to indicate that the called function
-     * object thought the error it encountered is recoverable. If the call fails
-     * with any other exception, then the current function returns with an error
-     * code of -1. In each of the last two cases, the exception thrown by `f`
-     * is captured and `eptr` is set to the exception. In case of success,
-     * `eptr` is set to `nullptr`.
-     */
-    template <typename F, typename... Args>
-    int
-    call_and_possibly_capture_exception(const F &           f,
-                                        std::exception_ptr &eptr,
-                                        Args &&...args)
-    {
-      // See whether there is already something in the exception pointer
-      // variable. This can only happen if we had previously had
-      // a recoverable exception, and the underlying library actually
-      // did recover successfully. In that case, we can abandon the
-      // exception previously thrown. If eptr contains anything other,
-      // then we really don't know how that could have happened, and
-      // should probably bail out:
-      if (eptr)
-        {
-          try
-            {
-              std::rethrow_exception(eptr);
-            }
-          catch (const RecoverableUserCallbackError &)
-            {
-              // ok, ignore, but reset the pointer
-              eptr = nullptr;
-            }
-          catch (...)
-            {
-              // uh oh:
-              AssertThrow(false, ExcInternalError());
-            }
-        }
-
-      // Call the function and if that succeeds, return zero:
-      try
-        {
-          f(std::forward<Args>(args)...);
-          eptr = nullptr;
-          return 0;
-        }
-      // If the call failed with a recoverable error, then
-      // ignore the exception for now (but store a pointer to it)
-      // and return a positive return value (+1). If the underlying
-      // implementation manages to recover
-      catch (const RecoverableUserCallbackError &)
-        {
-          eptr = std::current_exception();
-          return 1;
-        }
-      // For any other exception, capture the exception and
-      // return -1:
-      catch (...)
-        {
-          eptr = std::current_exception();
-          return -1;
-        }
-    }
-  } // namespace
-
   template <typename VectorType>
   KINSOL<VectorType>::AdditionalData::AdditionalData(
     const SolutionStrategy &strategy,
@@ -344,11 +274,11 @@ namespace SUNDIALS
 
           Assert(solver.iteration_function, ExcInternalError());
 
-          const int err =
-            call_and_possibly_capture_exception(solver.iteration_function,
-                                                solver.pending_exception,
-                                                *src_yy,
-                                                *dst_FF);
+          const int err = Utilities::call_and_possibly_capture_exception(
+            solver.iteration_function,
+            solver.pending_exception,
+            *src_yy,
+            *dst_FF);
 
           return err;
         },
@@ -366,7 +296,7 @@ namespace SUNDIALS
 
           Assert(solver.residual, ExcInternalError());
 
-          const int err = call_and_possibly_capture_exception(
+          const int err = Utilities::call_and_possibly_capture_exception(
             solver.residual, solver.pending_exception, *src_yy, *dst_FF);
 
           return err;
@@ -452,12 +382,12 @@ namespace SUNDIALS
               auto src_b = internal::unwrap_nvector_const<VectorType>(b);
               auto dst_x = internal::unwrap_nvector<VectorType>(x);
 
-              const int err =
-                call_and_possibly_capture_exception(solver.solve_with_jacobian,
-                                                    solver.pending_exception,
-                                                    *src_b,
-                                                    *dst_x,
-                                                    tol);
+              const int err = Utilities::call_and_possibly_capture_exception(
+                solver.solve_with_jacobian,
+                solver.pending_exception,
+                *src_b,
+                *dst_x,
+                tol);
 
               return err;
             }
@@ -481,7 +411,7 @@ namespace SUNDIALS
               // src_ycur and src_fcur, and so we simply pass dummy vector in.
               // These vectors will have zero lengths because we don't reinit
               // them above.
-              const int err = call_and_possibly_capture_exception(
+              const int err = Utilities::call_and_possibly_capture_exception(
                 solver.solve_jacobian_system,
                 solver.pending_exception,
                 *src_ycur,
@@ -552,10 +482,8 @@ namespace SUNDIALS
             auto fcur = internal::unwrap_nvector<VectorType>(f);
 
             // Call the user-provided setup function with these arguments:
-            return call_and_possibly_capture_exception(solver.setup_jacobian,
-                                                       solver.pending_exception,
-                                                       *ycur,
-                                                       *fcur);
+            return Utilities::call_and_possibly_capture_exception(
+              solver.setup_jacobian, solver.pending_exception, *ycur, *fcur);
           });
         AssertKINSOL(status);
       }

In the beginning the Universe was created. This has made a lot of people very angry and has been widely regarded as a bad move.

Douglas Adams


Typeset in Trocchi and Trocchi Bold Sans Serif.