19#ifdef DEAL_II_WITH_SUNDIALS
27# ifdef DEAL_II_TRILINOS_WITH_EPETRA
31# ifdef DEAL_II_TRILINOS_WITH_TPETRA
35# ifdef DEAL_II_WITH_PETSC
44# include <sundials/sundials_config.h>
46# if DEAL_II_SUNDIALS_VERSION_GTE(6, 0, 0)
47# include <kinsol/kinsol_ls.h>
49# include <kinsol/kinsol_direct.h>
51# include <kinsol/kinsol.h>
52# include <sunlinsol/sunlinsol_dense.h>
53# include <sunmatrix/sunmatrix_dense.h>
63#ifdef DEAL_II_WITH_SUNDIALS
67 template <
typename VectorType>
70 const unsigned int maximum_non_linear_iterations,
71 const double function_tolerance,
72 const double step_tolerance,
73 const bool no_init_setup,
74 const unsigned int maximum_setup_calls,
75 const double maximum_newton_step,
76 const double dq_relative_error,
77 const unsigned int maximum_beta_failures,
78 const unsigned int anderson_subspace_size,
81 , maximum_non_linear_iterations(maximum_non_linear_iterations)
82 , function_tolerance(function_tolerance)
83 , step_tolerance(step_tolerance)
84 , no_init_setup(no_init_setup)
85 , maximum_setup_calls(maximum_setup_calls)
86 , maximum_newton_step(maximum_newton_step)
87 , dq_relative_error(dq_relative_error)
88 , maximum_beta_failures(maximum_beta_failures)
89 , anderson_subspace_size(anderson_subspace_size)
90 , anderson_qr_orthogonalization(anderson_qr_orthogonalization)
95 template <
typename VectorType>
99 static std::string strategy_str(
"newton");
102 "Choose among newton|linesearch|fixed_point|picard",
104 "newton|linesearch|fixed_point|picard"));
105 prm.
add_action(
"Solution strategy", [&](
const std::string &value) {
106 if (value ==
"newton")
108 else if (value ==
"linesearch")
109 strategy = linesearch;
110 else if (value ==
"fixed_point")
111 strategy = fixed_point;
112 else if (value ==
"picard")
118 maximum_non_linear_iterations);
119 prm.
add_parameter(
"Function norm stopping tolerance", function_tolerance);
120 prm.
add_parameter(
"Scaled step stopping tolerance", step_tolerance);
125 maximum_setup_calls);
126 prm.
add_parameter(
"Maximum allowable scaled length of the Newton step",
127 maximum_newton_step);
128 prm.
add_parameter(
"Relative error for different quotient computation",
133 prm.
add_parameter(
"Maximum number of beta-condition failures",
134 maximum_beta_failures);
140 anderson_subspace_size);
142 static std::string orthogonalization_str(
"modified_gram_schmidt");
144 "Anderson QR orthogonalization",
145 orthogonalization_str,
146 "Choose among modified_gram_schmidt|inverse_compact|"
147 "classical_gram_schmidt|delayed_classical_gram_schmidt",
149 "modified_gram_schmidt|inverse_compact|classical_gram_schmidt|"
150 "delayed_classical_gram_schmidt"));
151 prm.
add_action(
"Anderson QR orthogonalization",
152 [&](
const std::string &value) {
153 if (value ==
"modified_gram_schmidt")
154 anderson_qr_orthogonalization = modified_gram_schmidt;
155 else if (value ==
"inverse_compact")
156 anderson_qr_orthogonalization = inverse_compact;
157 else if (value ==
"classical_gram_schmidt")
158 anderson_qr_orthogonalization = classical_gram_schmidt;
159 else if (value ==
"delayed_classical_gram_schmidt")
160 anderson_qr_orthogonalization =
161 delayed_classical_gram_schmidt;
170 template <
typename VectorType>
177 template <
typename VectorType>
181 , mpi_communicator(mpi_comm)
182 , kinsol_mem(nullptr)
184 , kinsol_ctx(nullptr)
186 , pending_exception(nullptr)
195# if DEAL_II_SUNDIALS_VERSION_GTE(7, 0, 0)
202# elif DEAL_II_SUNDIALS_VERSION_GTE(6, 0, 0)
214 template <
typename VectorType>
217 KINFree(&kinsol_mem);
218# if DEAL_II_SUNDIALS_VERSION_GTE(6, 0, 0)
219 const int status = SUNContext_Free(&kinsol_ctx);
229 template <
typename VectorType>
234 if (
data.strategy == AdditionalData::fixed_point)
236 Assert(iteration_function,
242 Assert(solve_with_jacobian,
250 KINFree(&kinsol_mem);
251# if DEAL_II_SUNDIALS_VERSION_GTE(6, 0, 0)
252 status = SUNContext_Free(&kinsol_ctx);
257# if DEAL_II_SUNDIALS_VERSION_GTE(7, 0, 0)
260 SUNContext_Create(mpi_communicator == MPI_COMM_SELF ? SUN_COMM_NULL :
265 kinsol_mem = KINCreate(kinsol_ctx);
266# elif DEAL_II_SUNDIALS_VERSION_GTE(6, 0, 0)
269 SUNContext_Create(mpi_communicator == MPI_COMM_SELF ?
nullptr :
274 kinsol_mem = KINCreate(kinsol_ctx);
276 kinsol_mem = KINCreate();
279 status = KINSetUserData(kinsol_mem,
static_cast<void *
>(
this));
284 const auto make_compatible_nvector_view =
285# if DEAL_II_SUNDIALS_VERSION_LT(6, 0, 0)
286 [](
auto &v) {
return internal::make_nvector_view(v); };
288 [
this](
auto &v) {
return internal::make_nvector_view(v, kinsol_ctx); };
294 if (!get_function_scaling || !get_solution_scaling)
300 auto u_scale = make_compatible_nvector_view(
301 get_solution_scaling ? get_solution_scaling() : ones);
302 auto f_scale = make_compatible_nvector_view(
303 get_function_scaling ? get_function_scaling() : ones);
305 auto solution = make_compatible_nvector_view(initial_guess_and_solution);
308 status = KINSetNumMaxIters(kinsol_mem,
data.maximum_non_linear_iterations);
312 status = KINSetMAA(kinsol_mem,
data.anderson_subspace_size);
315# if DEAL_II_SUNDIALS_VERSION_GTE(6, 0, 0)
317 status = KINSetOrthAA(kinsol_mem,
data.anderson_qr_orthogonalization);
321 data.anderson_qr_orthogonalization ==
322 AdditionalData::modified_gram_schmidt,
324 "You specified an orthogonalization strategy for QR factorization "
325 "different from the default (modified Gram-Schmidt) but the installed "
326 "SUNDIALS version does not support this feature. Either choose the "
327 "default or install a SUNDIALS version >= 6.0.0."));
330 if (
data.strategy == AdditionalData::fixed_point)
334 [](N_Vector yy, N_Vector FF,
void *user_data) ->
int {
338 auto src_yy = internal::unwrap_nvector_const<VectorType>(yy);
339 auto dst_FF = internal::unwrap_nvector<VectorType>(FF);
356 [](N_Vector yy, N_Vector FF,
void *user_data) ->
int {
360 auto src_yy = internal::unwrap_nvector_const<VectorType>(yy);
361 auto dst_FF = internal::unwrap_nvector<VectorType>(FF);
373 status = KINSetFuncNormTol(kinsol_mem,
data.function_tolerance);
376 status = KINSetScaledStepTol(kinsol_mem,
data.step_tolerance);
379 status = KINSetMaxSetupCalls(kinsol_mem,
data.maximum_setup_calls);
382 status = KINSetNoInitSetup(kinsol_mem,
data.no_init_setup);
385 status = KINSetMaxNewtonStep(kinsol_mem,
data.maximum_newton_step);
388 status = KINSetMaxBetaFails(kinsol_mem,
data.maximum_beta_failures);
391 status = KINSetRelErrFunc(kinsol_mem,
data.dq_relative_error);
394 SUNMatrix J =
nullptr;
398 if (solve_with_jacobian)
405# if DEAL_II_SUNDIALS_VERSION_LT(6, 0, 0)
406 LS = SUNLinSolNewEmpty();
408 LS = SUNLinSolNewEmpty(kinsol_ctx);
414 return SUNLINEARSOLVER_MATRIX_ITERATIVE;
420 LS->content =
nullptr;
445 auto src_b = internal::unwrap_nvector_const<VectorType>(b);
446 auto dst_x = internal::unwrap_nvector<VectorType>(x);
463# if DEAL_II_SUNDIALS_VERSION_LT(6, 0, 0)
464 J = SUNMatNewEmpty();
466 J = SUNMatNewEmpty(kinsol_ctx);
470 J->ops->getid = [](SUNMatrix ) -> SUNMatrix_ID {
471 return SUNMATRIX_CUSTOM;
474 J->ops->destroy = [](SUNMatrix A) {
477 A->content =
nullptr;
489 status = KINSetLinearSolver(kinsol_mem, LS, J);
499 status = KINSetJacFn(
510 const KINSOL<VectorType> &solver =
511 *
static_cast<const KINSOL<VectorType> *
>(user_data);
513 auto ycur = internal::unwrap_nvector_const<VectorType>(u);
514 auto fcur = internal::unwrap_nvector<VectorType>(f);
518 solver.setup_jacobian, solver.pending_exception, *ycur, *fcur);
526 custom_setup(kinsol_mem);
544 status = KINSol(kinsol_mem, solution,
data.strategy, u_scale, f_scale);
546 ScopeExit upon_exit([
this, &J, &LS]()
mutable {
551 KINFree(&kinsol_mem);
554 if (pending_exception)
558 std::rethrow_exception(pending_exception);
562 pending_exception =
nullptr;
570 pending_exception =
nullptr;
587 status = KINGetNumNonlinSolvIters(kinsol_mem, &nniters);
590 return static_cast<unsigned int>(nniters);
595 template <
typename VectorType>
599 reinit_vector = [](VectorType &) {
610# ifdef DEAL_II_WITH_MPI
612# ifdef DEAL_II_TRILINOS_WITH_EPETRA
617# ifdef DEAL_II_TRILINOS_WITH_TPETRA
630# ifdef DEAL_II_WITH_PETSC
631# ifndef PETSC_USE_COMPLEX
void add_parameter(const std::string &entry, ParameterType ¶meter, const std::string &documentation="", const Patterns::PatternBase &pattern= *Patterns::Tools::Convert< ParameterType >::to_pattern(), const bool has_to_be_set=false)
void enter_subsection(const std::string &subsection, const bool create_path_if_needed=true)
void add_action(const std::string &entry, const std::function< void(const std::string &value)> &action, const bool execute_action=true)
OrthogonalizationStrategy
AdditionalData(const SolutionStrategy &strategy=linesearch, const unsigned int maximum_non_linear_iterations=200, const double function_tolerance=0.0, const double step_tolerance=0.0, const bool no_init_setup=false, const unsigned int maximum_setup_calls=0, const double maximum_newton_step=0.0, const double dq_relative_error=0.0, const unsigned int maximum_beta_failures=0, const unsigned int anderson_subspace_size=0, const OrthogonalizationStrategy anderson_qr_orthogonalization=modified_gram_schmidt)
void add_parameters(ParameterHandler &prm)
void set_functions_to_trigger_an_assert()
MPI_Comm mpi_communicator
unsigned int solve(VectorType &initial_guess_and_solution)
std::function< void(const VectorType &src, VectorType &dst)> residual
std::function< void(const VectorType &src, VectorType &dst)> iteration_function
std::exception_ptr pending_exception
std::function< void(const VectorType &rhs, VectorType &dst, const double tolerance)> solve_with_jacobian
KINSOL(const AdditionalData &data=AdditionalData())
#define DEAL_II_NAMESPACE_OPEN
#define DEAL_II_SUNDIALS_VERSION_GTE(major, minor, patch)
#define DEAL_II_NAMESPACE_CLOSE
#define DEAL_II_ASSERT_UNREACHABLE()
#define AssertKINSOL(code)
static ::ExceptionBase & ExcFunctionNotProvided(std::string arg1)
#define Assert(cond, exc)
static ::ExceptionBase & ExcKINSOLError(int arg1)
static ::ExceptionBase & ExcInternalError()
static ::ExceptionBase & RecoverableUserCallbackError()
static ::ExceptionBase & ExcMessage(std::string arg1)
#define AssertThrow(cond, exc)
std::vector< index_type > data
Tpetra::Vector< Number, LO, GO, NodeType< MemorySpace > > VectorType
SymmetricTensor< 2, dim, Number > b(const Tensor< 2, dim, Number > &F)
int call_and_possibly_capture_exception(const F &f, std::exception_ptr &eptr, Args &&...args)