Block-Structured AMR Software Framework
Loading...
Searching...
No Matches
AMReX_SundialsIntegrator.H
Go to the documentation of this file.
1#ifndef AMREX_SUNDIALS_INTEGRATOR_H
2#define AMREX_SUNDIALS_INTEGRATOR_H
3
4#include <functional>
5#include <utility>
6
7#include <AMReX_Config.H>
8#include <AMReX_REAL.H>
9#include <AMReX_Vector.H>
10#include <AMReX_ParmParse.H>
13#include <AMReX_Sundials.H>
14
15#include <nvector/nvector_manyvector.h>
16#include <sunnonlinsol/sunnonlinsol_fixedpoint.h>
17#include <sunlinsol/sunlinsol_spgmr.h>
18#include <arkode/arkode_arkstep.h>
19#include <arkode/arkode_mristep.h>
20
21// SUNDIALS 7.1 deprecated the stepper-specific functions in favor of
22// ARKODE-wide ones.
23#if defined(SUNDIALS_VERSION_MAJOR) && \
24 ((SUNDIALS_VERSION_MAJOR > 7) || (SUNDIALS_VERSION_MAJOR == 7 && SUNDIALS_VERSION_MINOR >= 1))
25# define AMREX_SUNDIALS_ARKODE_API 1
26# define AMREX_ARKSTEP(f) ARKode##f
27# define AMREX_MRISTEP(f) ARKode##f
28#else
29# define AMREX_SUNDIALS_ARKODE_API 0
30# define AMREX_ARKSTEP(f) ARKStep##f
31# define AMREX_MRISTEP(f) MRIStep##f
32#endif
33
41namespace amrex {
42
50 std::function<int(amrex::Real, N_Vector, N_Vector, void*)> f;
51 std::function<int(amrex::Real, N_Vector, N_Vector, void*)> fi;
52 std::function<int(amrex::Real, N_Vector, N_Vector, void*)> fe;
53 std::function<int(amrex::Real, N_Vector, N_Vector, void*)> ff;
54 std::function<int(amrex::Real, N_Vector, void*)> post_stage;
55 std::function<int(amrex::Real, N_Vector, void*)> post_step;
56 std::function<int(amrex::Real, N_Vector, void*)> post_fast_stage;
57 std::function<int(amrex::Real, N_Vector, void*)> post_fast_step;
58};
59
60namespace SundialsUserFun {
61 static int f (amrex::Real t, N_Vector y_data, N_Vector y_rhs, void *user_data) {
62 SundialsUserData* udata = static_cast<SundialsUserData*>(user_data);
63 return udata->f(t, y_data, y_rhs, user_data);
64 }
65
66 static int fi (amrex::Real t, N_Vector y_data, N_Vector y_rhs, void *user_data) {
67 SundialsUserData* udata = static_cast<SundialsUserData*>(user_data);
68 return udata->fi(t, y_data, y_rhs, user_data);
69 }
70
71 static int fe (amrex::Real t, N_Vector y_data, N_Vector y_rhs, void *user_data) {
72 SundialsUserData* udata = static_cast<SundialsUserData*>(user_data);
73 return udata->fe(t, y_data, y_rhs, user_data);
74 }
75
76 static int ff (amrex::Real t, N_Vector y_data, N_Vector y_rhs, void *user_data) {
77 SundialsUserData* udata = static_cast<SundialsUserData*>(user_data);
78 return udata->ff(t, y_data, y_rhs, user_data);
79 }
80
81 static int post_stage (amrex::Real t, N_Vector y_data, void *user_data) {
82 SundialsUserData* udata = static_cast<SundialsUserData*>(user_data);
83 return udata->post_stage(t, y_data, user_data);
84 }
85
86 static int post_step (amrex::Real t, N_Vector y_data, void *user_data) {
87 SundialsUserData* udata = static_cast<SundialsUserData*>(user_data);
88 return udata->post_step(t, y_data, user_data);
89 }
90
91 static int post_fast_stage (amrex::Real t, N_Vector y_data, void *user_data) {
92 SundialsUserData* udata = static_cast<SundialsUserData*>(user_data);
93 return udata->post_fast_stage(t, y_data, user_data);
94 }
95
96 static int post_fast_step (amrex::Real t, N_Vector y_data, void *user_data) {
97 SundialsUserData* udata = static_cast<SundialsUserData*>(user_data);
98 return udata->post_fast_step(t, y_data, user_data);
99 }
100}
101
107template<class T>
109{
110private:
111 using BaseT = IntegratorBase<T>;
112
113 // Method type: ERK, DIRK, IMEX-RK, EX-MRI, IM-MRI, IMEX-MRI
114 std::string type = "ERK";
115
116 // Use SUNDIALS default methods
117 std::string method = "DEFAULT"; // ERK, DIRK, or slow method with MRI
118 std::string method_e = "DEFAULT"; // ERK in IMEX-RK
119 std::string method_i = "DEFAULT"; // DIRK in IMEX-RK
120
121 // Fast method type (ERK or DIRK) and method
122 std::string fast_type = "ERK";
123 std::string fast_method = "DEFAULT";
124
125 // Nonlinear solver
126 std::string nonlinear_solver = "Newton";
127 int max_nonlinear_iters = 0;
128
129 std::string fast_nonlinear_solver = "Newton";
130 int fast_max_nonlinear_iters = 0;
131
132 // Linear solver
133 std::string linear_solver = "GMRES";
134 int max_linear_iters = 0;
135
136 std::string fast_linear_solver = "GMRES";
137 int fast_max_linear_iters = 0;
138
139 // SUNDIALS package flags, set based on type
140 bool use_ark = false;
141 bool use_mri = false;
142
143 // structure for interfacing with user-supplied functions
144 SundialsUserData udata;
145
146 // SUNDIALS context
147 //
148 // We should probably use context created by amrex:sundials::Initialize but
149 // that context is not MPI-aware
150 ::sundials::Context sunctx;
151
152 // Single rate or slow time scale
153 void *arkode_mem = nullptr;
154 SUNLinearSolver LS = nullptr;
155 SUNNonlinearSolver NLS = nullptr;
156 amrex::Real step_applied = 0; // fixed step last given to SUNDIALS; 0: adaptive
157 amrex::Real rtol_applied = -1; // tolerances last given to SUNDIALS; -1: none
158 amrex::Real atol_applied = -1;
159
160 // Fast time scale
161 void *arkode_fast_mem = nullptr;
162 amrex::Real fast_step_applied = 0; // fast fixed step last given to SUNDIALS; 0: adaptive
163 amrex::Real fast_rtol_applied = -1; // fast tolerances last given to SUNDIALS; -1: none
164 amrex::Real fast_atol_applied = -1;
165 MRIStepInnerStepper fast_stepper = nullptr;
166 SUNLinearSolver fast_LS = nullptr;
167 SUNNonlinearSolver fast_NLS = nullptr;
168
169 // Integrator stop time
170 bool set_stop_time = false;
171 amrex::Real stop_time = 0.0;
172
173 // Max steps between returns
174 amrex::Long max_num_steps = 0;
175
177 void free_memory ()
178 {
179 if (use_mri) {
180 MRIStepInnerStepper_Free(&fast_stepper);
181 AMREX_ARKSTEP(Free)(&arkode_fast_mem);
182 AMREX_MRISTEP(Free)(&arkode_mem);
183 } else if (use_ark) {
184 AMREX_ARKSTEP(Free)(&arkode_mem);
185 }
186 SUNLinSolFree(LS);
187 LS = nullptr;
188 SUNLinSolFree(fast_LS);
189 fast_LS = nullptr;
190 SUNNonlinSolFree(NLS);
191 NLS = nullptr;
192 SUNNonlinSolFree(fast_NLS);
193 fast_NLS = nullptr;
194 use_ark = false;
195 use_mri = false;
196 }
197
198 void initialize_parameters ()
199 {
200 amrex::ParmParse pp("integration.sundials");
201
202 pp.query("type", type);
203 pp.query("method", method);
204 pp.query("method_e", method_e);
205 pp.query("method_i", method_i);
206
207 pp.query("fast_type", fast_type);
208 pp.query("fast_method", fast_method);
209
210 if (type == "ERK" || type == "DIRK" || type == "IMEX-RK") {
211 use_ark = true;
212 }
213 else if (type == "EX-MRI" || type == "IM-MRI" || type == "IMEX-MRI") {
214 use_mri = true;
215 }
216 else {
217 std::string msg("Unknown method type: ");
218 msg += type;
219 amrex::Error(msg.c_str());
220 }
221
222 pp.query("nonlinear_solver", nonlinear_solver);
223 pp.query("max_nonlinear_iters", max_nonlinear_iters);
224
225 pp.query("fast_nonlinear_solver", fast_nonlinear_solver);
226 pp.query("fast_max_nonlinear_iters", fast_max_nonlinear_iters);
227
228 pp.query("linear_solver", linear_solver);
229 pp.query("max_linear_iters", max_linear_iters);
230
231 pp.query("fast_linear_solver", fast_linear_solver);
232 pp.query("fast_max_linear_iters", fast_max_linear_iters);
233
234 set_stop_time = pp.query("stop_time", stop_time);
235
236 pp.query("max_num_steps", max_num_steps);
237 }
238
239 void SetupRK (amrex::Real time, N_Vector y_data)
240 {
241 step_applied = 0;
242 rtol_applied = -1;
243 atol_applied = -1;
244 if (amrex::Verbose()) { amrex::Print() << "Using SUNDIALS time integrator\n"; }
245 int flag = 0;
246
247 // Create integrator and select method
248 if (type == "ERK") {
249 if (amrex::Verbose()) { amrex::Print() << "ERK method: " << method << "\n"; }
250 arkode_mem = ARKStepCreate(SundialsUserFun::f, nullptr, time, y_data, sunctx);
251 AMREX_ALWAYS_ASSERT(arkode_mem != nullptr);
252 if (method != "DEFAULT") {
253 flag = ARKStepSetTableName(arkode_mem, "ARKODE_DIRK_NONE", method.c_str());
254 AMREX_ALWAYS_ASSERT(flag == 0);
255 }
256 }
257 else if (type == "DIRK") {
258 if (amrex::Verbose()) { amrex::Print() << "DIRK method: " << method << "\n"; }
259 arkode_mem = ARKStepCreate(nullptr, SundialsUserFun::f, time, y_data, sunctx);
260 AMREX_ALWAYS_ASSERT(arkode_mem != nullptr);
261 if (method != "DEFAULT") {
262 flag = ARKStepSetTableName(arkode_mem, method.c_str(), "ARKODE_ERK_NONE");
263 AMREX_ALWAYS_ASSERT(flag == 0);
264 }
265 }
266 else if (type == "IMEX-RK") {
267 if (amrex::Verbose()) { amrex::Print() << "IMEX-RK method: " << method_i << " and "
268 << method_e << "\n"; }
269 arkode_mem = ARKStepCreate(SundialsUserFun::fe, SundialsUserFun::fi, time, y_data, sunctx);
270 AMREX_ALWAYS_ASSERT(arkode_mem != 0);
271 if (method_e != "DEFAULT" && method_i != "DEFAULT")
272 {
273 flag = ARKStepSetTableName(arkode_mem, method_i.c_str(), method_e.c_str());
274 AMREX_ALWAYS_ASSERT(flag == 0);
275 }
276 }
277
278 // Attach structure with user-supplied function wrappers
279 flag = AMREX_ARKSTEP(SetUserData)(arkode_mem, &udata);
280 AMREX_ALWAYS_ASSERT(flag == 0);
281
282 // Set integrator tolerances
283 if (BaseT::use_adaptive_time_step || type == "DIRK" || type == "IMEX-RK") {
284 if (amrex::Verbose()) {
285 amrex::Print() << "Relative tolerance: " << BaseT::rel_tol << "\n";
286 amrex::Print() << "Absolute tolerance: " << BaseT::abs_tol << "\n";
287 }
288 flag = AMREX_ARKSTEP(SStolerances)(arkode_mem, BaseT::rel_tol, BaseT::abs_tol);
289 AMREX_ALWAYS_ASSERT(flag == 0);
290 rtol_applied = BaseT::rel_tol;
291 atol_applied = BaseT::abs_tol;
292 }
293
294 // Create and attach linear solver for implicit methods
295 if (type == "DIRK" || type == "IMEX-RK") {
296 if (amrex::Verbose()) {
297 amrex::Print() << "Nonlinear solver: " << nonlinear_solver << "\n";
298 amrex::Print() << "Max nonlinear iters: " << max_nonlinear_iters << "\n";
299 }
300 if (nonlinear_solver == "fixed-point") {
301 NLS = SUNNonlinSol_FixedPoint(y_data, 0, sunctx);
302 AMREX_ALWAYS_ASSERT(NLS != nullptr);
303 flag = AMREX_ARKSTEP(SetNonlinearSolver)(arkode_mem, NLS);
304 AMREX_ALWAYS_ASSERT(flag == 0);
305 }
306 flag = AMREX_ARKSTEP(SetMaxNonlinIters)(arkode_mem, max_nonlinear_iters);
307 AMREX_ALWAYS_ASSERT(flag == 0);
308
309 if (nonlinear_solver == "Newton") {
310 if (amrex::Verbose()) {
311 amrex::Print() << "Linear solver: " << linear_solver << "\n";
312 amrex::Print() << "Max linear iters: " << max_linear_iters << "\n";
313 }
314 LS = SUNLinSol_SPGMR(y_data, SUN_PREC_NONE, max_linear_iters, sunctx);
315 AMREX_ALWAYS_ASSERT(LS != nullptr);
316 flag = AMREX_ARKSTEP(SetLinearSolver)(arkode_mem, LS, nullptr);
317 AMREX_ALWAYS_ASSERT(flag == 0);
318 }
319 }
320
321 // Set post stage and step function
322 flag = AMREX_ARKSTEP(SetPostprocessStageFn)(arkode_mem, SundialsUserFun::post_stage);
323 AMREX_ALWAYS_ASSERT(flag == 0);
324 flag = AMREX_ARKSTEP(SetPostprocessStepFn)(arkode_mem, SundialsUserFun::post_step);
325 AMREX_ALWAYS_ASSERT(flag == 0);
326
327 // Set a stop time
328 if (set_stop_time) {
329 if (amrex::Verbose()) { amrex::Print() << "Stop time: " << stop_time << "\n"; }
330 flag = AMREX_ARKSTEP(SetStopTime)(arkode_mem, stop_time);
331 AMREX_ALWAYS_ASSERT(flag == 0);
332 }
333
334 // Set max number of steps between returns
335 flag = AMREX_ARKSTEP(SetMaxNumSteps)(arkode_mem, max_num_steps);
336 AMREX_ALWAYS_ASSERT(flag == 0);
337 }
338
340 void apply_tolerances ()
341 {
342 if ((BaseT::use_adaptive_time_step || type == "DIRK" || type == "IMEX-RK" ||
343 type == "IM-MRI" || type == "IMEX-MRI") &&
344 (BaseT::rel_tol != rtol_applied || BaseT::abs_tol != atol_applied))
345 {
346#if AMREX_SUNDIALS_ARKODE_API
347 int flag = ARKodeSStolerances(arkode_mem, BaseT::rel_tol, BaseT::abs_tol);
348#else
349 int flag = use_mri ? MRIStepSStolerances(arkode_mem, BaseT::rel_tol, BaseT::abs_tol)
350 : ARKStepSStolerances(arkode_mem, BaseT::rel_tol, BaseT::abs_tol);
351#endif
352 AMREX_ALWAYS_ASSERT(flag == 0);
353 rtol_applied = BaseT::rel_tol;
354 atol_applied = BaseT::abs_tol;
355 }
356 }
357
359 void apply_step (amrex::Real h)
360 {
361 if (h != step_applied) {
362#if AMREX_SUNDIALS_ARKODE_API
363 int flag = ARKodeSetFixedStep(arkode_mem, h);
364#else
365 int flag = use_mri ? MRIStepSetFixedStep(arkode_mem, h)
366 : ARKStepSetFixedStep(arkode_mem, h);
367#endif
368 AMREX_ALWAYS_ASSERT(flag == 0);
369 step_applied = h;
370 }
371 }
372
374 void apply_fast_step ()
375 {
376 if ((BaseT::use_adaptive_fast_time_step || fast_type == "DIRK" || fast_type == "IMEX-RK") &&
377 (BaseT::fast_rel_tol != fast_rtol_applied || BaseT::fast_abs_tol != fast_atol_applied))
378 {
379 int flag = AMREX_ARKSTEP(SStolerances)(arkode_fast_mem, BaseT::fast_rel_tol, BaseT::fast_abs_tol);
380 AMREX_ALWAYS_ASSERT(flag == 0);
381 fast_rtol_applied = BaseT::fast_rel_tol;
382 fast_atol_applied = BaseT::fast_abs_tol;
383 }
385 if (h != fast_step_applied) {
386 AMREX_ARKSTEP(SetFixedStep)(arkode_fast_mem, h);
387 fast_step_applied = h;
388 }
389 }
390
391 void SetupMRI (amrex::Real time, N_Vector y_data)
392 {
393 step_applied = 0;
394 rtol_applied = -1;
395 atol_applied = -1;
396 fast_step_applied = 0;
397 fast_rtol_applied = -1;
398 fast_atol_applied = -1;
399 if (amrex::Verbose()) { amrex::Print() << "Using SUNDIALS multirate time integrator\n"; }
400 int flag = 0;
401
402 // Create the fast integrator and select method
403 if (fast_type == "ERK") {
404 if (amrex::Verbose()) { amrex::Print() << "Fast ERK method: " << fast_method << "\n"; }
405 arkode_fast_mem = ARKStepCreate(SundialsUserFun::ff, nullptr, time, y_data, sunctx);
406 AMREX_ALWAYS_ASSERT(arkode_fast_mem != nullptr);
407 if (fast_method != "DEFAULT") {
408 flag = ARKStepSetTableName(arkode_fast_mem, "ARKODE_DIRK_NONE", fast_method.c_str());
409 AMREX_ALWAYS_ASSERT(flag == 0);
410 }
411 }
412 else if (fast_type == "DIRK") {
413 if (amrex::Verbose()) { amrex::Print() << "Fast DIRK method: " << fast_method << "\n"; }
414 arkode_fast_mem = ARKStepCreate(nullptr, SundialsUserFun::ff, time, y_data, sunctx);
415 AMREX_ALWAYS_ASSERT(arkode_fast_mem != nullptr);
416 if (fast_method != "DEFAULT") {
417 flag = ARKStepSetTableName(arkode_fast_mem, fast_method.c_str(), "ARKODE_ERK_NONE");
418 AMREX_ALWAYS_ASSERT(flag == 0);
419 }
420
421 if (amrex::Verbose()) {
422 amrex::Print() << "Fast nonlinear solver: " << fast_nonlinear_solver << "\n";
423 amrex::Print() << "Fast max nonlinear iters: " << fast_max_nonlinear_iters << "\n";
424 }
425 if (fast_nonlinear_solver == "fixed-point") {
426 fast_NLS = SUNNonlinSol_FixedPoint(y_data, 0, sunctx);
427 AMREX_ALWAYS_ASSERT(fast_NLS != nullptr);
428 flag = AMREX_ARKSTEP(SetNonlinearSolver)(arkode_fast_mem, fast_NLS);
429 AMREX_ALWAYS_ASSERT(flag == 0);
430 }
431 flag = AMREX_ARKSTEP(SetMaxNonlinIters)(arkode_fast_mem, fast_max_nonlinear_iters);
432 AMREX_ALWAYS_ASSERT(flag == 0);
433
434 if (fast_nonlinear_solver == "Newton") {
435 if (amrex::Verbose()) {
436 amrex::Print() << "Linear solver: " << fast_linear_solver << "\n";
437 amrex::Print() << "Max linear iters: " << fast_max_linear_iters << "\n";
438 }
439 fast_LS = SUNLinSol_SPGMR(y_data, SUN_PREC_NONE, fast_max_linear_iters, sunctx);
440 AMREX_ALWAYS_ASSERT(fast_LS != nullptr);
441 flag = AMREX_ARKSTEP(SetLinearSolver)(arkode_fast_mem, fast_LS, nullptr);
442 AMREX_ALWAYS_ASSERT(flag == 0);
443 }
444 }
445
446 // Attach structure with user-supplied function wrappers
447 flag = AMREX_ARKSTEP(SetUserData)(arkode_fast_mem, &udata);
448 AMREX_ALWAYS_ASSERT(flag == 0);
449
450 // Set integrator tolerances
451 if (BaseT::use_adaptive_fast_time_step || fast_type == "DIRK" || fast_type == "IMEX-RK") {
452 if (amrex::Verbose()) {
453 amrex::Print() << "Fast relative tolerance: " << BaseT::fast_rel_tol << "\n";
454 amrex::Print() << "Fast absolute tolerance: " << BaseT::fast_abs_tol << "\n";
455 }
456 flag = AMREX_ARKSTEP(SStolerances)(arkode_fast_mem, BaseT::fast_rel_tol, BaseT::fast_abs_tol);
457 AMREX_ALWAYS_ASSERT(flag == 0);
458 fast_rtol_applied = BaseT::fast_rel_tol;
459 fast_atol_applied = BaseT::fast_abs_tol;
460 }
461
462 // Set post stage and step function
463 flag = AMREX_ARKSTEP(SetPostprocessStageFn)(arkode_fast_mem, SundialsUserFun::post_fast_stage);
464 AMREX_ALWAYS_ASSERT(flag == 0);
465 flag = AMREX_ARKSTEP(SetPostprocessStepFn)(arkode_fast_mem, SundialsUserFun::post_fast_step);
466 AMREX_ALWAYS_ASSERT(flag == 0);
467
468 // Set max number of steps between returns
469 flag = AMREX_ARKSTEP(SetMaxNumSteps)(arkode_fast_mem, max_num_steps);
470 AMREX_ALWAYS_ASSERT(flag == 0);
471
472 // Wrap fast integrator as an inner stepper
473#if defined(SUNDIALS_VERSION_MAJOR) && \
474 ((SUNDIALS_VERSION_MAJOR > 7) || (SUNDIALS_VERSION_MAJOR == 7 && SUNDIALS_VERSION_MINOR >= 2))
475 flag = ARKodeCreateMRIStepInnerStepper(arkode_fast_mem, &fast_stepper);
476#else
477 flag = ARKStepCreateMRIStepInnerStepper(arkode_fast_mem, &fast_stepper);
478#endif
479 AMREX_ALWAYS_ASSERT(flag == 0);
480
481 // Create slow integrator
482 if (type == "EX-MRI") {
483 if (amrex::Verbose()) { amrex::Print() << "EX-MRI method: " << method << "\n"; }
484 arkode_mem = MRIStepCreate(SundialsUserFun::f, nullptr, time, y_data,
485 fast_stepper, sunctx);
486 AMREX_ALWAYS_ASSERT(arkode_mem != nullptr);
487 }
488 else if (type == "IM-MRI") {
489 if (amrex::Verbose()) { amrex::Print() << "IM-MRI method: " << method << "\n"; }
490 arkode_mem = MRIStepCreate(nullptr, SundialsUserFun::f, time, y_data,
491 fast_stepper, sunctx);
492 AMREX_ALWAYS_ASSERT(arkode_mem != nullptr);
493 }
494 else if (type == "IMEX-MRI") {
495 if (amrex::Verbose()) { amrex::Print() << "IMEX-MRI method: " << method << "\n"; }
496 arkode_mem = MRIStepCreate(SundialsUserFun::fe, SundialsUserFun::fi,
497 time, y_data, fast_stepper, sunctx);
498 AMREX_ALWAYS_ASSERT(arkode_mem != nullptr);
499 }
500
501 // Set method
502 if (method != "DEFAULT") {
503 MRIStepCoupling MRIC = MRIStepCoupling_LoadTableByName(method.c_str());
504 AMREX_ALWAYS_ASSERT(MRIC != nullptr);
505 flag = MRIStepSetCoupling(arkode_mem, MRIC);
506 AMREX_ALWAYS_ASSERT(flag == 0);
507 MRIStepCoupling_Free(MRIC);
508 }
509
510 // Attach structure with user-supplied function wrappers
511 flag = AMREX_MRISTEP(SetUserData)(arkode_mem, &udata);
512 AMREX_ALWAYS_ASSERT(flag == 0);
513
514 // Set integrator tolerances
515 if (BaseT::use_adaptive_time_step || type == "IM-MRI" || type == "IMEX-MRI") {
516 if (amrex::Verbose()) {
517 amrex::Print() << "Relative tolerance: " << BaseT::rel_tol << "\n";
518 amrex::Print() << "Absolute tolerance: " << BaseT::abs_tol << "\n";
519 }
520 flag = AMREX_MRISTEP(SStolerances)(arkode_mem, BaseT::rel_tol, BaseT::abs_tol);
521 AMREX_ALWAYS_ASSERT(flag == 0);
522 rtol_applied = BaseT::rel_tol;
523 atol_applied = BaseT::abs_tol;
524 }
525
526 // Create and attach linear solver
527 if (type == "IM-MRI" || type == "IMEX-MRI") {
528 if (amrex::Verbose()) {
529 amrex::Print() << "Nonlinear solver: " << nonlinear_solver << "\n";
530 amrex::Print() << "Max nonlinear iters: " << max_nonlinear_iters << "\n";
531 }
532 if (nonlinear_solver == "fixed-point") {
533 NLS = SUNNonlinSol_FixedPoint(y_data, 0, sunctx);
534 AMREX_ALWAYS_ASSERT(NLS != nullptr);
535 flag = AMREX_MRISTEP(SetNonlinearSolver)(arkode_mem, NLS);
536 AMREX_ALWAYS_ASSERT(flag == 0);
537 }
538 flag = AMREX_MRISTEP(SetMaxNonlinIters)(arkode_mem, max_nonlinear_iters);
539 AMREX_ALWAYS_ASSERT(flag == 0);
540
541 if (nonlinear_solver == "Newton") {
542 if (amrex::Verbose()) {
543 amrex::Print() << "Linear solver: " << linear_solver << "\n";
544 amrex::Print() << "Max linear iters: " << max_linear_iters << "\n";
545 }
546 LS = SUNLinSol_SPGMR(y_data, SUN_PREC_NONE, max_linear_iters, sunctx);
547 AMREX_ALWAYS_ASSERT(LS != nullptr);
548 flag = AMREX_MRISTEP(SetLinearSolver)(arkode_mem, LS, nullptr);
549 AMREX_ALWAYS_ASSERT(flag == 0);
550 }
551 }
552
553 // Set post stage and step function
554 flag = AMREX_MRISTEP(SetPostprocessStageFn)(arkode_mem, SundialsUserFun::post_stage);
555 AMREX_ALWAYS_ASSERT(flag == 0);
556 flag = AMREX_MRISTEP(SetPostprocessStepFn)(arkode_mem, SundialsUserFun::post_step);
557 AMREX_ALWAYS_ASSERT(flag == 0);
558
559 // Set a stop time
560 if (set_stop_time) {
561 if (amrex::Verbose()) { amrex::Print() << "Stop time: " << stop_time << "\n"; }
562 flag = AMREX_MRISTEP(SetStopTime)(arkode_mem, stop_time);
563 AMREX_ALWAYS_ASSERT(flag == 0);
564 }
565
566 // Set max number of steps between returns
567 flag = AMREX_MRISTEP(SetMaxNumSteps)(arkode_mem, max_num_steps);
568 AMREX_ALWAYS_ASSERT(flag == 0);
569 }
570
571 // -------------------------------------
572 // Vector<MultiFab> / N_Vector Utilities
573 // -------------------------------------
574
575 // Utility to unpack a SUNDIALS ManyVector into a vector of MultiFabs
576 void unpack_vector (N_Vector y_data, amrex::Vector<amrex::MultiFab>& S_data)
577 {
578 const int num_vecs = N_VGetNumSubvectors_ManyVector(y_data);
579 S_data.resize(num_vecs);
580
581 for(int i = 0; i < num_vecs; i++)
582 {
583 S_data.at(i) = amrex::MultiFab(*amrex::sundials::getMFptr(N_VGetSubvector_ManyVector(y_data, i)),
585 0,
586 amrex::sundials::getMFptr(N_VGetSubvector_ManyVector(y_data, i))->nComp());
587 }
588 }
589
590 // Utility to wrap vector of MultiFabs as a SUNDIALS ManyVector
591 N_Vector wrap_data (amrex::Vector<amrex::MultiFab>& S_data)
592 {
593 auto get_length = [&](int index) -> sunindextype {
594 auto* p_mf = &S_data[index];
595 return p_mf->nComp() * (p_mf->boxArray()).numPts();
596 };
597
598 sunindextype NV_len = S_data.size();
599 N_Vector* NV_array = new N_Vector[NV_len];
600
601 for (int i = 0; i < NV_len; ++i) {
602 NV_array[i] = amrex::sundials::N_VMake_MultiFab(get_length(i),
603 &S_data[i], &sunctx);
604 }
605
606 N_Vector y_data = N_VNew_ManyVector(NV_len, NV_array, sunctx);
607
608 delete[] NV_array;
609
610 return y_data;
611 }
612
613 // Utility to wrap vector of MultiFabs as a SUNDIALS ManyVector
614 N_Vector copy_data (const amrex::Vector<amrex::MultiFab>& S_data)
615 {
616 auto get_length = [&](int index) -> sunindextype {
617 auto* p_mf = &S_data[index];
618 return p_mf->nComp() * (p_mf->boxArray()).numPts();
619 };
620
621 sunindextype NV_len = S_data.size();
622 N_Vector* NV_array = new N_Vector[NV_len];
623
624 for (int i = 0; i < NV_len; ++i) {
625 NV_array[i] = amrex::sundials::N_VNew_MultiFab(get_length(i),
626 S_data[i].boxArray(),
627 S_data[i].DistributionMap(),
628 S_data[i].nComp(),
629 S_data[i].nGrow(),
630 &sunctx);
631
633 S_data[i],
634 0,
635 0,
636 S_data[i].nComp(),
637 S_data[i].nGrow());
638 }
639
640 N_Vector y_data = N_VNew_ManyVector(NV_len, NV_array, sunctx);
641
642 delete[] NV_array;
643
644 return y_data;
645 }
646
647 // -----------------------------
648 // MultiFab / N_Vector Utilities
649 // -----------------------------
650
651 // Utility to unpack a SUNDIALS Vector into a MultiFab
652 void unpack_vector (N_Vector y_data, amrex::MultiFab& S_data)
653 {
656 0,
658 }
659
660 // Utility to wrap a MultiFab as a SUNDIALS Vector
661 N_Vector wrap_data (amrex::MultiFab& S_data)
662 {
663 return amrex::sundials::N_VMake_MultiFab(S_data.nComp() * S_data.boxArray().numPts(),
664 &S_data, &sunctx);
665 }
666
667 // Utility to wrap a MultiFab as a SUNDIALS Vector
668 N_Vector copy_data (const amrex::MultiFab& S_data)
669 {
670 N_Vector y_data = amrex::sundials::N_VNew_MultiFab(S_data.nComp() * S_data.boxArray().numPts(),
671 S_data.boxArray(),
672 S_data.DistributionMap(),
673 S_data.nComp(),
674 S_data.nGrow(),
675 &sunctx);
676
678 S_data,
679 0,
680 0,
681 S_data.nComp(),
682 S_data.nGrow());
683
684 return y_data;
685 }
686
687public:
692
699 SundialsIntegrator (const T& S_data, const amrex::Real time = 0.0)
700 {
701 initialize(S_data, time);
702 }
703
710 void initialize (const T& S_data, const amrex::Real time = 0.0)
711 {
712 free_memory(); // no-op on the first call
713 {
714 // Destroy the current context. Move assignment below does not free
715 // it in SUNDIALS older than 7.6.
716 ::sundials::Context old_sunctx = std::move(sunctx);
717 }
718
719 initialize_parameters();
720#ifdef AMREX_USE_MPI
722#endif
723#if defined(SUNDIALS_VERSION_MAJOR) && (SUNDIALS_VERSION_MAJOR < 7)
724# ifdef AMREX_USE_MPI
725 sunctx = ::sundials::Context(&mpi_comm);
726# else
727 sunctx = ::sundials::Context(nullptr);
728# endif
729#else
730# ifdef AMREX_USE_MPI
731 sunctx = ::sundials::Context(mpi_comm);
732# else
733 sunctx = ::sundials::Context(SUN_COMM_NULL);
734# endif
735#endif
736
737 // Right-hand side function wrappers
738 udata.f = [&](amrex::Real rhs_time, N_Vector y_data, N_Vector y_rhs,
739 void * /* user_data */) -> int {
740
741 T state;
742 unpack_vector(y_data, state);
743
744 T S_rhs;
745 unpack_vector(y_rhs, S_rhs);
746
747 BaseT::Rhs(S_rhs, state, rhs_time);
748
749 return 0;
750 };
751
752 udata.fi = [&](amrex::Real rhs_time, N_Vector y_data, N_Vector y_rhs,
753 void * /* user_data */) -> int {
754
755 T state;
756 unpack_vector(y_data, state);
757
758 T S_rhs;
759 unpack_vector(y_rhs, S_rhs);
760
761 BaseT::RhsIm(S_rhs, state, rhs_time);
762
763 return 0;
764 };
765
766 udata.fe = [&](amrex::Real rhs_time, N_Vector y_data, N_Vector y_rhs,
767 void * /* user_data */) -> int {
768
769 T state;
770 unpack_vector(y_data, state);
771
772 T S_rhs;
773 unpack_vector(y_rhs, S_rhs);
774
775 BaseT::RhsEx(S_rhs, state, rhs_time);
776
777 return 0;
778 };
779
780 udata.ff = [&](amrex::Real rhs_time, N_Vector y_data, N_Vector y_rhs,
781 void * /* user_data */) -> int {
782
783 T state;
784 unpack_vector(y_data, state);
785
786 T S_rhs;
787 unpack_vector(y_rhs, S_rhs);
788
789 BaseT::RhsFast(S_rhs, state, rhs_time);
790
791 return 0;
792 };
793
794 udata.post_stage = [&](amrex::Real t, N_Vector y_data,
795 void * /* user_data */) -> int {
796
797 T state;
798 unpack_vector(y_data, state);
799
800 BaseT::post_stage_action(state, t);
801
802 return 0;
803 };
804
805 udata.post_step = [&](amrex::Real t, N_Vector y_data,
806 void * /* user_data */) -> int {
807
808 T state;
809 unpack_vector(y_data, state);
810
811 BaseT::post_step_action(state, t);
812
813 return 0;
814 };
815
816 udata.post_fast_stage = [&](amrex::Real t, N_Vector y_data,
817 void * /* user_data */) -> int {
818
819 T state;
820 unpack_vector(y_data, state);
821
823
824 return 0;
825 };
826
827 udata.post_fast_step = [&](amrex::Real t, N_Vector y_data,
828 void * /* user_data */) -> int {
829
830 T state;
831 unpack_vector(y_data, state);
832
834
835 return 0;
836 };
837
838 N_Vector y_data = copy_data(S_data); // ideally just wrap and ignore const
839
840 if (use_ark) {
841 SetupRK(time, y_data);
842 }
843 else if (use_mri)
844 {
845 SetupMRI(time, y_data);
846 }
847
848 N_VDestroy(y_data);
849 }
850
855 // Print integrator statistics
856 if (amrex::Verbose()) {
857 if (type == "EX-MRI" || type == "IM-MRI" || type == "IMEX-MRI") {
858 amrex::Print() << "Slow Time Integrator Stats\n";
860 AMREX_MRISTEP(PrintAllStats)(arkode_mem, stdout, SUN_OUTPUTFORMAT_TABLE);
861 }
862 amrex::Print() << "Fast Time Integrator Stats\n";
864 AMREX_ARKSTEP(PrintAllStats)(arkode_fast_mem, stdout, SUN_OUTPUTFORMAT_TABLE);
865 }
866 } else {
867 amrex::Print() << "Time Integrator Stats\n";
869 AMREX_ARKSTEP(PrintAllStats)(arkode_mem, stdout, SUN_OUTPUTFORMAT_TABLE);
870 }
871 }
872 }
873
874 // Clean up allocated memory
875 free_memory();
876 }
877
887 amrex::Real advance (T& S_old, T& S_new, amrex::Real time, const amrex::Real dt) override
888 {
889 amrex::Real tout = time + dt;
890 amrex::Real tret;
891
892 N_Vector y_old = wrap_data(S_old);
893 N_Vector y_new = wrap_data(S_new);
894
895 if (use_ark) {
896 AMREX_ARKSTEP(Reset)(arkode_mem, time, y_old); // should probably resize
897 apply_tolerances();
898 AMREX_ARKSTEP(SetFixedStep)(arkode_mem, dt);
899 step_applied = dt;
900 int flag = AMREX_ARKSTEP(Evolve)(arkode_mem, tout, y_new, &tret, ARK_ONE_STEP);
901 AMREX_ALWAYS_ASSERT(flag >= 0);
902 }
903 else if (use_mri) {
904 AMREX_MRISTEP(Reset)(arkode_mem, time, y_old); // should probably resize -- need to resize inner stepper
905 apply_tolerances();
906 AMREX_MRISTEP(SetFixedStep)(arkode_mem, dt);
907 step_applied = dt;
908 apply_fast_step();
909 int flag = AMREX_MRISTEP(Evolve)(arkode_mem, tout, y_new, &tret, ARK_ONE_STEP);
910 AMREX_ALWAYS_ASSERT(flag >= 0);
911 } else {
912 Error("SUNDIALS integrator type not specified.");
913 }
914
915 N_VDestroy(y_old);
916 N_VDestroy(y_new);
917
918 return dt;
919 }
920
927 void evolve (T& S_out, const amrex::Real time_out) override
928 {
929 int flag = 0; // SUNDIALS return status
930 amrex::Real time_ret; // SUNDIALS return time
931
932 N_Vector y_out = wrap_data(S_out);
933
934 if (use_ark) {
935 apply_tolerances();
937 flag = AMREX_ARKSTEP(Evolve)(arkode_mem, time_out, y_out, &time_ret, ARK_NORMAL);
938 AMREX_ALWAYS_ASSERT(flag >= 0);
939 }
940 else if (use_mri) {
941#if defined(SUNDIALS_VERSION_MAJOR) && \
942 ((SUNDIALS_VERSION_MAJOR < 7) || (SUNDIALS_VERSION_MAJOR == 7 && SUNDIALS_VERSION_MINOR < 2))
943 if (BaseT::use_adaptive_time_step && step_applied == 0) {
944 amrex::Abort("SundialsIntegrator: adaptive slow time steps with MRI methods need SUNDIALS 7.2 or later");
945 }
946#endif
947 apply_tolerances();
948 // Do not switch a fixed slow step back to adaptive; the fixed-step MRI table may lack an embedding.
950 apply_step(BaseT::time_step);
951 }
952 apply_fast_step();
953 flag = AMREX_MRISTEP(Evolve)(arkode_mem, time_out, y_out, &time_ret, ARK_NORMAL);
954 AMREX_ALWAYS_ASSERT(flag >= 0);
955 } else {
956 Error("SUNDIALS integrator type not specified.");
957 }
958
959 N_VDestroy(y_out);
960 }
961
965 void time_interpolate (const T& /* S_new */, const T& /* S_old */, amrex::Real /* timestep_fraction */, T& /* data */) override {}
966
970 void map_data (std::function<void(T&)> /* Map */) override {}
971};
972
973}
974
975#undef AMREX_SUNDIALS_ARKODE_API
976#undef AMREX_ARKSTEP
977#undef AMREX_MRISTEP
978
979#endif
#define AMREX_ALWAYS_ASSERT(EX)
Definition AMReX_BLassert.H:50
amrex::ParmParse pp
Input file parser instance for the given namespace.
Definition AMReX_HypreIJIface.cpp:18
#define AMREX_MRISTEP(f)
Definition AMReX_SundialsIntegrator.H:31
#define AMREX_ARKSTEP(f)
Definition AMReX_SundialsIntegrator.H:30
Long numPts() const noexcept
Returns the total number of cells contained in all boxes in the BoxArray.
Definition AMReX_BoxArray.cpp:394
int nGrow(int direction=0) const noexcept
Return the grow factor that defines the region of definition.
Definition AMReX_FabArrayBase.H:83
const DistributionMapping & DistributionMap() const noexcept
Return constant reference to associated DistributionMapping.
Definition AMReX_FabArrayBase.H:135
int nComp() const noexcept
Return number of variables (aka components) associated with each point.
Definition AMReX_FabArrayBase.H:88
const BoxArray & boxArray() const noexcept
Return a constant reference to the BoxArray that defines the valid region associated with this FabArr...
Definition AMReX_FabArrayBase.H:100
Definition AMReX_IntegratorBase.H:167
bool use_adaptive_fast_time_step
Flag to enable/disable adaptive time stepping at the fast time scale in multirate methods (bool)
Definition AMReX_IntegratorBase.H:249
amrex::Real fast_rel_tol
Relative tolerance for adaptive time stepping at the fast time scale (Real)
Definition AMReX_IntegratorBase.H:285
amrex::Real rel_tol
Relative tolerance for adaptive time stepping (Real)
Definition AMReX_IntegratorBase.H:270
std::function< void(T &, amrex::Real)> post_fast_stage_action
The post_stage_action function is called by the integrator on the computed stage just after it is com...
Definition AMReX_IntegratorBase.H:221
amrex::Real fast_abs_tol
Absolute tolerance for adaptive time stepping at the fast time scale (Real)
Definition AMReX_IntegratorBase.H:294
amrex::Real fast_time_step
Current integrator fast time scale time step size with multirate methods (Real)
Definition AMReX_IntegratorBase.H:255
std::function< void(T &rhs, T &state, const amrex::Real time)> RhsEx
RhsEx is the explicit right-hand-side function an ImEx integrator will use.
Definition AMReX_IntegratorBase.H:197
std::function< void(T &, amrex::Real)> post_step_action
The post_step_action function is called by the integrator on the computed state just after it is comp...
Definition AMReX_IntegratorBase.H:215
std::function< void(T &, amrex::Real)> post_fast_step_action
The post_step_action function is called by the integrator on the computed state just after it is comp...
Definition AMReX_IntegratorBase.H:227
std::function< void(T &rhs, T &state, const amrex::Real time)> RhsIm
RhsIm is the implicit right-hand-side function an ImEx integrator will use.
Definition AMReX_IntegratorBase.H:191
std::function< void(T &rhs, T &state, const amrex::Real time)> Rhs
Rhs is the right-hand-side function the integrator will use.
Definition AMReX_IntegratorBase.H:185
bool use_adaptive_time_step
Flag to enable/disable adaptive time stepping in single rate methods or at the slow time scale in mul...
Definition AMReX_IntegratorBase.H:233
std::function< void(T &, amrex::Real)> post_stage_action
The post_stage_action function is called by the integrator on the computed stage just after it is com...
Definition AMReX_IntegratorBase.H:209
amrex::Real time_step
Current integrator time step size (Real)
Definition AMReX_IntegratorBase.H:238
std::function< void(T &rhs, T &state, const amrex::Real time)> RhsFast
RhsFast is the fast timescale right-hand-side function a multirate integrator will use.
Definition AMReX_IntegratorBase.H:203
amrex::Real abs_tol
Absolute tolerance for adaptive time stepping (Real)
Definition AMReX_IntegratorBase.H:278
A collection (stored as an array) of FArrayBox objects.
Definition AMReX_MultiFab.H:40
static void Copy(MultiFab &dst, const MultiFab &src, int srccomp, int dstcomp, int numcomp, int nghost)
Copy from src to dst including nghost ghost cells. The two MultiFabs MUST have the same underlying Bo...
Definition AMReX_MultiFab.cpp:193
Parse Parameters From Command Line and Input Files.
Definition AMReX_ParmParse.H:354
int query(std::string_view name, bool &ref, int ival=FIRST) const
Same as querykth() but searches for the last occurrence of name.
Definition AMReX_ParmParse.cpp:2010
This class provides the user with a few print options.
Definition AMReX_Print.H:35
IntegratorBase implementation powered by SUNDIALS ARKStep/MRIStep.
Definition AMReX_SundialsIntegrator.H:109
void time_interpolate(const T &, const T &, amrex::Real, T &) override
Interpolate between SUNDIALS stages (not yet implemented for this integrator).
Definition AMReX_SundialsIntegrator.H:965
SundialsIntegrator()
Construct an uninitialized integrator; call initialize() before use.
Definition AMReX_SundialsIntegrator.H:691
void initialize(const T &S_data, const amrex::Real time=0.0)
Configure (or reconfigure) the SUNDIALS integrator for the provided state.
Definition AMReX_SundialsIntegrator.H:710
amrex::Real advance(T &S_old, T &S_new, amrex::Real time, const amrex::Real dt) override
Take a single time step of size dt starting from S_old.
Definition AMReX_SundialsIntegrator.H:887
void evolve(T &S_out, const amrex::Real time_out) override
Evolve the solution in S_out up to time_out using ARKStep/MRIStep.
Definition AMReX_SundialsIntegrator.H:927
virtual ~SundialsIntegrator()
Destroy the integrator, printing summary statistics when verbose.
Definition AMReX_SundialsIntegrator.H:854
SundialsIntegrator(const T &S_data, const amrex::Real time=0.0)
Construct and immediately configure the integrator with S_data at time time.
Definition AMReX_SundialsIntegrator.H:699
void map_data(std::function< void(T &)>) override
Apply a user-supplied mapping to every MultiFab in the integrator (unused placeholder).
Definition AMReX_SundialsIntegrator.H:970
This class is a thin wrapper around std::vector. Unlike vector, Vector::operator[] provides bound che...
Definition AMReX_Vector.H:29
Long size() const noexcept
Definition AMReX_Vector.H:54
amrex_real Real
Floating Point Type for Fields.
Definition AMReX_REAL.H:80
amrex_long Long
Definition AMReX_INT.H:30
bool IOProcessor() noexcept
Is this CPU the I/O Processor? To get the rank number, call IOProcessorNumber()
Definition AMReX_ParallelDescriptor.H:289
MPI_Comm CommunicatorSub() noexcept
sub-communicator for current frame
Definition AMReX_ParallelContext.H:70
static int fi(amrex::Real t, N_Vector y_data, N_Vector y_rhs, void *user_data)
Definition AMReX_SundialsIntegrator.H:66
static int fe(amrex::Real t, N_Vector y_data, N_Vector y_rhs, void *user_data)
Definition AMReX_SundialsIntegrator.H:71
static int post_fast_step(amrex::Real t, N_Vector y_data, void *user_data)
Definition AMReX_SundialsIntegrator.H:96
static int f(amrex::Real t, N_Vector y_data, N_Vector y_rhs, void *user_data)
Definition AMReX_SundialsIntegrator.H:61
static int post_step(amrex::Real t, N_Vector y_data, void *user_data)
Definition AMReX_SundialsIntegrator.H:86
static int ff(amrex::Real t, N_Vector y_data, N_Vector y_rhs, void *user_data)
Definition AMReX_SundialsIntegrator.H:76
static int post_stage(amrex::Real t, N_Vector y_data, void *user_data)
Definition AMReX_SundialsIntegrator.H:81
static int post_fast_stage(amrex::Real t, N_Vector y_data, void *user_data)
Definition AMReX_SundialsIntegrator.H:91
int MPI_Comm
Definition AMReX_ccse-mpi.H:51
N_Vector N_VMake_MultiFab(sunindextype length, amrex::MultiFab *v_mf, ::sundials::Context *sunctx)
Wrap an existing MultiFab mf as an N_Vector without copying.
Definition AMReX_NVector_MultiFab.cpp:105
amrex::MultiFab *& getMFptr(N_Vector v)
Access the MultiFab pointer stored inside v (non-const).
Definition AMReX_NVector_MultiFab.cpp:233
N_Vector N_VNew_MultiFab(sunindextype length, const amrex::BoxArray &ba, const amrex::DistributionMapping &dm, sunindextype nComp, sunindextype nGhost, ::sundials::Context *sunctx)
Allocate a MultiFab-backed N_Vector of length vec_length.
Definition AMReX_NVector_MultiFab.cpp:80
Definition AMReX_Amr.cpp:50
@ make_alias
Definition AMReX_MakeType.H:7
BoxArray const & boxArray(FabArrayBase const &fa)
Convenience wrapper that forwards to fa.boxArray().
Definition AMReX_FabArrayBase.cpp:2949
DistributionMapping const & DistributionMap(FabArrayBase const &fa)
Convenience wrapper that forwards to fa.DistributionMap().
Definition AMReX_FabArrayBase.cpp:2954
int nComp(FabArrayBase const &fa)
Convenience wrapper that forwards to fa.nComp().
Definition AMReX_FabArrayBase.cpp:2939
void Error(const std::string &msg)
Print a message to stderr and abort the program.
Definition AMReX.cpp:238
int Verbose() noexcept
Return the verbosity level configured via ParmParse or SetVerbose().
Definition AMReX.cpp:184
void Abort(const std::string &msg)
Print a fatal-error message to stderr and abort execution.
Definition AMReX.cpp:244
const int[]
Definition AMReX_BLProfiler.cpp:1665
User-supplied callbacks consumed by the AMReX/SUNDIALS bridge.
Definition AMReX_SundialsIntegrator.H:49
std::function< int(amrex::Real, N_Vector, N_Vector, void *)> fi
Implicit RHS for ImEx schemes.
Definition AMReX_SundialsIntegrator.H:51
std::function< int(amrex::Real, N_Vector, void *)> post_fast_stage
Hook for MRI fast stages.
Definition AMReX_SundialsIntegrator.H:56
std::function< int(amrex::Real, N_Vector, void *)> post_step
Hook invoked after each time step.
Definition AMReX_SundialsIntegrator.H:55
std::function< int(amrex::Real, N_Vector, N_Vector, void *)> f
ERK/DIRK RHS or MRI slow RHS.
Definition AMReX_SundialsIntegrator.H:50
std::function< int(amrex::Real, N_Vector, void *)> post_stage
Hook invoked after each stage.
Definition AMReX_SundialsIntegrator.H:54
std::function< int(amrex::Real, N_Vector, N_Vector, void *)> ff
MRI fast-scale RHS.
Definition AMReX_SundialsIntegrator.H:53
std::function< int(amrex::Real, N_Vector, void *)> post_fast_step
Hook for MRI fast steps.
Definition AMReX_SundialsIntegrator.H:57
std::function< int(amrex::Real, N_Vector, N_Vector, void *)> fe
Explicit RHS for ImEx schemes.
Definition AMReX_SundialsIntegrator.H:52