From 8b71729376c6dadef50abc2ae6e7c153146021af Mon Sep 17 00:00:00 2001 From: "Daniel R. Reynolds" Date: Fri, 1 Nov 2024 15:55:57 -0500 Subject: [PATCH] Added counter for the number of recoverable failures reported by the MRIStepInnerStepper --- CHANGELOG.md | 4 +- .../source/Usage/MRIStep/User_callable.rst | 15 +++++++- doc/shared/RecentChanges.rst | 4 +- .../arkode/CXX_serial/ark_kpr_nestedmri.cpp | 12 ++++-- .../arkode/CXX_serial/ark_kpr_nestedmri.out | 4 +- include/arkode/arkode_mristep.h | 2 + src/arkode/arkode_mristep.c | 38 +++++++++++++------ src/arkode/arkode_mristep_impl.h | 13 ++++--- src/arkode/arkode_mristep_io.c | 29 +++++++++++++- 9 files changed, 92 insertions(+), 29 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 94734867e2..d12b8529b6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -35,7 +35,9 @@ Added support for multirate time step adaptivity controllers, based on the recently introduced `SUNAdaptController` base class, to ARKODE's MRIStep module. As a part of this, we added embeddings for existing MRI-GARK methods, as well as support for embedded MERK and IMEX-MRI-SR methods. Added new default MRI methods -for temporally adaptive versus fixed-step runs. +for temporally adaptive versus fixed-step runs. Added the function +`MRIStepGetNumInnerStepperFails` to retrieve the number of recoverable +failures reported by the MRIStepInnerStepper. Added functionality to ARKODE to accumulate a temporal error estimate over multiple time steps. See the routines `ARKodeSetAccumulatedErrorType`, diff --git a/doc/arkode/guide/source/Usage/MRIStep/User_callable.rst b/doc/arkode/guide/source/Usage/MRIStep/User_callable.rst index 553375f16e..24b23e75d9 100644 --- a/doc/arkode/guide/source/Usage/MRIStep/User_callable.rst +++ b/doc/arkode/guide/source/Usage/MRIStep/User_callable.rst @@ -338,7 +338,7 @@ MRIStep solver function :retval ARK_ROOT_RETURN: if :c:func:`MRIStepEvolve()` succeeded, and found one or more roots. If the number of root functions, *nrtfn*, is greater than 1, call - :c:func:`MRIStepGetRootInfo()` to see which + :c:func:`ARKodeGetRootInfo()` to see which :math:`g_i` were found to have a root at (*\*tret*). :retval ARK_TSTOP_RETURN: if :c:func:`MRIStepEvolve()` succeeded and returned at *tstop*. @@ -1547,6 +1547,19 @@ Main solver optional output functions ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +.. c:function:: int MRIStepGetNumInnerStepperFails(void* arkode_mem, long int* inner_fails) + + Returns the number of recoverable failures reported by the inner stepper (so far). + + :param arkode_mem: pointer to the MRIStep memory block. + :param inner_fails: number of slow steps taken in the solver. + + :retval ARK_SUCCESS: if successful + :retval ARK_MEM_NULL: if the MRIStep memory was ``NULL`` + + .. versionadded:: x.y.z + + .. c:function:: int MRIStepGetWorkSpace(void* arkode_mem, long int* lenrw, long int* leniw) Returns the MRIStep real and integer workspace sizes. diff --git a/doc/shared/RecentChanges.rst b/doc/shared/RecentChanges.rst index 51638cb9d9..aaea73efe9 100644 --- a/doc/shared/RecentChanges.rst +++ b/doc/shared/RecentChanges.rst @@ -37,7 +37,9 @@ Added support for multirate time step adaptivity controllers, based on the recently introduced :c:type:`SUNAdaptController` base class, to ARKODE's MRIStep module. As a part of this, we added embeddings for existing MRI-GARK methods, as well as support for embedded MERK and IMEX-MRI-SR methods. Added new default MRI methods -for temporally adaptive versus fixed-step runs. +for temporally adaptive versus fixed-step runs. Added the function +:c:func:`MRIStepGetNumInnerStepperFails` to retrieve the number of recoverable +failures reported by the MRIStepInnerStepper. Added functionality to ARKODE to accumulate a temporal error estimate over multiple time steps. See the routines diff --git a/examples/arkode/CXX_serial/ark_kpr_nestedmri.cpp b/examples/arkode/CXX_serial/ark_kpr_nestedmri.cpp index e71ecdba09..0a486a7a95 100644 --- a/examples/arkode/CXX_serial/ark_kpr_nestedmri.cpp +++ b/examples/arkode/CXX_serial/ark_kpr_nestedmri.cpp @@ -1013,7 +1013,7 @@ int main(int argc, char* argv[]) // // Get some slow integrator statistics - long int nsts, natts, netfs, nfse, nfsi; + long int nsts, natts, netfs, nfse, nfsi, nifs; retval = ARKodeGetNumSteps(arkode_mem, &nsts); check_flag(retval, "ARKodeGetNumSteps"); retval = ARKodeGetNumStepAttempts(arkode_mem, &natts); @@ -1024,9 +1024,11 @@ int main(int argc, char* argv[]) check_flag(retval, "ARKodeGetNumRhsEvals"); retval = ARKodeGetNumRhsEvals(arkode_mem, 1, &nfsi); check_flag(retval, "ARKodeGetNumRhsEvals"); + retval = MRIStepGetNumInnerStepperFails(arkode_mem, &nifs); + check_flag(retval, "MRIStepGetNumInnerStepperFails"); // Get some intermediate integrator statistics - long int nstm, nattm, netfm, nfme, nfmi; + long int nstm, nattm, netfm, nfme, nfmi, nifm; retval = ARKodeGetNumSteps(mid_arkode_mem, &nstm); check_flag(retval, "ARKodeGetNumSteps"); retval = ARKodeGetNumStepAttempts(mid_arkode_mem, &nattm); @@ -1037,6 +1039,8 @@ int main(int argc, char* argv[]) check_flag(retval, "ARKodeGetNumRhsEvals"); retval = ARKodeGetNumRhsEvals(mid_arkode_mem, 1, &nfmi); check_flag(retval, "ARKodeGetNumRhsEvals"); + retval = MRIStepGetNumInnerStepperFails(mid_arkode_mem, &nifm); + check_flag(retval, "MRIStepGetNumInnerStepperFails"); // Get some fast integrator statistics long int nstf, nattf, netff, nff; @@ -1056,9 +1060,9 @@ int main(int argc, char* argv[]) errtot = std::sqrt(errtot / SUN_RCONST(3.0) / (sunrealtype)nsts); std::cout << "\nFinal Solver Statistics:\n"; std::cout << " Slow steps = " << nsts << " (attempts = " << natts - << ", fails = " << netfs << ")\n"; + << ", fails = " << netfs << ", innerfails = " << nifs << ")\n"; std::cout << " Intermediate steps = " << nstm << " (attempts = " << nattm - << ", fails = " << netfm << ")\n"; + << ", fails = " << netfm << ", innerfails = " << nifm << ")\n"; std::cout << " Fast steps = " << nstf << " (attempts = " << nattf << ", fails = " << netff << ")\n"; std::cout << " u error = " << uerrtot << ", v error = " << verrtot diff --git a/examples/arkode/CXX_serial/ark_kpr_nestedmri.out b/examples/arkode/CXX_serial/ark_kpr_nestedmri.out index 355b43d35d..5b1c1c4f87 100644 --- a/examples/arkode/CXX_serial/ark_kpr_nestedmri.out +++ b/examples/arkode/CXX_serial/ark_kpr_nestedmri.out @@ -43,8 +43,8 @@ Adaptive nested multirate nonlinear Kvaerno-Prothero-Robinson test problem: ---------------------------------------------------------------------------- Final Solver Statistics: - Slow steps = 25 (attempts = 29, fails = 4) - Intermediate steps = 769 (attempts = 975, fails = 206) + Slow steps = 25 (attempts = 29, fails = 4, innerfails = 0) + Intermediate steps = 769 (attempts = 975, fails = 206, innerfails = 0) Fast steps = 193380 (attempts = 215494, fails = 22114) u error = 0.00784081, v error = 0.0203181, total error = 0.0150336 Relative accuracy = 674.105 diff --git a/include/arkode/arkode_mristep.h b/include/arkode/arkode_mristep.h index 39be4a4407..fe3888bb58 100644 --- a/include/arkode/arkode_mristep.h +++ b/include/arkode/arkode_mristep.h @@ -194,6 +194,8 @@ SUNDIALS_EXPORT int MRIStepSetPostInnerFn(void* arkode_mem, SUNDIALS_EXPORT int MRIStepGetCurrentCoupling(void* arkode_mem, MRIStepCoupling* MRIC); SUNDIALS_EXPORT int MRIStepGetLastInnerStepFlag(void* arkode_mem, int* flag); +SUNDIALS_EXPORT int MRIStepGetNumInnerStepperFails(void* arkode_mem, + long int* inner_fails); /* Custom inner stepper functions */ SUNDIALS_EXPORT int MRIStepInnerStepper_Create(SUNContext sunctx, diff --git a/src/arkode/arkode_mristep.c b/src/arkode/arkode_mristep.c index c3efcb06e2..52237bfa33 100644 --- a/src/arkode/arkode_mristep.c +++ b/src/arkode/arkode_mristep.c @@ -210,12 +210,13 @@ void* MRIStepCreate(ARKRhsFn fse, ARKRhsFn fsi, sunrealtype t0, N_Vector y0, step_mem->eRNrm = ONE; /* Initialize all the counters */ - step_mem->nfse = 0; - step_mem->nfsi = 0; - step_mem->nsetups = 0; - step_mem->nstlp = 0; - step_mem->nls_iters = 0; - step_mem->nls_fails = 0; + step_mem->nfse = 0; + step_mem->nfsi = 0; + step_mem->nsetups = 0; + step_mem->nstlp = 0; + step_mem->nls_iters = 0; + step_mem->nls_fails = 0; + step_mem->inner_fails = 0; /* Initialize fused op work space */ step_mem->cvals = NULL; @@ -352,11 +353,13 @@ int MRIStepReInit(void* arkode_mem, ARKRhsFn fse, ARKRhsFn fsi, sunrealtype t0, step_mem->fsi_is_current = SUNFALSE; /* Initialize all the counters */ - step_mem->nfse = 0; - step_mem->nfsi = 0; - step_mem->nsetups = 0; - step_mem->nstlp = 0; - step_mem->nls_iters = 0; + step_mem->nfse = 0; + step_mem->nfsi = 0; + step_mem->nsetups = 0; + step_mem->nstlp = 0; + step_mem->nls_iters = 0; + step_mem->nls_fails = 0; + step_mem->inner_fails = 0; return (ARK_SUCCESS); } @@ -701,6 +704,8 @@ void mriStep_PrintMem(ARKodeMem ark_mem, FILE* outfile) fprintf(outfile, "MRIStep: nsetups = %li\n", step_mem->nsetups); fprintf(outfile, "MRIStep: nstlp = %li\n", step_mem->nstlp); fprintf(outfile, "MRIStep: nls_iters = %li\n", step_mem->nls_iters); + fprintf(outfile, "MRIStep: nls_fails = %li\n", step_mem->nls_fails); + fprintf(outfile, "MRIStep: inner_fails = %li\n", step_mem->inner_fails); /* output boolean quantities */ fprintf(outfile, "MRIStep: user_linear = %i\n", step_mem->linear); @@ -3453,7 +3458,16 @@ int mriStep_StageERKFast(ARKodeMem ark_mem, ARKodeMRIStepMem step_mem, "Failure when evolving the inner stepper"); return (ARK_INNERSTEP_FAIL); } - if (retval > 0) { return TRY_AGAIN; } + if (retval > 0) + { + /* increment stepper-specific counter, and decrement ARKODE-level nonlinear + solver counter (since that will be incremented automatically by ARKODE). + Return with "TRY_AGAIN" which should cause ARKODE to cut the step size + and retry the step. */ + step_mem->inner_fails++; + ark_mem->ncfn--; + return TRY_AGAIN; + } /* for normal stages (i.e., not the embedding) with MRI adaptivity enabled, get an estimate for the fast time scale error */ diff --git a/src/arkode/arkode_mristep_impl.h b/src/arkode/arkode_mristep_impl.h index 8b4a7d5ac5..0db8ec9768 100644 --- a/src/arkode/arkode_mristep_impl.h +++ b/src/arkode/arkode_mristep_impl.h @@ -140,12 +140,13 @@ typedef struct ARKodeMRIStepMemRec sunrealtype inner_rtol_factor_new; /* upcoming control parameter */ /* Counters */ - long int nfse; /* num fse calls */ - long int nfsi; /* num fsi calls */ - long int nsetups; /* num linear solver setup calls */ - long int nls_iters; /* num nonlinear solver iters */ - long int nls_fails; /* num nonlinear solver fails */ - int nfusedopvecs; /* length of cvals and Xvecs arrays */ + long int nfse; /* num fse calls */ + long int nfsi; /* num fsi calls */ + long int nsetups; /* num linear solver setup calls */ + long int nls_iters; /* num nonlinear solver iters */ + long int nls_fails; /* num nonlinear solver fails */ + long int inner_fails; /* num recov. inner solver fails */ + int nfusedopvecs; /* length of cvals and Xvecs arrays */ /* Data for using MRIStep with external polynomial forcing */ sunbooleantype expforcing; /* add forcing to explicit RHS */ diff --git a/src/arkode/arkode_mristep_io.c b/src/arkode/arkode_mristep_io.c index ed4eab3d5c..3642612870 100644 --- a/src/arkode/arkode_mristep_io.c +++ b/src/arkode/arkode_mristep_io.c @@ -222,6 +222,28 @@ int MRIStepGetLastInnerStepFlag(void* arkode_mem, int* flag) return (ARK_SUCCESS); } +/*--------------------------------------------------------------- + MRIStepGetNumInnerStepperFails: + + Returns the number of recoverable failures encountered by the + inner stepper. + ---------------------------------------------------------------*/ +int MRIStepGetNumInnerStepperFails(void* arkode_mem, long int* inner_fails) +{ + ARKodeMem ark_mem; + ARKodeMRIStepMem step_mem; + int retval; + + /* access ARKodeMem and ARKodeMRIStepMem structures */ + retval = mriStep_AccessARKODEStepMem(arkode_mem, __func__, &ark_mem, &step_mem); + if (retval != ARK_SUCCESS) { return (retval); } + + /* set output from step_mem */ + *inner_fails = step_mem->inner_fails; + + return (ARK_SUCCESS); +} + /*=============================================================== Private functions attached to ARKODE ===============================================================*/ @@ -811,7 +833,9 @@ int mriStep_PrintAllStats(ARKodeMem ark_mem, FILE* outfile, SUNOutputFormat fmt) fprintf(outfile, "Explicit slow RHS fn evals = %ld\n", step_mem->nfse); fprintf(outfile, "Implicit slow RHS fn evals = %ld\n", step_mem->nfsi); - /* nonlinear solver stats */ + /* inner stepper and nonlinear solver stats */ + fprintf(outfile, "Inner stepper failures = %ld\n", + step_mem->inner_fails); fprintf(outfile, "NLS iters = %ld\n", step_mem->nls_iters); fprintf(outfile, "NLS fails = %ld\n", step_mem->nls_fails); if (ark_mem->nst > 0) @@ -852,7 +876,8 @@ int mriStep_PrintAllStats(ARKodeMem ark_mem, FILE* outfile, SUNOutputFormat fmt) fprintf(outfile, ",Explicit slow RHS fn evals,%ld", step_mem->nfse); fprintf(outfile, ",Implicit slow RHS fn evals,%ld", step_mem->nfsi); - /* nonlinear solver stats */ + /* inner stepper and nonlinear solver stats */ + fprintf(outfile, ",Inner stepper failures,%ld", step_mem->inner_fails); fprintf(outfile, ",NLS iters,%ld", step_mem->nls_iters); fprintf(outfile, ",NLS fails,%ld", step_mem->nls_fails); if (ark_mem->nst > 0)