Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Convert ARKode interfaces to conform to our callback policy. #15223

Merged
merged 5 commits into from
May 19, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
5 changes: 3 additions & 2 deletions doc/news/changes/major/20230508Bangerth
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@ positive value for a recoverable error.

This approach does not scale across the many interfaces we have. As a
consequence, we standardized how callbacks should behave, as
documented in @ref GlossUserProvidedCallBack "this glossary entry".
The interfaces in SUNDIALS::KINSOL have been changed correspondingly.
documented in @ref GlossUserProvidedCallBack "this glossary entry".
The interfaces in SUNDIALS::KINSOL and SUNDIALS::ARKode have been
changed correspondingly.
<br>
(Wolfgang Bangerth, 2023/05/08)
203 changes: 115 additions & 88 deletions include/deal.II/sundials/arkode.h
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@
# include <sundials/sundials_math.h>
# include <sundials/sundials_types.h>

# include <exception>
# include <memory>


Expand Down Expand Up @@ -579,15 +580,15 @@ namespace SUNDIALS
* provided. According to which one is provided, explicit, implicit, or
* mixed RK methods are used.
*
* This function should return:
* - 0: Success
* - >0: Recoverable error, ARKode will reattempt the solution and call this
* function again.
* - <0: Unrecoverable error, the computation will be aborted and an
* assertion will be thrown.
* @note This variable represents a
* @ref GlossUserProvidedCallBack "user provided callback".
* See there for a description of how to deal with errors and other
* requirements and conventions. In particular, ARKode can deal
* with "recoverable" errors in some circumstances, so callbacks
* can throw exceptions of type RecoverableUserCallbackError.
*/
std::function<
int(const double t, const VectorType &y, VectorType &explicit_f)>
void(const double t, const VectorType &y, VectorType &explicit_f)>
explicit_function;

/**
Expand All @@ -599,14 +600,14 @@ namespace SUNDIALS
* provided. According to which one is provided, explicit, implicit, or
* mixed RK methods are used.
*
* This function should return:
* - 0: Success
* - >0: Recoverable error, ARKode will reattempt the solution and call this
* function again.
* - <0: Unrecoverable error, the computation will be aborted and an
* assertion will be thrown.
* @note This variable represents a
* @ref GlossUserProvidedCallBack "user provided callback".
* See there for a description of how to deal with errors and other
* requirements and conventions. In particular, ARKode can deal
* with "recoverable" errors in some circumstances, so callbacks
* can throw exceptions of type RecoverableUserCallbackError.
*/
std::function<int(const double t, const VectorType &y, VectorType &res)>
std::function<void(const double t, const VectorType &y, VectorType &res)>
implicit_function;

/**
Expand All @@ -619,14 +620,14 @@ namespace SUNDIALS
* A call to this function should store in `Mv` the result of $M$
* applied to `v`.
*
* This function should return:
* - 0: Success
* - >0: Recoverable error, ARKode will reattempt the solution and call this
* function again.
* - <0: Unrecoverable error, the computation will be aborted and an
* assertion will be thrown.
* @note This variable represents a
* @ref GlossUserProvidedCallBack "user provided callback".
* See there for a description of how to deal with errors and other
* requirements and conventions. In particular, ARKode can deal
* with "recoverable" errors in some circumstances, so callbacks
* can throw exceptions of type RecoverableUserCallbackError.
*/
std::function<int(double t, const VectorType &v, VectorType &Mv)>
std::function<void(const double t, const VectorType &v, VectorType &Mv)>
mass_times_vector;

/**
Expand Down Expand Up @@ -656,14 +657,14 @@ namespace SUNDIALS
*
* @param t The current evaluation time
*
* This function should return:
* - 0: Success
* - >0: Recoverable error, ARKode will reattempt the solution and call this
* function again.
* - <0: Unrecoverable error, the computation will be aborted and an
* assertion will be thrown.
* @note This variable represents a
* @ref GlossUserProvidedCallBack "user provided callback".
* See there for a description of how to deal with errors and other
* requirements and conventions. In particular, ARKode can deal
* with "recoverable" errors in some circumstances, so callbacks
* can throw exceptions of type RecoverableUserCallbackError.
*/
std::function<int(const double t)> mass_times_setup;
std::function<void(const double t)> mass_times_setup;

/**
* A function object that users may supply and that is intended to compute
Expand All @@ -684,18 +685,18 @@ namespace SUNDIALS
* @param[in] fy The current value of the implicit right-hand side at y,
* $f_I (t_n, y)$.
*
* This function should return:
* - 0: Success
* - >0: Recoverable error, ARKode will reattempt the solution and call this
* function again.
* - <0: Unrecoverable error, the computation will be aborted and an
* assertion will be thrown.
* @note This variable represents a
* @ref GlossUserProvidedCallBack "user provided callback".
* See there for a description of how to deal with errors and other
* requirements and conventions. In particular, ARKode can deal
* with "recoverable" errors in some circumstances, so callbacks
* can throw exceptions of type RecoverableUserCallbackError.
*/
std::function<int(const VectorType &v,
VectorType & Jv,
double t,
const VectorType &y,
const VectorType &fy)>
std::function<void(const VectorType &v,
VectorType & Jv,
const double t,
const VectorType &y,
const VectorType &fy)>
jacobian_times_vector;

/**
Expand Down Expand Up @@ -725,14 +726,15 @@ namespace SUNDIALS
* @param fy The implicit right-hand side function evaluated at the
* current time $t$ and state $y$, i.e., $f_I(y,t)$
*
* This function should return:
* - 0: Success
* - >0: Recoverable error, ARKode will reattempt the solution and call this
* function again.
* - <0: Unrecoverable error, the computation will be aborted and an
* assertion will be thrown.
* @note This variable represents a
* @ref GlossUserProvidedCallBack "user provided callback".
* See there for a description of how to deal with errors and other
* requirements and conventions. In particular, ARKode can deal
* with "recoverable" errors in some circumstances, so callbacks
* can throw exceptions of type RecoverableUserCallbackError.
*/
std::function<int(realtype t, const VectorType &y, const VectorType &fy)>
std::function<
void(const double t, const VectorType &y, const VectorType &fy)>
jacobian_times_setup;

/**
Expand All @@ -753,6 +755,13 @@ namespace SUNDIALS
* SUNDIALS packaged SPGMR solver with default settings is used.
*
* For more details on the function type refer to LinearSolveFunction.
*
* @note This variable represents a
* @ref GlossUserProvidedCallBack "user provided callback".
* See there for a description of how to deal with errors and other
* requirements and conventions. In particular, ARKode can deal
* with "recoverable" errors in some circumstances, so callbacks
* can throw exceptions of type RecoverableUserCallbackError.
*/
LinearSolveFunction<VectorType> solve_linearized_system;

Expand All @@ -770,6 +779,13 @@ namespace SUNDIALS
* and applied in mass_times_vector().
*
* For more details on the function type refer to LinearSolveFunction.
*
* @note This variable represents a
* @ref GlossUserProvidedCallBack "user provided callback".
* See there for a description of how to deal with errors and other
* requirements and conventions. In particular, ARKode can deal
* with "recoverable" errors in some circumstances, so callbacks
* can throw exceptions of type RecoverableUserCallbackError.
*/
LinearSolveFunction<VectorType> solve_mass;

Expand Down Expand Up @@ -797,21 +813,21 @@ namespace SUNDIALS
* (lr = 2). Only relevant if used with a SUNDIALS packaged solver. If
* used with a custom solve_mass() function this will be set to zero.
*
* This function should return:
* - 0: Success
* - >0: Recoverable error, ARKode will reattempt the solution and call this
* function again.
* - <0: Unrecoverable error, the computation will be aborted and an
* assertion will be thrown.
* @note This variable represents a
* @ref GlossUserProvidedCallBack "user provided callback".
* See there for a description of how to deal with errors and other
* requirements and conventions. In particular, ARKode can deal
* with "recoverable" errors in some circumstances, so callbacks
* can throw exceptions of type RecoverableUserCallbackError.
*/
std::function<int(double t,
const VectorType &y,
const VectorType &fy,
const VectorType &r,
VectorType & z,
double gamma,
double tol,
int lr)>
std::function<void(const double t,
const VectorType &y,
const VectorType &fy,
const VectorType &r,
VectorType & z,
const double gamma,
const double tol,
const int lr)>
jacobian_preconditioner_solve;

/**
Expand Down Expand Up @@ -849,19 +865,19 @@ namespace SUNDIALS
* @param[in] gamma The value $\gamma$ in $M-\gamma J$. The preconditioner
* should approximate the inverse of this matrix.
*
* This function should return:
* - 0: Success
* - >0: Recoverable error, ARKode will reattempt the solution and call this
* function again.
* - <0: Unrecoverable error, the computation will be aborted and an
* assertion will be thrown.
* @note This variable represents a
* @ref GlossUserProvidedCallBack "user provided callback".
* See there for a description of how to deal with errors and other
* requirements and conventions. In particular, ARKode can deal
* with "recoverable" errors in some circumstances, so callbacks
* can throw exceptions of type RecoverableUserCallbackError.
*/
std::function<int(double t,
const VectorType &y,
const VectorType &fy,
int jok,
int & jcur,
double gamma)>
std::function<void(const double t,
const VectorType &y,
const VectorType &fy,
const int jok,
int & jcur,
const double gamma)>
jacobian_preconditioner_setup;

/**
Expand All @@ -884,15 +900,18 @@ namespace SUNDIALS
* (lr = 2). Only relevant if used with a SUNDIALS packaged solver. If
* used with a custom solve_mass() function this will be set to zero.
*
* This function should return:
* - 0: Success
* - >0: Recoverable error, ARKode will reattempt the solution and call this
* function again.
* - <0: Unrecoverable error, the computation will be aborted and an
* assertion will be thrown.
* @note This variable represents a
* @ref GlossUserProvidedCallBack "user provided callback".
* See there for a description of how to deal with errors and other
* requirements and conventions. In particular, ARKode can deal
* with "recoverable" errors in some circumstances, so callbacks
* can throw exceptions of type RecoverableUserCallbackError.
*/
std::function<
int(double t, const VectorType &r, VectorType &z, double tol, int lr)>
std::function<void(const double t,
const VectorType &r,
VectorType & z,
const double tol,
const int lr)>
mass_preconditioner_solve;

/**
Expand All @@ -912,14 +931,14 @@ namespace SUNDIALS
*
* @param[in] t The current time
*
* This function should return:
* - 0: Success
* - >0: Recoverable error, ARKode will reattempt the solution and call this
* function again.
* - <0: Unrecoverable error, the computation will be aborted and an
* assertion will be thrown.
* @note This variable represents a
* @ref GlossUserProvidedCallBack "user provided callback".
* See there for a description of how to deal with errors and other
* requirements and conventions. In particular, ARKode can deal
* with "recoverable" errors in some circumstances, so callbacks
* can throw exceptions of type RecoverableUserCallbackError.
*/
std::function<int(double t)> mass_preconditioner_setup;
std::function<void(const double t)> mass_preconditioner_setup;

/**
* A function object that users may supply and that is intended to
Expand Down Expand Up @@ -983,7 +1002,7 @@ namespace SUNDIALS
* @endcode
*
* @note This function will be called at the end of all other set up right
* before the actual time evloution is started or continued with
* before the actual time evolution is started or continued with
* solve_ode(). This function is also called when the solver is restarted,
* see solver_should_restart(). Consult the SUNDIALS manual to see which
* options are still available at this point.
Expand Down Expand Up @@ -1068,6 +1087,14 @@ namespace SUNDIALS
std::unique_ptr<internal::LinearSolverWrapper<VectorType>> linear_solver;
std::unique_ptr<internal::LinearSolverWrapper<VectorType>> mass_solver;

public:
/**
* A pointer to any exception that may have been thrown in user-defined
* call-backs and that we have to deal after the KINSOL function we call
* has returned.
*/
mutable std::exception_ptr pending_exception;

# ifdef DEAL_II_WITH_PETSC
# ifdef PETSC_USE_COMPLEX
static_assert(!std::is_same<VectorType, PETScWrappers::MPI::Vector>::value,
Expand Down
34 changes: 19 additions & 15 deletions include/deal.II/sundials/sunlinsol_wrapper.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@

# include <sundials/sundials_linearsolver.h>

# include <exception>
# include <functional>
# include <memory>

Expand Down Expand Up @@ -171,7 +172,7 @@ namespace SUNDIALS
};

/**
* Type of function objects to interface with SUNDIALS linear solvers
* Type of function objects to interface with SUNDIALS' linear solvers
*
* This function type encapsulates the action of solving $P^{-1}Ax=P^{-1}b$.
* The LinearOperator @p op encapsulates the matrix vector product $Ax$ and
Expand All @@ -188,20 +189,21 @@ namespace SUNDIALS
* @param[in] b The right-hand side
* @param[in] tol Tolerance for the iterative solver
*
* This function should return:
* - 0: Success
* - >0: Recoverable error, ARKode will reattempt the solution and call this
* function again.
* - <0: Unrecoverable error, the computation will be aborted and an
* assertion will be thrown.
*
* @note This variable represents a
* @ref GlossUserProvidedCallBack "user provided callback".
* See there for a description of how to deal with errors and other
* requirements and conventions. In particular, ARKode can deal
* with "recoverable" errors in some circumstances, so callbacks
* can throw exceptions of type RecoverableUserCallbackError.
*/
template <typename VectorType>
using LinearSolveFunction =
std::function<int(SundialsOperator<VectorType> & op,
SundialsPreconditioner<VectorType> &prec,
VectorType & x,
const VectorType & b,
double tol)>;
std::function<void(SundialsOperator<VectorType> & op,
SundialsPreconditioner<VectorType> &prec,
VectorType & x,
const VectorType & b,
double tol)>;

namespace internal
{
Expand All @@ -215,10 +217,12 @@ namespace SUNDIALS
class LinearSolverWrapper
{
public:
explicit LinearSolverWrapper(LinearSolveFunction<VectorType> lsolve
explicit LinearSolverWrapper(
const LinearSolveFunction<VectorType> &lsolve,
std::exception_ptr & pending_exception
# if DEAL_II_SUNDIALS_VERSION_GTE(6, 0, 0)
,
SUNContext linsol_ctx
,
SUNContext linsol_ctx
# endif
);

Expand Down