diff --git a/doc/arkode/guide/source/Usage/ARKStep_c_interface/Relaxation.rst b/doc/arkode/guide/source/Usage/ARKStep_c_interface/Relaxation.rst index 93074e8499..eaf515ec2e 100644 --- a/doc/arkode/guide/source/Usage/ARKStep_c_interface/Relaxation.rst +++ b/doc/arkode/guide/source/Usage/ARKStep_c_interface/Relaxation.rst @@ -151,7 +151,7 @@ method. :math:`\leq 0.0` will result in the default value being used. :param arkode_mem: the ARKStep memory structure - :param tol: the nonlinear solver residual tolerance to use + :param res_tol: the nonlinear solver residual tolerance to use :retval ARK_SUCCESS: the value was successfully set :retval ARK_MEM_NULL: ``arkode_mem`` was ``NULL`` @@ -172,8 +172,8 @@ method. will result in the default value being used. :param arkode_mem: the ARKStep memory structure - :param tol: the nonlinear solver relative solution tolerance to use - :param tol: the nonlinear solver absolute solution tolerance to use + :param rel_tol: the nonlinear solver relative solution tolerance to use + :param abs_tol: the nonlinear solver absolute solution tolerance to use :retval ARK_SUCCESS: the value was successfully set :retval ARK_MEM_NULL: ``arkode_mem`` was ``NULL`` diff --git a/doc/arkode/guide/source/Usage/ERKStep_c_interface/Relaxation.rst b/doc/arkode/guide/source/Usage/ERKStep_c_interface/Relaxation.rst index d16a016849..c0dd5dbfaf 100644 --- a/doc/arkode/guide/source/Usage/ERKStep_c_interface/Relaxation.rst +++ b/doc/arkode/guide/source/Usage/ERKStep_c_interface/Relaxation.rst @@ -151,7 +151,7 @@ method. :math:`\leq 0.0` will result in the default value being used. :param arkode_mem: the ERKStep memory structure - :param tol: the nonlinear solver residual tolerance to use + :param res_tol: the nonlinear solver residual tolerance to use :retval ARK_SUCCESS: the value was successfully set :retval ARK_MEM_NULL: ``arkode_mem`` was ``NULL`` @@ -172,8 +172,8 @@ method. will result in the default value being used. :param arkode_mem: the ERKStep memory structure - :param tol: the nonlinear solver relative solution tolerance to use - :param tol: the nonlinear solver absolute solution tolerance to use + :param rel_tol: the nonlinear solver relative solution tolerance to use + :param rel_tol: the nonlinear solver absolute solution tolerance to use :retval ARK_SUCCESS: the value was successfully set :retval ARK_MEM_NULL: ``arkode_mem`` was ``NULL`` diff --git a/include/arkode/arkode_arkstep.h b/include/arkode/arkode_arkstep.h index c30ba72f21..62312a128f 100644 --- a/include/arkode/arkode_arkstep.h +++ b/include/arkode/arkode_arkstep.h @@ -486,6 +486,8 @@ SUNDIALS_EXPORT int ARKStepSetRelaxSolver(void* arkode_mem, ARKRelaxSolver solver); SUNDIALS_EXPORT int ARKStepSetRelaxResTol(void* arkode_mem, sunrealtype res_tol); +SUNDIALS_EXPORT int ARKStepSetRelaxTol(void* arkode_mem, sunrealtype rel_tol, + sunrealtype abs_tol); SUNDIALS_EXPORT int ARKStepSetRelaxUpperBound(void* arkode_mem, sunrealtype upper); SUNDIALS_EXPORT int ARKStepGetNumRelaxFnEvals(void* arkode_mem, diff --git a/include/arkode/arkode_erkstep.h b/include/arkode/arkode_erkstep.h index 71e47f2b0b..d4a31afa66 100644 --- a/include/arkode/arkode_erkstep.h +++ b/include/arkode/arkode_erkstep.h @@ -273,6 +273,8 @@ SUNDIALS_EXPORT int ERKStepSetRelaxSolver(void* arkode_mem, ARKRelaxSolver solver); SUNDIALS_EXPORT int ERKStepSetRelaxResTol(void* arkode_mem, sunrealtype res_tol); +SUNDIALS_EXPORT int ERKStepSetRelaxTol(void* arkode_mem, sunrealtype rel_tol, + sunrealtype abs_tol); SUNDIALS_EXPORT int ERKStepSetRelaxUpperBound(void* arkode_mem, sunrealtype upper); SUNDIALS_EXPORT int ERKStepGetNumRelaxFnEvals(void* arkode_mem, diff --git a/src/arkode/arkode_arkstep_io.c b/src/arkode/arkode_arkstep_io.c index a62b285925..772fc3c0d1 100644 --- a/src/arkode/arkode_arkstep_io.c +++ b/src/arkode/arkode_arkstep_io.c @@ -299,6 +299,12 @@ int ARKStepSetRelaxResTol(void* arkode_mem, sunrealtype res_tol) return arkRelaxSetResTol(arkode_mem, res_tol); } +int ARKStepSetRelaxTol(void* arkode_mem, sunrealtype rel_tol, + sunrealtype abs_tol) +{ + return arkRelaxSetTol(arkode_mem, rel_tol, abs_tol); +} + int ARKStepSetRelaxUpperBound(void* arkode_mem, sunrealtype upper) { return arkRelaxSetUpperBound(arkode_mem, upper); diff --git a/src/arkode/arkode_erkstep_io.c b/src/arkode/arkode_erkstep_io.c index c1aeade36b..4390371f0f 100644 --- a/src/arkode/arkode_erkstep_io.c +++ b/src/arkode/arkode_erkstep_io.c @@ -190,6 +190,12 @@ int ERKStepSetRelaxResTol(void* arkode_mem, sunrealtype res_tol) return arkRelaxSetResTol(arkode_mem, res_tol); } +int ERKStepSetRelaxTol(void* arkode_mem, sunrealtype rel_tol, + sunrealtype abs_tol) +{ + return arkRelaxSetTol(arkode_mem, rel_tol, abs_tol); +} + int ERKStepSetRelaxUpperBound(void* arkode_mem, sunrealtype upper) { return arkRelaxSetUpperBound(arkode_mem, upper); diff --git a/src/arkode/arkode_relaxation.c b/src/arkode/arkode_relaxation.c index f914ce8c41..fa6c239fbb 100644 --- a/src/arkode/arkode_relaxation.c +++ b/src/arkode/arkode_relaxation.c @@ -112,6 +112,7 @@ static int arkRelaxResidualJacobian(sunrealtype relax_param, static int arkRelaxNewtonSolve(ARKodeMem ark_mem) { int i, retval; + sunrealtype tol, delta; ARKodeRelaxMem relax_mem = ark_mem->relax_mem; for (i = 0; i < ark_mem->relax_mem->max_iters; i++) @@ -122,17 +123,25 @@ static int arkRelaxNewtonSolve(ARKodeMem ark_mem) if (retval) return retval; /* Check for convergence */ - if (SUNRabs(relax_mem->res) < relax_mem->res_tol) return ARK_SUCCESS; + if (SUNRabs(relax_mem->res) < relax_mem->res_tol) { return ARK_SUCCESS; } - /* Compute Jacobian and update */ + /* Compute Jacobian */ retval = arkRelaxResidualJacobian(relax_mem->relax_param, &(relax_mem->jac), ark_mem); if (retval) return retval; - relax_mem->relax_param -= relax_mem->res / relax_mem->jac; + /* Update step length tolerance and solution */ + tol = (relax_mem->rel_tol * SUNRabs(relax_mem->relax_param) + + relax_mem->abs_tol); + + delta = relax_mem->res / relax_mem->jac; + relax_mem->relax_param -= delta; /* Update cumulative iteration count */ relax_mem->nls_iters++; + + /* Check for small update */ + if (SUNRabs(delta) < tol) { return ARK_SUCCESS; } } return ARK_RELAX_SOLVE_RECV; @@ -333,7 +342,7 @@ static int arkRelaxFixedPointSolve(ARKodeMem ark_mem) if (retval) return retval; /* Check for convergence */ - if (SUNRabs(relax_mem->res) < relax_mem->res_tol) return ARK_SUCCESS; + if (SUNRabs(relax_mem->res) < relax_mem->res_tol) { return ARK_SUCCESS; } relax_mem->relax_param -= relax_mem->res; @@ -503,7 +512,8 @@ int arkRelaxSetResTol(void* arkode_mem, sunrealtype res_tol) ARKodeMem ark_mem; ARKodeRelaxMem relax_mem; - retval = arkRelaxAccessMem(arkode_mem, "arkRelaxSetResTol", &ark_mem, &relax_mem); + retval = arkRelaxAccessMem(arkode_mem, "arkRelaxSetResTol", &ark_mem, + &relax_mem); if (retval) return retval; if (res_tol > SUN_RCONST(0.0)) relax_mem->res_tol = res_tol; @@ -512,6 +522,25 @@ int arkRelaxSetResTol(void* arkode_mem, sunrealtype res_tol) return ARK_SUCCESS; } +int arkRelaxSetTol(void* arkode_mem, sunrealtype rel_tol, sunrealtype abs_tol) +{ + int retval; + ARKodeMem ark_mem; + ARKodeRelaxMem relax_mem; + + retval = arkRelaxAccessMem(arkode_mem, "arkRelaxSetTol", &ark_mem, + &relax_mem); + if (retval) return retval; + + if (rel_tol > SUN_RCONST(0.0)) relax_mem->rel_tol = rel_tol; + else relax_mem->rel_tol = ARK_RELAX_DEFAULT_REL_TOL; + + if (abs_tol > SUN_RCONST(0.0)) relax_mem->abs_tol = abs_tol; + else relax_mem->abs_tol = ARK_RELAX_DEFAULT_ABS_TOL; + + return ARK_SUCCESS; +} + int arkRelaxSetUpperBound(void* arkode_mem, sunrealtype upper) { int retval; diff --git a/src/arkode/arkode_relaxation_impl.h b/src/arkode/arkode_relaxation_impl.h index d8e64cd165..de6e248094 100644 --- a/src/arkode/arkode_relaxation_impl.h +++ b/src/arkode/arkode_relaxation_impl.h @@ -118,6 +118,7 @@ int arkRelaxSetMaxFails(void* arkode_mem, int max_fails); int arkRelaxSetMaxIters(void* arkode_mem, int max_iters); int arkRelaxSetSolver(void* arkode_mem, ARKRelaxSolver solver); int arkRelaxSetResTol(void* arkode_mem, sunrealtype res_tol); +int arkRelaxSetTol(void* arkode_mem, sunrealtype rel_tol, sunrealtype abs_tol); int arkRelaxSetUpperBound(void* arkode_mem, sunrealtype upper); int arkRelaxGetNumRelaxFnEvals(void* arkode_mem, long int* r_evals);