Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feautre/adapt opt #565

Draft
wants to merge 50 commits into
base: feature/rk_defaults
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
50 commits
Select commit Hold shift + click to select a range
14ecd14
Remove special case of negative base in SUNRpowerR
Steven-Roberts Jul 30, 2024
dcb14bc
Fix assert condition
Steven-Roberts Jul 30, 2024
19f2dc9
Remove magic constant
Steven-Roberts Jul 30, 2024
53f3dde
Remove TINY parameter
Steven-Roberts Jul 30, 2024
e838c4e
Remove TINY from imexgus controller
Steven-Roberts Jul 30, 2024
9cde50a
Switch to assert
Steven-Roberts Jul 30, 2024
2c2444c
Fix sign of controller in nan case
Steven-Roberts Jul 30, 2024
9cb7bba
Start adaptivity unit test
Steven-Roberts Jul 31, 2024
743913a
Add const and comments to test
Steven-Roberts Aug 1, 2024
b75e78e
Simplify Soderlind controller and handle inf/nan better
Steven-Roberts Aug 1, 2024
2caec18
Clean up controllers
Steven-Roberts Aug 1, 2024
3fbda5b
Apply formatter
Steven-Roberts Aug 1, 2024
ef01f92
Merge branch 'develop' into feature/min-err
Steven-Roberts Aug 23, 2024
299cd5c
Variable initialization cleanup
Steven-Roberts Sep 6, 2024
405ff41
Use I controller on first 2 steps of Soderlind
Steven-Roberts Sep 6, 2024
bc9f312
Remove assert for pow testing
Steven-Roberts Sep 6, 2024
54aa1d5
Update docs
Steven-Roberts Sep 6, 2024
bfdf75e
Update IMEX controller docs
Steven-Roberts Sep 6, 2024
dde1379
Update changelog
Steven-Roberts Sep 6, 2024
facfc39
Clean up time step sign
Steven-Roberts Sep 6, 2024
7badd78
Additional simplifications
Steven-Roberts Sep 6, 2024
641ad92
Merge branch 'develop' into feature/min-err
Steven-Roberts Sep 6, 2024
c472ffe
Additional testing of controller
Steven-Roberts Sep 6, 2024
2452bd6
Remove unnecessary header
Steven-Roberts Sep 6, 2024
13cce12
Correct function names
Steven-Roberts Sep 6, 2024
1950356
Convert SUNRpowerR to macro
Steven-Roberts Sep 6, 2024
01b50b6
Switch to proposed adaptivity parameters
Steven-Roberts Sep 8, 2024
b733fa3
Merge branch 'feature/min-err' into feautre/adapt-opt
Steven-Roberts Sep 8, 2024
5bd4790
Update comments based on @drreynolds suggestions
Steven-Roberts Sep 10, 2024
7e325c8
Merge branch 'feature/min-err' into feautre/adapt-opt
Steven-Roberts Sep 10, 2024
9bb63c0
Fix typos in changelog
Steven-Roberts Sep 10, 2024
875ae20
Merge branch 'develop' into feautre/adapt-opt
Steven-Roberts Sep 10, 2024
8d7a267
Fix typos in changelog
Steven-Roberts Sep 10, 2024
a02ca62
Merge branch 'develop' into feature/min-err
Steven-Roberts Sep 10, 2024
9ee43b3
Merge branch 'feature/min-err' into feautre/adapt-opt
Steven-Roberts Sep 10, 2024
65836d5
Merge branch 'feature/rk_defaults' into feautre/adapt-opt
Steven-Roberts Sep 10, 2024
7d5161b
Update test/unit_tests/arkode/C_serial/ark_test_adapt.c
Steven-Roberts Sep 11, 2024
fcb7dc6
Add missing SUN_RCONST
Steven-Roberts Sep 11, 2024
1db5b33
Update test/unit_tests/arkode/C_serial/ark_test_adapt.c
Steven-Roberts Sep 11, 2024
f81a60d
Merge branch 'develop' into feature/min-err
Steven-Roberts Sep 11, 2024
7669c93
Add more asserts to controllers
Steven-Roberts Sep 11, 2024
332a7d0
Merge branch 'feature/rk_defaults' into feautre/adapt-opt
Steven-Roberts Sep 16, 2024
ed094a8
Merge branch 'develop' into feature/min-err
Steven-Roberts Sep 16, 2024
8a49e61
Merge branch 'feature/min-err' into feautre/adapt-opt
Steven-Roberts Sep 16, 2024
a1eb43c
Added constructors for additional 'recommended' controllers from Sylv…
drreynolds Sep 18, 2024
afea9c0
Spelling fix
drreynolds Sep 18, 2024
7fe8654
Formatting
drreynolds Sep 18, 2024
cc26cf2
Fixed typo
drreynolds Sep 20, 2024
47ceedd
Added FAQ on temporal adaptivity controller selection
drreynolds Sep 20, 2024
fa46710
spelling
drreynolds Sep 20, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -44,6 +46,12 @@ specific linker flags e.g., MKL.

### 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 of omitting unavailable terms.

Comment on lines +49 to +54
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure that these are "bug fixes" per-se. Should these be moved to "enhancements" section above?

Fixed `ARKodeResize` not using the default `hscale` when an argument of `0` was
provided.

Expand Down
44 changes: 44 additions & 0 deletions doc/shared/FAQ.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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 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.

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 <SUNAdaptController>` 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.Soderlind>` SUNAdaptController allows complete control
over all internal parameters via the :c:func:`SUNAdaptController_SetParams_Soderlind` function.


KINSOL
------

Expand Down
8 changes: 8 additions & 0 deletions doc/shared/RecentChanges.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -55,6 +56,13 @@ specific linker flags e.g., MKL.

**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 <SUNAdaptController.Soderlind>` uses an I controller
instead of omitting unavailable terms.

Comment on lines +59 to +65
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure that these are "bug fixes" per-se. Should these be moved to "enhancements" section above?

Fixed c:func:`ARKodeResize` not using the default ``hscale`` when an argument of
``0`` was provided.

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
74 changes: 63 additions & 11 deletions doc/shared/sunadaptcontroller/SUNAdaptController_Soderlind.rst
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +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. 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. 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_n^{-1/(p+1)}` is used.

The SUNAdaptController_Soderlind controller is implemented as a derived
SUNAdaptController class, and defines its *content* field as:
Expand Down Expand Up @@ -72,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
Expand Down Expand Up @@ -243,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::
Expand Down Expand Up @@ -313,3 +314,54 @@ 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);
20 changes: 13 additions & 7 deletions examples/arkode/CXX_serial/ark_heat2D.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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; }
Expand Down
9 changes: 9 additions & 0 deletions include/sunadaptcontroller/sunadaptcontroller_soderlind.h
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,15 @@ 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
Expand Down
53 changes: 43 additions & 10 deletions include/sundials/sundials_math.h
Original file line number Diff line number Diff line change
Expand Up @@ -160,18 +160,27 @@ extern "C" {

/*
* -----------------------------------------------------------------
* Function : SUNRpowerI
* Function : SUNRcopysign
* -----------------------------------------------------------------
* Usage : int exponent;
* sunrealtype base, ans;
* ans = SUNRpowerI(base,exponent);
* Usage : sunrealtype z;
* z = SUNRcopysign(x, y);
* -----------------------------------------------------------------
* SUNRpowerI returns the value of base^exponent, where base is of type
* sunrealtype and exponent is of type int.
* SUNRcopysign(x, y) returns x with the sign of y.
* -----------------------------------------------------------------
*/

SUNDIALS_EXPORT sunrealtype SUNRpowerI(sunrealtype base, int exponent);
#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

/*
* -----------------------------------------------------------------
Expand All @@ -181,12 +190,36 @@ SUNDIALS_EXPORT sunrealtype SUNRpowerI(sunrealtype base, int exponent);
* ans = SUNRpowerR(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.
* exponent are of type sunrealtype.
* -----------------------------------------------------------------
*/
#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 : SUNRpowerI
* -----------------------------------------------------------------
* Usage : int exponent;
* sunrealtype base, ans;
* ans = SUNRpowerI(base,exponent);
* -----------------------------------------------------------------
* 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);

/*
* -----------------------------------------------------------------
Expand Down
Loading
Loading