21 #ifdef DEAL_II_WITH_SUNDIALS
28 # ifdef DEAL_II_WITH_TRILINOS
32 # ifdef DEAL_II_WITH_PETSC
39 # include <sundials/sundials_config.h>
40 # if DEAL_II_SUNDIALS_VERSION_LT(4, 0, 0)
41 # ifdef DEAL_II_SUNDIALS_WITH_IDAS
42 # include <idas/idas_impl.h>
44 # include <ida/ida_impl.h>
47 # if DEAL_II_SUNDIALS_VERSION_LT(5, 0, 0)
61 template <
typename VectorType>
63 t_dae_residual(realtype tt,
69 IDA<VectorType> &solver = *
static_cast<IDA<VectorType> *
>(user_data);
71 auto *src_yy = internal::unwrap_nvector_const<VectorType>(yy);
72 auto *src_yp = internal::unwrap_nvector_const<VectorType>(yp);
73 auto *residual = internal::unwrap_nvector<VectorType>(rr);
75 int err = solver.residual(tt, *src_yy, *src_yp, *residual);
82 # if DEAL_II_SUNDIALS_VERSION_LT(4, 0, 0)
83 template <
typename VectorType>
85 t_dae_lsetup(IDAMem IDA_mem,
97 IDA<VectorType> &solver =
98 *
static_cast<IDA<VectorType> *
>(IDA_mem->ida_user_data);
100 auto *src_yy = internal::unwrap_nvector_const<VectorType>(yy);
101 auto *src_yp = internal::unwrap_nvector_const<VectorType>(yp);
103 int err = solver.setup_jacobian(IDA_mem->ida_tn,
113 template <
typename VectorType>
115 t_dae_solve(IDAMem IDA_mem,
126 IDA<VectorType> &solver =
127 *
static_cast<IDA<VectorType> *
>(IDA_mem->ida_user_data);
131 solver.reinit_vector(*dst);
133 auto *src = internal::unwrap_nvector<VectorType>(
b);
135 int err = solver.solve_jacobian_system(*src, *dst);
144 template <
typename VectorType>
146 t_dae_jacobian_setup(realtype tt,
158 IDA<VectorType> &solver = *
static_cast<IDA<VectorType> *
>(user_data);
160 auto *src_yy = internal::unwrap_nvector_const<VectorType>(yy);
161 auto *src_yp = internal::unwrap_nvector_const<VectorType>(yp);
163 int err = solver.setup_jacobian(tt, *src_yy, *src_yp, cj);
170 template <
typename VectorType>
172 t_dae_solve_jacobian_system(SUNLinearSolver LS,
178 IDA<VectorType> &solver = *
static_cast<IDA<VectorType> *
>(LS->content);
180 auto *src_b = internal::unwrap_nvector_const<VectorType>(
b);
181 auto *dst_x = internal::unwrap_nvector<VectorType>(x);
183 if (solver.solve_with_jacobian)
184 err = solver.solve_with_jacobian(*src_b, *dst_x, tol);
185 else if (solver.solve_jacobian_system)
186 err = solver.solve_jacobian_system(*src_b, *dst_x);
198 template <
typename VectorType>
209 template <
typename VectorType>
214 # ifdef DEAL_II_WITH_MPI
217 const int ierr = MPI_Comm_free(&communicator);
226 template <
typename VectorType>
230 double t = data.initial_time;
231 double h = data.initial_step_size;
232 unsigned int step_number = 0;
237 reset(data.initial_time, data.initial_step_size, solution, solution_dot);
243 double next_time = data.initial_time;
245 output_step(0, solution, solution_dot, 0);
247 while (t < data.final_time)
249 next_time += data.output_period;
251 auto yy = internal::make_nvector_view(solution);
252 auto yp = internal::make_nvector_view(solution_dot);
254 status = IDASolve(ida_mem, next_time, &t, yy, yp, IDA_NORMAL);
257 status = IDAGetLastStep(ida_mem, &h);
260 while (solver_should_restart(t, solution, solution_dot))
261 reset(t, h, solution, solution_dot);
265 output_step(t, solution, solution_dot, step_number);
273 template <
typename VectorType>
276 const double current_time_step,
277 VectorType & solution,
278 VectorType & solution_dot)
280 bool first_step = (current_time == data.initial_time);
285 ida_mem = IDACreate();
290 auto yy = internal::make_nvector_view(solution);
291 auto yp = internal::make_nvector_view(solution_dot);
293 status = IDAInit(ida_mem, t_dae_residual<VectorType>, current_time, yy, yp);
295 if (get_local_tolerances)
297 const auto abs_tols =
298 internal::make_nvector_view(get_local_tolerances());
299 status = IDASVtolerances(ida_mem, data.relative_tolerance, abs_tols);
304 status = IDASStolerances(ida_mem,
305 data.relative_tolerance,
306 data.absolute_tolerance);
310 status = IDASetInitStep(ida_mem, current_time_step);
313 status = IDASetUserData(ida_mem,
this);
316 if (data.ic_type == AdditionalData::use_y_diff ||
317 data.reset_type == AdditionalData::use_y_diff ||
318 data.ignore_algebraic_terms_for_errors)
320 VectorType diff_comp_vector(solution);
321 diff_comp_vector = 0.0;
322 auto dc = differential_components();
323 for (
auto i = dc.begin(); i != dc.end(); ++i)
324 diff_comp_vector[*i] = 1.0;
327 const auto diff_id = internal::make_nvector_view(diff_comp_vector);
328 status = IDASetId(ida_mem, diff_id);
332 status = IDASetSuppressAlg(ida_mem, data.ignore_algebraic_terms_for_errors);
336 status = IDASetStopTime(ida_mem, data.final_time);
339 status = IDASetMaxNonlinIters(ida_mem, data.maximum_non_linear_iterations);
343 # if DEAL_II_SUNDIALS_VERSION_LT(4, 0, 0)
344 auto IDA_mem =
static_cast<IDAMem
>(ida_mem);
346 IDA_mem->ida_lsetup = t_dae_lsetup<VectorType>;
348 if (solve_jacobian_system)
349 IDA_mem->ida_lsolve = t_dae_solve<VectorType>;
351 AssertThrow(
false, ExcFunctionNotProvided(
"solve_jacobian_system"));
352 # if DEAL_II_SUNDIALS_VERSION_LT(3, 0, 0)
353 IDA_mem->ida_setupNonNull =
true;
356 SUNMatrix J =
nullptr;
357 SUNLinearSolver LS =
nullptr;
366 LS->ops->gettype = [](SUNLinearSolver ) -> SUNLinearSolver_Type {
367 return SUNLINEARSOLVER_MATRIX_ITERATIVE;
370 LS->ops->free = [](SUNLinearSolver LS) ->
int {
373 LS->content =
nullptr;
385 AssertThrow(solve_jacobian_system || solve_with_jacobian,
386 ExcFunctionNotProvided(
387 "solve_jacobian_system or solve_with_jacobian"));
388 LS->ops->solve = t_dae_solve_jacobian_system<VectorType>;
397 LS->ops->resid = [](SUNLinearSolver ) -> N_Vector {
403 LS->ops->numiters = [](SUNLinearSolver ) ->
int {
return 1; };
409 J = SUNMatNewEmpty();
412 J->ops->getid = [](SUNMatrix ) -> SUNMatrix_ID {
413 return SUNMATRIX_CUSTOM;
416 J->ops->destroy = [](SUNMatrix
A) {
419 A->content =
nullptr;
431 status = IDASetLinearSolver(ida_mem, LS, J);
434 status = IDASetLSNormFactor(ida_mem, data.ls_norm_factor);
439 status = IDASetJacFn(ida_mem, &t_dae_jacobian_setup<VectorType>);
442 status = IDASetMaxOrd(ida_mem, data.maximum_order);
449 type = data.reset_type;
452 IDASetMaxNumItersIC(ida_mem, data.maximum_non_linear_iterations_ic);
455 if (type == AdditionalData::use_y_dot)
459 IDACalcIC(ida_mem, IDA_Y_INIT, current_time + current_time_step);
462 status = IDAGetConsistentIC(ida_mem, yy, yp);
465 else if (type == AdditionalData::use_y_diff)
468 IDACalcIC(ida_mem, IDA_YA_YDP_INIT, current_time + current_time_step);
471 status = IDAGetConsistentIC(ida_mem, yy, yp);
476 template <
typename VectorType>
480 reinit_vector = [](VectorType &) {
481 AssertThrow(
false, ExcFunctionNotProvided(
"reinit_vector"));
484 residual = [](
const double,
487 VectorType &) ->
int {
489 AssertThrow(
false, ExcFunctionNotProvided(
"residual"));
494 output_step = [](
const double,
497 const unsigned int) {
return; };
499 solver_should_restart =
500 [](
const double, VectorType &, VectorType &) ->
bool {
return false; };
502 differential_components = [&]() ->
IndexSet {
506 return v->locally_owned_elements();
513 # ifdef DEAL_II_WITH_MPI
515 # ifdef DEAL_II_WITH_TRILINOS
520 # ifdef DEAL_II_WITH_PETSC
521 # ifndef PETSC_USE_COMPLEX
InitialConditionCorrection
unsigned int solve_dae(VectorType &solution, VectorType &solution_dot)
void set_functions_to_trigger_an_assert()
void reset(const double t, const double h, VectorType &y, VectorType &yp)
IDA(const AdditionalData &data=AdditionalData(), const MPI_Comm &mpi_comm=MPI_COMM_WORLD)
#define DEAL_II_NAMESPACE_OPEN
#define DEAL_II_NAMESPACE_CLOSE
static ::ExceptionBase & ExcInternalError()
#define Assert(cond, exc)
#define AssertNothrow(cond, exc)
#define AssertThrow(cond, exc)
SymmetricTensor< 2, dim, Number > b(const Tensor< 2, dim, Number > &F)
SUNLinearSolver SUNLinSolNewEmpty()
MPI_Comm duplicate_communicator(const MPI_Comm &mpi_communicator)