From 14ecd14b10aa8ad724b77429d26f3e1c074a5606 Mon Sep 17 00:00:00 2001 From: Steven Roberts Date: Mon, 29 Jul 2024 20:02:28 -0700 Subject: [PATCH 01/39] Remove special case of negative base in SUNRpowerR --- src/sundials/sundials_math.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/sundials/sundials_math.c b/src/sundials/sundials_math.c index b60e9c2540..7b05330d1c 100644 --- a/src/sundials/sundials_math.c +++ b/src/sundials/sundials_math.c @@ -22,6 +22,8 @@ #include #include +#include + sunrealtype SUNRpowerI(sunrealtype base, int exponent) { int i, expt; @@ -36,7 +38,9 @@ sunrealtype SUNRpowerI(sunrealtype base, int exponent) sunrealtype SUNRpowerR(sunrealtype base, sunrealtype exponent) { - if (base <= SUN_RCONST(0.0)) { return (SUN_RCONST(0.0)); } + // TODO(SBR): cleanup this and header + // if (base <= SUN_RCONST(0.0)) { return (SUN_RCONST(0.0)); } + SUNAssert(base >= 0.0, "Base should be positive"); #if defined(SUNDIALS_DOUBLE_PRECISION) return (pow(base, exponent)); From dcb14bc1340af8c204f1571c55b9625786c4d574 Mon Sep 17 00:00:00 2001 From: Steven Roberts Date: Mon, 29 Jul 2024 20:49:36 -0700 Subject: [PATCH 02/39] Fix assert condition --- src/sundials/sundials_math.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sundials/sundials_math.c b/src/sundials/sundials_math.c index 7b05330d1c..8e6b303290 100644 --- a/src/sundials/sundials_math.c +++ b/src/sundials/sundials_math.c @@ -40,7 +40,7 @@ sunrealtype SUNRpowerR(sunrealtype base, sunrealtype exponent) { // TODO(SBR): cleanup this and header // if (base <= SUN_RCONST(0.0)) { return (SUN_RCONST(0.0)); } - SUNAssert(base >= 0.0, "Base should be positive"); + SUNAssert(base > 0.0, "Base should be positive"); #if defined(SUNDIALS_DOUBLE_PRECISION) return (pow(base, exponent)); From 19f2dc957e8341c45265a7806bddc88fe2d04e91 Mon Sep 17 00:00:00 2001 From: Steven Roberts Date: Mon, 29 Jul 2024 20:52:02 -0700 Subject: [PATCH 03/39] Remove magic constant --- src/arkode/arkode_adapt.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/arkode/arkode_adapt.c b/src/arkode/arkode_adapt.c index 7fef0ec2ae..6bd9aa18a1 100644 --- a/src/arkode/arkode_adapt.c +++ b/src/arkode/arkode_adapt.c @@ -131,7 +131,7 @@ int arkAdapt(ARKodeMem ark_mem, ARKodeHAdaptMem hadapt_mem, N_Vector ycur, "Error in explicit stability function."); return (ARK_ILL_INPUT); } - if (h_cfl <= ZERO) { h_cfl = SUN_RCONST(1.0e30) * SUNRabs(hcur); } + if (h_cfl <= ZERO) { h_cfl = INFINITY; } #if SUNDIALS_LOGGING_LEVEL >= SUNDIALS_LOGGING_INFO SUNLogger_QueueMsg(ARK_LOGGER, SUN_LOGLEVEL_INFO, "ARKODE::arkAdapt", From 53f3dde8403b4e4f44fac29143a707472bc04cae Mon Sep 17 00:00:00 2001 From: Steven Roberts Date: Mon, 29 Jul 2024 21:33:31 -0700 Subject: [PATCH 04/39] Remove TINY parameter --- src/arkode/arkode_adapt.c | 2 +- .../soderlind/sunadaptcontroller_soderlind.c | 11 +++++++---- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/src/arkode/arkode_adapt.c b/src/arkode/arkode_adapt.c index 6bd9aa18a1..a4758436eb 100644 --- a/src/arkode/arkode_adapt.c +++ b/src/arkode/arkode_adapt.c @@ -156,7 +156,7 @@ int arkAdapt(ARKodeMem ark_mem, ARKodeHAdaptMem hadapt_mem, N_Vector ycur, #endif /* increment the relevant step counter, set desired step */ - if (SUNRabs(h_acc) < SUNRabs(h_cfl)) { hadapt_mem->nst_acc++; } + if (SUNRabs(h_acc) <= SUNRabs(h_cfl)) { hadapt_mem->nst_acc++; } else { hadapt_mem->nst_exp++; } h_acc = int_dir * SUNMIN(SUNRabs(h_acc), SUNRabs(h_cfl)); diff --git a/src/sunadaptcontroller/soderlind/sunadaptcontroller_soderlind.c b/src/sunadaptcontroller/soderlind/sunadaptcontroller_soderlind.c index bca88252cb..b2924f12f0 100644 --- a/src/sunadaptcontroller/soderlind/sunadaptcontroller_soderlind.c +++ b/src/sunadaptcontroller/soderlind/sunadaptcontroller_soderlind.c @@ -62,7 +62,6 @@ #define DEFAULT_IMPGUS_K1 SUN_RCONST(0.98) /* Implicit Gustafsson parameters */ #define DEFAULT_IMPGUS_K2 SUN_RCONST(0.95) #define DEFAULT_BIAS SUN_RCONST(1.5) -#define TINY SUN_RCONST(1.0e-10) /* ----------------------------------------------------------------- * exported functions @@ -322,9 +321,9 @@ SUNErrCode SUNAdaptController_EstimateStep_Soderlind(SUNAdaptController C, const sunrealtype k3 = -SODERLIND_K3(C) / ord; const sunrealtype k4 = SODERLIND_K4(C); const sunrealtype k5 = SODERLIND_K5(C); - const sunrealtype e1 = SUNMAX(SODERLIND_BIAS(C) * dsm, TINY); - const sunrealtype e2 = SUNMAX(SODERLIND_EP(C), TINY); - const sunrealtype e3 = SUNMAX(SODERLIND_EPP(C), TINY); + const sunrealtype e1 = SODERLIND_BIAS(C) * dsm; + const sunrealtype e2 = SODERLIND_EP(C); + const sunrealtype e3 = SODERLIND_EPP(C); const sunrealtype hrat = h / SODERLIND_HP(C); const sunrealtype hrat2 = SODERLIND_HP(C) / SODERLIND_HPP(C); @@ -340,6 +339,10 @@ SUNErrCode SUNAdaptController_EstimateStep_Soderlind(SUNAdaptController C, SUNRpowerR(hrat, k4) * SUNRpowerR(hrat2, k5); } + if (isnan(*hnew)) { + *hnew = INFINITY; + } + /* return with success */ return SUN_SUCCESS; } From e838c4ee2d6d4e76de79ddb8f7508620de0a3a06 Mon Sep 17 00:00:00 2001 From: Steven Roberts Date: Mon, 29 Jul 2024 21:37:41 -0700 Subject: [PATCH 05/39] Remove TINY from imexgus controller --- .../imexgus/sunadaptcontroller_imexgus.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/sunadaptcontroller/imexgus/sunadaptcontroller_imexgus.c b/src/sunadaptcontroller/imexgus/sunadaptcontroller_imexgus.c index e4bb23e6dd..a4d28779e8 100644 --- a/src/sunadaptcontroller/imexgus/sunadaptcontroller_imexgus.c +++ b/src/sunadaptcontroller/imexgus/sunadaptcontroller_imexgus.c @@ -48,7 +48,6 @@ #define DEFAULT_K1I SUN_RCONST(0.95) #define DEFAULT_K2I SUN_RCONST(0.95) #define DEFAULT_BIAS SUN_RCONST(1.5) -#define TINY SUN_RCONST(1.0e-10) /* ----------------------------------------------------------------- * exported functions @@ -135,15 +134,15 @@ SUNErrCode SUNAdaptController_EstimateStep_ImExGus(SUNAdaptController C, /* set usable time-step adaptivity parameters -- first step */ const sunrealtype k = -SUN_RCONST(1.0) / ord; - const sunrealtype e = SUNMAX(SACIMEXGUS_BIAS(C) * dsm, TINY); + const sunrealtype e = SACIMEXGUS_BIAS(C) * dsm; /* set usable time-step adaptivity parameters -- subsequent steps */ const sunrealtype k1e = -SACIMEXGUS_K1E(C) / ord; const sunrealtype k2e = -SACIMEXGUS_K2E(C) / ord; const sunrealtype k1i = -SACIMEXGUS_K1I(C) / ord; const sunrealtype k2i = -SACIMEXGUS_K2I(C) / ord; - const sunrealtype e1 = SUNMAX(SACIMEXGUS_BIAS(C) * dsm, TINY); - const sunrealtype e2 = e1 / SUNMAX(SACIMEXGUS_EP(C), TINY); + const sunrealtype e1 = SACIMEXGUS_BIAS(C) * dsm; + const sunrealtype e2 = e1 / SACIMEXGUS_EP(C); const sunrealtype hrat = h / SACIMEXGUS_HP(C); /* compute estimated time step size, modifying the first step formula */ @@ -154,6 +153,10 @@ SUNErrCode SUNAdaptController_EstimateStep_ImExGus(SUNAdaptController C, SUNRpowerR(e1, k1e) * SUNRpowerR(e2, k2e)); } + if (isnan(*hnew)) { + *hnew = INFINITY; + } + /* return with success */ return SUN_SUCCESS; } From 9cde50af083b8d9de7d6c73c88dc6c5074e08e85 Mon Sep 17 00:00:00 2001 From: Steven Roberts Date: Mon, 29 Jul 2024 21:44:20 -0700 Subject: [PATCH 06/39] Switch to assert --- src/sundials/sundials_math.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/sundials/sundials_math.c b/src/sundials/sundials_math.c index 8e6b303290..8c5f5fc942 100644 --- a/src/sundials/sundials_math.c +++ b/src/sundials/sundials_math.c @@ -22,7 +22,7 @@ #include #include -#include +#include sunrealtype SUNRpowerI(sunrealtype base, int exponent) { @@ -40,7 +40,7 @@ sunrealtype SUNRpowerR(sunrealtype base, sunrealtype exponent) { // TODO(SBR): cleanup this and header // if (base <= SUN_RCONST(0.0)) { return (SUN_RCONST(0.0)); } - SUNAssert(base > 0.0, "Base should be positive"); + assert(base > 0.0); #if defined(SUNDIALS_DOUBLE_PRECISION) return (pow(base, exponent)); From 2c2444c9f4012790cf0abe29ed70812eb22728fa Mon Sep 17 00:00:00 2001 From: Steven Roberts Date: Mon, 29 Jul 2024 22:10:04 -0700 Subject: [PATCH 07/39] Fix sign of controller in nan case --- .../imexgus/sunadaptcontroller_imexgus.c | 7 +++++-- .../soderlind/sunadaptcontroller_soderlind.c | 7 +++++-- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/src/sunadaptcontroller/imexgus/sunadaptcontroller_imexgus.c b/src/sunadaptcontroller/imexgus/sunadaptcontroller_imexgus.c index a4d28779e8..8f881b49dc 100644 --- a/src/sunadaptcontroller/imexgus/sunadaptcontroller_imexgus.c +++ b/src/sunadaptcontroller/imexgus/sunadaptcontroller_imexgus.c @@ -153,8 +153,11 @@ SUNErrCode SUNAdaptController_EstimateStep_ImExGus(SUNAdaptController C, SUNRpowerR(e1, k1e) * SUNRpowerR(e2, k2e)); } - if (isnan(*hnew)) { - *hnew = INFINITY; + if (isnan(*hnew)) + { + /* hnew can be NAN if multiple e's are 0. In that case, make hnew inf with + * the same sign as h */ + *hnew = h / SUN_RCONST(0.0); } /* return with success */ diff --git a/src/sunadaptcontroller/soderlind/sunadaptcontroller_soderlind.c b/src/sunadaptcontroller/soderlind/sunadaptcontroller_soderlind.c index b2924f12f0..0ffc9313b9 100644 --- a/src/sunadaptcontroller/soderlind/sunadaptcontroller_soderlind.c +++ b/src/sunadaptcontroller/soderlind/sunadaptcontroller_soderlind.c @@ -339,8 +339,11 @@ SUNErrCode SUNAdaptController_EstimateStep_Soderlind(SUNAdaptController C, SUNRpowerR(hrat, k4) * SUNRpowerR(hrat2, k5); } - if (isnan(*hnew)) { - *hnew = INFINITY; + if (isnan(*hnew)) + { + /* hnew can be NAN if multiple e's are 0. In that case, make hnew inf with + * the same sign as h */ + *hnew = h / SUN_RCONST(0.0); } /* return with success */ From 9cb7bba27aebd116eafefa2296d5aab92d356f85 Mon Sep 17 00:00:00 2001 From: Steven Roberts Date: Tue, 30 Jul 2024 21:49:21 -0700 Subject: [PATCH 08/39] Start adaptivity unit test --- .../unit_tests/arkode/C_serial/CMakeLists.txt | 1 + .../arkode/C_serial/ark_test_adapt.c | 122 ++++++++++++++++++ 2 files changed, 123 insertions(+) create mode 100644 test/unit_tests/arkode/C_serial/ark_test_adapt.c diff --git a/test/unit_tests/arkode/C_serial/CMakeLists.txt b/test/unit_tests/arkode/C_serial/CMakeLists.txt index 6794a213b4..3670b76da4 100644 --- a/test/unit_tests/arkode/C_serial/CMakeLists.txt +++ b/test/unit_tests/arkode/C_serial/CMakeLists.txt @@ -16,6 +16,7 @@ # List of test tuples of the form "name\;args" set(ARKODE_unit_tests + "ark_test_adapt\;" "ark_test_arkstepsetforcing\;1 0" "ark_test_arkstepsetforcing\;1 1" "ark_test_arkstepsetforcing\;1 2" diff --git a/test/unit_tests/arkode/C_serial/ark_test_adapt.c b/test/unit_tests/arkode/C_serial/ark_test_adapt.c new file mode 100644 index 0000000000..4e98e2fe4b --- /dev/null +++ b/test/unit_tests/arkode/C_serial/ark_test_adapt.c @@ -0,0 +1,122 @@ +/* ----------------------------------------------------------------------------- + * Programmer(s): Steven B. Roberts @ LLNL + * ----------------------------------------------------------------------------- + * SUNDIALS Copyright Start + * Copyright (c) 2002-2024, Lawrence Livermore National Security + * and Southern Methodist University. + * All rights reserved. + * + * See the top-level LICENSE and NOTICE files for details. + * + * SPDX-License-Identifier: BSD-3-Clause + * SUNDIALS Copyright End + * ----------------------------------------------------------------------------- + * Unit test for GetUserData functions + * ---------------------------------------------------------------------------*/ + +#include +#include + +#include "arkode/arkode_erkstep.h" +#include "nvector/nvector_serial.h" + +static void err_fn(int line, const char* func, const char* file, const char* msg, + SUNErrCode err_code, void* err_user_data, SUNContext sunctx) +{ + fprintf(stderr, "Error at line %i of %s in %s: %s\n", line, func, file, msg); + exit(err_code); +} + +static int f(sunrealtype t, N_Vector y, N_Vector ydot, void* user_data) +{ + N_VConst(SUN_RCONST(0.0), ydot); + return 0; +} + +static int check_step(void* arkode_mem, N_Vector y, sunrealtype h_expected) +{ + static int step = 0; + step++; + + sunrealtype tret; + ARKodeEvolve(arkode_mem, SUN_RCONST(1.0), y, &tret, ARK_ONE_STEP); + + long int local_err_fails; + ARKodeGetNumErrTestFails(arkode_mem, &local_err_fails); + if (local_err_fails != 0) + { + fprintf(stderr, "Expected 0 local error failures at step %i but is %li\n", + step, local_err_fails); + } + + const N_Vector err = N_VClone(y); + ARKodeGetEstLocalErrors(arkode_mem, err); + sunrealtype err_norm = N_VMaxNorm(err); + N_VDestroy(err); + + if (err_norm != 0) + { + fprintf(stderr, "Expected local error at step %i to be 0 but is %g\n", step, + err_norm); + return 1; + } + + sunrealtype h_actual; + ARKodeGetCurrentStep(arkode_mem, &h_actual); + if (h_expected != h_actual) + { + fprintf(stderr, "Expected h at step %i to be %g but is %g\n", step, + h_expected, h_actual); + return 1; + } + + return 0; +} + +int main() +{ + SUNContext sunctx; + int retval = SUNContext_Create(SUN_COMM_NULL, &sunctx); + if (retval != 0) + { + fprintf(stderr, "SUNContext_Create returned %i\n", retval); + return 1; + } + + retval = SUNContext_PushErrHandler(sunctx, err_fn, NULL); + if (retval != 0) + { + fprintf(stderr, "SUNContext_PushErrHandler returned %i\n", retval); + return 1; + } + + const N_Vector y = N_VNew_Serial(1, sunctx); + N_VConst(SUN_RCONST(1.0), y); + + void* arkode_mem = ERKStepCreate(f, SUN_RCONST(0.0), y, sunctx); + + const sunrealtype h0 = SUN_RCONST(1.0e-4); + const sunrealtype first_growth = SUN_RCONST(1234.0); + const sunrealtype growth = SUN_RCONST(3.0); + + ARKodeSetInitStep(arkode_mem, h0); + ARKodeSetMaxFirstGrowth(arkode_mem, first_growth); + ARKodeSetMaxGrowth(arkode_mem, growth); + + sunrealtype h_expect = first_growth * h0; + + for (int i = 0; i < 4; i++) + { + retval = check_step(arkode_mem, y, h_expect); + if (retval != 0) { return retval; } + h_expect *= growth; + } + + ARKodeFree(&arkode_mem); + N_VDestroy(y); + SUNContext_Free(&sunctx); + + printf("SUCCESS\n"); + + return 0; +} From 743913a76e0eec612bced620f12f44fcdf353b7b Mon Sep 17 00:00:00 2001 From: Steven Roberts Date: Wed, 31 Jul 2024 18:13:37 -0700 Subject: [PATCH 09/39] Add const and comments to test --- .../arkode/C_serial/ark_test_adapt.c | 27 +++++++++++-------- 1 file changed, 16 insertions(+), 11 deletions(-) diff --git a/test/unit_tests/arkode/C_serial/ark_test_adapt.c b/test/unit_tests/arkode/C_serial/ark_test_adapt.c index 4e98e2fe4b..01fa551559 100644 --- a/test/unit_tests/arkode/C_serial/ark_test_adapt.c +++ b/test/unit_tests/arkode/C_serial/ark_test_adapt.c @@ -20,25 +20,28 @@ #include "arkode/arkode_erkstep.h" #include "nvector/nvector_serial.h" -static void err_fn(int line, const char* func, const char* file, const char* msg, - SUNErrCode err_code, void* err_user_data, SUNContext sunctx) +static void err_fn(const int line, const char* const func, const char* const file, + const char* const msg, const SUNErrCode err_code, + void* const err_user_data, const SUNContext sunctx) { fprintf(stderr, "Error at line %i of %s in %s: %s\n", line, func, file, msg); exit(err_code); } -static int f(sunrealtype t, N_Vector y, N_Vector ydot, void* user_data) +// RHS for the simple ODE y' = 0 +static int f(const sunrealtype t, const N_Vector y, const N_Vector ydot, + void* const user_data) { N_VConst(SUN_RCONST(0.0), ydot); return 0; } -static int check_step(void* arkode_mem, N_Vector y, sunrealtype h_expected) +static int check_step(void* const arkode_mem, const N_Vector y, + const sunrealtype h_expected, const int step) { - static int step = 0; - step++; - sunrealtype tret; + /* The ERK method should be able to take the maximum possible timestep for the + simple ODE y' = 0 without any rejected steps or local error */ ARKodeEvolve(arkode_mem, SUN_RCONST(1.0), y, &tret, ARK_ONE_STEP); long int local_err_fails; @@ -51,7 +54,7 @@ static int check_step(void* arkode_mem, N_Vector y, sunrealtype h_expected) const N_Vector err = N_VClone(y); ARKodeGetEstLocalErrors(arkode_mem, err); - sunrealtype err_norm = N_VMaxNorm(err); + const sunrealtype err_norm = N_VMaxNorm(err); N_VDestroy(err); if (err_norm != 0) @@ -104,10 +107,12 @@ int main() ARKodeSetMaxGrowth(arkode_mem, growth); sunrealtype h_expect = first_growth * h0; - - for (int i = 0; i < 4; i++) + /* Take several steps to see the special behavior at step one then to allow + the adaptivity controller history fill up */ + const int num_steps = 5; + for (int step = 1; step <= num_steps; step++) { - retval = check_step(arkode_mem, y, h_expect); + retval = check_step(arkode_mem, y, h_expect, step); if (retval != 0) { return retval; } h_expect *= growth; } From b75e78e9af1c37b0e4fa1b83ae7daeac3f5ff71f Mon Sep 17 00:00:00 2001 From: Steven Roberts Date: Wed, 31 Jul 2024 19:26:29 -0700 Subject: [PATCH 10/39] Simplify Soderlind controller and handle inf/nan better --- .../soderlind/sunadaptcontroller_soderlind.c | 41 ++++++++----------- 1 file changed, 17 insertions(+), 24 deletions(-) diff --git a/src/sunadaptcontroller/soderlind/sunadaptcontroller_soderlind.c b/src/sunadaptcontroller/soderlind/sunadaptcontroller_soderlind.c index 0ffc9313b9..fef0d82b6e 100644 --- a/src/sunadaptcontroller/soderlind/sunadaptcontroller_soderlind.c +++ b/src/sunadaptcontroller/soderlind/sunadaptcontroller_soderlind.c @@ -316,33 +316,26 @@ SUNErrCode SUNAdaptController_EstimateStep_Soderlind(SUNAdaptController C, const int ord = p + 1; /* set usable time-step adaptivity parameters */ - const sunrealtype k1 = -SODERLIND_K1(C) / ord; - const sunrealtype k2 = -SODERLIND_K2(C) / ord; - const sunrealtype k3 = -SODERLIND_K3(C) / ord; - const sunrealtype k4 = SODERLIND_K4(C); - const sunrealtype k5 = SODERLIND_K5(C); - const sunrealtype e1 = SODERLIND_BIAS(C) * dsm; - const sunrealtype e2 = SODERLIND_EP(C); - const sunrealtype e3 = SODERLIND_EPP(C); - const sunrealtype hrat = h / SODERLIND_HP(C); - const sunrealtype hrat2 = SODERLIND_HP(C) / SODERLIND_HPP(C); - - /* compute estimated optimal time step size */ - if (SODERLIND_FIRSTSTEPS(C) < 1) { *hnew = h * SUNRpowerR(e1, k1); } - else if (SODERLIND_FIRSTSTEPS(C) < 2) - { - *hnew = h * SUNRpowerR(e1, k1) * SUNRpowerR(e2, k2) * SUNRpowerR(hrat, k4); - } - else - { - *hnew = h * SUNRpowerR(e1, k1) * SUNRpowerR(e2, k2) * SUNRpowerR(e3, k3) * - SUNRpowerR(hrat, k4) * SUNRpowerR(hrat2, k5); + const sunrealtype ke[] = {-SODERLIND_K1(C) / ord, -SODERLIND_K2(C) / ord, -SODERLIND_K3(C) / ord}; + const sunrealtype kh[] = {SODERLIND_K4(C), SODERLIND_K5(C)}; + // TODO: Should e2 and e3 be set to e1 when we don't have enough history yet? + const sunrealtype e[] = {SODERLIND_BIAS(C) * dsm, SODERLIND_EP(C), SODERLIND_EPP(C)}; + const sunrealtype hrat[] = {h / SODERLIND_HP(C), SODERLIND_HP(C) / SODERLIND_HPP(C)}; + + // This assumes ke[0] is nonzero. Otherwise we could have pow(0, 0) which is undefined behavior in C + *hnew = h * SUNRpowerR(e[0], ke[0]); + for (int i = 0; i < SUNMIN(2, SODERLIND_FIRSTSTEPS(C)); i++) { + *hnew *= SUNRpowerR(hrat[i], kh[i]); + if (ke[i + 1] != 0) { + // This check avoids pow(0, 0) + *hnew *= SUNRpowerR(e[i + 1], ke[i + 1]); + } } - if (isnan(*hnew)) + if (!isfinite(*hnew)) { - /* hnew can be NAN if multiple e's are 0. In that case, make hnew inf with - * the same sign as h */ + /* hnew can be INFINITY or NAN if multiple e's are 0 or there are overflows. + * In that case, make hnew INFINITY with the same sign as h */ *hnew = h / SUN_RCONST(0.0); } From 2caec18128a0e2f92187b2de2b91061464d8fe0d Mon Sep 17 00:00:00 2001 From: Steven Roberts Date: Wed, 31 Jul 2024 20:11:37 -0700 Subject: [PATCH 11/39] Clean up controllers --- .../imexgus/sunadaptcontroller_imexgus.c | 35 ++++++++++--------- .../soderlind/sunadaptcontroller_soderlind.c | 7 +--- 2 files changed, 19 insertions(+), 23 deletions(-) diff --git a/src/sunadaptcontroller/imexgus/sunadaptcontroller_imexgus.c b/src/sunadaptcontroller/imexgus/sunadaptcontroller_imexgus.c index 8f881b49dc..cfb73cb5a0 100644 --- a/src/sunadaptcontroller/imexgus/sunadaptcontroller_imexgus.c +++ b/src/sunadaptcontroller/imexgus/sunadaptcontroller_imexgus.c @@ -132,31 +132,32 @@ SUNErrCode SUNAdaptController_EstimateStep_ImExGus(SUNAdaptController C, /* order parameter to use */ const int ord = p + 1; - /* set usable time-step adaptivity parameters -- first step */ - const sunrealtype k = -SUN_RCONST(1.0) / ord; - const sunrealtype e = SACIMEXGUS_BIAS(C) * dsm; - - /* set usable time-step adaptivity parameters -- subsequent steps */ - const sunrealtype k1e = -SACIMEXGUS_K1E(C) / ord; - const sunrealtype k2e = -SACIMEXGUS_K2E(C) / ord; - const sunrealtype k1i = -SACIMEXGUS_K1I(C) / ord; - const sunrealtype k2i = -SACIMEXGUS_K2I(C) / ord; - const sunrealtype e1 = SACIMEXGUS_BIAS(C) * dsm; - const sunrealtype e2 = e1 / SACIMEXGUS_EP(C); - const sunrealtype hrat = h / SACIMEXGUS_HP(C); - /* compute estimated time step size, modifying the first step formula */ - if (SACIMEXGUS_FIRSTSTEP(C)) { *hnew = h * SUNRpowerR(e, k); } + if (SACIMEXGUS_FIRSTSTEP(C)) { + // TODO: could this case be handled by setting e1 = e2? + /* set usable time-step adaptivity parameters -- first step */ + const sunrealtype k = -SUN_RCONST(1.0) / ord; + const sunrealtype e = SACIMEXGUS_BIAS(C) * dsm; + *hnew = h * SUNRpowerR(e, k); + } else { + /* set usable time-step adaptivity parameters -- subsequent steps */ + const sunrealtype k1e = -SACIMEXGUS_K1E(C) / ord; + const sunrealtype k2e = -SACIMEXGUS_K2E(C) / ord; + const sunrealtype k1i = -SACIMEXGUS_K1I(C) / ord; + const sunrealtype k2i = -SACIMEXGUS_K2I(C) / ord; + const sunrealtype e1 = SACIMEXGUS_BIAS(C) * dsm; + const sunrealtype e2 = e1 / SACIMEXGUS_EP(C); + const sunrealtype hrat = h / SACIMEXGUS_HP(C); *hnew = h * SUNMIN(hrat * SUNRpowerR(e1, k1i) * SUNRpowerR(e2, k2i), SUNRpowerR(e1, k1e) * SUNRpowerR(e2, k2e)); } - if (isnan(*hnew)) + if (!isfinite(*hnew)) { - /* hnew can be NAN if multiple e's are 0. In that case, make hnew inf with - * the same sign as h */ + /* hnew can be INFINITY or NAN if multiple e's are 0 or there are overflows. + * In that case, make hnew INFINITY with the same sign as h */ *hnew = h / SUN_RCONST(0.0); } diff --git a/src/sunadaptcontroller/soderlind/sunadaptcontroller_soderlind.c b/src/sunadaptcontroller/soderlind/sunadaptcontroller_soderlind.c index fef0d82b6e..b4286ff011 100644 --- a/src/sunadaptcontroller/soderlind/sunadaptcontroller_soderlind.c +++ b/src/sunadaptcontroller/soderlind/sunadaptcontroller_soderlind.c @@ -322,14 +322,9 @@ SUNErrCode SUNAdaptController_EstimateStep_Soderlind(SUNAdaptController C, const sunrealtype e[] = {SODERLIND_BIAS(C) * dsm, SODERLIND_EP(C), SODERLIND_EPP(C)}; const sunrealtype hrat[] = {h / SODERLIND_HP(C), SODERLIND_HP(C) / SODERLIND_HPP(C)}; - // This assumes ke[0] is nonzero. Otherwise we could have pow(0, 0) which is undefined behavior in C *hnew = h * SUNRpowerR(e[0], ke[0]); for (int i = 0; i < SUNMIN(2, SODERLIND_FIRSTSTEPS(C)); i++) { - *hnew *= SUNRpowerR(hrat[i], kh[i]); - if (ke[i + 1] != 0) { - // This check avoids pow(0, 0) - *hnew *= SUNRpowerR(e[i + 1], ke[i + 1]); - } + *hnew *= SUNRpowerR(hrat[i], kh[i]) * SUNRpowerR(e[i + 1], ke[i + 1]); } if (!isfinite(*hnew)) From 3fbda5b1be8f202e64bc5d98ca439030e72b14c3 Mon Sep 17 00:00:00 2001 From: Steven Roberts Date: Wed, 31 Jul 2024 20:16:36 -0700 Subject: [PATCH 12/39] Apply formatter --- .../imexgus/sunadaptcontroller_imexgus.c | 5 +++-- .../soderlind/sunadaptcontroller_soderlind.c | 12 ++++++++---- 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/src/sunadaptcontroller/imexgus/sunadaptcontroller_imexgus.c b/src/sunadaptcontroller/imexgus/sunadaptcontroller_imexgus.c index cfb73cb5a0..fbbea251dc 100644 --- a/src/sunadaptcontroller/imexgus/sunadaptcontroller_imexgus.c +++ b/src/sunadaptcontroller/imexgus/sunadaptcontroller_imexgus.c @@ -133,12 +133,13 @@ SUNErrCode SUNAdaptController_EstimateStep_ImExGus(SUNAdaptController C, const int ord = p + 1; /* compute estimated time step size, modifying the first step formula */ - if (SACIMEXGUS_FIRSTSTEP(C)) { + if (SACIMEXGUS_FIRSTSTEP(C)) + { // TODO: could this case be handled by setting e1 = e2? /* set usable time-step adaptivity parameters -- first step */ const sunrealtype k = -SUN_RCONST(1.0) / ord; const sunrealtype e = SACIMEXGUS_BIAS(C) * dsm; - *hnew = h * SUNRpowerR(e, k); + *hnew = h * SUNRpowerR(e, k); } else { diff --git a/src/sunadaptcontroller/soderlind/sunadaptcontroller_soderlind.c b/src/sunadaptcontroller/soderlind/sunadaptcontroller_soderlind.c index b4286ff011..62c0e823b0 100644 --- a/src/sunadaptcontroller/soderlind/sunadaptcontroller_soderlind.c +++ b/src/sunadaptcontroller/soderlind/sunadaptcontroller_soderlind.c @@ -316,14 +316,18 @@ SUNErrCode SUNAdaptController_EstimateStep_Soderlind(SUNAdaptController C, const int ord = p + 1; /* set usable time-step adaptivity parameters */ - const sunrealtype ke[] = {-SODERLIND_K1(C) / ord, -SODERLIND_K2(C) / ord, -SODERLIND_K3(C) / ord}; + const sunrealtype ke[] = {-SODERLIND_K1(C) / ord, -SODERLIND_K2(C) / ord, + -SODERLIND_K3(C) / ord}; const sunrealtype kh[] = {SODERLIND_K4(C), SODERLIND_K5(C)}; // TODO: Should e2 and e3 be set to e1 when we don't have enough history yet? - const sunrealtype e[] = {SODERLIND_BIAS(C) * dsm, SODERLIND_EP(C), SODERLIND_EPP(C)}; - const sunrealtype hrat[] = {h / SODERLIND_HP(C), SODERLIND_HP(C) / SODERLIND_HPP(C)}; + const sunrealtype e[] = {SODERLIND_BIAS(C) * dsm, SODERLIND_EP(C), + SODERLIND_EPP(C)}; + const sunrealtype hrat[] = {h / SODERLIND_HP(C), + SODERLIND_HP(C) / SODERLIND_HPP(C)}; *hnew = h * SUNRpowerR(e[0], ke[0]); - for (int i = 0; i < SUNMIN(2, SODERLIND_FIRSTSTEPS(C)); i++) { + for (int i = 0; i < SUNMIN(2, SODERLIND_FIRSTSTEPS(C)); i++) + { *hnew *= SUNRpowerR(hrat[i], kh[i]) * SUNRpowerR(e[i + 1], ke[i + 1]); } From 299cd5cf89f80236a9b1527eb559c05b88246389 Mon Sep 17 00:00:00 2001 From: Steven Roberts Date: Thu, 5 Sep 2024 21:44:42 -0700 Subject: [PATCH 13/39] Variable initialization cleanup --- .../soderlind/sunadaptcontroller_soderlind.c | 26 +++++-------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/src/sunadaptcontroller/soderlind/sunadaptcontroller_soderlind.c b/src/sunadaptcontroller/soderlind/sunadaptcontroller_soderlind.c index 62c0e823b0..4b306b972c 100644 --- a/src/sunadaptcontroller/soderlind/sunadaptcontroller_soderlind.c +++ b/src/sunadaptcontroller/soderlind/sunadaptcontroller_soderlind.c @@ -75,12 +75,8 @@ SUNAdaptController SUNAdaptController_Soderlind(SUNContext sunctx) { SUNFunctionBegin(sunctx); - SUNAdaptController C; - SUNAdaptControllerContent_Soderlind content; - /* Create an empty controller object */ - C = NULL; - C = SUNAdaptController_NewEmpty(sunctx); + SUNAdaptController C = SUNAdaptController_NewEmpty(sunctx); SUNCheckLastErrNull(); /* Attach operations */ @@ -94,12 +90,8 @@ SUNAdaptController SUNAdaptController_Soderlind(SUNContext sunctx) C->ops->space = SUNAdaptController_Space_Soderlind; /* Create content */ - content = NULL; - content = (SUNAdaptControllerContent_Soderlind)malloc(sizeof *content); - SUNAssertNull(content, SUN_ERR_MALLOC_FAIL); - - /* Attach content */ - C->content = content; + C->content = (SUNAdaptControllerContent_Soderlind)malloc(sizeof *C->content); + SUNAssertNull(C->content, SUN_ERR_MALLOC_FAIL); /* Fill content with default/reset values */ SUNCheckCallNull(SUNAdaptController_SetDefaults_Soderlind(C)); @@ -168,8 +160,7 @@ SUNAdaptController SUNAdaptController_PI(SUNContext sunctx) { SUNFunctionBegin(sunctx); - SUNAdaptController C; - C = SUNAdaptController_Soderlind(sunctx); + SUNAdaptController C = SUNAdaptController_Soderlind(sunctx); SUNCheckLastErrNull(); SUNCheckCallNull( @@ -202,8 +193,7 @@ SUNAdaptController SUNAdaptController_I(SUNContext sunctx) { SUNFunctionBegin(sunctx); - SUNAdaptController C; - C = SUNAdaptController_Soderlind(sunctx); + SUNAdaptController C = SUNAdaptController_Soderlind(sunctx); SUNCheckLastErrNull(); SUNCheckCallNull(SUNAdaptController_SetParams_I(C, DEFAULT_I_K1)); @@ -234,8 +224,7 @@ SUNAdaptController SUNAdaptController_ExpGus(SUNContext sunctx) { SUNFunctionBegin(sunctx); - SUNAdaptController C; - C = SUNAdaptController_Soderlind(sunctx); + SUNAdaptController C = SUNAdaptController_Soderlind(sunctx); SUNCheckLastErrNull(); SUNCheckCallNull(SUNAdaptController_SetParams_ExpGus(C, DEFAULT_EXPGUS_K1, @@ -268,8 +257,7 @@ SUNAdaptController SUNAdaptController_ImpGus(SUNContext sunctx) { SUNFunctionBegin(sunctx); - SUNAdaptController C; - C = SUNAdaptController_Soderlind(sunctx); + SUNAdaptController C = SUNAdaptController_Soderlind(sunctx); SUNCheckLastErrNull(); SUNCheckCallNull(SUNAdaptController_SetParams_ImpGus(C, DEFAULT_IMPGUS_K1, From 405ff411ecbd6ecbce9b35a69d087f1d1d78a39d Mon Sep 17 00:00:00 2001 From: Steven Roberts Date: Thu, 5 Sep 2024 22:50:49 -0700 Subject: [PATCH 14/39] Use I controller on first 2 steps of Soderlind --- .../imexgus/sunadaptcontroller_imexgus.c | 1 - .../soderlind/sunadaptcontroller_soderlind.c | 34 +++++++++++-------- 2 files changed, 20 insertions(+), 15 deletions(-) diff --git a/src/sunadaptcontroller/imexgus/sunadaptcontroller_imexgus.c b/src/sunadaptcontroller/imexgus/sunadaptcontroller_imexgus.c index fbbea251dc..5880f24a31 100644 --- a/src/sunadaptcontroller/imexgus/sunadaptcontroller_imexgus.c +++ b/src/sunadaptcontroller/imexgus/sunadaptcontroller_imexgus.c @@ -135,7 +135,6 @@ SUNErrCode SUNAdaptController_EstimateStep_ImExGus(SUNAdaptController C, /* compute estimated time step size, modifying the first step formula */ if (SACIMEXGUS_FIRSTSTEP(C)) { - // TODO: could this case be handled by setting e1 = e2? /* set usable time-step adaptivity parameters -- first step */ const sunrealtype k = -SUN_RCONST(1.0) / ord; const sunrealtype e = SACIMEXGUS_BIAS(C) * dsm; diff --git a/src/sunadaptcontroller/soderlind/sunadaptcontroller_soderlind.c b/src/sunadaptcontroller/soderlind/sunadaptcontroller_soderlind.c index 4b306b972c..1545cbab4e 100644 --- a/src/sunadaptcontroller/soderlind/sunadaptcontroller_soderlind.c +++ b/src/sunadaptcontroller/soderlind/sunadaptcontroller_soderlind.c @@ -303,20 +303,26 @@ SUNErrCode SUNAdaptController_EstimateStep_Soderlind(SUNAdaptController C, /* order parameter to use */ const int ord = p + 1; - /* set usable time-step adaptivity parameters */ - const sunrealtype ke[] = {-SODERLIND_K1(C) / ord, -SODERLIND_K2(C) / ord, - -SODERLIND_K3(C) / ord}; - const sunrealtype kh[] = {SODERLIND_K4(C), SODERLIND_K5(C)}; - // TODO: Should e2 and e3 be set to e1 when we don't have enough history yet? - const sunrealtype e[] = {SODERLIND_BIAS(C) * dsm, SODERLIND_EP(C), - SODERLIND_EPP(C)}; - const sunrealtype hrat[] = {h / SODERLIND_HP(C), - SODERLIND_HP(C) / SODERLIND_HPP(C)}; - - *hnew = h * SUNRpowerR(e[0], ke[0]); - for (int i = 0; i < SUNMIN(2, SODERLIND_FIRSTSTEPS(C)); i++) - { - *hnew *= SUNRpowerR(hrat[i], kh[i]) * SUNRpowerR(e[i + 1], ke[i + 1]); + if (SODERLIND_FIRSTSTEPS(C) > 1) { + /* After the first 2 steps, there is sufficient history */ + const sunrealtype k1 = -SODERLIND_K1(C) / ord; + const sunrealtype k2 = -SODERLIND_K2(C) / ord; + const sunrealtype k3 = -SODERLIND_K3(C) / ord; + const sunrealtype k4 = SODERLIND_K4(C); + const sunrealtype k5 = SODERLIND_K5(C); + const sunrealtype e1 = SODERLIND_BIAS(C) * dsm; + const sunrealtype e2 = SODERLIND_EP(C); + const sunrealtype e3 = SODERLIND_EPP(C); + const sunrealtype hrat = h / SODERLIND_HP(C); + const sunrealtype hrat2 = SODERLIND_HP(C) / SODERLIND_HPP(C); + + *hnew = h * SUNRpowerR(e1, k1) * SUNRpowerR(e2, k2) * SUNRpowerR(e3, k3) * + SUNRpowerR(hrat, k4) * SUNRpowerR(hrat2, k5); + } else { + /* Use an I controller on the first two steps */ + const sunrealtype k = -SUN_RCONST(1.0) / ord; + const sunrealtype e = SODERLIND_BIAS(C) * dsm; + *hnew = h * SUNRpowerR(e, k); } if (!isfinite(*hnew)) From bc9f312a12ca9c09b9fe00c7268116c410a4af5d Mon Sep 17 00:00:00 2001 From: Steven Roberts Date: Thu, 5 Sep 2024 22:54:04 -0700 Subject: [PATCH 15/39] Remove assert for pow testing --- src/sundials/sundials_math.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/sundials/sundials_math.c b/src/sundials/sundials_math.c index 8c5f5fc942..c78bb59068 100644 --- a/src/sundials/sundials_math.c +++ b/src/sundials/sundials_math.c @@ -38,10 +38,6 @@ sunrealtype SUNRpowerI(sunrealtype base, int exponent) sunrealtype SUNRpowerR(sunrealtype base, sunrealtype exponent) { - // TODO(SBR): cleanup this and header - // if (base <= SUN_RCONST(0.0)) { return (SUN_RCONST(0.0)); } - assert(base > 0.0); - #if defined(SUNDIALS_DOUBLE_PRECISION) return (pow(base, exponent)); #elif defined(SUNDIALS_SINGLE_PRECISION) From 54aa1d5a859bfdfa168a477ce31d9ae57f39f45a Mon Sep 17 00:00:00 2001 From: Steven Roberts Date: Thu, 5 Sep 2024 23:16:13 -0700 Subject: [PATCH 16/39] Update docs --- .../sunadaptcontroller/SUNAdaptController_Soderlind.rst | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/doc/shared/sunadaptcontroller/SUNAdaptController_Soderlind.rst b/doc/shared/sunadaptcontroller/SUNAdaptController_Soderlind.rst index 0c1b0cc620..830a7f2d17 100644 --- a/doc/shared/sunadaptcontroller/SUNAdaptController_Soderlind.rst +++ b/doc/shared/sunadaptcontroller/SUNAdaptController_Soderlind.rst @@ -27,11 +27,10 @@ and :cite:p:`Sod:06`. This controller has the form with default parameter values :math:`k_1 = 1.25`, :math:`k_2 = 0.5`, :math:`k_3 = -0.75`, :math:`k_4 = 0.25`, and :math:`k_5 = 0.75`, where -:math:`p` is the global order of the time integration method. In this estimate, -a floor of :math:`\varepsilon_* > 10^{-10}` is enforced to avoid division-by-zero -errors. During the first two steps (when :math:`\varepsilon_{n-2}`, -:math:`\varepsilon_{n-1}`, :math:`h_{n-2}`, and :math:`h_{n-2}` may be unavailable), -the corresponding terms are merely omitted during estimation of :math:`h'`. +:math:`p` is the global order of the time integration method. During the first +two steps (when :math:`\varepsilon_{n-2}`, :math:`\varepsilon_{n-1}`, +:math:`h_{n-2}`, and :math:`h_{n-2}` may be unavailable), the I controller +:math:`h' = h_n \varepsilon_1^{-1/(p+1)}` is used. The SUNAdaptController_Soderlind controller is implemented as a derived SUNAdaptController class, and defines its *content* field as: From bfdf75e0e56e60cc6721b237c7780e275c53c872 Mon Sep 17 00:00:00 2001 From: Steven Roberts Date: Thu, 5 Sep 2024 23:35:46 -0700 Subject: [PATCH 17/39] Update IMEX controller docs --- doc/shared/sunadaptcontroller/SUNAdaptController_ImExGus.rst | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/doc/shared/sunadaptcontroller/SUNAdaptController_ImExGus.rst b/doc/shared/sunadaptcontroller/SUNAdaptController_ImExGus.rst index 0afdf7d786..11284031c3 100644 --- a/doc/shared/sunadaptcontroller/SUNAdaptController_ImExGus.rst +++ b/doc/shared/sunadaptcontroller/SUNAdaptController_ImExGus.rst @@ -45,9 +45,7 @@ with the form In the above formulas, the default values of :math:`k_1^E`, :math:`k_2^E`, :math:`k_1^I`, and :math:`k_2^I` are 0.367, 0.268, 0.98, and 0.95, respectively, -and :math:`p` is the global order of the time integration method. In these -estimates, a floor of :math:`\varepsilon_* > 10^{-10}` is enforced to avoid -division-by-zero errors. +and :math:`p` is the global order of the time integration method. The SUNAdaptController_ImExGus controller implements both formulas :eq:`expGusController` and :eq:`impGusController`, and sets its recommended step From dde1379cdac876a28d4ae13b880e6c0f7a8ab613 Mon Sep 17 00:00:00 2001 From: Steven Roberts Date: Thu, 5 Sep 2024 23:35:54 -0700 Subject: [PATCH 18/39] Update changelog --- CHANGELOG.md | 6 ++++++ doc/shared/RecentChanges.rst | 7 +++++++ 2 files changed, 13 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3a82dd8621..641d5e6a2f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,12 @@ architecture for their system. ### Bug Fixes +Removed error floors from the SUNAdaptController implementations which could +unnecessarily limit the time size growth, particularly after the first step. + +On the first two time steps, the Soderlind controller uses an I controller +instead omitting unavailable terms. + Fixed the loading of ARKStep's default first order explicit method. Fixed a CMake bug regarding usage of missing "print_warning" macro diff --git a/doc/shared/RecentChanges.rst b/doc/shared/RecentChanges.rst index 0cd3986ee3..d77b9d1e20 100644 --- a/doc/shared/RecentChanges.rst +++ b/doc/shared/RecentChanges.rst @@ -10,6 +10,13 @@ override this value with the architecture for their system. **Bug Fixes** +Removed error floors from the SUNAdaptController implementations which could +unnecessarily limit the time size growth, particularly after the first step. + +On the first two time steps, the +:ref:`Soderlind controller ` uses an I controller +instead omitting unavailable terms. + Fixed the loading of ARKStep's default first order explicit method. Fixed a CMake bug regarding usage of missing "print_warning" macro From facfc39b935f4ac4753e01607c811c4bb9523fc2 Mon Sep 17 00:00:00 2001 From: Steven Roberts Date: Fri, 6 Sep 2024 02:40:26 -0700 Subject: [PATCH 19/39] Clean up time step sign --- include/sundials/sundials_math.h | 24 +++++++++++++++++++ src/arkode/arkode_adapt.c | 18 +++++++------- .../imexgus/sunadaptcontroller_imexgus.c | 2 +- .../soderlind/sunadaptcontroller_soderlind.c | 4 ++-- 4 files changed, 35 insertions(+), 13 deletions(-) diff --git a/include/sundials/sundials_math.h b/include/sundials/sundials_math.h index 4585c7c7f4..bc6cd2f9eb 100644 --- a/include/sundials/sundials_math.h +++ b/include/sundials/sundials_math.h @@ -158,6 +158,30 @@ extern "C" { #endif #endif +/* + * ----------------------------------------------------------------- + * Function : SUNRcopysign + * ----------------------------------------------------------------- + * Usage : sunrealtype z; + * z = SUNRcopysign(x, y); + * ----------------------------------------------------------------- + * SUNRcopysign(x, y) returns x with the sign of y. + * ----------------------------------------------------------------- + */ + +#ifndef SUNRcopysign +#if defined(SUNDIALS_DOUBLE_PRECISION) +#define SUNRcopysign(x, y) (copysign((x), (y))) +#elif defined(SUNDIALS_SINGLE_PRECISION) +#define SUNRcopysign(x, y) (copysignf((x), (y))) +#elif defined(SUNDIALS_EXTENDED_PRECISION) +#define SUNRcopysign(x, y) (copysignl((x), (y))) +#else +#error \ + "SUNDIALS precision not defined, report to github.com/LLNL/sundials/issues" +#endif +#endif + /* * ----------------------------------------------------------------- * Function : SUNRpowerI diff --git a/src/arkode/arkode_adapt.c b/src/arkode/arkode_adapt.c index a4758436eb..93a09bf683 100644 --- a/src/arkode/arkode_adapt.c +++ b/src/arkode/arkode_adapt.c @@ -95,7 +95,7 @@ int arkAdapt(ARKodeMem ark_mem, ARKodeHAdaptMem hadapt_mem, N_Vector ycur, sunrealtype tcur, sunrealtype hcur, sunrealtype dsm) { int retval; - sunrealtype h_acc, h_cfl, int_dir; + sunrealtype h_acc, h_cfl; int controller_order; /* Request error-based step size from adaptivity controller */ @@ -120,9 +120,6 @@ int arkAdapt(ARKodeMem ark_mem, ARKodeHAdaptMem hadapt_mem, N_Vector ycur, return (ARK_CONTROLLER_ERR); } - /* determine direction of integration */ - int_dir = hcur / SUNRabs(hcur); - /* Call explicit stability function */ retval = hadapt_mem->expstab(ycur, tcur, &h_cfl, hadapt_mem->estab_data); if (retval != ARK_SUCCESS) @@ -141,24 +138,25 @@ int arkAdapt(ARKodeMem ark_mem, ARKodeHAdaptMem hadapt_mem, N_Vector ycur, /* enforce safety factors */ h_acc *= hadapt_mem->safety; - h_cfl *= hadapt_mem->cfl * int_dir; + h_cfl *= hadapt_mem->cfl; /* enforce maximum bound on time step growth */ - h_acc = int_dir * SUNMIN(SUNRabs(h_acc), SUNRabs(hadapt_mem->etamax * hcur)); + h_acc = SUNMIN(SUNRabs(h_acc), SUNRabs(hadapt_mem->etamax * hcur)); /* enforce minimum bound time step reduction */ - h_acc = int_dir * SUNMAX(SUNRabs(h_acc), SUNRabs(hadapt_mem->etamin * hcur)); + h_acc = SUNMAX(h_acc, SUNRabs(hadapt_mem->etamin * hcur)); #if SUNDIALS_LOGGING_LEVEL >= SUNDIALS_LOGGING_INFO SUNLogger_QueueMsg(ARK_LOGGER, SUN_LOGLEVEL_INFO, "ARKODE::arkAdapt", "new-step-after-max-min-bounds", - "h_acc = %" RSYM ", h_cfl = %" RSYM, h_acc, h_cfl); + "h_acc = %" RSYM ", h_cfl = %" RSYM, + SUNRcopysign(h_acc, hcur), h_cfl); #endif /* increment the relevant step counter, set desired step */ - if (SUNRabs(h_acc) <= SUNRabs(h_cfl)) { hadapt_mem->nst_acc++; } + if (h_acc <= h_cfl) { hadapt_mem->nst_acc++; } else { hadapt_mem->nst_exp++; } - h_acc = int_dir * SUNMIN(SUNRabs(h_acc), SUNRabs(h_cfl)); + h_acc = SUNRcopysign(SUNMIN(h_acc, h_cfl), hcur); /* enforce adaptivity bounds to retain Jacobian/preconditioner accuracy */ if (dsm <= ONE) diff --git a/src/sunadaptcontroller/imexgus/sunadaptcontroller_imexgus.c b/src/sunadaptcontroller/imexgus/sunadaptcontroller_imexgus.c index 5880f24a31..650ffc52df 100644 --- a/src/sunadaptcontroller/imexgus/sunadaptcontroller_imexgus.c +++ b/src/sunadaptcontroller/imexgus/sunadaptcontroller_imexgus.c @@ -158,7 +158,7 @@ SUNErrCode SUNAdaptController_EstimateStep_ImExGus(SUNAdaptController C, { /* hnew can be INFINITY or NAN if multiple e's are 0 or there are overflows. * In that case, make hnew INFINITY with the same sign as h */ - *hnew = h / SUN_RCONST(0.0); + *hnew = SUNRcopysign(INFINITY, h); } /* return with success */ diff --git a/src/sunadaptcontroller/soderlind/sunadaptcontroller_soderlind.c b/src/sunadaptcontroller/soderlind/sunadaptcontroller_soderlind.c index 1545cbab4e..2f0d0e71e1 100644 --- a/src/sunadaptcontroller/soderlind/sunadaptcontroller_soderlind.c +++ b/src/sunadaptcontroller/soderlind/sunadaptcontroller_soderlind.c @@ -90,7 +90,7 @@ SUNAdaptController SUNAdaptController_Soderlind(SUNContext sunctx) C->ops->space = SUNAdaptController_Space_Soderlind; /* Create content */ - C->content = (SUNAdaptControllerContent_Soderlind)malloc(sizeof *C->content); + C->content = (SUNAdaptControllerContent_Soderlind)malloc(sizeof(struct _SUNAdaptControllerContent_Soderlind)); SUNAssertNull(C->content, SUN_ERR_MALLOC_FAIL); /* Fill content with default/reset values */ @@ -329,7 +329,7 @@ SUNErrCode SUNAdaptController_EstimateStep_Soderlind(SUNAdaptController C, { /* hnew can be INFINITY or NAN if multiple e's are 0 or there are overflows. * In that case, make hnew INFINITY with the same sign as h */ - *hnew = h / SUN_RCONST(0.0); + *hnew = SUNRcopysign(INFINITY, h); } /* return with success */ From 7badd781110b5d644c731fecf61ead24ce124f3c Mon Sep 17 00:00:00 2001 From: Steven Roberts Date: Fri, 6 Sep 2024 03:01:05 -0700 Subject: [PATCH 20/39] Additional simplifications --- src/arkode/arkode_adapt.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/arkode/arkode_adapt.c b/src/arkode/arkode_adapt.c index 93a09bf683..9f91b684de 100644 --- a/src/arkode/arkode_adapt.c +++ b/src/arkode/arkode_adapt.c @@ -155,18 +155,18 @@ int arkAdapt(ARKodeMem ark_mem, ARKodeHAdaptMem hadapt_mem, N_Vector ycur, /* increment the relevant step counter, set desired step */ if (h_acc <= h_cfl) { hadapt_mem->nst_acc++; } - else { hadapt_mem->nst_exp++; } - h_acc = SUNRcopysign(SUNMIN(h_acc, h_cfl), hcur); + else { hadapt_mem->nst_exp++; h_acc = h_cfl; } /* enforce adaptivity bounds to retain Jacobian/preconditioner accuracy */ if (dsm <= ONE) { - if ((SUNRabs(h_acc) > SUNRabs(hcur * hadapt_mem->lbound * ONEMSM)) && - (SUNRabs(h_acc) < SUNRabs(hcur * hadapt_mem->ubound * ONEPSM))) + if ((h_acc > SUNRabs(hcur * hadapt_mem->lbound * ONEMSM)) && + (h_acc < SUNRabs(hcur * hadapt_mem->ubound * ONEPSM))) { h_acc = hcur; } } + h_acc = SUNRcopysign(h_acc, hcur); /* set basic value of ark_eta */ ark_mem->eta = h_acc / hcur; From c472ffed440afc414b4c1dcf5f4545b3139bc313 Mon Sep 17 00:00:00 2001 From: Steven Roberts Date: Fri, 6 Sep 2024 14:14:51 -0700 Subject: [PATCH 21/39] Additional testing of controller --- src/arkode/arkode_adapt.c | 6 +- .../soderlind/sunadaptcontroller_soderlind.c | 10 ++- .../arkode/C_serial/ark_test_adapt.c | 75 +++++++++++++------ 3 files changed, 63 insertions(+), 28 deletions(-) diff --git a/src/arkode/arkode_adapt.c b/src/arkode/arkode_adapt.c index 9f91b684de..88ff02fe3d 100644 --- a/src/arkode/arkode_adapt.c +++ b/src/arkode/arkode_adapt.c @@ -155,7 +155,11 @@ int arkAdapt(ARKodeMem ark_mem, ARKodeHAdaptMem hadapt_mem, N_Vector ycur, /* increment the relevant step counter, set desired step */ if (h_acc <= h_cfl) { hadapt_mem->nst_acc++; } - else { hadapt_mem->nst_exp++; h_acc = h_cfl; } + else + { + hadapt_mem->nst_exp++; + h_acc = h_cfl; + } /* enforce adaptivity bounds to retain Jacobian/preconditioner accuracy */ if (dsm <= ONE) diff --git a/src/sunadaptcontroller/soderlind/sunadaptcontroller_soderlind.c b/src/sunadaptcontroller/soderlind/sunadaptcontroller_soderlind.c index 2f0d0e71e1..17ef9493dc 100644 --- a/src/sunadaptcontroller/soderlind/sunadaptcontroller_soderlind.c +++ b/src/sunadaptcontroller/soderlind/sunadaptcontroller_soderlind.c @@ -90,7 +90,8 @@ SUNAdaptController SUNAdaptController_Soderlind(SUNContext sunctx) C->ops->space = SUNAdaptController_Space_Soderlind; /* Create content */ - C->content = (SUNAdaptControllerContent_Soderlind)malloc(sizeof(struct _SUNAdaptControllerContent_Soderlind)); + C->content = (SUNAdaptControllerContent_Soderlind)malloc( + sizeof(struct _SUNAdaptControllerContent_Soderlind)); SUNAssertNull(C->content, SUN_ERR_MALLOC_FAIL); /* Fill content with default/reset values */ @@ -303,7 +304,8 @@ SUNErrCode SUNAdaptController_EstimateStep_Soderlind(SUNAdaptController C, /* order parameter to use */ const int ord = p + 1; - if (SODERLIND_FIRSTSTEPS(C) > 1) { + if (SODERLIND_FIRSTSTEPS(C) > 1) + { /* After the first 2 steps, there is sufficient history */ const sunrealtype k1 = -SODERLIND_K1(C) / ord; const sunrealtype k2 = -SODERLIND_K2(C) / ord; @@ -318,7 +320,9 @@ SUNErrCode SUNAdaptController_EstimateStep_Soderlind(SUNAdaptController C, *hnew = h * SUNRpowerR(e1, k1) * SUNRpowerR(e2, k2) * SUNRpowerR(e3, k3) * SUNRpowerR(hrat, k4) * SUNRpowerR(hrat2, k5); - } else { + } + else + { /* Use an I controller on the first two steps */ const sunrealtype k = -SUN_RCONST(1.0) / ord; const sunrealtype e = SODERLIND_BIAS(C) * dsm; diff --git a/test/unit_tests/arkode/C_serial/ark_test_adapt.c b/test/unit_tests/arkode/C_serial/ark_test_adapt.c index 01fa551559..874378f663 100644 --- a/test/unit_tests/arkode/C_serial/ark_test_adapt.c +++ b/test/unit_tests/arkode/C_serial/ark_test_adapt.c @@ -11,7 +11,8 @@ * SPDX-License-Identifier: BSD-3-Clause * SUNDIALS Copyright End * ----------------------------------------------------------------------------- - * Unit test for GetUserData functions + * Unit test for step size growth and handling of inf/nan within a controller + * due to 0 local error. * ---------------------------------------------------------------------------*/ #include @@ -20,6 +21,7 @@ #include "arkode/arkode_erkstep.h" #include "nvector/nvector_serial.h" +/* If an error occurs, print to stderr and exit */ static void err_fn(const int line, const char* const func, const char* const file, const char* const msg, const SUNErrCode err_code, void* const err_user_data, const SUNContext sunctx) @@ -28,7 +30,7 @@ static void err_fn(const int line, const char* const func, const char* const fil exit(err_code); } -// RHS for the simple ODE y' = 0 +/* RHS for the simple ODE y'=0 */ static int f(const sunrealtype t, const N_Vector y, const N_Vector ydot, void* const user_data) { @@ -36,13 +38,16 @@ static int f(const sunrealtype t, const N_Vector y, const N_Vector ydot, return 0; } +/* Take a single time step solving y'=0 and check the max growth was attained */ static int check_step(void* const arkode_mem, const N_Vector y, const sunrealtype h_expected, const int step) { + /* Integration much farther than expected step */ + const sunrealtype tout = SUN_RCONST(100.0) * h_expected; sunrealtype tret; /* The ERK method should be able to take the maximum possible timestep for the - simple ODE y' = 0 without any rejected steps or local error */ - ARKodeEvolve(arkode_mem, SUN_RCONST(1.0), y, &tret, ARK_ONE_STEP); + without any rejected steps or local error */ + ARKodeEvolve(arkode_mem, tout, y, &tret, ARK_ONE_STEP); long int local_err_fails; ARKodeGetNumErrTestFails(arkode_mem, &local_err_fails); @@ -66,7 +71,7 @@ static int check_step(void* const arkode_mem, const N_Vector y, sunrealtype h_actual; ARKodeGetCurrentStep(arkode_mem, &h_actual); - if (h_expected != h_actual) + if (SUNRCompare(h_expected, h_actual)) { fprintf(stderr, "Expected h at step %i to be %g but is %g\n", step, h_expected, h_actual); @@ -76,6 +81,29 @@ static int check_step(void* const arkode_mem, const N_Vector y, return 0; } +/* Take several steps solving y'=0 and check the max growth was attained */ +static int check_steps(void* const arkode_mem, const N_Vector y, + const sunrealtype h0, const sunrealtype first_growth, + const sunrealtype growth) +{ + ARKodeSetInitStep(arkode_mem, h0); + ARKodeSetMaxFirstGrowth(arkode_mem, first_growth); + ARKodeSetMaxGrowth(arkode_mem, growth); + + sunrealtype h_expect = first_growth * h0; + /* Take several steps to see the special behavior at step one then to allow + the adaptivity controller history fill up */ + const int num_steps = 5; + for (int step = 1; step <= num_steps; step++) + { + const int retval = check_step_no_err(arkode_mem, y, h_expect, step); + if (retval != 0) { return retval; } + h_expect *= growth; + } + + return 0; +} + int main() { SUNContext sunctx; @@ -96,26 +124,25 @@ int main() const N_Vector y = N_VNew_Serial(1, sunctx); N_VConst(SUN_RCONST(1.0), y); + /* Forward integration from 0 */ void* arkode_mem = ERKStepCreate(f, SUN_RCONST(0.0), y, sunctx); - - const sunrealtype h0 = SUN_RCONST(1.0e-4); - const sunrealtype first_growth = SUN_RCONST(1234.0); - const sunrealtype growth = SUN_RCONST(3.0); - - ARKodeSetInitStep(arkode_mem, h0); - ARKodeSetMaxFirstGrowth(arkode_mem, first_growth); - ARKodeSetMaxGrowth(arkode_mem, growth); - - sunrealtype h_expect = first_growth * h0; - /* Take several steps to see the special behavior at step one then to allow - the adaptivity controller history fill up */ - const int num_steps = 5; - for (int step = 1; step <= num_steps; step++) - { - retval = check_step(arkode_mem, y, h_expect, step); - if (retval != 0) { return retval; } - h_expect *= growth; - } + retval = check_steps_no_err(arkode_mem, y, SUN_RCONST(1.0e-4), + SUN_RCONST(1234.0), SUN_RCONST(3.0)); + if (retval != 0) { return retval; } + + /* Backward integration from positive time */ + ERKStepReInit(arkode_mem, f, SUN_RCONST(999.0), y); + retval = check_steps_no_err(arkode_mem, y, SUN_RCONST(-1.0e-2), + SUN_RCONST(1.6), SUN_RCONST(2.3)); + if (retval != 0) { return retval; } + + /* Forward integration from a negative time */ + ERKStepReInit(arkode_mem, f, SUN_RCONST(-999.0), y); + retval = check_steps_no_err(arkode_mem, y, SUN_RCONST(20.0), + SUN_RCONST(1.0e5), SUN_RCONST(1.1e3)); + if (retval != 0) { return retval; } + + /* TODO(SBR): add additional tests for more the default controller */ ARKodeFree(&arkode_mem); N_VDestroy(y); From 2452bd691d93fa14fde2e2d3fa7249f803609f80 Mon Sep 17 00:00:00 2001 From: Steven Roberts Date: Fri, 6 Sep 2024 14:20:36 -0700 Subject: [PATCH 22/39] Remove unnecessary header --- src/sundials/sundials_math.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/sundials/sundials_math.c b/src/sundials/sundials_math.c index c78bb59068..4036149cee 100644 --- a/src/sundials/sundials_math.c +++ b/src/sundials/sundials_math.c @@ -22,8 +22,6 @@ #include #include -#include - sunrealtype SUNRpowerI(sunrealtype base, int exponent) { int i, expt; From 13cce1285cfee6debba7163f3daf9c7f11b235ab Mon Sep 17 00:00:00 2001 From: Steven Roberts Date: Fri, 6 Sep 2024 14:39:50 -0700 Subject: [PATCH 23/39] Correct function names --- test/unit_tests/arkode/C_serial/ark_test_adapt.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/test/unit_tests/arkode/C_serial/ark_test_adapt.c b/test/unit_tests/arkode/C_serial/ark_test_adapt.c index 874378f663..72c6d493f0 100644 --- a/test/unit_tests/arkode/C_serial/ark_test_adapt.c +++ b/test/unit_tests/arkode/C_serial/ark_test_adapt.c @@ -96,7 +96,7 @@ static int check_steps(void* const arkode_mem, const N_Vector y, const int num_steps = 5; for (int step = 1; step <= num_steps; step++) { - const int retval = check_step_no_err(arkode_mem, y, h_expect, step); + const int retval = check_step(arkode_mem, y, h_expect, step); if (retval != 0) { return retval; } h_expect *= growth; } @@ -126,20 +126,20 @@ int main() /* Forward integration from 0 */ void* arkode_mem = ERKStepCreate(f, SUN_RCONST(0.0), y, sunctx); - retval = check_steps_no_err(arkode_mem, y, SUN_RCONST(1.0e-4), - SUN_RCONST(1234.0), SUN_RCONST(3.0)); + retval = check_steps(arkode_mem, y, SUN_RCONST(1.0e-4), SUN_RCONST(1234.0), + SUN_RCONST(3.0)); if (retval != 0) { return retval; } /* Backward integration from positive time */ ERKStepReInit(arkode_mem, f, SUN_RCONST(999.0), y); - retval = check_steps_no_err(arkode_mem, y, SUN_RCONST(-1.0e-2), - SUN_RCONST(1.6), SUN_RCONST(2.3)); + retval = check_steps(arkode_mem, y, SUN_RCONST(-1.0e-2), SUN_RCONST(1.6), + SUN_RCONST(2.3)); if (retval != 0) { return retval; } /* Forward integration from a negative time */ ERKStepReInit(arkode_mem, f, SUN_RCONST(-999.0), y); - retval = check_steps_no_err(arkode_mem, y, SUN_RCONST(20.0), - SUN_RCONST(1.0e5), SUN_RCONST(1.1e3)); + retval = check_steps(arkode_mem, y, SUN_RCONST(20.0), SUN_RCONST(1.0e5), + SUN_RCONST(1.1e3)); if (retval != 0) { return retval; } /* TODO(SBR): add additional tests for more the default controller */ From 19503568fd4599cacb07ee017f074dc172d832e2 Mon Sep 17 00:00:00 2001 From: Steven Roberts Date: Fri, 6 Sep 2024 15:05:30 -0700 Subject: [PATCH 24/39] Convert SUNRpowerR to macro --- include/sundials/sundials_math.h | 39 ++++++++++++++++++++------------ src/sundials/sundials_math.c | 14 ------------ 2 files changed, 24 insertions(+), 29 deletions(-) diff --git a/include/sundials/sundials_math.h b/include/sundials/sundials_math.h index bc6cd2f9eb..c89be0af1e 100644 --- a/include/sundials/sundials_math.h +++ b/include/sundials/sundials_math.h @@ -184,33 +184,42 @@ extern "C" { /* * ----------------------------------------------------------------- - * Function : SUNRpowerI + * Function : SUNRpowerR * ----------------------------------------------------------------- - * Usage : int exponent; - * sunrealtype base, ans; - * ans = SUNRpowerI(base,exponent); + * Usage : sunrealtype base, exponent, ans; + * ans = SUNRpowerR(base,exponent); * ----------------------------------------------------------------- - * SUNRpowerI returns the value of base^exponent, where base is of type - * sunrealtype and exponent is of type int. + * SUNRpowerR returns the value of base^exponent, where both base and + * exponent are of type sunrealtype. * ----------------------------------------------------------------- */ - -SUNDIALS_EXPORT sunrealtype SUNRpowerI(sunrealtype base, int exponent); +#ifndef SUNRpowerR +#if defined(SUNDIALS_DOUBLE_PRECISION) +#define SUNRpowerR(base, exponent) (pow(base, exponent)) +#elif defined(SUNDIALS_SINGLE_PRECISION) +#define SUNRpowerR(base, exponent) (powf(base, exponent)) +#elif defined(SUNDIALS_EXTENDED_PRECISION) +#define SUNRpowerR(base, exponent) (powl(base, exponent)) +#else +#error \ + "SUNDIALS precision not defined, report to github.com/LLNL/sundials/issues" +#endif +#endif /* * ----------------------------------------------------------------- - * Function : SUNRpowerR + * Function : SUNRpowerI * ----------------------------------------------------------------- - * Usage : sunrealtype base, exponent, ans; - * ans = SUNRpowerR(base,exponent); + * Usage : int exponent; + * sunrealtype base, ans; + * ans = SUNRpowerI(base,exponent); * ----------------------------------------------------------------- - * SUNRpowerR returns the value of base^exponent, where both base and - * exponent are of type sunrealtype. If base < ZERO, then SUNRpowerR - * returns ZERO. + * SUNRpowerI returns the value of base^exponent, where base is of type + * sunrealtype and exponent is of type int. * ----------------------------------------------------------------- */ -SUNDIALS_EXPORT sunrealtype SUNRpowerR(sunrealtype base, sunrealtype exponent); +SUNDIALS_EXPORT sunrealtype SUNRpowerI(sunrealtype base, int exponent); /* * ----------------------------------------------------------------- diff --git a/src/sundials/sundials_math.c b/src/sundials/sundials_math.c index 4036149cee..4e4122c7be 100644 --- a/src/sundials/sundials_math.c +++ b/src/sundials/sundials_math.c @@ -34,20 +34,6 @@ sunrealtype SUNRpowerI(sunrealtype base, int exponent) return (prod); } -sunrealtype SUNRpowerR(sunrealtype base, sunrealtype exponent) -{ -#if defined(SUNDIALS_DOUBLE_PRECISION) - return (pow(base, exponent)); -#elif defined(SUNDIALS_SINGLE_PRECISION) - return (powf(base, exponent)); -#elif defined(SUNDIALS_EXTENDED_PRECISION) - return (powl(base, exponent)); -#else -#error \ - "SUNDIALS precision not defined, report to github.com/LLNL/sundials/issues" -#endif -} - sunbooleantype SUNRCompare(sunrealtype a, sunrealtype b) { return (SUNRCompareTol(a, b, 10 * SUN_UNIT_ROUNDOFF)); From 01b50b62af186896b1931b1589d14956f7a81429 Mon Sep 17 00:00:00 2001 From: Steven Roberts Date: Sun, 8 Sep 2024 12:24:58 -0700 Subject: [PATCH 25/39] Switch to proposed adaptivity parameters --- src/arkode/arkode_adapt_impl.h | 6 +++--- src/arkode/arkode_arkstep_io.c | 2 ++ src/arkode/arkode_erkstep_io.c | 8 +------- src/arkode/arkode_io.c | 6 +++--- .../imexgus/sunadaptcontroller_imexgus.c | 2 +- .../soderlind/sunadaptcontroller_soderlind.c | 2 +- 6 files changed, 11 insertions(+), 15 deletions(-) diff --git a/src/arkode/arkode_adapt_impl.h b/src/arkode/arkode_adapt_impl.h index 7dd9460a1e..4bb41deaff 100644 --- a/src/arkode/arkode_adapt_impl.h +++ b/src/arkode/arkode_adapt_impl.h @@ -38,10 +38,10 @@ extern "C" { /* Time step controller default values */ #define CFLFAC SUN_RCONST(0.5) -#define SAFETY SUN_RCONST(0.96) /* CVODE uses 1.0 */ +#define SAFETY SUN_RCONST(0.9) /* CVODE uses 1.0 */ #define GROWTH SUN_RCONST(20.0) /* CVODE uses 10.0 */ #define HFIXED_LB SUN_RCONST(1.0) /* CVODE uses 1.0 */ -#define HFIXED_UB SUN_RCONST(1.5) /* CVODE uses 1.5 */ +#define HFIXED_UB SUN_RCONST(1.0) /* CVODE uses 1.5 */ /* maximum step size change on first step */ #define ETAMX1 SUN_RCONST(10000.0) @@ -60,7 +60,7 @@ extern "C" { DEPRECATED, REMOVE AT SAME TIME AS ARKStepSetAdaptivityMethod */ #define PQ 0 /* adjustment to apply within controller to method order of accuracy */ -#define ADJUST -1 +#define ADJUST 0 /*=============================================================== ARKODE Time Step Adaptivity Data Structure diff --git a/src/arkode/arkode_arkstep_io.c b/src/arkode/arkode_arkstep_io.c index 7df74cb590..0dd15ed77d 100644 --- a/src/arkode/arkode_arkstep_io.c +++ b/src/arkode/arkode_arkstep_io.c @@ -1451,6 +1451,8 @@ int ARKStepSetDefaults(void* arkode_mem) int ARKStepSetOptimalParams(void* arkode_mem) { + /* TODO: do we need to do something here? This is depricated with no + * ARKodeSetOptimalParams to replace it */ ARKodeMem ark_mem; ARKodeARKStepMem step_mem; ARKodeHAdaptMem hadapt_mem; diff --git a/src/arkode/arkode_erkstep_io.c b/src/arkode/arkode_erkstep_io.c index ffbf9a18fb..4769ad4568 100644 --- a/src/arkode/arkode_erkstep_io.c +++ b/src/arkode/arkode_erkstep_io.c @@ -308,13 +308,7 @@ int erkStep_SetDefaults(ARKodeMem ark_mem) step_mem->p = 0; /* embedding order */ step_mem->stages = 0; /* no stages */ step_mem->B = NULL; /* no Butcher table */ - ark_mem->hadapt_mem->etamxf = SUN_RCONST(0.3); /* max change on error-failed step */ - ark_mem->hadapt_mem->safety = SUN_RCONST(0.99); /* step adaptivity safety factor */ - ark_mem->hadapt_mem->growth = SUN_RCONST(25.0); /* step adaptivity growth factor */ - (void)SUNAdaptController_SetErrorBias(ark_mem->hadapt_mem->hcontroller, - SUN_RCONST(1.2)); - (void)SUNAdaptController_SetParams_PI(ark_mem->hadapt_mem->hcontroller, - SUN_RCONST(0.8), -SUN_RCONST(0.31)); + /* TODO: add ERK-specific config here if needed */ return (ARK_SUCCESS); } diff --git a/src/arkode/arkode_io.c b/src/arkode/arkode_io.c index 357912409d..ea1441785f 100644 --- a/src/arkode/arkode_io.c +++ b/src/arkode/arkode_io.c @@ -933,11 +933,11 @@ int ARKodeSetAdaptController(void* arkode_mem, SUNAdaptController C) /* On NULL-valued input, create default SUNAdaptController object */ if (C == NULL) { - C = SUNAdaptController_PID(ark_mem->sunctx); + C = SUNAdaptController_I(ark_mem->sunctx); if (C == NULL) { arkProcessError(ark_mem, ARK_MEM_FAIL, __LINE__, __func__, __FILE__, - "SUNAdaptControllerPID allocation failure"); + "SUNAdaptControllerI allocation failure"); return (ARK_MEM_FAIL); } ark_mem->hadapt_mem->owncontroller = SUNTRUE; @@ -1604,7 +1604,7 @@ int ARKodeSetSafetyFactor(void* arkode_mem, sunrealtype safety) } /* check for allowable parameters */ - if (safety >= ONE) + if (safety > ONE) { arkProcessError(ark_mem, ARK_ILL_INPUT, __LINE__, __func__, __FILE__, "Illegal safety factor"); diff --git a/src/sunadaptcontroller/imexgus/sunadaptcontroller_imexgus.c b/src/sunadaptcontroller/imexgus/sunadaptcontroller_imexgus.c index e4bb23e6dd..043b2f6f82 100644 --- a/src/sunadaptcontroller/imexgus/sunadaptcontroller_imexgus.c +++ b/src/sunadaptcontroller/imexgus/sunadaptcontroller_imexgus.c @@ -47,7 +47,7 @@ #define DEFAULT_K2E SUN_RCONST(0.268) #define DEFAULT_K1I SUN_RCONST(0.95) #define DEFAULT_K2I SUN_RCONST(0.95) -#define DEFAULT_BIAS SUN_RCONST(1.5) +#define DEFAULT_BIAS SUN_RCONST(1.0) #define TINY SUN_RCONST(1.0e-10) /* ----------------------------------------------------------------- diff --git a/src/sunadaptcontroller/soderlind/sunadaptcontroller_soderlind.c b/src/sunadaptcontroller/soderlind/sunadaptcontroller_soderlind.c index bca88252cb..cf689b898f 100644 --- a/src/sunadaptcontroller/soderlind/sunadaptcontroller_soderlind.c +++ b/src/sunadaptcontroller/soderlind/sunadaptcontroller_soderlind.c @@ -61,7 +61,7 @@ #define DEFAULT_EXPGUS_K2 SUN_RCONST(0.268) #define DEFAULT_IMPGUS_K1 SUN_RCONST(0.98) /* Implicit Gustafsson parameters */ #define DEFAULT_IMPGUS_K2 SUN_RCONST(0.95) -#define DEFAULT_BIAS SUN_RCONST(1.5) +#define DEFAULT_BIAS SUN_RCONST(1.0) #define TINY SUN_RCONST(1.0e-10) /* ----------------------------------------------------------------- From 5bd47904b0de5732cfe0fcc8b5af846c29927863 Mon Sep 17 00:00:00 2001 From: Steven Roberts Date: Mon, 9 Sep 2024 21:29:50 -0700 Subject: [PATCH 26/39] Update comments based on @drreynolds suggestions --- test/unit_tests/arkode/C_serial/ark_test_adapt.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/test/unit_tests/arkode/C_serial/ark_test_adapt.c b/test/unit_tests/arkode/C_serial/ark_test_adapt.c index 72c6d493f0..e7510bcb08 100644 --- a/test/unit_tests/arkode/C_serial/ark_test_adapt.c +++ b/test/unit_tests/arkode/C_serial/ark_test_adapt.c @@ -45,8 +45,8 @@ static int check_step(void* const arkode_mem, const N_Vector y, /* Integration much farther than expected step */ const sunrealtype tout = SUN_RCONST(100.0) * h_expected; sunrealtype tret; - /* The ERK method should be able to take the maximum possible timestep for the - without any rejected steps or local error */ + /* The ERK method should be able to take the maximum possible timestep without + any rejected steps or local error */ ARKodeEvolve(arkode_mem, tout, y, &tret, ARK_ONE_STEP); long int local_err_fails; @@ -91,8 +91,7 @@ static int check_steps(void* const arkode_mem, const N_Vector y, ARKodeSetMaxGrowth(arkode_mem, growth); sunrealtype h_expect = first_growth * h0; - /* Take several steps to see the special behavior at step one then to allow - the adaptivity controller history fill up */ + /* Take enough steps to allow the controller history to fill up */ const int num_steps = 5; for (int step = 1; step <= num_steps; step++) { @@ -142,7 +141,7 @@ int main() SUN_RCONST(1.1e3)); if (retval != 0) { return retval; } - /* TODO(SBR): add additional tests for more the default controller */ + /* TODO(SBR): test non-default controllers */ ARKodeFree(&arkode_mem); N_VDestroy(y); From 9bb63c0c057e0592962a2da49a8499ba7029707a Mon Sep 17 00:00:00 2001 From: Steven Roberts Date: Tue, 10 Sep 2024 16:09:58 -0700 Subject: [PATCH 27/39] Fix typos in changelog --- CHANGELOG.md | 2 +- doc/shared/RecentChanges.rst | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c05ff67e80..db216cfcc6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -37,7 +37,7 @@ Removed error floors from the SUNAdaptController implementations which could unnecessarily limit the time size growth, particularly after the first step. On the first two time steps, the Soderlind controller uses an I controller -instead omitting unavailable terms. +instead of omitting unavailable terms. Fixed the loading of ARKStep's default first order explicit method. diff --git a/doc/shared/RecentChanges.rst b/doc/shared/RecentChanges.rst index cd930d1c2f..6b935c5dd5 100644 --- a/doc/shared/RecentChanges.rst +++ b/doc/shared/RecentChanges.rst @@ -49,7 +49,7 @@ unnecessarily limit the time size growth, particularly after the first step. On the first two time steps, the :ref:`Soderlind controller ` uses an I controller -instead omitting unavailable terms. +instead of omitting unavailable terms. Fixed the loading of ARKStep's default first order explicit method. From 8d7a2678426ba60b8334946dedc224d0af7cee7b Mon Sep 17 00:00:00 2001 From: Steven Roberts Date: Tue, 10 Sep 2024 16:11:07 -0700 Subject: [PATCH 28/39] Fix typos in changelog --- CHANGELOG.md | 2 +- doc/shared/RecentChanges.rst | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 641d5e6a2f..6d5f294e36 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,7 +18,7 @@ Removed error floors from the SUNAdaptController implementations which could unnecessarily limit the time size growth, particularly after the first step. On the first two time steps, the Soderlind controller uses an I controller -instead omitting unavailable terms. +instead of omitting unavailable terms. Fixed the loading of ARKStep's default first order explicit method. diff --git a/doc/shared/RecentChanges.rst b/doc/shared/RecentChanges.rst index d77b9d1e20..ba3585e20c 100644 --- a/doc/shared/RecentChanges.rst +++ b/doc/shared/RecentChanges.rst @@ -15,7 +15,7 @@ unnecessarily limit the time size growth, particularly after the first step. On the first two time steps, the :ref:`Soderlind controller ` uses an I controller -instead omitting unavailable terms. +instead of omitting unavailable terms. Fixed the loading of ARKStep's default first order explicit method. From 7d5161b64033fdee8f153296040d4c49284c761e Mon Sep 17 00:00:00 2001 From: Steven Roberts Date: Tue, 10 Sep 2024 19:48:37 -0700 Subject: [PATCH 29/39] Update test/unit_tests/arkode/C_serial/ark_test_adapt.c Co-authored-by: David Gardner --- test/unit_tests/arkode/C_serial/ark_test_adapt.c | 1 + 1 file changed, 1 insertion(+) diff --git a/test/unit_tests/arkode/C_serial/ark_test_adapt.c b/test/unit_tests/arkode/C_serial/ark_test_adapt.c index e7510bcb08..b8fe34bf03 100644 --- a/test/unit_tests/arkode/C_serial/ark_test_adapt.c +++ b/test/unit_tests/arkode/C_serial/ark_test_adapt.c @@ -55,6 +55,7 @@ static int check_step(void* const arkode_mem, const N_Vector y, { fprintf(stderr, "Expected 0 local error failures at step %i but is %li\n", step, local_err_fails); + return 1; } const N_Vector err = N_VClone(y); From fcb7dc6ce2acef1bc4899b7eb552c91410d165f7 Mon Sep 17 00:00:00 2001 From: Steven Roberts Date: Tue, 10 Sep 2024 19:56:14 -0700 Subject: [PATCH 30/39] Add missing SUN_RCONST --- test/unit_tests/arkode/C_serial/ark_test_adapt.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/unit_tests/arkode/C_serial/ark_test_adapt.c b/test/unit_tests/arkode/C_serial/ark_test_adapt.c index b8fe34bf03..d3d47a7f15 100644 --- a/test/unit_tests/arkode/C_serial/ark_test_adapt.c +++ b/test/unit_tests/arkode/C_serial/ark_test_adapt.c @@ -63,7 +63,7 @@ static int check_step(void* const arkode_mem, const N_Vector y, const sunrealtype err_norm = N_VMaxNorm(err); N_VDestroy(err); - if (err_norm != 0) + if (err_norm != SUN_RCONST(0)) { fprintf(stderr, "Expected local error at step %i to be 0 but is %g\n", step, err_norm); From 1db5b33e8f411b151a44a3a504acfa9d692ddf72 Mon Sep 17 00:00:00 2001 From: Steven Roberts Date: Tue, 10 Sep 2024 20:10:02 -0700 Subject: [PATCH 31/39] Update test/unit_tests/arkode/C_serial/ark_test_adapt.c Co-authored-by: David Gardner --- test/unit_tests/arkode/C_serial/ark_test_adapt.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/unit_tests/arkode/C_serial/ark_test_adapt.c b/test/unit_tests/arkode/C_serial/ark_test_adapt.c index d3d47a7f15..deb282dcb6 100644 --- a/test/unit_tests/arkode/C_serial/ark_test_adapt.c +++ b/test/unit_tests/arkode/C_serial/ark_test_adapt.c @@ -63,7 +63,7 @@ static int check_step(void* const arkode_mem, const N_Vector y, const sunrealtype err_norm = N_VMaxNorm(err); N_VDestroy(err); - if (err_norm != SUN_RCONST(0)) + if (err_norm != SUN_RCONST(0.0)) { fprintf(stderr, "Expected local error at step %i to be 0 but is %g\n", step, err_norm); From 7669c933c7416a6202c41b4cbd97ffb3be7a4515 Mon Sep 17 00:00:00 2001 From: Steven Roberts Date: Tue, 10 Sep 2024 21:00:16 -0700 Subject: [PATCH 32/39] Add more asserts to controllers --- .../imexgus/sunadaptcontroller_imexgus.c | 2 -- .../soderlind/sunadaptcontroller_soderlind.c | 1 - src/sundials/sundials_adaptcontroller.c | 7 +++++++ 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/src/sunadaptcontroller/imexgus/sunadaptcontroller_imexgus.c b/src/sunadaptcontroller/imexgus/sunadaptcontroller_imexgus.c index 650ffc52df..0bbcda4b0a 100644 --- a/src/sunadaptcontroller/imexgus/sunadaptcontroller_imexgus.c +++ b/src/sunadaptcontroller/imexgus/sunadaptcontroller_imexgus.c @@ -127,8 +127,6 @@ SUNErrCode SUNAdaptController_EstimateStep_ImExGus(SUNAdaptController C, { SUNFunctionBegin(C->sunctx); - SUNAssert(hnew, SUN_ERR_ARG_CORRUPT); - /* order parameter to use */ const int ord = p + 1; diff --git a/src/sunadaptcontroller/soderlind/sunadaptcontroller_soderlind.c b/src/sunadaptcontroller/soderlind/sunadaptcontroller_soderlind.c index 17ef9493dc..ebee48b849 100644 --- a/src/sunadaptcontroller/soderlind/sunadaptcontroller_soderlind.c +++ b/src/sunadaptcontroller/soderlind/sunadaptcontroller_soderlind.c @@ -299,7 +299,6 @@ SUNErrCode SUNAdaptController_EstimateStep_Soderlind(SUNAdaptController C, sunrealtype* hnew) { SUNFunctionBegin(C->sunctx); - SUNAssert(hnew, SUN_ERR_ARG_CORRUPT); /* order parameter to use */ const int ord = p + 1; diff --git a/src/sundials/sundials_adaptcontroller.c b/src/sundials/sundials_adaptcontroller.c index 39a56480d0..925d3fae50 100644 --- a/src/sundials/sundials_adaptcontroller.c +++ b/src/sundials/sundials_adaptcontroller.c @@ -18,6 +18,7 @@ #include #include +#include #include "sundials/sundials_errors.h" @@ -131,6 +132,9 @@ SUNErrCode SUNAdaptController_EstimateStep(SUNAdaptController C, sunrealtype h, SUNErrCode ier = SUN_SUCCESS; if (C == NULL) { return SUN_ERR_ARG_CORRUPT; } SUNFunctionBegin(C->sunctx); + SUNAssert(isfinite(h), SUN_ERR_ARG_OUTOFRANGE); + SUNAssert(p > 0, SUN_ERR_ARG_OUTOFRANGE); + SUNAssert(dsm >= SUN_RCONST(0.0), SUN_ERR_ARG_OUTOFRANGE); SUNAssert(hnew, SUN_ERR_ARG_CORRUPT); *hnew = h; /* initialize output with identity */ if (C->ops->estimatestep) { ier = C->ops->estimatestep(C, h, p, dsm, hnew); } @@ -170,6 +174,7 @@ SUNErrCode SUNAdaptController_SetErrorBias(SUNAdaptController C, sunrealtype bia SUNErrCode ier = SUN_SUCCESS; if (C == NULL) { return SUN_ERR_ARG_CORRUPT; } SUNFunctionBegin(C->sunctx); + SUNAssert(bias >= SUN_RCONST(1.0), SUN_ERR_ARG_OUTOFRANGE); if (C->ops->seterrorbias) { ier = C->ops->seterrorbias(C, bias); } return (ier); } @@ -180,6 +185,8 @@ SUNErrCode SUNAdaptController_UpdateH(SUNAdaptController C, sunrealtype h, SUNErrCode ier = SUN_SUCCESS; if (C == NULL) { return SUN_ERR_ARG_CORRUPT; } SUNFunctionBegin(C->sunctx); + SUNAssert(isfinite(h), SUN_ERR_ARG_OUTOFRANGE); + SUNAssert(dsm >= SUN_RCONST(0.0), SUN_ERR_ARG_OUTOFRANGE); if (C->ops->updateh) { ier = C->ops->updateh(C, h, dsm); } return (ier); } From a1eb43c7aede70317eb11f295c351c3d4052a8d1 Mon Sep 17 00:00:00 2001 From: "Daniel R. Reynolds" Date: Wed, 18 Sep 2024 15:28:48 -0500 Subject: [PATCH 33/39] Added constructors for additional 'recommended' controllers from Sylvia's tests --- CHANGELOG.md | 2 + doc/shared/RecentChanges.rst | 1 + .../SUNAdaptController_Soderlind.rst | 66 +++++++++++++++++-- examples/arkode/CXX_serial/ark_heat2D.cpp | 20 ++++-- .../sunadaptcontroller_soderlind.h | 10 +++ .../fsunadaptcontroller_soderlind_mod.c | 36 ++++++++++ .../fsunadaptcontroller_soderlind_mod.f90 | 66 +++++++++++++++++++ .../fsunadaptcontroller_soderlind_mod.c | 36 ++++++++++ .../fsunadaptcontroller_soderlind_mod.f90 | 66 +++++++++++++++++++ .../soderlind/sunadaptcontroller_soderlind.c | 62 ++++++++++++++++- 10 files changed, 351 insertions(+), 14 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 61d78f9770..97b5a09c70 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -25,6 +25,8 @@ Improved the efficiency of default ARKODE methods with the following changes: | 4th Order ARK | `ARKODE_ARK436L2SA_ERK_6_3_4` and `ARKODE_ARK436L2SA_DIRK_6_3_4` | `ARKODE_ARK437L2SA_ERK_7_3_4` and `ARKODE_ARK437L2SA_DIRK_7_3_4` | | 5th Order ARK | `ARKODE_ARK548L2SA_ERK_8_4_5` and `ARKODE_ARK548L2SA_DIRK_8_4_5` | `ARKODE_ARK548L2SAb_ERK_8_4_5` and `ARKODE_ARK548L2SAb_DIRK_8_4_5` | +Added new temporal adaptivity controller utility constructors, `SUNAdaptController_H0211`, `SUNAdaptController_H211`, and `SUNAdaptController_H312`. + The default value of `CMAKE_CUDA_ARCHITECTURES` is no longer set to `70` and is now determined automatically by CMake. The previous default was only valid for Volta GPUs while the automatically selected value will vary across compilers and diff --git a/doc/shared/RecentChanges.rst b/doc/shared/RecentChanges.rst index e1865cb285..4d35af4170 100644 --- a/doc/shared/RecentChanges.rst +++ b/doc/shared/RecentChanges.rst @@ -35,6 +35,7 @@ Improved the efficiency of default ARKODE methods with the following changes: | | ``ARKODE_ARK548L2SA_DIRK_8_4_5`` | ``ARKODE_ARK548L2SAb_DIRK_8_4_5`` | +--------------------+-------------------------------------+--------------------------------------+ +Added new temporal adaptivity controller utility constructors, :c:func:`SUNAdaptController_H0211`, :c:func:`SUNAdaptController_H211`, and :c:func:`SUNAdaptController_H312`. The default value of :cmakeop:`CMAKE_CUDA_ARCHITECTURES` is no longer set to ``70`` and is now determined automatically by CMake. The previous default was diff --git a/doc/shared/sunadaptcontroller/SUNAdaptController_Soderlind.rst b/doc/shared/sunadaptcontroller/SUNAdaptController_Soderlind.rst index 830a7f2d17..4dfb6fc010 100644 --- a/doc/shared/sunadaptcontroller/SUNAdaptController_Soderlind.rst +++ b/doc/shared/sunadaptcontroller/SUNAdaptController_Soderlind.rst @@ -27,7 +27,9 @@ and :cite:p:`Sod:06`. This controller has the form with default parameter values :math:`k_1 = 1.25`, :math:`k_2 = 0.5`, :math:`k_3 = -0.75`, :math:`k_4 = 0.25`, and :math:`k_5 = 0.75`, where -:math:`p` is the global order of the time integration method. During the first +:math:`p` is the global order of the time integration method. We note that +this combination of parameters corresponds with the :math:`H_{0}321` +controller described in :cite:p:`Sod:03`. During the first two steps (when :math:`\varepsilon_{n-2}`, :math:`\varepsilon_{n-1}`, :math:`h_{n-2}`, and :math:`h_{n-2}` may be unavailable), the I controller :math:`h' = h_n \varepsilon_1^{-1/(p+1)}` is used. @@ -71,11 +73,11 @@ The header file to be included when using this module is ``sunadaptcontroller/sunadaptcontroller_soderlind.h``. We note that through appropriate selection of the parameters :math:`k_*`, -this controller may create a wide range of proposed temporal adaptivity controllers, -including the PID, PI, I, as well as Gustafsson's explicit and implicit controllers, -:cite:p:`Gust:91` and :cite:p:`Gust:94`. As a convenience, utility routines to -create these controllers and set their parameters (as special cases of the -SUNAdaptController_Soderlind) are provided. +this controller may create a wide range of proposed temporal adaptivity +controllers, including the :math:`H_{0}321`, I, PI, PID, as well as Gustafsson's +explicit and implicit controllers, :cite:p:`Gust:91` and :cite:p:`Gust:94`, +among others. As a convenience, utility routines to create a variety of these +controllers and set their parameters (as special cases of SUNAdaptController_Soderlind) are provided. The SUNAdaptController_Soderlind class provides implementations of all operations relevant to a ``SUN_ADAPTCONTROLLER_H`` controller listed in @@ -312,3 +314,55 @@ also provides the following additional user-callable routines: .. code-block:: c retval = SUNAdaptController_SetParams_ImpGus(C, 0.98, 0.95); + +.. c:function:: SUNAdaptController SUNAdaptController_H0211(SUNContext sunctx) + + This constructor creates and allocates memory for a + SUNAdaptController_Soderlind object, set up to replicate the :math:`H_{0}211` + controller from :cite:p:`Sod:03`, corresponding with the parameters :math:`k_1=0.5`, + :math:`k_2=0.5`, :math:`k_4=-0.5`, and :math:`k_3=k_5=0`. + + :param sunctx: the current :c:type:`SUNContext` object. + :return: if successful, a usable :c:type:`SUNAdaptController` object; + otherwise it will return ``NULL``. + + Usage: + + .. code-block:: c + + SUNAdaptController C = SUNAdaptController_H0211(sunctx); + +.. c:function:: SUNAdaptController SUNAdaptController_H211(SUNContext sunctx) + + This constructor creates and allocates memory for a + SUNAdaptController_Soderlind object, set up to replicate the :math:`H211` + controller from :cite:p:`Sod:03`, corresponding with the parameters :math:`k_1=0.25`, + :math:`k_2=0.25`, :math:`k_4=-0.25`, and :math:`k_3=k_5=0`. + + :param sunctx: the current :c:type:`SUNContext` object. + :return: if successful, a usable :c:type:`SUNAdaptController` object; + otherwise it will return ``NULL``. + + Usage: + + .. code-block:: c + + SUNAdaptController C = SUNAdaptController_H211(sunctx); + +.. c:function:: SUNAdaptController SUNAdaptController_H312(SUNContext sunctx) + + This constructor creates and allocates memory for a + SUNAdaptController_Soderlind object, set up to replicate the :math:`H312` + controller from :cite:p:`Sod:03`, corresponding with the parameters :math:`k_1=0.125`, + :math:`k_2=0.25`, :math:`k_3=0.125`, :math:`k_4=-0.375`, and :math:`k_5=-0.125`. + + :param sunctx: the current :c:type:`SUNContext` object. + :return: if successful, a usable :c:type:`SUNAdaptController` object; + otherwise it will return ``NULL``. + + Usage: + + .. code-block:: c + + SUNAdaptController C = SUNAdaptController_H312(sunctx); + diff --git a/examples/arkode/CXX_serial/ark_heat2D.cpp b/examples/arkode/CXX_serial/ark_heat2D.cpp index 3298eac1f9..d25b137f87 100644 --- a/examples/arkode/CXX_serial/ark_heat2D.cpp +++ b/examples/arkode/CXX_serial/ark_heat2D.cpp @@ -106,7 +106,9 @@ struct UserData sunrealtype atol; // absolute tolerance sunrealtype hfixed; // fixed step size int order; // ARKode method order - int controller; // step size adaptivity method + int controller; // step size adaptivity method: 0=PID, 1=PI, + // 2=I, 3=ExpGus, 4=ImpGus, 5=ImExGus, + // 6=H0321, 7=H0211, 8=H211, 9=H312 int maxsteps; // max number of steps between outputs bool linear; // enable/disable linearly implicit option bool diagnostics; // output diagnostics @@ -360,12 +362,16 @@ int main(int argc, char* argv[]) { switch (udata->controller) { - case (ARK_ADAPT_PID): C = SUNAdaptController_PID(ctx); break; - case (ARK_ADAPT_PI): C = SUNAdaptController_PI(ctx); break; - case (ARK_ADAPT_I): C = SUNAdaptController_I(ctx); break; - case (ARK_ADAPT_EXP_GUS): C = SUNAdaptController_ExpGus(ctx); break; - case (ARK_ADAPT_IMP_GUS): C = SUNAdaptController_ImpGus(ctx); break; - case (ARK_ADAPT_IMEX_GUS): C = SUNAdaptController_ImExGus(ctx); break; + case (0): C = SUNAdaptController_PID(ctx); break; + case (1): C = SUNAdaptController_PI(ctx); break; + case (2): C = SUNAdaptController_I(ctx); break; + case (3): C = SUNAdaptController_ExpGus(ctx); break; + case (4): C = SUNAdaptController_ImpGus(ctx); break; + case (5): C = SUNAdaptController_ImExGus(ctx); break; + case (6): C = SUNAdaptController_Soderlind(ctx); break; + case (7): C = SUNAdaptController_H0211(ctx); break; + case (8): C = SUNAdaptController_H211(ctx); break; + case (9): C = SUNAdaptController_H312(ctx); break; } flag = ARKodeSetAdaptController(arkode_mem, C); if (check_flag(&flag, "ARKodeSetAdaptController", 1)) { return 1; } diff --git a/include/sunadaptcontroller/sunadaptcontroller_soderlind.h b/include/sunadaptcontroller/sunadaptcontroller_soderlind.h index 898e8be117..d71c902b11 100644 --- a/include/sunadaptcontroller/sunadaptcontroller_soderlind.h +++ b/include/sunadaptcontroller/sunadaptcontroller_soderlind.h @@ -125,6 +125,16 @@ SUNDIALS_EXPORT SUNErrCode SUNAdaptController_SetParams_ImpGus(SUNAdaptController C, sunrealtype k1, sunrealtype k2); +SUNDIALS_EXPORT +SUNAdaptController SUNAdaptController_H0211(SUNContext sunctx); + +SUNDIALS_EXPORT +SUNAdaptController SUNAdaptController_H211(SUNContext sunctx); + +SUNDIALS_EXPORT +SUNAdaptController SUNAdaptController_H312(SUNContext sunctx); + + #ifdef __cplusplus } #endif diff --git a/src/sunadaptcontroller/soderlind/fmod_int32/fsunadaptcontroller_soderlind_mod.c b/src/sunadaptcontroller/soderlind/fmod_int32/fsunadaptcontroller_soderlind_mod.c index f3da8c259b..84fee7b214 100644 --- a/src/sunadaptcontroller/soderlind/fmod_int32/fsunadaptcontroller_soderlind_mod.c +++ b/src/sunadaptcontroller/soderlind/fmod_int32/fsunadaptcontroller_soderlind_mod.c @@ -498,4 +498,40 @@ SWIGEXPORT int _wrap_FSUNAdaptController_SetParams_ImpGus(SUNAdaptController far } +SWIGEXPORT SUNAdaptController _wrap_FSUNAdaptController_H0211(void *farg1) { + SUNAdaptController fresult ; + SUNContext arg1 = (SUNContext) 0 ; + SUNAdaptController result; + + arg1 = (SUNContext)(farg1); + result = (SUNAdaptController)SUNAdaptController_H0211(arg1); + fresult = result; + return fresult; +} + + +SWIGEXPORT SUNAdaptController _wrap_FSUNAdaptController_H211(void *farg1) { + SUNAdaptController fresult ; + SUNContext arg1 = (SUNContext) 0 ; + SUNAdaptController result; + + arg1 = (SUNContext)(farg1); + result = (SUNAdaptController)SUNAdaptController_H211(arg1); + fresult = result; + return fresult; +} + + +SWIGEXPORT SUNAdaptController _wrap_FSUNAdaptController_H312(void *farg1) { + SUNAdaptController fresult ; + SUNContext arg1 = (SUNContext) 0 ; + SUNAdaptController result; + + arg1 = (SUNContext)(farg1); + result = (SUNAdaptController)SUNAdaptController_H312(arg1); + fresult = result; + return fresult; +} + + diff --git a/src/sunadaptcontroller/soderlind/fmod_int32/fsunadaptcontroller_soderlind_mod.f90 b/src/sunadaptcontroller/soderlind/fmod_int32/fsunadaptcontroller_soderlind_mod.f90 index cd6bc5262a..1f1d5a4b85 100644 --- a/src/sunadaptcontroller/soderlind/fmod_int32/fsunadaptcontroller_soderlind_mod.f90 +++ b/src/sunadaptcontroller/soderlind/fmod_int32/fsunadaptcontroller_soderlind_mod.f90 @@ -45,6 +45,9 @@ module fsunadaptcontroller_soderlind_mod public :: FSUNAdaptController_SetParams_ExpGus public :: FSUNAdaptController_ImpGus public :: FSUNAdaptController_SetParams_ImpGus + public :: FSUNAdaptController_H0211 + public :: FSUNAdaptController_H211 + public :: FSUNAdaptController_H312 ! WRAPPER DECLARATIONS interface @@ -233,6 +236,30 @@ function swigc_FSUNAdaptController_SetParams_ImpGus(farg1, farg2, farg3) & integer(C_INT) :: fresult end function +function swigc_FSUNAdaptController_H0211(farg1) & +bind(C, name="_wrap_FSUNAdaptController_H0211") & +result(fresult) +use, intrinsic :: ISO_C_BINDING +type(C_PTR), value :: farg1 +type(C_PTR) :: fresult +end function + +function swigc_FSUNAdaptController_H211(farg1) & +bind(C, name="_wrap_FSUNAdaptController_H211") & +result(fresult) +use, intrinsic :: ISO_C_BINDING +type(C_PTR), value :: farg1 +type(C_PTR) :: fresult +end function + +function swigc_FSUNAdaptController_H312(farg1) & +bind(C, name="_wrap_FSUNAdaptController_H312") & +result(fresult) +use, intrinsic :: ISO_C_BINDING +type(C_PTR), value :: farg1 +type(C_PTR) :: fresult +end function + end interface @@ -573,5 +600,44 @@ function FSUNAdaptController_SetParams_ImpGus(c, k1, k2) & swig_result = fresult end function +function FSUNAdaptController_H0211(sunctx) & +result(swig_result) +use, intrinsic :: ISO_C_BINDING +type(SUNAdaptController), pointer :: swig_result +type(C_PTR) :: sunctx +type(C_PTR) :: fresult +type(C_PTR) :: farg1 + +farg1 = sunctx +fresult = swigc_FSUNAdaptController_H0211(farg1) +call c_f_pointer(fresult, swig_result) +end function + +function FSUNAdaptController_H211(sunctx) & +result(swig_result) +use, intrinsic :: ISO_C_BINDING +type(SUNAdaptController), pointer :: swig_result +type(C_PTR) :: sunctx +type(C_PTR) :: fresult +type(C_PTR) :: farg1 + +farg1 = sunctx +fresult = swigc_FSUNAdaptController_H211(farg1) +call c_f_pointer(fresult, swig_result) +end function + +function FSUNAdaptController_H312(sunctx) & +result(swig_result) +use, intrinsic :: ISO_C_BINDING +type(SUNAdaptController), pointer :: swig_result +type(C_PTR) :: sunctx +type(C_PTR) :: fresult +type(C_PTR) :: farg1 + +farg1 = sunctx +fresult = swigc_FSUNAdaptController_H312(farg1) +call c_f_pointer(fresult, swig_result) +end function + end module diff --git a/src/sunadaptcontroller/soderlind/fmod_int64/fsunadaptcontroller_soderlind_mod.c b/src/sunadaptcontroller/soderlind/fmod_int64/fsunadaptcontroller_soderlind_mod.c index f3da8c259b..84fee7b214 100644 --- a/src/sunadaptcontroller/soderlind/fmod_int64/fsunadaptcontroller_soderlind_mod.c +++ b/src/sunadaptcontroller/soderlind/fmod_int64/fsunadaptcontroller_soderlind_mod.c @@ -498,4 +498,40 @@ SWIGEXPORT int _wrap_FSUNAdaptController_SetParams_ImpGus(SUNAdaptController far } +SWIGEXPORT SUNAdaptController _wrap_FSUNAdaptController_H0211(void *farg1) { + SUNAdaptController fresult ; + SUNContext arg1 = (SUNContext) 0 ; + SUNAdaptController result; + + arg1 = (SUNContext)(farg1); + result = (SUNAdaptController)SUNAdaptController_H0211(arg1); + fresult = result; + return fresult; +} + + +SWIGEXPORT SUNAdaptController _wrap_FSUNAdaptController_H211(void *farg1) { + SUNAdaptController fresult ; + SUNContext arg1 = (SUNContext) 0 ; + SUNAdaptController result; + + arg1 = (SUNContext)(farg1); + result = (SUNAdaptController)SUNAdaptController_H211(arg1); + fresult = result; + return fresult; +} + + +SWIGEXPORT SUNAdaptController _wrap_FSUNAdaptController_H312(void *farg1) { + SUNAdaptController fresult ; + SUNContext arg1 = (SUNContext) 0 ; + SUNAdaptController result; + + arg1 = (SUNContext)(farg1); + result = (SUNAdaptController)SUNAdaptController_H312(arg1); + fresult = result; + return fresult; +} + + diff --git a/src/sunadaptcontroller/soderlind/fmod_int64/fsunadaptcontroller_soderlind_mod.f90 b/src/sunadaptcontroller/soderlind/fmod_int64/fsunadaptcontroller_soderlind_mod.f90 index cd6bc5262a..1f1d5a4b85 100644 --- a/src/sunadaptcontroller/soderlind/fmod_int64/fsunadaptcontroller_soderlind_mod.f90 +++ b/src/sunadaptcontroller/soderlind/fmod_int64/fsunadaptcontroller_soderlind_mod.f90 @@ -45,6 +45,9 @@ module fsunadaptcontroller_soderlind_mod public :: FSUNAdaptController_SetParams_ExpGus public :: FSUNAdaptController_ImpGus public :: FSUNAdaptController_SetParams_ImpGus + public :: FSUNAdaptController_H0211 + public :: FSUNAdaptController_H211 + public :: FSUNAdaptController_H312 ! WRAPPER DECLARATIONS interface @@ -233,6 +236,30 @@ function swigc_FSUNAdaptController_SetParams_ImpGus(farg1, farg2, farg3) & integer(C_INT) :: fresult end function +function swigc_FSUNAdaptController_H0211(farg1) & +bind(C, name="_wrap_FSUNAdaptController_H0211") & +result(fresult) +use, intrinsic :: ISO_C_BINDING +type(C_PTR), value :: farg1 +type(C_PTR) :: fresult +end function + +function swigc_FSUNAdaptController_H211(farg1) & +bind(C, name="_wrap_FSUNAdaptController_H211") & +result(fresult) +use, intrinsic :: ISO_C_BINDING +type(C_PTR), value :: farg1 +type(C_PTR) :: fresult +end function + +function swigc_FSUNAdaptController_H312(farg1) & +bind(C, name="_wrap_FSUNAdaptController_H312") & +result(fresult) +use, intrinsic :: ISO_C_BINDING +type(C_PTR), value :: farg1 +type(C_PTR) :: fresult +end function + end interface @@ -573,5 +600,44 @@ function FSUNAdaptController_SetParams_ImpGus(c, k1, k2) & swig_result = fresult end function +function FSUNAdaptController_H0211(sunctx) & +result(swig_result) +use, intrinsic :: ISO_C_BINDING +type(SUNAdaptController), pointer :: swig_result +type(C_PTR) :: sunctx +type(C_PTR) :: fresult +type(C_PTR) :: farg1 + +farg1 = sunctx +fresult = swigc_FSUNAdaptController_H0211(farg1) +call c_f_pointer(fresult, swig_result) +end function + +function FSUNAdaptController_H211(sunctx) & +result(swig_result) +use, intrinsic :: ISO_C_BINDING +type(SUNAdaptController), pointer :: swig_result +type(C_PTR) :: sunctx +type(C_PTR) :: fresult +type(C_PTR) :: farg1 + +farg1 = sunctx +fresult = swigc_FSUNAdaptController_H211(farg1) +call c_f_pointer(fresult, swig_result) +end function + +function FSUNAdaptController_H312(sunctx) & +result(swig_result) +use, intrinsic :: ISO_C_BINDING +type(SUNAdaptController), pointer :: swig_result +type(C_PTR) :: sunctx +type(C_PTR) :: fresult +type(C_PTR) :: farg1 + +farg1 = sunctx +fresult = swigc_FSUNAdaptController_H312(farg1) +call c_f_pointer(fresult, swig_result) +end function + end module diff --git a/src/sunadaptcontroller/soderlind/sunadaptcontroller_soderlind.c b/src/sunadaptcontroller/soderlind/sunadaptcontroller_soderlind.c index abdfeebc15..b94965145d 100644 --- a/src/sunadaptcontroller/soderlind/sunadaptcontroller_soderlind.c +++ b/src/sunadaptcontroller/soderlind/sunadaptcontroller_soderlind.c @@ -68,7 +68,7 @@ * ----------------------------------------------------------------- */ /* ----------------------------------------------------------------- - * Function to create a new Soderlind controller + * Function to create a new Soderlind controller (a.k.a., H_{0}321) */ SUNAdaptController SUNAdaptController_Soderlind(SUNContext sunctx) @@ -283,6 +283,66 @@ SUNErrCode SUNAdaptController_SetParams_ImpGus(SUNAdaptController C, return SUN_SUCCESS; } +/* ----------------------------------------------------------------- + * Function to create an H_{0}211 controller (subset of Soderlind) + */ + +SUNAdaptController SUNAdaptController_H0211(SUNContext sunctx) +{ + SUNFunctionBegin(sunctx); + + SUNAdaptController C = SUNAdaptController_Soderlind(sunctx); + SUNCheckLastErrNull(); + + SODERLIND_K1(C) = SUN_RCONST(0.5); + SODERLIND_K2(C) = SUN_RCONST(0.5); + SODERLIND_K3(C) = SUN_RCONST(0.0); + SODERLIND_K4(C) = -SUN_RCONST(0.5); + SODERLIND_K5(C) = SUN_RCONST(0.0); + + return (C); +} + +/* ----------------------------------------------------------------- + * Function to create an H211 controller (subset of Soderlind) + */ + +SUNAdaptController SUNAdaptController_H211(SUNContext sunctx) +{ + SUNFunctionBegin(sunctx); + + SUNAdaptController C = SUNAdaptController_Soderlind(sunctx); + SUNCheckLastErrNull(); + + SODERLIND_K1(C) = SUN_RCONST(0.25); + SODERLIND_K2(C) = SUN_RCONST(0.25); + SODERLIND_K3(C) = SUN_RCONST(0.0); + SODERLIND_K4(C) = -SUN_RCONST(0.25); + SODERLIND_K5(C) = SUN_RCONST(0.0); + + return (C); +} + +/* ----------------------------------------------------------------- + * Function to create an H312 controller (subset of Soderlind) + */ + +SUNAdaptController SUNAdaptController_H312(SUNContext sunctx) +{ + SUNFunctionBegin(sunctx); + + SUNAdaptController C = SUNAdaptController_Soderlind(sunctx); + SUNCheckLastErrNull(); + + SODERLIND_K1(C) = SUN_RCONST(1.0) / SUN_RCONST(8.0); + SODERLIND_K2(C) = SUN_RCONST(0.25); + SODERLIND_K3(C) = SUN_RCONST(1.0) / SUN_RCONST(8.0); + SODERLIND_K4(C) = -SUN_RCONST(3.0) / SUN_RCONST(8.0); + SODERLIND_K5(C) = -SUN_RCONST(1.0) / SUN_RCONST(8.0); + + return (C); +} + /* ----------------------------------------------------------------- * implementation of controller operations * ----------------------------------------------------------------- */ From afea9c073922d2b8c14c56676cac65eec02bca70 Mon Sep 17 00:00:00 2001 From: "Daniel R. Reynolds" Date: Wed, 18 Sep 2024 16:32:22 -0500 Subject: [PATCH 34/39] Spelling fix --- src/arkode/arkode_arkstep_io.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/arkode/arkode_arkstep_io.c b/src/arkode/arkode_arkstep_io.c index be0c016f3b..b75e81848d 100644 --- a/src/arkode/arkode_arkstep_io.c +++ b/src/arkode/arkode_arkstep_io.c @@ -1507,7 +1507,7 @@ int ARKStepSetDefaults(void* arkode_mem) int ARKStepSetOptimalParams(void* arkode_mem) { - /* TODO: do we need to do something here? This is depricated with no + /* TODO: do we need to do something here? This is deprecated with no * ARKodeSetOptimalParams to replace it */ ARKodeMem ark_mem; ARKodeARKStepMem step_mem; From 7fe8654bbededebf99cc3349b914169a227570d2 Mon Sep 17 00:00:00 2001 From: "Daniel R. Reynolds" Date: Wed, 18 Sep 2024 16:36:04 -0500 Subject: [PATCH 35/39] Formatting --- examples/arkode/CXX_serial/ark_heat2D.cpp | 4 ++-- include/sunadaptcontroller/sunadaptcontroller_soderlind.h | 1 - src/arkode/arkode_adapt_impl.h | 2 +- src/sundials/sundials_adaptcontroller.c | 2 +- 4 files changed, 4 insertions(+), 5 deletions(-) diff --git a/examples/arkode/CXX_serial/ark_heat2D.cpp b/examples/arkode/CXX_serial/ark_heat2D.cpp index d25b137f87..9c54427699 100644 --- a/examples/arkode/CXX_serial/ark_heat2D.cpp +++ b/examples/arkode/CXX_serial/ark_heat2D.cpp @@ -106,8 +106,8 @@ struct UserData sunrealtype atol; // absolute tolerance sunrealtype hfixed; // fixed step size int order; // ARKode method order - int controller; // step size adaptivity method: 0=PID, 1=PI, - // 2=I, 3=ExpGus, 4=ImpGus, 5=ImExGus, + int controller; // step size adaptivity method: 0=PID, 1=PI, + // 2=I, 3=ExpGus, 4=ImpGus, 5=ImExGus, // 6=H0321, 7=H0211, 8=H211, 9=H312 int maxsteps; // max number of steps between outputs bool linear; // enable/disable linearly implicit option diff --git a/include/sunadaptcontroller/sunadaptcontroller_soderlind.h b/include/sunadaptcontroller/sunadaptcontroller_soderlind.h index d71c902b11..031b852ddc 100644 --- a/include/sunadaptcontroller/sunadaptcontroller_soderlind.h +++ b/include/sunadaptcontroller/sunadaptcontroller_soderlind.h @@ -134,7 +134,6 @@ SUNAdaptController SUNAdaptController_H211(SUNContext sunctx); SUNDIALS_EXPORT SUNAdaptController SUNAdaptController_H312(SUNContext sunctx); - #ifdef __cplusplus } #endif diff --git a/src/arkode/arkode_adapt_impl.h b/src/arkode/arkode_adapt_impl.h index 4bb41deaff..844f4ab4c5 100644 --- a/src/arkode/arkode_adapt_impl.h +++ b/src/arkode/arkode_adapt_impl.h @@ -38,7 +38,7 @@ extern "C" { /* Time step controller default values */ #define CFLFAC SUN_RCONST(0.5) -#define SAFETY SUN_RCONST(0.9) /* CVODE uses 1.0 */ +#define SAFETY SUN_RCONST(0.9) /* CVODE uses 1.0 */ #define GROWTH SUN_RCONST(20.0) /* CVODE uses 10.0 */ #define HFIXED_LB SUN_RCONST(1.0) /* CVODE uses 1.0 */ #define HFIXED_UB SUN_RCONST(1.0) /* CVODE uses 1.5 */ diff --git a/src/sundials/sundials_adaptcontroller.c b/src/sundials/sundials_adaptcontroller.c index 925d3fae50..43430bd363 100644 --- a/src/sundials/sundials_adaptcontroller.c +++ b/src/sundials/sundials_adaptcontroller.c @@ -16,9 +16,9 @@ * operations listed in sundials_adaptcontroller.h * -----------------------------------------------------------------*/ +#include #include #include -#include #include "sundials/sundials_errors.h" From cc26cf245786f1e2c1a1e8a34cb5bd4c764087c9 Mon Sep 17 00:00:00 2001 From: "Daniel R. Reynolds" Date: Fri, 20 Sep 2024 14:09:07 -0500 Subject: [PATCH 36/39] Fixed typo --- .../SUNAdaptController_Soderlind.rst | 33 +++++++++---------- 1 file changed, 16 insertions(+), 17 deletions(-) diff --git a/doc/shared/sunadaptcontroller/SUNAdaptController_Soderlind.rst b/doc/shared/sunadaptcontroller/SUNAdaptController_Soderlind.rst index 4dfb6fc010..e714363fe8 100644 --- a/doc/shared/sunadaptcontroller/SUNAdaptController_Soderlind.rst +++ b/doc/shared/sunadaptcontroller/SUNAdaptController_Soderlind.rst @@ -27,12 +27,12 @@ and :cite:p:`Sod:06`. This controller has the form with default parameter values :math:`k_1 = 1.25`, :math:`k_2 = 0.5`, :math:`k_3 = -0.75`, :math:`k_4 = 0.25`, and :math:`k_5 = 0.75`, where -:math:`p` is the global order of the time integration method. We note that -this combination of parameters corresponds with the :math:`H_{0}321` +:math:`p` is the global order of the time integration method. We note that +this combination of parameters corresponds with the :math:`H_{0}321` controller described in :cite:p:`Sod:03`. During the first two steps (when :math:`\varepsilon_{n-2}`, :math:`\varepsilon_{n-1}`, :math:`h_{n-2}`, and :math:`h_{n-2}` may be unavailable), the I controller -:math:`h' = h_n \varepsilon_1^{-1/(p+1)}` is used. +:math:`h' = h_n \varepsilon_n^{-1/(p+1)}` is used. The SUNAdaptController_Soderlind controller is implemented as a derived SUNAdaptController class, and defines its *content* field as: @@ -73,10 +73,10 @@ The header file to be included when using this module is ``sunadaptcontroller/sunadaptcontroller_soderlind.h``. We note that through appropriate selection of the parameters :math:`k_*`, -this controller may create a wide range of proposed temporal adaptivity +this controller may create a wide range of proposed temporal adaptivity controllers, including the :math:`H_{0}321`, I, PI, PID, as well as Gustafsson's -explicit and implicit controllers, :cite:p:`Gust:91` and :cite:p:`Gust:94`, -among others. As a convenience, utility routines to create a variety of these +explicit and implicit controllers, :cite:p:`Gust:91` and :cite:p:`Gust:94`, +among others. As a convenience, utility routines to create a variety of these controllers and set their parameters (as special cases of SUNAdaptController_Soderlind) are provided. The SUNAdaptController_Soderlind class provides implementations of all operations @@ -244,7 +244,7 @@ also provides the following additional user-callable routines: .. c:function:: SUNErrCode SUNAdaptController_SetParams_ExpGus(SUNAdaptController C, sunrealtype k1_hat, sunrealtype k2_hat) This user-callable function provides control over the relevant parameters - above for the explicit Gustafsson controller, setting :math:`k_3 = k_4 = k_5 = 0`. + above for the explicit Gustafsson controller, setting :math:`k_3 = k_4 = k_5 = 0`. This should be called *before* the time integrator is called to evolve the problem. .. note:: @@ -317,9 +317,9 @@ also provides the following additional user-callable routines: .. c:function:: SUNAdaptController SUNAdaptController_H0211(SUNContext sunctx) - This constructor creates and allocates memory for a - SUNAdaptController_Soderlind object, set up to replicate the :math:`H_{0}211` - controller from :cite:p:`Sod:03`, corresponding with the parameters :math:`k_1=0.5`, + This constructor creates and allocates memory for a + SUNAdaptController_Soderlind object, set up to replicate the :math:`H_{0}211` + controller from :cite:p:`Sod:03`, corresponding with the parameters :math:`k_1=0.5`, :math:`k_2=0.5`, :math:`k_4=-0.5`, and :math:`k_3=k_5=0`. :param sunctx: the current :c:type:`SUNContext` object. @@ -334,9 +334,9 @@ also provides the following additional user-callable routines: .. c:function:: SUNAdaptController SUNAdaptController_H211(SUNContext sunctx) - This constructor creates and allocates memory for a - SUNAdaptController_Soderlind object, set up to replicate the :math:`H211` - controller from :cite:p:`Sod:03`, corresponding with the parameters :math:`k_1=0.25`, + This constructor creates and allocates memory for a + SUNAdaptController_Soderlind object, set up to replicate the :math:`H211` + controller from :cite:p:`Sod:03`, corresponding with the parameters :math:`k_1=0.25`, :math:`k_2=0.25`, :math:`k_4=-0.25`, and :math:`k_3=k_5=0`. :param sunctx: the current :c:type:`SUNContext` object. @@ -351,9 +351,9 @@ also provides the following additional user-callable routines: .. c:function:: SUNAdaptController SUNAdaptController_H312(SUNContext sunctx) - This constructor creates and allocates memory for a - SUNAdaptController_Soderlind object, set up to replicate the :math:`H312` - controller from :cite:p:`Sod:03`, corresponding with the parameters :math:`k_1=0.125`, + This constructor creates and allocates memory for a + SUNAdaptController_Soderlind object, set up to replicate the :math:`H312` + controller from :cite:p:`Sod:03`, corresponding with the parameters :math:`k_1=0.125`, :math:`k_2=0.25`, :math:`k_3=0.125`, :math:`k_4=-0.375`, and :math:`k_5=-0.125`. :param sunctx: the current :c:type:`SUNContext` object. @@ -365,4 +365,3 @@ also provides the following additional user-callable routines: .. code-block:: c SUNAdaptController C = SUNAdaptController_H312(sunctx); - From 47ceedd1c322db643f966b49a4b5a0720be9be78 Mon Sep 17 00:00:00 2001 From: "Daniel R. Reynolds" Date: Fri, 20 Sep 2024 14:09:33 -0500 Subject: [PATCH 37/39] Added FAQ on temporal adaptivity controller selection --- doc/shared/FAQ.rst | 44 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/doc/shared/FAQ.rst b/doc/shared/FAQ.rst index f81e96f3a8..64873a59bd 100644 --- a/doc/shared/FAQ.rst +++ b/doc/shared/FAQ.rst @@ -286,6 +286,50 @@ CVODE(S) / IDA(S) / ARKODE integrals (very often a large number of them) need to be computed for adjoint sensitivity. +.. collapse:: When should I select a non-default temporal adaptivity controller in ARKODE? + + The default temporal adaptivity controller in ARKODE was selected due to its robust performance on test + problems that ranged in difficulty and stiffness, and when running with a wide range of solution tolerances + and method orders. While we hope that this default runs well on most applications, it is unlikely to be + optimal. A prime indicator that an alterate adaptivity controller may be useful is if the default results + in a large number of rejected steps. Alternately, for higher-cost calculations where a reduction of 10%-20% + in the number of time steps would be important, users may want to try another controller option. + + The default temporal adaptivity controller in ARKODE is the industry-standard *I* controller: + + .. math:: + h' = h_n \varepsilon_n^{-1/(p+1)} + + where :math:`\varepsilon_n = \text{bias}*\text{dsm}_n`, and :math:`\text{dsm}_n` is the WRMS norm of the + local temporal error when using the time step :math:`h_n`, weighted by the user-requested tolerances. + However, the :ref:`SUNAdaptController class ` in SUNDIALS provides a range of more + advanced temporal error controllers that could be applied to a given application problem, including the + :math:`H_{0}321`, :math:`H_{0}211`, :math:`H211`, and :math:`H312` controllers from :cite:p:`Sod:03`, + as well as a variety of controllers (*PI*, *PID*, *ExpGus*, *ImpGus*, and *ImExGus*) that were included + in the initial ARKODE release. + + The adaptive time-stepping controllers introduced by Soderlind in :cite:p:`Sod:03` can be classified into + two groups; *deadbeat* controllers and *non-deadbeat* controllers. A controller is known as deadbeat if + the roots of its characteristic equation are located at the origin. These controllers are generalized + forms of the *I* controller, are denoted with a zero subscript as part of the controller name (e.g., + :math:`H_{0}321`), and are generally recommended for applications with smooth solutions as a function of time. + + While it is impossible to exhaustively explore the question of controller optimality for all application + problems, we have performed tests on the range of provided controllers on a variety of stiff and non-stiff + problems, at varying tolerances (:math:`10^{-9} \to 10^{-3}`), and for Runge--Kutta methods at a wide range + of orders of accuracy (ERK orders 2-9, and DIRK orders 2-5). From our experiments, stiff problems benefitted + from the *I*, *PI*, :math:`H_{0}211`, :math:`H_{0}321`, and *ImpGus* controllers. On the other hand, + non-stiff test problems ran most efficiently when using the *PID*, *I*, *ExpGus*, :math:`H211`, and + :math:`H312` controllers. + + Lastly, we note that the internal controller parameters for the legacy ARKODE controllers (*PI*, *PID*, + *ExpGus*, *ImpGus*, and *ImExGus*) were determined via numerical optimization over a given set of test + problems. As a result, although those controllers work very well for some applications, they may not + work well with others. For users who are interested in exploring novel controller methods, we point out + that the :ref:`"Soderlind" ` SUNAdaptController allows complete control + over all internal parameters via the :c:func:`SUNAdaptController_SetParams_Soderlind` function. + + KINSOL ------ From fa467103ca861b688fc7772d88e502ae69467c95 Mon Sep 17 00:00:00 2001 From: "Daniel R. Reynolds" Date: Fri, 20 Sep 2024 14:27:22 -0500 Subject: [PATCH 38/39] spelling --- doc/shared/FAQ.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/shared/FAQ.rst b/doc/shared/FAQ.rst index 64873a59bd..fdfc9184e9 100644 --- a/doc/shared/FAQ.rst +++ b/doc/shared/FAQ.rst @@ -291,7 +291,7 @@ CVODE(S) / IDA(S) / ARKODE The default temporal adaptivity controller in ARKODE was selected due to its robust performance on test problems that ranged in difficulty and stiffness, and when running with a wide range of solution tolerances and method orders. While we hope that this default runs well on most applications, it is unlikely to be - optimal. A prime indicator that an alterate adaptivity controller may be useful is if the default results + optimal. A prime indicator that an alternate adaptivity controller may be useful is if the default results in a large number of rejected steps. Alternately, for higher-cost calculations where a reduction of 10%-20% in the number of time steps would be important, users may want to try another controller option. From 27fca0a8073500d8b71b9f5b9391f233dd6e815d Mon Sep 17 00:00:00 2001 From: "Daniel R. Reynolds" Date: Wed, 16 Oct 2024 09:41:12 -0500 Subject: [PATCH 39/39] Added ARKodeSetAdaptControllerByName --- .../guide/source/Usage/User_callable.rst | 36 ++++++++- .../CXX_parallel/ark_diffusion_reaction_p.cpp | 63 +++++----------- examples/arkode/CXX_parallel/ark_heat2D_p.cpp | 39 ++++------ .../arkode/CXX_parhyp/ark_heat2D_hypre_ls.cpp | 41 ++++------ .../CXX_parhyp/ark_heat2D_hypre_pfmg.cpp | 39 ++++------ .../CXX_parhyp/ark_heat2D_hypre_pfmg_imex.cpp | 49 +++++------- .../CXX_parhyp/ark_heat2D_hypre_pfmg_mri.cpp | 34 +++------ .../ark_advection_diffusion_reaction.cpp | 67 +++++------------ .../ark_advection_diffusion_reaction.hpp | 75 ++++++------------- include/arkode/arkode.h | 2 + src/arkode/arkode_io.c | 67 +++++++++++++++++ src/arkode/fmod_int32/farkode_mod.c | 14 ++++ src/arkode/fmod_int32/farkode_mod.f90 | 72 ++++++++++++------ src/arkode/fmod_int64/farkode_mod.c | 14 ++++ src/arkode/fmod_int64/farkode_mod.f90 | 72 ++++++++++++------ 15 files changed, 357 insertions(+), 327 deletions(-) diff --git a/doc/arkode/guide/source/Usage/User_callable.rst b/doc/arkode/guide/source/Usage/User_callable.rst index fd9b572382..614859158a 100644 --- a/doc/arkode/guide/source/Usage/User_callable.rst +++ b/doc/arkode/guide/source/Usage/User_callable.rst @@ -1073,8 +1073,9 @@ Set max number of constraint failures :c:func:`ARKodeSetMaxNumConstr :c:func:`ARKodeSetMinReduction`, :c:func:`ARKodeSetSafetyFactor`, :c:func:`ARKodeSetSmallNumEFails`, - :c:func:`ARKodeSetStabilityFn`, and - :c:func:`ARKodeSetAdaptController` + :c:func:`ARKodeSetStabilityFn`, + :c:func:`ARKodeSetAdaptController`, and + :c:func:`ARKodeSetAdaptControllerByName` will be ignored, since temporal adaptivity is disabled. If both :c:func:`ARKodeSetFixedStep` and @@ -1414,7 +1415,8 @@ the code, is provided in :numref:`ARKODE.Mathematics.Adaptivity`. Optional input Function name Default ========================================================= ========================================== ======== Provide a :c:type:`SUNAdaptController` for ARKODE to use :c:func:`ARKodeSetAdaptController` PID -Adjust the method order used in the controller :c:func:`ERKStepSetAdaptivityAdjustment` -1 +Specify a :c:type:`SUNAdaptController` for ARKODE to use :c:func:`ARKodeSetAdaptControllerByName` PID +Adjust the method order used in the controller :c:func:`ARKodeSetAdaptivityAdjustment` -1 Explicit stability safety factor :c:func:`ARKodeSetCFLFraction` 0.5 Time step error bias factor :c:func:`ARKodeSetErrorBias` 1.5 Bounds determining no change in step size :c:func:`ARKodeSetFixedStepBounds` 1.0 1.5 @@ -1451,6 +1453,34 @@ Explicit stability function :c:func:`ARKodeSetSt .. versionadded:: 6.1.0 +.. c:function:: int ARKodeSetAdaptControllerByName(void* arkode_mem, const char* cname) + + Sets a user-supplied time-step controller object by name. + + :param arkode_mem: pointer to the ARKODE memory block. + :param cname: name of the time adaptivity controller to use. Allowable values + currently include ``"Soderlind"``, ``"PID"``, ``"PI"``, ``"I"``, + ``"ExpGus"``, ``"ImpGus"``, ``"H0211"``, ``"H211"``, ``"H312"``. For + information on these options, see :numref:`SUNAdaptController.Soderlind`. + + :retval ARK_SUCCESS: the function exited successfully. + :retval ARK_ILL_INPUT: *cname* did not match an allowed value. + :retval ARK_MEM_NULL: ``arkode_mem`` was ``NULL``. + :retval ARK_STEPPER_UNSUPPORTED: adaptive step sizes are not supported + by the current time-stepping module. + + .. note:: + + This is only compatible with time-stepping modules that support temporal adaptivity. + + It is not possible to adjust the internal controller parameters when using this + function. Users who wish to adjust these parameters should create and configure + the :c:type:`SUNAdaptController` object manually, and then call + :c:func:`ARKodeSetAdaptController`. + + .. versionadded:: x.y.z + + .. c:function:: int ARKodeSetAdaptivityAdjustment(void* arkode_mem, int adjust) Called by a user to adjust the method order supplied to the temporal adaptivity diff --git a/examples/arkode/CXX_parallel/ark_diffusion_reaction_p.cpp b/examples/arkode/CXX_parallel/ark_diffusion_reaction_p.cpp index 5643211620..38667880f1 100644 --- a/examples/arkode/CXX_parallel/ark_diffusion_reaction_p.cpp +++ b/examples/arkode/CXX_parallel/ark_diffusion_reaction_p.cpp @@ -63,6 +63,7 @@ #include #include #include +#include // Include MPI #include "mpi.h" @@ -282,10 +283,10 @@ struct UserData // Shared IMEX and MRI settings // ---------------------------- - int controller = 0; // step size adaptivity method (0 = use default) - int maxsteps = 0; // max steps between outputs (0 = use default) - bool linear = true; // enable/disable linearly implicit option - bool diagnostics = false; // output diagnostics + string controller = "PID"; // step size adaptivity method + int maxsteps = 0; // max steps between outputs (0 = use default) + bool linear = true; // enable/disable linearly implicit option + bool diagnostics = false; // output diagnostics // ----------------------------------------- // Nonlinear solver settings @@ -379,11 +380,10 @@ static int SetupDecomp(UserData* udata); // Integrator setup functions static int SetupARK(SUNContext ctx, UserData* udata, N_Vector u, - SUNLinearSolver LS, SUNAdaptController* Ctrl, - void** arkode_mem); + SUNLinearSolver LS, void** arkode_mem); static int SetupMRI(SUNContext ctx, UserData* udata, N_Vector u, - SUNLinearSolver LS, SUNAdaptController* Ctrl, - void** arkode_mem, MRIStepInnerStepper* stepper); + SUNLinearSolver LS, void** arkode_mem, + MRIStepInnerStepper* stepper); static int SetupMRICVODE(SUNContext ctx, UserData* udata, N_Vector u, SUNLinearSolver LS, SUNNonlinearSolver* NLS, void** arkode_mem, MRIStepInnerStepper* stepper); @@ -557,18 +557,15 @@ int main(int argc, char* argv[]) // Inner stepper nonlinear solver (CVODE) SUNNonlinearSolver NLS = NULL; - // Timestep adaptivity controller - SUNAdaptController Ctrl = NULL; - // Create integrator switch (udata.integrator) { case (0): - flag = SetupARK(ctx, &udata, u, LS, &Ctrl, &arkode_mem); + flag = SetupARK(ctx, &udata, u, LS, &arkode_mem); if (check_flag((void*)arkode_mem, "SetupARK", 0)) { return 1; } break; case (1): - flag = SetupMRI(ctx, &udata, u, LS, &Ctrl, &arkode_mem, &stepper); + flag = SetupMRI(ctx, &udata, u, LS, &arkode_mem, &stepper); if (check_flag((void*)arkode_mem, "SetupMRI", 0)) { return 1; } break; case (2): @@ -700,7 +697,6 @@ int main(int argc, char* argv[]) N_VDestroy(N_VGetLocalVector_MPIPlusX(u)); N_VDestroy(u); FreeUserData(&udata); - (void)SUNAdaptController_Destroy(Ctrl); SUNContext_Free(&ctx); flag = MPI_Finalize(); return 0; @@ -906,8 +902,7 @@ static int SetupDecomp(UserData* udata) // ----------------------------------------------------------------------------- static int SetupARK(SUNContext ctx, UserData* udata, N_Vector u, - SUNLinearSolver LS, SUNAdaptController* Ctrl, - void** arkode_mem) + SUNLinearSolver LS, void** arkode_mem) { int flag; @@ -968,17 +963,8 @@ static int SetupARK(SUNContext ctx, UserData* udata, N_Vector u, } else { - switch (udata->controller) - { - case (ARK_ADAPT_PID): *Ctrl = SUNAdaptController_PID(ctx); break; - case (ARK_ADAPT_PI): *Ctrl = SUNAdaptController_PI(ctx); break; - case (ARK_ADAPT_I): *Ctrl = SUNAdaptController_I(ctx); break; - case (ARK_ADAPT_EXP_GUS): *Ctrl = SUNAdaptController_ExpGus(ctx); break; - case (ARK_ADAPT_IMP_GUS): *Ctrl = SUNAdaptController_ImpGus(ctx); break; - case (ARK_ADAPT_IMEX_GUS): *Ctrl = SUNAdaptController_ImExGus(ctx); break; - } - flag = ARKodeSetAdaptController(*arkode_mem, *Ctrl); - if (check_flag(&flag, "ARKodeSetAdaptController", 1)) { return 1; } + flag = ARKodeSetAdaptControllerByName(*arkode_mem, udata->controller.c_str()); + if (check_flag(&flag, "ARKodeSetAdaptControllerByName", 1)) { return 1; } } // Set max steps between outputs @@ -993,8 +979,8 @@ static int SetupARK(SUNContext ctx, UserData* udata, N_Vector u, } static int SetupMRI(SUNContext ctx, UserData* udata, N_Vector y, - SUNLinearSolver LS, SUNAdaptController* Ctrl, - void** arkode_mem, MRIStepInnerStepper* stepper) + SUNLinearSolver LS, void** arkode_mem, + MRIStepInnerStepper* stepper) { int flag; @@ -1026,17 +1012,9 @@ static int SetupMRI(SUNContext ctx, UserData* udata, N_Vector y, } else { - switch (udata->controller) - { - case (ARK_ADAPT_PID): *Ctrl = SUNAdaptController_PID(ctx); break; - case (ARK_ADAPT_PI): *Ctrl = SUNAdaptController_PI(ctx); break; - case (ARK_ADAPT_I): *Ctrl = SUNAdaptController_I(ctx); break; - case (ARK_ADAPT_EXP_GUS): *Ctrl = SUNAdaptController_ExpGus(ctx); break; - case (ARK_ADAPT_IMP_GUS): *Ctrl = SUNAdaptController_ImpGus(ctx); break; - case (ARK_ADAPT_IMEX_GUS): *Ctrl = SUNAdaptController_ImExGus(ctx); break; - } - flag = ARKodeSetAdaptController(inner_arkode_mem, *Ctrl); - if (check_flag(&flag, "ARKodeSetAdaptController", 1)) { return 1; } + flag = ARKodeSetAdaptControllerByName(inner_arkode_mem, + udata->controller.c_str()); + if (check_flag(&flag, "ARKodeSetAdaptControllerByName", 1)) { return 1; } } // Set max steps between outputs @@ -2221,10 +2199,7 @@ static int ReadInputs(int* argc, char*** argv, UserData* udata) else if (arg == "--h_slow") { udata->h_slow = stod((*argv)[arg_idx++]); } else if (arg == "--h_fast") { udata->h_fast = stod((*argv)[arg_idx++]); } // Shared IMEX and MRI settings - else if (arg == "--controller") - { - udata->controller = stoi((*argv)[arg_idx++]); - } + else if (arg == "--controller") { udata->controller = (*argv)[arg_idx++]; } else if (arg == "--nonlinear") { udata->linear = false; } else if (arg == "--diagnostics") { udata->diagnostics = true; } // Linear solver settings diff --git a/examples/arkode/CXX_parallel/ark_heat2D_p.cpp b/examples/arkode/CXX_parallel/ark_heat2D_p.cpp index 0bf8d97ba7..ed1c751130 100644 --- a/examples/arkode/CXX_parallel/ark_heat2D_p.cpp +++ b/examples/arkode/CXX_parallel/ark_heat2D_p.cpp @@ -51,6 +51,7 @@ #include #include #include +#include #include "arkode/arkode_arkstep.h" // access to ARKStep #include "mpi.h" // MPI header file @@ -164,7 +165,7 @@ struct UserData sunrealtype atol; // absolute tolerance sunrealtype hfixed; // fixed step size int order; // ARKode method order - int controller; // step size adaptivity method + string controller; // step size adaptivity method int maxsteps; // max number of steps between outputs bool linear; // enable/disable linearly implicit option bool diagnostics; // output diagnostics @@ -271,12 +272,11 @@ static int check_flag(void* flagvalue, const string funcname, int opt); int main(int argc, char* argv[]) { - int flag; // reusable error-checking flag - UserData* udata = NULL; // user data structure - N_Vector u = NULL; // vector for storing solution - SUNLinearSolver LS = NULL; // linear solver memory structure - void* arkode_mem = NULL; // ARKODE memory structure - SUNAdaptController C = NULL; // timestep adaptivity controller + int flag; // reusable error-checking flag + UserData* udata = NULL; // user data structure + N_Vector u = NULL; // vector for storing solution + SUNLinearSolver LS = NULL; // linear solver memory structure + void* arkode_mem = NULL; // ARKODE memory structure // Timing variables double t1 = 0.0; @@ -450,17 +450,8 @@ int main(int argc, char* argv[]) } else { - switch (udata->controller) - { - case (ARK_ADAPT_PID): C = SUNAdaptController_PID(ctx); break; - case (ARK_ADAPT_PI): C = SUNAdaptController_PI(ctx); break; - case (ARK_ADAPT_I): C = SUNAdaptController_I(ctx); break; - case (ARK_ADAPT_EXP_GUS): C = SUNAdaptController_ExpGus(ctx); break; - case (ARK_ADAPT_IMP_GUS): C = SUNAdaptController_ImpGus(ctx); break; - case (ARK_ADAPT_IMEX_GUS): C = SUNAdaptController_ImExGus(ctx); break; - } - flag = ARKodeSetAdaptController(arkode_mem, C); - if (check_flag(&flag, "ARKodeSetAdaptController", 1)) { return 1; } + flag = ARKodeSetAdaptControllerByName(arkode_mem, udata->controller.c_str()); + if (check_flag(&flag, "ARKodeSetAdaptControllerByName", 1)) { return 1; } } // Specify linearly implicit non-time-dependent RHS @@ -565,9 +556,8 @@ int main(int argc, char* argv[]) N_VDestroy(u); // Free vectors FreeUserData(udata); // Free user data delete udata; - (void)SUNAdaptController_Destroy(C); // Free timestep adaptivity controller - SUNContext_Free(&ctx); // Free context - flag = MPI_Finalize(); // Finalize MPI + SUNContext_Free(&ctx); // Free context + flag = MPI_Finalize(); // Finalize MPI return 0; } @@ -1330,7 +1320,7 @@ static int InitUserData(UserData* udata) udata->atol = SUN_RCONST(1.e-10); // absolute tolerance udata->hfixed = ZERO; // using adaptive step sizes udata->order = 3; // method order - udata->controller = 0; // PID controller + udata->controller = "PID"; // controller udata->maxsteps = 0; // use default udata->linear = true; // linearly implicit problem udata->diagnostics = false; // output diagnostics @@ -1440,10 +1430,7 @@ static int ReadInputs(int* argc, char*** argv, UserData* udata, bool outproc) else if (arg == "--atol") { udata->atol = stod((*argv)[arg_idx++]); } else if (arg == "--fixedstep") { udata->hfixed = stod((*argv)[arg_idx++]); } else if (arg == "--order") { udata->order = stoi((*argv)[arg_idx++]); } - else if (arg == "--controller") - { - udata->controller = stoi((*argv)[arg_idx++]); - } + else if (arg == "--controller") { udata->controller = (*argv)[arg_idx++]; } else if (arg == "--nonlinear") { udata->linear = false; } else if (arg == "--diagnostics") { udata->diagnostics = true; } // Linear solver settings diff --git a/examples/arkode/CXX_parhyp/ark_heat2D_hypre_ls.cpp b/examples/arkode/CXX_parhyp/ark_heat2D_hypre_ls.cpp index 14786d9c98..d483577ee0 100644 --- a/examples/arkode/CXX_parhyp/ark_heat2D_hypre_ls.cpp +++ b/examples/arkode/CXX_parhyp/ark_heat2D_hypre_ls.cpp @@ -52,6 +52,7 @@ #include #include #include +#include #include "HYPRE_struct_ls.h" // HYPRE structured grid solver interface #include "arkode/arkode_arkstep.h" // access to ARKStep @@ -166,7 +167,7 @@ struct UserData sunrealtype atol; // absolute tolerance sunrealtype hfixed; // fixed step size int order; // ARKode method order - int controller; // step size adaptivity method + string controller; // step size adaptivity method int maxsteps; // max number of steps between outputs bool linear; // enable/disable linearly implicit option @@ -354,13 +355,12 @@ static int check_flag(void* flagvalue, const string funcname, int opt); int main(int argc, char* argv[]) { - int flag; // reusable error-checking flag - UserData* udata = NULL; // user data structure - N_Vector u = NULL; // vector for storing solution - SUNMatrix A = NULL; // matrix for Jacobian - SUNLinearSolver LS = NULL; // linear solver memory structure - void* arkode_mem = NULL; // ARKODE memory structure - SUNAdaptController C = NULL; // timestep adaptivity controlle + int flag; // reusable error-checking flag + UserData* udata = NULL; // user data structure + N_Vector u = NULL; // vector for storing solution + SUNMatrix A = NULL; // matrix for Jacobian + SUNLinearSolver LS = NULL; // linear solver memory structure + void* arkode_mem = NULL; // ARKODE memory structure // Timing variables double t1 = 0.0; @@ -489,17 +489,8 @@ int main(int argc, char* argv[]) } else { - switch (udata->controller) - { - case (ARK_ADAPT_PID): C = SUNAdaptController_PID(ctx); break; - case (ARK_ADAPT_PI): C = SUNAdaptController_PI(ctx); break; - case (ARK_ADAPT_I): C = SUNAdaptController_I(ctx); break; - case (ARK_ADAPT_EXP_GUS): C = SUNAdaptController_ExpGus(ctx); break; - case (ARK_ADAPT_IMP_GUS): C = SUNAdaptController_ImpGus(ctx); break; - case (ARK_ADAPT_IMEX_GUS): C = SUNAdaptController_ImExGus(ctx); break; - } - flag = ARKodeSetAdaptController(arkode_mem, C); - if (check_flag(&flag, "ARKodeSetAdaptController", 1)) { return 1; } + flag = ARKodeSetAdaptControllerByName(arkode_mem, udata->controller.c_str()); + if (check_flag(&flag, "ARKodeSetAdaptControllerByName", 1)) { return 1; } } // Specify linearly implicit non-time-dependent RHS @@ -612,9 +603,8 @@ int main(int argc, char* argv[]) N_VDestroy(u); // Free vectors FreeUserData(udata); // Free user data delete udata; - (void)SUNAdaptController_Destroy(C); // Free time adaptivity controller - SUNContext_Free(&ctx); // Free context - flag = MPI_Finalize(); // Finalize MPI + SUNContext_Free(&ctx); // Free context + flag = MPI_Finalize(); // Finalize MPI return 0; } @@ -1620,7 +1610,7 @@ static int InitUserData(UserData* udata) udata->atol = SUN_RCONST(1.e-10); // absolute tolerance udata->hfixed = ZERO; // using adaptive step sizes udata->order = 3; // method order - udata->controller = 0; // PID controller + udata->controller = "PID"; // controller udata->maxsteps = 0; // use default udata->linear = true; // linearly implicit problem @@ -1723,10 +1713,7 @@ static int ReadInputs(int* argc, char*** argv, UserData* udata, bool outproc) else if (arg == "--atol") { udata->atol = stod((*argv)[arg_idx++]); } else if (arg == "--fixedstep") { udata->hfixed = stod((*argv)[arg_idx++]); } else if (arg == "--order") { udata->order = stoi((*argv)[arg_idx++]); } - else if (arg == "--controller") - { - udata->controller = stoi((*argv)[arg_idx++]); - } + else if (arg == "--controller") { udata->controller = (*argv)[arg_idx++]; } else if (arg == "--nonlinear") { udata->linear = false; } // Linear solver settings else if (arg == "--gmres") { udata->pcg = false; } diff --git a/examples/arkode/CXX_parhyp/ark_heat2D_hypre_pfmg.cpp b/examples/arkode/CXX_parhyp/ark_heat2D_hypre_pfmg.cpp index d408bcdf78..fc9fa39a9e 100644 --- a/examples/arkode/CXX_parhyp/ark_heat2D_hypre_pfmg.cpp +++ b/examples/arkode/CXX_parhyp/ark_heat2D_hypre_pfmg.cpp @@ -52,6 +52,7 @@ #include #include #include +#include #include "HYPRE_struct_ls.h" // HYPRE structured grid solver interface #include "arkode/arkode_arkstep.h" // access to ARKStep @@ -166,7 +167,7 @@ struct UserData sunrealtype atol; // absolute tolerance sunrealtype hfixed; // fixed step size int order; // ARKode method order - int controller; // step size adaptivity method + string controller; // step size adaptivity method int maxsteps; // max number of steps between outputs bool linear; // enable/disable linearly implicit option @@ -312,12 +313,11 @@ static int check_flag(void* flagvalue, const string funcname, int opt); int main(int argc, char* argv[]) { - int flag; // reusable error-checking flag - UserData* udata = NULL; // user data structure - N_Vector u = NULL; // vector for storing solution - SUNLinearSolver LS = NULL; // linear solver memory structure - void* arkode_mem = NULL; // ARKODE memory structure - SUNAdaptController C = NULL; // timestep adaptivity controller + int flag; // reusable error-checking flag + UserData* udata = NULL; // user data structure + N_Vector u = NULL; // vector for storing solution + SUNLinearSolver LS = NULL; // linear solver memory structure + void* arkode_mem = NULL; // ARKODE memory structure // Timing variables double t1 = 0.0; @@ -494,17 +494,8 @@ int main(int argc, char* argv[]) } else { - switch (udata->controller) - { - case (ARK_ADAPT_PID): C = SUNAdaptController_PID(ctx); break; - case (ARK_ADAPT_PI): C = SUNAdaptController_PI(ctx); break; - case (ARK_ADAPT_I): C = SUNAdaptController_I(ctx); break; - case (ARK_ADAPT_EXP_GUS): C = SUNAdaptController_ExpGus(ctx); break; - case (ARK_ADAPT_IMP_GUS): C = SUNAdaptController_ImpGus(ctx); break; - case (ARK_ADAPT_IMEX_GUS): C = SUNAdaptController_ImExGus(ctx); break; - } - flag = ARKodeSetAdaptController(arkode_mem, C); - if (check_flag(&flag, "ARKodeSetAdaptController", 1)) { return 1; } + flag = ARKodeSetAdaptControllerByName(arkode_mem, udata->controller.c_str()); + if (check_flag(&flag, "ARKodeSetAdaptControllerByName", 1)) { return 1; } } // Specify linearly implicit non-time-dependent RHS @@ -616,9 +607,8 @@ int main(int argc, char* argv[]) N_VDestroy(u); // Free vectors FreeUserData(udata); // Free user data delete udata; - (void)SUNAdaptController_Destroy(C); // Free timestep adaptivity controller - SUNContext_Free(&ctx); // Free context - flag = MPI_Finalize(); // Finalize MPI + SUNContext_Free(&ctx); // Free context + flag = MPI_Finalize(); // Finalize MPI return 0; } @@ -2114,7 +2104,7 @@ static int InitUserData(UserData* udata) udata->atol = SUN_RCONST(1.e-10); // absolute tolerance udata->hfixed = ZERO; // using adaptive step sizes udata->order = 3; // method order - udata->controller = 0; // PID controller + udata->controller = "PID"; // PID controller udata->maxsteps = 0; // use default udata->linear = true; // linearly implicit problem @@ -2256,10 +2246,7 @@ static int ReadInputs(int* argc, char*** argv, UserData* udata, bool outproc) else if (arg == "--atol") { udata->atol = stod((*argv)[arg_idx++]); } else if (arg == "--fixedstep") { udata->hfixed = stod((*argv)[arg_idx++]); } else if (arg == "--order") { udata->order = stoi((*argv)[arg_idx++]); } - else if (arg == "--controller") - { - udata->controller = stoi((*argv)[arg_idx++]); - } + else if (arg == "--controller") { udata->controller = (*argv)[arg_idx++]; } else if (arg == "--nonlinear") { udata->linear = false; } // Linear solver settings else if (arg == "--gmres") { udata->pcg = false; } diff --git a/examples/arkode/CXX_parhyp/ark_heat2D_hypre_pfmg_imex.cpp b/examples/arkode/CXX_parhyp/ark_heat2D_hypre_pfmg_imex.cpp index ddf689ac47..29b48f6da0 100644 --- a/examples/arkode/CXX_parhyp/ark_heat2D_hypre_pfmg_imex.cpp +++ b/examples/arkode/CXX_parhyp/ark_heat2D_hypre_pfmg_imex.cpp @@ -52,6 +52,7 @@ #include #include #include +#include #include "HYPRE_struct_ls.h" // HYPRE structured grid solver interface #include "arkode/arkode_arkstep.h" // access to ARKStep @@ -172,9 +173,9 @@ struct UserData bool linear; // enable/disable linearly implicit option int order; // ARKode method order - sunrealtype hf; // fixed step size - int controller; // step size adaptivity method - int maxsteps; // max number of steps between outputs + sunrealtype hf; // fixed step size + string controller; // step size adaptivity method + int maxsteps; // max number of steps between outputs // Linear solver and preconditioner settings int liniters; // number of linear iterations @@ -310,11 +311,10 @@ static int check_flag(void* flagvalue, const string funcname, int opt); int main(int argc, char* argv[]) { - int flag; // reusable error-checking flag - N_Vector u = NULL; // vector for storing solution - SUNLinearSolver LS = NULL; // linear solver memory structure - void* arkode_mem = NULL; // ARKode memory structure - SUNAdaptController C = NULL; // Time adaptivity controller + int flag; // reusable error-checking flag + N_Vector u = NULL; // vector for storing solution + SUNLinearSolver LS = NULL; // linear solver memory structure + void* arkode_mem = NULL; // ARKode memory structure // Timing variables double t1 = 0.0; @@ -448,17 +448,8 @@ int main(int argc, char* argv[]) } else { - switch (udata.controller) - { - case (ARK_ADAPT_PID): C = SUNAdaptController_PID(sunctx); break; - case (ARK_ADAPT_PI): C = SUNAdaptController_PI(sunctx); break; - case (ARK_ADAPT_I): C = SUNAdaptController_I(sunctx); break; - case (ARK_ADAPT_EXP_GUS): C = SUNAdaptController_ExpGus(sunctx); break; - case (ARK_ADAPT_IMP_GUS): C = SUNAdaptController_ImpGus(sunctx); break; - case (ARK_ADAPT_IMEX_GUS): C = SUNAdaptController_ImExGus(sunctx); break; - } - flag = ARKodeSetAdaptController(arkode_mem, C); - if (check_flag(&flag, "ARKodeSetAdaptController", 1)) { return 1; } + flag = ARKodeSetAdaptControllerByName(arkode_mem, udata.controller.c_str()); + if (check_flag(&flag, "ARKodeSetAdaptControllerByName", 1)) { return 1; } } // Specify linearly implicit non-time-dependent RHS @@ -553,11 +544,10 @@ int main(int argc, char* argv[]) if (check_flag(&flag, "HYPRE_Finalize", 1)) { return 1; } #endif - ARKodeFree(&arkode_mem); // Free integrator memory - SUNLinSolFree(LS); // Free linear solver - N_VDestroy(u); // Free vectors - FreeUserData(&udata); // Free user data - (void)SUNAdaptController_Destroy(C); // Free time adaptivity controller + ARKodeFree(&arkode_mem); // Free integrator memory + SUNLinSolFree(LS); // Free linear solver + N_VDestroy(u); // Free vectors + FreeUserData(&udata); // Free user data } // Finalize MPI @@ -2295,9 +2285,9 @@ static int InitUserData(UserData* udata) udata->linear = false; // linearly implicit problem udata->order = 3; // method order - udata->hf = ZERO; // using adaptive step sizes at fast - udata->controller = 0; // PID controller - udata->maxsteps = 0; // use ARKode default + udata->hf = ZERO; // using adaptive step sizes at fast + udata->controller = "PID"; // PID controller + udata->maxsteps = 0; // use ARKode default // Linear solver and preconditioner options udata->liniters = 10; // max linear iterations @@ -2429,10 +2419,7 @@ static int ReadInputs(int* argc, char*** argv, UserData* udata, bool outproc) else if (arg == "--linear") { udata->linear = true; } else if (arg == "--order") { udata->order = stoi((*argv)[arg_idx++]); } else if (arg == "--hf") { udata->hf = stod((*argv)[arg_idx++]); } - else if (arg == "--controller") - { - udata->controller = stoi((*argv)[arg_idx++]); - } + else if (arg == "--controller") { udata->controller = (*argv)[arg_idx++]; } // Linear solver settings else if (arg == "--liniters") { diff --git a/examples/arkode/CXX_parhyp/ark_heat2D_hypre_pfmg_mri.cpp b/examples/arkode/CXX_parhyp/ark_heat2D_hypre_pfmg_mri.cpp index aa75c8b61c..88f9669611 100644 --- a/examples/arkode/CXX_parhyp/ark_heat2D_hypre_pfmg_mri.cpp +++ b/examples/arkode/CXX_parhyp/ark_heat2D_hypre_pfmg_mri.cpp @@ -50,6 +50,7 @@ #include #include #include +#include #include "HYPRE_struct_ls.h" // HYPRE structured grid solver interface #include "arkode/arkode_arkstep.h" // access to ARKStep @@ -172,10 +173,10 @@ struct UserData int sorder; // slow method order int forder; // fast ARKode method order - sunrealtype hf; // fast fixed step size - sunrealtype hs; // slow timestep fixed - int controller; // step size adaptivity method - int maxsteps; // max number of steps between outputs + sunrealtype hf; // fast fixed step size + sunrealtype hs; // slow timestep fixed + string controller; // step size adaptivity method + int maxsteps; // max number of steps between outputs // Linear solver and preconditioner settings int liniters; // number of linear iterations @@ -321,7 +322,6 @@ int main(int argc, char* argv[]) void* inner_arkode_mem = NULL; // ARKode memory structure MRIStepInnerStepper inner_stepper = NULL; // inner stepper MRIStepCoupling C = NULL; // slow coupling coefficients - SUNAdaptController Ctrl = NULL; // timestep adaptivity controller // Timing variables double t1 = 0.0; @@ -442,19 +442,9 @@ int main(int argc, char* argv[]) } else { - switch (udata.controller) - { - case (ARK_ADAPT_PID): Ctrl = SUNAdaptController_PID(sunctx); break; - case (ARK_ADAPT_PI): Ctrl = SUNAdaptController_PI(sunctx); break; - case (ARK_ADAPT_I): Ctrl = SUNAdaptController_I(sunctx); break; - case (ARK_ADAPT_EXP_GUS): Ctrl = SUNAdaptController_ExpGus(sunctx); break; - case (ARK_ADAPT_IMP_GUS): Ctrl = SUNAdaptController_ImpGus(sunctx); break; - case (ARK_ADAPT_IMEX_GUS): - Ctrl = SUNAdaptController_ImExGus(sunctx); - break; - } - flag = ARKodeSetAdaptController(inner_arkode_mem, Ctrl); - if (check_flag(&flag, "ARKodeSetAdaptController", 1)) { return 1; } + flag = ARKodeSetAdaptControllerByName(inner_arkode_mem, + udata.controller.c_str()); + if (check_flag(&flag, "ARKodeSetAdaptControllerByName", 1)) { return 1; } } // Attach user data @@ -626,7 +616,6 @@ int main(int argc, char* argv[]) SUNLinSolFree(LSf); // Free linear solver N_VDestroy(u); // Free vectors FreeUserData(&udata); // Free user data - (void)SUNAdaptController_Destroy(Ctrl); // Free timestep adaptivity controller } // Finalize MPI @@ -2251,7 +2240,7 @@ static int InitUserData(UserData* udata) udata->hf = ZERO; // using adaptive step sizes at fast udata->hs = 0.001; // slow step size - udata->controller = 0; // PID controller + udata->controller = "PID"; // PID controller udata->maxsteps = 0; // use ARKode default // Linear solver and preconditioner options @@ -2387,10 +2376,7 @@ static int ReadInputs(int* argc, char*** argv, UserData* udata, bool outproc) else if (arg == "--forder") { udata->forder = stoi((*argv)[arg_idx++]); } else if (arg == "--hf") { udata->hf = stod((*argv)[arg_idx++]); } else if (arg == "--hs") { udata->hs = stod((*argv)[arg_idx++]); } - else if (arg == "--controller") - { - udata->controller = stoi((*argv)[arg_idx++]); - } + else if (arg == "--controller") { udata->controller = (*argv)[arg_idx++]; } // Linear solver settings else if (arg == "--liniters") { diff --git a/examples/arkode/CXX_serial/ark_advection_diffusion_reaction.cpp b/examples/arkode/CXX_serial/ark_advection_diffusion_reaction.cpp index 4ee2587c82..9f989fda60 100644 --- a/examples/arkode/CXX_serial/ark_advection_diffusion_reaction.cpp +++ b/examples/arkode/CXX_serial/ark_advection_diffusion_reaction.cpp @@ -185,9 +185,6 @@ int main(int argc, char* argv[]) SUNMatrix A = nullptr; SUNLinearSolver LS = nullptr; - // Adaptivity controller for DIRK, IMEX or MRI fast integrators - SUNAdaptController C = nullptr; - // Matrix and linear solver for MRI fast integrator SUNMatrix A_fast = nullptr; SUNLinearSolver LS_fast = nullptr; @@ -198,12 +195,10 @@ int main(int argc, char* argv[]) // Create integrator switch (uopts.integrator) { - case (0): flag = SetupERK(ctx, udata, uopts, y, &C, &arkode_mem); break; - case (1): - flag = SetupARK(ctx, udata, uopts, y, &A, &LS, &C, &arkode_mem); - break; + case (0): flag = SetupERK(ctx, udata, uopts, y, &arkode_mem); break; + case (1): flag = SetupARK(ctx, udata, uopts, y, &A, &LS, &arkode_mem); break; case (2): - flag = SetupMRIARK(ctx, udata, uopts, y, &A, &LS, &A_fast, &LS_fast, &C, + flag = SetupMRIARK(ctx, udata, uopts, y, &A, &LS, &A_fast, &LS_fast, &fast_mem, &arkode_mem); break; case (3): @@ -311,7 +306,6 @@ int main(int argc, char* argv[]) SUNLinSolFree(LS); SUNMatDestroy(A_fast); SUNLinSolFree(LS_fast); - (void)SUNAdaptController_Destroy(C); return 0; } @@ -321,7 +315,7 @@ int main(int argc, char* argv[]) // ----------------------------------------------------------------------------- int SetupERK(SUNContext ctx, UserData& udata, UserOptions& uopts, N_Vector y, - SUNAdaptController* C, void** arkode_mem) + void** arkode_mem) { // Problem configuration ARKRhsFn f_RHS; // explicit RHS function @@ -369,19 +363,10 @@ int SetupERK(SUNContext ctx, UserData& udata, UserOptions& uopts, N_Vector y, flag = ARKodeSetFixedStep(*arkode_mem, uopts.fixed_h); if (check_flag(flag, "ARKodeSetFixedStep")) { return 1; } } - else if (uopts.controller >= 0) + else { - switch (uopts.controller) - { - case (ARK_ADAPT_PID): *C = SUNAdaptController_PID(ctx); break; - case (ARK_ADAPT_PI): *C = SUNAdaptController_PI(ctx); break; - case (ARK_ADAPT_I): *C = SUNAdaptController_I(ctx); break; - case (ARK_ADAPT_EXP_GUS): *C = SUNAdaptController_ExpGus(ctx); break; - case (ARK_ADAPT_IMP_GUS): *C = SUNAdaptController_ImpGus(ctx); break; - case (ARK_ADAPT_IMEX_GUS): *C = SUNAdaptController_ImExGus(ctx); break; - } - flag = ARKodeSetAdaptController(*arkode_mem, *C); - if (check_flag(flag, "ARKodeSetAdaptController")) { return 1; } + flag = ARKodeSetAdaptControllerByName(*arkode_mem, uopts.controller.c_str()); + if (check_flag(flag, "ARKodeSetAdaptControllerByName")) { return 1; } } // Set max steps between outputs @@ -396,8 +381,7 @@ int SetupERK(SUNContext ctx, UserData& udata, UserOptions& uopts, N_Vector y, } int SetupARK(SUNContext ctx, UserData& udata, UserOptions& uopts, N_Vector y, - SUNMatrix* A, SUNLinearSolver* LS, SUNAdaptController* C, - void** arkode_mem) + SUNMatrix* A, SUNLinearSolver* LS, void** arkode_mem) { // Problem configuration ARKRhsFn fe_RHS; // explicit RHS function @@ -624,19 +608,10 @@ int SetupARK(SUNContext ctx, UserData& udata, UserOptions& uopts, N_Vector y, flag = ARKodeSetFixedStep(*arkode_mem, uopts.fixed_h); if (check_flag(flag, "ARKodeSetFixedStep")) { return 1; } } - else if (uopts.controller >= 0) + else { - switch (uopts.controller) - { - case (ARK_ADAPT_PID): *C = SUNAdaptController_PID(ctx); break; - case (ARK_ADAPT_PI): *C = SUNAdaptController_PI(ctx); break; - case (ARK_ADAPT_I): *C = SUNAdaptController_I(ctx); break; - case (ARK_ADAPT_EXP_GUS): *C = SUNAdaptController_ExpGus(ctx); break; - case (ARK_ADAPT_IMP_GUS): *C = SUNAdaptController_ImpGus(ctx); break; - case (ARK_ADAPT_IMEX_GUS): *C = SUNAdaptController_ImExGus(ctx); break; - } - flag = ARKodeSetAdaptController(*arkode_mem, *C); - if (check_flag(flag, "ARKodeSetAdaptController")) { return 1; } + flag = ARKodeSetAdaptControllerByName(*arkode_mem, uopts.controller.c_str()); + if (check_flag(flag, "ARKodeSetAdaptControllerByName")) { return 1; } } // Set max steps between outputs @@ -652,8 +627,8 @@ int SetupARK(SUNContext ctx, UserData& udata, UserOptions& uopts, N_Vector y, int SetupMRIARK(SUNContext ctx, UserData& udata, UserOptions& uopts, N_Vector y, SUNMatrix* A, SUNLinearSolver* LS, SUNMatrix* A_fast, - SUNLinearSolver* LS_fast, SUNAdaptController* C, - MRIStepInnerStepper* fast_mem, void** arkode_mem) + SUNLinearSolver* LS_fast, MRIStepInnerStepper* fast_mem, + void** arkode_mem) { // Problem configuration ARKRhsFn fse_RHS; // slow explicit RHS function @@ -763,19 +738,11 @@ int SetupMRIARK(SUNContext ctx, UserData& udata, UserOptions& uopts, N_Vector y, flag = ARKodeSetFixedStep(fast_arkode_mem, uopts.fixed_h_fast); if (check_flag(flag, "ARKodeSetFixedStep")) { return 1; } } - else if (uopts.controller_fast >= 0) + else { - switch (uopts.controller_fast) - { - case (ARK_ADAPT_PID): *C = SUNAdaptController_PID(ctx); break; - case (ARK_ADAPT_PI): *C = SUNAdaptController_PI(ctx); break; - case (ARK_ADAPT_I): *C = SUNAdaptController_I(ctx); break; - case (ARK_ADAPT_EXP_GUS): *C = SUNAdaptController_ExpGus(ctx); break; - case (ARK_ADAPT_IMP_GUS): *C = SUNAdaptController_ImpGus(ctx); break; - case (ARK_ADAPT_IMEX_GUS): *C = SUNAdaptController_ImExGus(ctx); break; - } - flag = ARKodeSetAdaptController(fast_arkode_mem, *C); - if (check_flag(flag, "ARKodeSetAdaptController")) { return 1; } + flag = ARKodeSetAdaptControllerByName(fast_arkode_mem, + uopts.controller_fast.c_str()); + if (check_flag(flag, "ARKodeSetAdaptControllerByName")) { return 1; } } // Set max steps between outputs diff --git a/examples/arkode/CXX_serial/ark_advection_diffusion_reaction.hpp b/examples/arkode/CXX_serial/ark_advection_diffusion_reaction.hpp index 9b50109742..63459338b9 100644 --- a/examples/arkode/CXX_serial/ark_advection_diffusion_reaction.hpp +++ b/examples/arkode/CXX_serial/ark_advection_diffusion_reaction.hpp @@ -23,6 +23,7 @@ #include #include #include +#include #include // Include desired integrators, vectors, linear solvers, and nonlinear solvers @@ -145,13 +146,13 @@ struct UserOptions sunrealtype etamx1_fast = ZERO; int maxsteps = 10000; // max steps between outputs - int controller = -1; // step size adaptivity method + string controller = "PID"; // step size adaptivity method int predictor = 0; // predictor for nonlinear systems int ls_setup_freq = 0; // linear solver setup frequency - int controller_fast = -1; // fast step size adaptivity method - int predictor_fast = 0; // predictor for fast nonlinear systems - int ls_setup_freq_fast = 0; // fast linear solver setup frequency + string controller_fast = "PID"; // fast step size adaptivity method + int predictor_fast = 0; // predictor for fast nonlinear systems + int ls_setup_freq_fast = 0; // fast linear solver setup frequency bool linear = false; // signal that the problem is linearly implicit @@ -242,16 +243,15 @@ int J_adv_diff_react(sunrealtype t, N_Vector y, N_Vector fy, SUNMatrix J, // Integrator setup functions int SetupERK(SUNContext ctx, UserData& udata, UserOptions& uopts, N_Vector y, - SUNAdaptController* C, void** arkode_mem); + void** arkode_mem); int SetupARK(SUNContext ctx, UserData& udata, UserOptions& uopts, N_Vector y, - SUNMatrix* A, SUNLinearSolver* LS, SUNAdaptController* C, - void** arkode_mem); + SUNMatrix* A, SUNLinearSolver* LS, void** arkode_mem); int SetupMRIARK(SUNContext ctx, UserData& udata, UserOptions& uopts, N_Vector y, SUNMatrix* A, SUNLinearSolver* LS, SUNMatrix* A_fast, - SUNLinearSolver* LS_fast, SUNAdaptController* C_fast, - MRIStepInnerStepper* fast_mem, void** arkode_mem); + SUNLinearSolver* LS_fast, MRIStepInnerStepper* fast_mem, + void** arkode_mem); int SetupMRICVODE(SUNContext ctx, UserData& udata, UserOptions& uopts, N_Vector y, SUNMatrix* A, SUNLinearSolver* LS, @@ -596,10 +596,10 @@ static void InputHelp() cout << " --atol_fast : MRI fast absolute tolerance\n"; cout << " --fixed_h : fixed step size\n"; cout << " --fixed_h_fast : MRI fast fixed step size\n"; - cout << " --controller : time step adaptivity\n"; + cout << " --controller : time step adaptivity\n"; cout << " --predictor : nonlinear solver predictor\n"; cout << " --lssetupfreq : LS setup frequency\n"; - cout << " --controller_fast : MRI fast time step adaptivity\n"; + cout << " --controller_fast : MRI fast time step adaptivity\n"; cout << " --predictor_fast : MRI fast nonlinear solver predictor\n"; cout << " --lssetupfreq_fast : MRI fast LS setup frequency\n"; cout << " --maxsteps : max steps between outputs\n"; @@ -662,6 +662,16 @@ inline void find_arg(vector& args, const string key, bool& dest, } } +inline void find_arg(vector& args, const string key, string& dest) +{ + auto it = find(args.cbegin(), args.cend(), key); + if (it != args.end()) + { + dest = move(*(it + 1)); + args.erase(it, it + 2); + } +} + static int ReadInputs(vector& args, UserData& udata, UserOptions& uopts, SUNContext ctx) { @@ -1036,22 +1046,7 @@ static int PrintSetup(UserData& udata, UserOptions& uopts) cout << " rtol = " << uopts.rtol << endl; cout << " atol = " << uopts.atol << endl; cout << " fixed h = " << uopts.fixed_h << endl; - if (uopts.controller <= 0) { cout << " controller = PID" << endl; } - else if (uopts.controller == 1) { cout << " controller = PI" << endl; } - else if (uopts.controller == 2) { cout << " controller = I" << endl; } - else if (uopts.controller == 3) - { - cout << " controller = explicit Gustafsson" << endl; - } - else if (uopts.controller == 4) - { - cout << " controller = implicit Gustafsson" << endl; - } - else if (uopts.controller == 5) - { - cout << " controller = IMEX Gustafsson" << endl; - } - else { cout << " controller = " << uopts.controller << endl; } + cout << " controller = " << uopts.controller << endl; if (uopts.integrator > 0) { if (uopts.predictor == 0) @@ -1082,31 +1077,7 @@ static int PrintSetup(UserData& udata, UserOptions& uopts) cout << " atol = " << uopts.atol_fast << endl; cout << " order = " << uopts.order_fast << endl; cout << " fixed h = " << uopts.fixed_h_fast << endl; - if (uopts.controller_fast <= 0) - { - cout << " controller = PID" << endl; - } - else if (uopts.controller_fast == 1) - { - cout << " controller = PI" << endl; - } - else if (uopts.controller_fast == 2) - { - cout << " controller = I" << endl; - } - else if (uopts.controller_fast == 3) - { - cout << " controller = explicit Gustafsson" << endl; - } - else if (uopts.controller_fast == 4) - { - cout << " controller = implicit Gustafsson" << endl; - } - else if (uopts.controller_fast == 5) - { - cout << " controller = IMEX Gustafsson" << endl; - } - else { cout << " controller = " << uopts.controller_fast << endl; } + cout << " fast controller = PID" << uopts.controller_fast << endl; if (uopts.predictor_fast == 0) { cout << " predictor = trivial" << endl; diff --git a/include/arkode/arkode.h b/include/arkode/arkode.h index f4e0667d72..e9924158b3 100644 --- a/include/arkode/arkode.h +++ b/include/arkode/arkode.h @@ -259,6 +259,8 @@ SUNDIALS_EXPORT int ARKodeSetStagePredictFn(void* arkode_mem, /* Optional input functions (temporal adaptivity) */ SUNDIALS_EXPORT int ARKodeSetAdaptController(void* arkode_mem, SUNAdaptController C); +SUNDIALS_EXPORT int ARKodeSetAdaptControllerByName(void* arkode_mem, + const char* cname); SUNDIALS_EXPORT int ARKodeSetAdaptivityAdjustment(void* arkode_mem, int adjust); SUNDIALS_EXPORT int ARKodeSetCFLFraction(void* arkode_mem, sunrealtype cfl_frac); SUNDIALS_EXPORT int ARKodeSetErrorBias(void* arkode_mem, sunrealtype bias); diff --git a/src/arkode/arkode_io.c b/src/arkode/arkode_io.c index 356c46e4d1..27f61e368e 100644 --- a/src/arkode/arkode_io.c +++ b/src/arkode/arkode_io.c @@ -959,6 +959,73 @@ int ARKodeSetAdaptController(void* arkode_mem, SUNAdaptController C) return (ARK_SUCCESS); } +/*--------------------------------------------------------------- + ARKodeSetAdaptControllerByName: + + Specifies a SUNAdaptController time step controller object by + its name. + ---------------------------------------------------------------*/ +int ARKodeSetAdaptControllerByName(void* arkode_mem, const char* cname) +{ + int retval; + ARKodeMem ark_mem; + if (arkode_mem == NULL) + { + arkProcessError(NULL, ARK_MEM_NULL, __LINE__, __func__, __FILE__, + MSG_ARK_NO_MEM); + return (ARK_MEM_NULL); + } + ark_mem = (ARKodeMem)arkode_mem; + + /* Create new controller based on the name */ + SUNAdaptController C = NULL; + if (strcmp(cname, "Soderlind") == 0) + { + C = SUNAdaptController_Soderlind(ark_mem->sunctx); + } + if (strcmp(cname, "PID") == 0) + { + C = SUNAdaptController_PID(ark_mem->sunctx); + } + if (strcmp(cname, "PI") == 0) { C = SUNAdaptController_PI(ark_mem->sunctx); } + if (strcmp(cname, "I") == 0) { C = SUNAdaptController_I(ark_mem->sunctx); } + if (strcmp(cname, "ExpGus") == 0) + { + C = SUNAdaptController_ExpGus(ark_mem->sunctx); + } + if (strcmp(cname, "ImpGus") == 0) + { + C = SUNAdaptController_ImpGus(ark_mem->sunctx); + } + if (strcmp(cname, "H0211") == 0) + { + C = SUNAdaptController_H0211(ark_mem->sunctx); + } + if (strcmp(cname, "H211") == 0) + { + C = SUNAdaptController_H211(ark_mem->sunctx); + } + if (strcmp(cname, "H312") == 0) + { + C = SUNAdaptController_H312(ark_mem->sunctx); + } + if (C == NULL) + { + arkProcessError(NULL, ARK_ILL_INPUT, __LINE__, __func__, __FILE__, + "Unknown controller"); + return ARK_ILL_INPUT; + } + + /* Send controller to be used by ARKODE */ + retval = ARKodeSetAdaptController(arkode_mem, C); + if (retval != ARK_SUCCESS) { return retval; } + + /* Update controller ownership flag */ + ark_mem->hadapt_mem->owncontroller = SUNTRUE; + + return ARK_SUCCESS; +} + /*--------------------------------------------------------------- ARKodeSetMaxNumSteps: diff --git a/src/arkode/fmod_int32/farkode_mod.c b/src/arkode/fmod_int32/farkode_mod.c index 1423d2e582..a916398a02 100644 --- a/src/arkode/fmod_int32/farkode_mod.c +++ b/src/arkode/fmod_int32/farkode_mod.c @@ -869,6 +869,20 @@ SWIGEXPORT int _wrap_FARKodeSetAdaptController(void *farg1, SUNAdaptController f } +SWIGEXPORT int _wrap_FARKodeSetAdaptControllerByName(void *farg1, SwigArrayWrapper *farg2) { + int fresult ; + void *arg1 = (void *) 0 ; + char *arg2 = (char *) 0 ; + int result; + + arg1 = (void *)(farg1); + arg2 = (char *)(farg2->data); + result = (int)ARKodeSetAdaptControllerByName(arg1,(char const *)arg2); + fresult = (int)(result); + return fresult; +} + + SWIGEXPORT int _wrap_FARKodeSetAdaptivityAdjustment(void *farg1, int const *farg2) { int fresult ; void *arg1 = (void *) 0 ; diff --git a/src/arkode/fmod_int32/farkode_mod.f90 b/src/arkode/fmod_int32/farkode_mod.f90 index 70e4d51066..b4a2a5a503 100644 --- a/src/arkode/fmod_int32/farkode_mod.f90 +++ b/src/arkode/fmod_int32/farkode_mod.f90 @@ -141,6 +141,11 @@ module farkode_mod public :: FARKodeSetNonlinConvCoef public :: FARKodeSetStagePredictFn public :: FARKodeSetAdaptController + type, bind(C) :: SwigArrayWrapper + type(C_PTR), public :: data = C_NULL_PTR + integer(C_SIZE_T), public :: size = 0 + end type + public :: FARKodeSetAdaptControllerByName public :: FARKodeSetAdaptivityAdjustment public :: FARKodeSetCFLFraction public :: FARKodeSetErrorBias @@ -173,10 +178,6 @@ module farkode_mod public :: FARKodeGetRootInfo public :: FARKodeGetUserData public :: FARKodePrintAllStats - type, bind(C) :: SwigArrayWrapper - type(C_PTR), public :: data = C_NULL_PTR - integer(C_SIZE_T), public :: size = 0 - end type public :: FARKodeGetReturnFlagName public :: FARKodeWriteParameters public :: FARKodeGetNumExpSteps @@ -816,6 +817,16 @@ function swigc_FARKodeSetAdaptController(farg1, farg2) & integer(C_INT) :: fresult end function +function swigc_FARKodeSetAdaptControllerByName(farg1, farg2) & +bind(C, name="_wrap_FARKodeSetAdaptControllerByName") & +result(fresult) +use, intrinsic :: ISO_C_BINDING +import :: swigarraywrapper +type(C_PTR), value :: farg1 +type(SwigArrayWrapper) :: farg2 +integer(C_INT) :: fresult +end function + function swigc_FARKodeSetAdaptivityAdjustment(farg1, farg2) & bind(C, name="_wrap_FARKodeSetAdaptivityAdjustment") & result(fresult) @@ -3008,6 +3019,41 @@ function FARKodeSetAdaptController(arkode_mem, c) & swig_result = fresult end function + +subroutine SWIG_string_to_chararray(string, chars, wrap) + use, intrinsic :: ISO_C_BINDING + character(kind=C_CHAR, len=*), intent(IN) :: string + character(kind=C_CHAR), dimension(:), target, allocatable, intent(OUT) :: chars + type(SwigArrayWrapper), intent(OUT) :: wrap + integer :: i + + allocate(character(kind=C_CHAR) :: chars(len(string) + 1)) + do i=1,len(string) + chars(i) = string(i:i) + end do + i = len(string) + 1 + chars(i) = C_NULL_CHAR ! C string compatibility + wrap%data = c_loc(chars) + wrap%size = len(string) +end subroutine + +function FARKodeSetAdaptControllerByName(arkode_mem, cname) & +result(swig_result) +use, intrinsic :: ISO_C_BINDING +integer(C_INT) :: swig_result +type(C_PTR) :: arkode_mem +character(kind=C_CHAR, len=*), target :: cname +character(kind=C_CHAR), dimension(:), allocatable, target :: farg2_chars +integer(C_INT) :: fresult +type(C_PTR) :: farg1 +type(SwigArrayWrapper) :: farg2 + +farg1 = arkode_mem +call SWIG_string_to_chararray(cname, farg2_chars, farg2) +fresult = swigc_FARKodeSetAdaptControllerByName(farg1, farg2) +swig_result = fresult +end function + function FARKodeSetAdaptivityAdjustment(arkode_mem, adjust) & result(swig_result) use, intrinsic :: ISO_C_BINDING @@ -5134,24 +5180,6 @@ function FARKodeButcherTable_LoadDIRK(imethod) & swig_result = fresult end function - -subroutine SWIG_string_to_chararray(string, chars, wrap) - use, intrinsic :: ISO_C_BINDING - character(kind=C_CHAR, len=*), intent(IN) :: string - character(kind=C_CHAR), dimension(:), target, allocatable, intent(OUT) :: chars - type(SwigArrayWrapper), intent(OUT) :: wrap - integer :: i - - allocate(character(kind=C_CHAR) :: chars(len(string) + 1)) - do i=1,len(string) - chars(i) = string(i:i) - end do - i = len(string) + 1 - chars(i) = C_NULL_CHAR ! C string compatibility - wrap%data = c_loc(chars) - wrap%size = len(string) -end subroutine - function FARKodeButcherTable_LoadDIRKByName(imethod) & result(swig_result) use, intrinsic :: ISO_C_BINDING diff --git a/src/arkode/fmod_int64/farkode_mod.c b/src/arkode/fmod_int64/farkode_mod.c index 7b2c3c9811..fd0aa90f7b 100644 --- a/src/arkode/fmod_int64/farkode_mod.c +++ b/src/arkode/fmod_int64/farkode_mod.c @@ -869,6 +869,20 @@ SWIGEXPORT int _wrap_FARKodeSetAdaptController(void *farg1, SUNAdaptController f } +SWIGEXPORT int _wrap_FARKodeSetAdaptControllerByName(void *farg1, SwigArrayWrapper *farg2) { + int fresult ; + void *arg1 = (void *) 0 ; + char *arg2 = (char *) 0 ; + int result; + + arg1 = (void *)(farg1); + arg2 = (char *)(farg2->data); + result = (int)ARKodeSetAdaptControllerByName(arg1,(char const *)arg2); + fresult = (int)(result); + return fresult; +} + + SWIGEXPORT int _wrap_FARKodeSetAdaptivityAdjustment(void *farg1, int const *farg2) { int fresult ; void *arg1 = (void *) 0 ; diff --git a/src/arkode/fmod_int64/farkode_mod.f90 b/src/arkode/fmod_int64/farkode_mod.f90 index cf37c6eb1c..84ccc64ed9 100644 --- a/src/arkode/fmod_int64/farkode_mod.f90 +++ b/src/arkode/fmod_int64/farkode_mod.f90 @@ -141,6 +141,11 @@ module farkode_mod public :: FARKodeSetNonlinConvCoef public :: FARKodeSetStagePredictFn public :: FARKodeSetAdaptController + type, bind(C) :: SwigArrayWrapper + type(C_PTR), public :: data = C_NULL_PTR + integer(C_SIZE_T), public :: size = 0 + end type + public :: FARKodeSetAdaptControllerByName public :: FARKodeSetAdaptivityAdjustment public :: FARKodeSetCFLFraction public :: FARKodeSetErrorBias @@ -173,10 +178,6 @@ module farkode_mod public :: FARKodeGetRootInfo public :: FARKodeGetUserData public :: FARKodePrintAllStats - type, bind(C) :: SwigArrayWrapper - type(C_PTR), public :: data = C_NULL_PTR - integer(C_SIZE_T), public :: size = 0 - end type public :: FARKodeGetReturnFlagName public :: FARKodeWriteParameters public :: FARKodeGetNumExpSteps @@ -816,6 +817,16 @@ function swigc_FARKodeSetAdaptController(farg1, farg2) & integer(C_INT) :: fresult end function +function swigc_FARKodeSetAdaptControllerByName(farg1, farg2) & +bind(C, name="_wrap_FARKodeSetAdaptControllerByName") & +result(fresult) +use, intrinsic :: ISO_C_BINDING +import :: swigarraywrapper +type(C_PTR), value :: farg1 +type(SwigArrayWrapper) :: farg2 +integer(C_INT) :: fresult +end function + function swigc_FARKodeSetAdaptivityAdjustment(farg1, farg2) & bind(C, name="_wrap_FARKodeSetAdaptivityAdjustment") & result(fresult) @@ -3008,6 +3019,41 @@ function FARKodeSetAdaptController(arkode_mem, c) & swig_result = fresult end function + +subroutine SWIG_string_to_chararray(string, chars, wrap) + use, intrinsic :: ISO_C_BINDING + character(kind=C_CHAR, len=*), intent(IN) :: string + character(kind=C_CHAR), dimension(:), target, allocatable, intent(OUT) :: chars + type(SwigArrayWrapper), intent(OUT) :: wrap + integer :: i + + allocate(character(kind=C_CHAR) :: chars(len(string) + 1)) + do i=1,len(string) + chars(i) = string(i:i) + end do + i = len(string) + 1 + chars(i) = C_NULL_CHAR ! C string compatibility + wrap%data = c_loc(chars) + wrap%size = len(string) +end subroutine + +function FARKodeSetAdaptControllerByName(arkode_mem, cname) & +result(swig_result) +use, intrinsic :: ISO_C_BINDING +integer(C_INT) :: swig_result +type(C_PTR) :: arkode_mem +character(kind=C_CHAR, len=*), target :: cname +character(kind=C_CHAR), dimension(:), allocatable, target :: farg2_chars +integer(C_INT) :: fresult +type(C_PTR) :: farg1 +type(SwigArrayWrapper) :: farg2 + +farg1 = arkode_mem +call SWIG_string_to_chararray(cname, farg2_chars, farg2) +fresult = swigc_FARKodeSetAdaptControllerByName(farg1, farg2) +swig_result = fresult +end function + function FARKodeSetAdaptivityAdjustment(arkode_mem, adjust) & result(swig_result) use, intrinsic :: ISO_C_BINDING @@ -5134,24 +5180,6 @@ function FARKodeButcherTable_LoadDIRK(imethod) & swig_result = fresult end function - -subroutine SWIG_string_to_chararray(string, chars, wrap) - use, intrinsic :: ISO_C_BINDING - character(kind=C_CHAR, len=*), intent(IN) :: string - character(kind=C_CHAR), dimension(:), target, allocatable, intent(OUT) :: chars - type(SwigArrayWrapper), intent(OUT) :: wrap - integer :: i - - allocate(character(kind=C_CHAR) :: chars(len(string) + 1)) - do i=1,len(string) - chars(i) = string(i:i) - end do - i = len(string) + 1 - chars(i) = C_NULL_CHAR ! C string compatibility - wrap%data = c_loc(chars) - wrap%size = len(string) -end subroutine - function FARKodeButcherTable_LoadDIRKByName(imethod) & result(swig_result) use, intrinsic :: ISO_C_BINDING