22#ifdef DEAL_II_WITH_SUNDIALS
30# ifdef DEAL_II_WITH_TRILINOS
34# ifdef DEAL_II_WITH_PETSC
43# include <arkode/arkode_arkstep.h>
44# include <sunlinsol/sunlinsol_spgmr.h>
45# include <sunnonlinsol/sunnonlinsol_fixedpoint.h>
53 template <
typename VectorType>
55 :
ARKode(data, MPI_COMM_SELF)
59 template <
typename VectorType>
67 , mpi_communicator(mpi_comm)
68 , last_end_time(data.initial_time)
69 , pending_exception(nullptr)
73# if DEAL_II_SUNDIALS_VERSION_GTE(6, 0, 0)
90 template <
typename VectorType>
93 ARKStepFree(&arkode_mem);
95# if DEAL_II_SUNDIALS_VERSION_GTE(6, 0, 0)
96 const int status = SUNContext_Free(&arkode_ctx);
106 template <
typename VectorType>
112 data.initial_step_size);
114 return do_evolve_time(solution, time,
true);
119 template <
typename VectorType>
122 const double intermediate_time,
123 const bool reset_solver)
126 intermediate_time > last_end_time,
128 "The requested intermediate time is smaller than the last requested "
129 "intermediate time."));
131 const bool do_reset = reset_solver || arkode_mem ==
nullptr;
132 DiscreteTime time(last_end_time, intermediate_time, data.initial_step_size);
133 return do_evolve_time(solution, time, do_reset);
138 template <
typename VectorType>
158 const int status = ARKStepSetStopTime(arkode_mem, time.
get_end_time());
163 auto solution_nvector = internal::make_nvector_view(solution
182 double actual_next_time;
183 const auto status = ARKStepEvolve(arkode_mem,
188 if (pending_exception)
192 std::rethrow_exception(pending_exception);
196 pending_exception =
nullptr;
204 pending_exception =
nullptr;
233 template <
typename VectorType>
236 const double current_time_step,
237 const VectorType &solution)
239 last_end_time = current_time;
243# if DEAL_II_SUNDIALS_VERSION_GTE(6, 0, 0)
244 status = SUNContext_Free(&arkode_ctx);
248 SUNContext_Create(mpi_communicator == MPI_COMM_SELF ?
nullptr :
256 ARKStepFree(&arkode_mem);
262 auto initial_condition_nvector = internal::make_nvector_view(solution
269 Assert(explicit_function || implicit_function,
272 auto explicit_function_callback =
273 [](realtype tt, N_Vector yy, N_Vector yp,
void *user_data) ->
int {
278 auto *src_yy = internal::unwrap_nvector_const<VectorType>(yy);
279 auto *dst_yp = internal::unwrap_nvector<VectorType>(yp);
290 auto implicit_function_callback =
291 [](realtype tt, N_Vector yy, N_Vector yp,
void *user_data) ->
int {
296 auto *src_yy = internal::unwrap_nvector_const<VectorType>(yy);
297 auto *dst_yp = internal::unwrap_nvector<VectorType>(yp);
307 arkode_mem = ARKStepCreate(explicit_function ? explicit_function_callback :
309 implicit_function ? implicit_function_callback :
312 initial_condition_nvector
313# if DEAL_II_SUNDIALS_VERSION_GTE(6, 0, 0)
320 if (get_local_tolerances)
322 const auto abs_tols = internal::make_nvector_view(get_local_tolerances()
329 ARKStepSVtolerances(arkode_mem, data.relative_tolerance, abs_tols);
334 status = ARKStepSStolerances(arkode_mem,
335 data.relative_tolerance,
336 data.absolute_tolerance);
341 status = ARKStepSetUserData(arkode_mem,
this);
344 setup_system_solver(solution);
346 setup_mass_solver(solution);
348 status = ARKStepSetInitStep(arkode_mem, current_time_step);
351 status = ARKStepSetStopTime(arkode_mem, data.final_time);
354 status = ARKStepSetOrder(arkode_mem, data.maximum_order);
358 custom_setup(arkode_mem);
363 template <
typename VectorType>
368 if (!implicit_function)
375 if (jacobian_times_vector)
378 if (solve_linearized_system)
381 std::make_unique<internal::LinearSolverWrapper<VectorType>>(
382 solve_linearized_system,
384# if DEAL_II_SUNDIALS_VERSION_GTE(6, 0, 0)
389 sun_linear_solver = *linear_solver;
395 auto y_template = internal::make_nvector_view(solution
401# if DEAL_II_SUNDIALS_VERSION_LT(6, 0, 0)
403 SUNLinSol_SPGMR(y_template,
408 SUNLinSol_SPGMR(y_template,
414 status = ARKStepSetLinearSolver(arkode_mem, sun_linear_solver,
nullptr);
417 auto jacobian_times_vector_callback = [](N_Vector v,
428 auto *src_v = internal::unwrap_nvector_const<VectorType>(v);
429 auto *src_y = internal::unwrap_nvector_const<VectorType>(y);
430 auto *src_fy = internal::unwrap_nvector_const<VectorType>(fy);
432 auto *dst_Jv = internal::unwrap_nvector<VectorType>(Jv);
444 auto jacobian_times_vector_setup_callback =
445 [](realtype t, N_Vector y, N_Vector fy,
void *user_data) ->
int {
450 auto *src_y = internal::unwrap_nvector_const<VectorType>(y);
451 auto *src_fy = internal::unwrap_nvector_const<VectorType>(fy);
460 status = ARKStepSetJacTimes(arkode_mem,
461 jacobian_times_setup ?
462 jacobian_times_vector_setup_callback :
463 ARKLsJacTimesSetupFn(
nullptr),
464 jacobian_times_vector_callback);
466 if (jacobian_preconditioner_solve)
468 auto solve_with_jacobian_callback = [](realtype t,
476 void * user_data) ->
int {
481 auto *src_y = internal::unwrap_nvector_const<VectorType>(y);
482 auto *src_fy = internal::unwrap_nvector_const<VectorType>(fy);
483 auto *src_r = internal::unwrap_nvector_const<VectorType>(r);
485 auto *dst_z = internal::unwrap_nvector<VectorType>(z);
500 auto jacobian_solver_setup_callback = [](realtype t,
504 booleantype *jcurPtr,
506 void *user_data) ->
int {
511 auto *src_y = internal::unwrap_nvector_const<VectorType>(y);
512 auto *src_fy = internal::unwrap_nvector_const<VectorType>(fy);
525 status = ARKStepSetPreconditioner(arkode_mem,
526 jacobian_preconditioner_setup ?
527 jacobian_solver_setup_callback :
528 ARKLsPrecSetupFn(
nullptr),
529 solve_with_jacobian_callback);
532 if (data.implicit_function_is_linear)
534 status = ARKStepSetLinear(
535 arkode_mem, data.implicit_function_is_time_independent ? 0 : 1);
541 auto y_template = internal::make_nvector_view(solution
548# if DEAL_II_SUNDIALS_VERSION_LT(6, 0, 0)
549 SUNNonlinearSolver fixed_point_solver =
550 SUNNonlinSol_FixedPoint(y_template,
551 data.anderson_acceleration_subspace);
553 SUNNonlinearSolver fixed_point_solver =
554 SUNNonlinSol_FixedPoint(y_template,
555 data.anderson_acceleration_subspace,
559 status = ARKStepSetNonlinearSolver(arkode_mem, fixed_point_solver);
564 ARKStepSetMaxNonlinIters(arkode_mem, data.maximum_non_linear_iterations);
570 template <
typename VectorType>
577 if (mass_times_vector)
583 std::make_unique<internal::LinearSolverWrapper<VectorType>>(
587# if DEAL_II_SUNDIALS_VERSION_GTE(6, 0, 0)
592 sun_mass_linear_solver = *mass_solver;
596 auto y_template = internal::make_nvector_view(solution
602# if DEAL_II_SUNDIALS_VERSION_LT(6, 0, 0)
603 sun_mass_linear_solver =
604 SUNLinSol_SPGMR(y_template,
608 sun_mass_linear_solver =
609 SUNLinSol_SPGMR(y_template,
615 booleantype mass_time_dependent =
616 data.mass_is_time_independent ? SUNFALSE : SUNTRUE;
617 status = ARKStepSetMassLinearSolver(arkode_mem,
618 sun_mass_linear_solver,
620 mass_time_dependent);
623 auto mass_matrix_times_vector_setup_callback =
624 [](realtype t,
void *mtimes_data) ->
int {
633 auto mass_matrix_times_vector_callback =
634 [](N_Vector v, N_Vector Mv, realtype t,
void *mtimes_data) ->
int {
639 auto *src_v = internal::unwrap_nvector_const<VectorType>(v);
640 auto *dst_Mv = internal::unwrap_nvector<VectorType>(Mv);
650 status = ARKStepSetMassTimes(arkode_mem,
652 mass_matrix_times_vector_setup_callback :
653 ARKLsMassTimesSetupFn(
nullptr),
654 mass_matrix_times_vector_callback,
658 if (mass_preconditioner_solve)
660 auto mass_matrix_solver_setup_callback =
661 [](realtype t,
void *user_data) ->
int {
670 auto solve_with_mass_matrix_callback = [](realtype t,
675 void *user_data) ->
int {
680 auto *src_r = internal::unwrap_nvector_const<VectorType>(r);
681 auto *dst_z = internal::unwrap_nvector<VectorType>(z);
694 ARKStepSetMassPreconditioner(arkode_mem,
695 mass_preconditioner_setup ?
696 mass_matrix_solver_setup_callback :
697 ARKLsMassPrecSetupFn(
nullptr),
698 solve_with_mass_matrix_callback);
706 template <
typename VectorType>
710 solver_should_restart = [](
const double, VectorType &) ->
bool {
717 template <
typename VectorType>
730# ifdef DEAL_II_WITH_MPI
732# ifdef DEAL_II_WITH_TRILINOS
738# ifdef DEAL_II_WITH_PETSC
739# ifndef PETSC_USE_COMPLEX
#define AssertARKode(code)
double get_next_step_size() const
void set_desired_next_step_size(const double time_step_size)
unsigned int get_step_number() const
double get_current_time() const
void set_next_step_size(const double time_step_size)
double get_next_time() const
double get_previous_step_size() const
double get_end_time() const
void setup_mass_solver(const VectorType &solution)
std::function< void(const double t)> mass_preconditioner_setup
std::function< void(const double t, const VectorType &y, VectorType &explicit_f)> explicit_function
std::exception_ptr pending_exception
ARKode(const AdditionalData &data=AdditionalData())
std::function< void(const double t, const VectorType &y, const VectorType &fy, const int jok, int &jcur, const double gamma)> jacobian_preconditioner_setup
void * get_arkode_memory() const
std::function< void(const VectorType &v, VectorType &Jv, const double t, const VectorType &y, const VectorType &fy)> jacobian_times_vector
std::function< void(const double t, const VectorType &y, VectorType &res)> implicit_function
int do_evolve_time(VectorType &solution, ::DiscreteTime &time, const bool do_reset)
MPI_Comm mpi_communicator
void reset(const double t, const double h, const VectorType &y)
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
std::function< void(const double t)> mass_times_setup
void set_functions_to_trigger_an_assert()
std::function< void(const double t, const VectorType &v, VectorType &Mv)> mass_times_vector
std::function< void(const double t, const VectorType &r, VectorType &z, const double tol, const int lr)> mass_preconditioner_solve
std::function< void(const double t, const VectorType &y, const VectorType &fy)> jacobian_times_setup
unsigned int solve_ode(VectorType &solution)
void setup_system_solver(const VectorType &solution)
unsigned int solve_ode_incrementally(VectorType &solution, const double intermediate_time, const bool reset_solver=false)
#define DEAL_II_NAMESPACE_OPEN
#define DEAL_II_SUNDIALS_VERSION_GTE(major, minor, patch)
#define DEAL_II_NAMESPACE_CLOSE
static ::ExceptionBase & ExcFunctionNotProvided(std::string arg1)
#define Assert(cond, exc)
static ::ExceptionBase & ExcInternalError()
static ::ExceptionBase & RecoverableUserCallbackError()
static ::ExceptionBase & ExcMessage(std::string arg1)
#define AssertThrow(cond, exc)
int call_and_possibly_capture_exception(const F &f, std::exception_ptr &eptr, Args &&...args)