From cba1fd7fed1f53c3cdc3707d301f48f2abccd546 Mon Sep 17 00:00:00 2001 From: David Gardner Date: Wed, 4 Oct 2023 12:28:41 -0700 Subject: [PATCH] Bugfix: stop time and output time reached in same step (#349) Fixes #339: A regression was introduced by the stop time bug fix in v6.6.1 causing integrators to return at the stop time rather than the requested output time if the stop time was reached in the same step in which the output time was passed. Also fixes a missing check in ARKODE to interpolate (or not) the solution at the stop time. --- CHANGELOG.md | 25 +- doc/arkode/guide/source/Introduction.rst | 22 +- doc/cvode/guide/source/Introduction.rst | 18 +- doc/cvodes/guide/source/Introduction.rst | 21 +- doc/ida/guide/source/Introduction.rst | 11 +- doc/idas/guide/source/Introduction.rst | 14 +- doc/kinsol/guide/source/Introduction.rst | 3 +- scripts/arkode | 23 +- scripts/cvode | 20 +- scripts/cvodes | 20 +- scripts/ida | 17 +- scripts/idas | 16 +- scripts/kinsol | 7 +- scripts/shared | 13 +- src/arkode/arkode.c | 70 +++-- src/cvode/cvode.c | 80 +++--- src/cvodes/cvodes.c | 80 +++--- src/ida/ida.c | 67 +++-- src/idas/idas.c | 69 +++-- test/answers | 2 +- .../unit_tests/arkode/C_serial/CMakeLists.txt | 1 + .../arkode/C_serial/ark_test_tstop.c | 231 +++++++++++++++++ test/unit_tests/cvode/C_serial/CMakeLists.txt | 1 + .../unit_tests/cvode/C_serial/cv_test_tstop.c | 234 +++++++++++++++++ .../unit_tests/cvodes/C_serial/CMakeLists.txt | 1 + .../cvodes/C_serial/cvs_test_tstop.c | 234 +++++++++++++++++ test/unit_tests/ida/C_serial/CMakeLists.txt | 1 + test/unit_tests/ida/C_serial/ida_test_tstop.c | 243 ++++++++++++++++++ test/unit_tests/idas/C_serial/CMakeLists.txt | 1 + .../idas/C_serial/idas_test_tstop.c | 243 ++++++++++++++++++ 30 files changed, 1511 insertions(+), 277 deletions(-) create mode 100644 test/unit_tests/arkode/C_serial/ark_test_tstop.c create mode 100644 test/unit_tests/cvode/C_serial/cv_test_tstop.c create mode 100644 test/unit_tests/cvodes/C_serial/cvs_test_tstop.c create mode 100644 test/unit_tests/ida/C_serial/ida_test_tstop.c create mode 100644 test/unit_tests/idas/C_serial/idas_test_tstop.c diff --git a/CHANGELOG.md b/CHANGELOG.md index ff09a5aa6b..419bec2d04 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,17 +3,29 @@ ## Changes to SUNDIALS in release X.X.X -Fixed a bug in `ARKStepSetTableNum` wherein it did not recognize `ARKODE_ARK2_ERK_3_1_2` and -`ARKODE_ARK2_DIRK_3_1_2` as a valid additive Runge--Kutta Butcher table pair. +Fixed a regression introduced by the stop time bug fix in v6.6.1 where ARKODE, +CVODE, CVODES, IDA, and IDAS would return at the stop time rather than the +requested output time if the stop time was reached in the same step in which the +output time was passed. -Renamed some internal types in CVODES and IDAS to allow both packages to be built together in the same binary. +Fixed a bug in ARKODE where `ARKStepSetInterpolateStopTime` would return an +interpolated solution at the stop time in some cases when interpolation was +disabled. + +Fixed a bug in `ARKStepSetTableNum` wherein it did not recognize +`ARKODE_ARK2_ERK_3_1_2` and `ARKODE_ARK2_DIRK_3_1_2` as a valid additive +Runge--Kutta Butcher table pair. + +Renamed some internal types in CVODES and IDAS to allow both packages to be +built together in the same binary. Improved computational complexity of `SUNMatScaleAddI_Sparse` from `O(M*N)` to `O(NNZ)`. Fixed scaling bug in `SUNMatScaleAddI_Sparse` for non-square matrices. -Fixed missing soversions in some `SUNLinearSolver` CMake targets. +Fixed missing soversions in some `SUNLinearSolver` and `SUNNonlinearSolver` +CMake targets. ## Changes to SUNDIALS in release 6.6.2 @@ -29,8 +41,9 @@ object. Fixed a bug in ARKODE, CVODE, CVODES, IDA, and IDAS where the stop time may not be cleared when using normal mode if the requested output time is the same as -the stop time. Additionally, with ARKODE, CVODE, and CVODES an unnecessary -interpolation of the solution at the stop time may occur in this case. +the stop time. Additionally, with ARKODE, CVODE, and CVODES this fix removes an +unnecessary interpolation of the solution at the stop time that could occur in +this case. ## Changes to SUNDIALS in release 6.6.0 diff --git a/doc/arkode/guide/source/Introduction.rst b/doc/arkode/guide/source/Introduction.rst index 1fb8ee41c5..64f3ef65a8 100644 --- a/doc/arkode/guide/source/Introduction.rst +++ b/doc/arkode/guide/source/Introduction.rst @@ -133,16 +133,25 @@ Changes from previous versions Changes in vX.X.X ----------------- +Fixed a regression introduced by the stop time bug fix in v6.6.1 where ARKODE +steppers would return at the stop time rather than the requested output time if +the stop time was reached in the same step in which the output time was passed. + +Fixed a bug in ARKODE where :c:func:`ARKStepSetInterpolateStopTime` would return +an interpolated solution at the stop time in some cases when interpolation was +disabled. + Fixed a bug in :c:func:`ARKStepSetTableNum` wherein it did not recognize `ARKODE_ARK2_ERK_3_1_2` and `ARKODE_ARK2_DIRK_3_1_2` as a valid additive Runge--Kutta Butcher table pair. -Improved computational complexity of ``SUNMatScaleAddI_Sparse`` from ``O(M*N)`` to -``O(NNZ)``. +Improved computational complexity of ``SUNMatScaleAddI_Sparse`` from ``O(M*N)`` +to ``O(NNZ)``. Fixed scaling bug in ``SUNMatScaleAddI_Sparse`` for non-square matrices. -Fixed missing soversions in some ``SUNLinearSolver`` CMake targets. +Fixed missing soversions in some ``SUNLinearSolver`` and ``SUNNonlinearSolver`` +CMake targets. Changes in v5.6.2 ----------------- @@ -158,9 +167,10 @@ Updated the Tpetra NVector interface to support Trilinos 14. Fixed a memory leak when destroying a CUDA, HIP, SYCL, or system SUNMemoryHelper object. -Fixed a bug where the stop time may not be cleared and an unnecessary -interpolation may occur when using normal mode if the requested output time is -the same as the stop time. +Fixed a bug where the stop time may not be cleared when using normal mode if the +requested output time is the same as the stop time. Additionally, this fix +removes an unnecessary interpolation of the solution at the stop time that could +occur in this case. Changes in v5.6.0 ----------------- diff --git a/doc/cvode/guide/source/Introduction.rst b/doc/cvode/guide/source/Introduction.rst index db22299523..9511fdc3ef 100644 --- a/doc/cvode/guide/source/Introduction.rst +++ b/doc/cvode/guide/source/Introduction.rst @@ -114,12 +114,17 @@ Changes from previous versions Changes in vX.X.X ----------------- -Improved computational complexity of ``SUNMatScaleAddI_Sparse`` from ``O(M*N)`` to -``O(NNZ)``. +Fixed a regression introduced by the stop time bug fix in v6.6.1 where CVODE +would return at the stop time rather than the requested output time if the stop +time was reached in the same step in which the output time was passed. + +Improved computational complexity of ``SUNMatScaleAddI_Sparse`` from ``O(M*N)`` +to ``O(NNZ)``. Fixed scaling bug in ``SUNMatScaleAddI_Sparse`` for non-square matrices. -Fixed missing soversions in some ``SUNLinearSolver`` CMake targets. +Fixed missing soversions in some ``SUNLinearSolver`` and ``SUNNonlinearSolver`` +CMake targets. Changes in v6.6.2 ----------------- @@ -135,9 +140,10 @@ Updated the Tpetra NVector interface to support Trilinos 14. Fixed a memory leak when destroying a CUDA, HIP, SYCL, or system SUNMemoryHelper object. -Fixed a bug where the stop time may not be cleared and an unnecessary -interpolation may occur when using normal mode if the requested output time is -the same as the stop time. +Fixed a bug where the stop time may not be cleared when using normal mode if the +requested output time is the same as the stop time. Additionally, this fix +removes an unnecessary interpolation of the solution at the stop time that could +occur in this case. Changes in v6.6.0 ----------------- diff --git a/doc/cvodes/guide/source/Introduction.rst b/doc/cvodes/guide/source/Introduction.rst index eeec1ce541..8c1f3549a5 100644 --- a/doc/cvodes/guide/source/Introduction.rst +++ b/doc/cvodes/guide/source/Introduction.rst @@ -114,14 +114,20 @@ Changes from previous versions Changes in vX.X.X ----------------- -Renamed some internal types in CVODES and IDAS to allow both packages to be built together in the same binary. +Fixed a regression introduced by the stop time bug fix in v6.6.1 where CVODES +would return at the stop time rather than the requested output time if the stop +time was reached in the same step in which the output time was passed. -Improved computational complexity of ``SUNMatScaleAddI_Sparse`` from ``O(M*N)`` to -``O(NNZ)``. +Renamed some internal types in CVODES and IDAS to allow both packages to be +built together in the same binary. + +Improved computational complexity of ``SUNMatScaleAddI_Sparse`` from ``O(M*N)`` +to ``O(NNZ)``. Fixed scaling bug in ``SUNMatScaleAddI_Sparse`` for non-square matrices. -Fixed missing soversions in some ``SUNLinearSolver`` CMake targets. +Fixed missing soversions in some ``SUNLinearSolver`` and ``SUNNonlinearSolver`` +CMake targets. Changes in v6.6.2 ----------------- @@ -137,9 +143,10 @@ Updated the Tpetra NVector interface to support Trilinos 14. Fixed a memory leak when destroying a CUDA, HIP, SYCL, or system SUNMemoryHelper object. -Fixed a bug where the stop time may not be cleared and an unnecessary -interpolation may occur when using normal mode if the requested output time is -the same as the stop time. +Fixed a bug where the stop time may not be cleared when using normal mode if the +requested output time is the same as the stop time. Additionally, this fix +removes an unnecessary interpolation of the solution at the stop time that could +occur in this case. Changes in v6.6.0 ----------------- diff --git a/doc/ida/guide/source/Introduction.rst b/doc/ida/guide/source/Introduction.rst index 128fd3d4d9..af750dcda5 100644 --- a/doc/ida/guide/source/Introduction.rst +++ b/doc/ida/guide/source/Introduction.rst @@ -75,12 +75,17 @@ Changes from previous versions Changes in vX.X.X ----------------- -Improved computational complexity of ``SUNMatScaleAddI_Sparse`` from ``O(M*N)`` to -``O(NNZ)``. +Fixed a regression introduced by the stop time bug fix in v6.6.1 where IDA would +return at the stop time rather than the requested output time if the stop time +was reached in the same step in which the output time was passed. + +Improved computational complexity of ``SUNMatScaleAddI_Sparse`` from ``O(M*N)`` +to ``O(NNZ)``. Fixed scaling bug in ``SUNMatScaleAddI_Sparse`` for non-square matrices. -Fixed missing soversions in some ``SUNLinearSolver`` CMake targets. +Fixed missing soversions in some ``SUNLinearSolver`` and ``SUNNonlinearSolver`` +CMake targets. Changes in v6.6.2 ----------------- diff --git a/doc/idas/guide/source/Introduction.rst b/doc/idas/guide/source/Introduction.rst index 0961904bcd..e88d274dbd 100644 --- a/doc/idas/guide/source/Introduction.rst +++ b/doc/idas/guide/source/Introduction.rst @@ -89,14 +89,20 @@ Changes from previous versions Changes in vX.X.X ----------------- -Renamed some internal types in CVODES and IDAS to allow both packages to be built together in the same binary. +Fixed a regression introduced by the stop time bug fix in v6.6.1 where IDAS +would return at the stop time rather than the requested output time if the stop +time was reached in the same step in which the output time was passed. -Improved computational complexity of ``SUNMatScaleAddI_Sparse`` from ``O(M*N)`` to -``O(NNZ)``. +Renamed some internal types in CVODES and IDAS to allow both packages to be +built together in the same binary. + +Improved computational complexity of ``SUNMatScaleAddI_Sparse`` from ``O(M*N)`` +to ``O(NNZ)``. Fixed scaling bug in ``SUNMatScaleAddI_Sparse`` for non-square matrices. -Fixed missing soversions in some ``SUNLinearSolver`` CMake targets. +Fixed missing soversions in some ``SUNLinearSolver`` and ``SUNNonlinearSolver`` +CMake targets. Changes in v5.6.2 ----------------- diff --git a/doc/kinsol/guide/source/Introduction.rst b/doc/kinsol/guide/source/Introduction.rst index edfe682859..cd370e36e9 100644 --- a/doc/kinsol/guide/source/Introduction.rst +++ b/doc/kinsol/guide/source/Introduction.rst @@ -96,7 +96,8 @@ Improved computational complexity of ``SUNMatScaleAddI_Sparse`` from ``O(M*N)`` Fixed scaling bug in ``SUNMatScaleAddI_Sparse`` for non-square matrices. -Fixed missing soversions in some ``SUNLinearSolver`` CMake targets. +Fixed missing soversions in some ``SUNLinearSolver`` and ``SUNNonlinearSolver`` +CMake targets. Changes in v6.6.2 ----------------- diff --git a/scripts/arkode b/scripts/arkode index bb216f7248..6df8c34b75 100755 --- a/scripts/arkode +++ b/scripts/arkode @@ -387,25 +387,4 @@ $tar $tarfile $distrobase/examples/arkode/F2003_serial/test_ark_butcher_f2003.f9 echo " --- Add arkode unit tests to $tarfile" -$tar $tarfile $distrobase/test/unit_tests/arkode/CMakeLists.txt -$tar $tarfile $distrobase/test/unit_tests/arkode/C_serial/CMakeLists.txt -$tar $tarfile $distrobase/test/unit_tests/arkode/C_serial/ark_test_arkstepsetforcing.c -$tar $tarfile $distrobase/test/unit_tests/arkode/C_serial/ark_test_getuserdata.c -$tar $tarfile $distrobase/test/unit_tests/arkode/C_serial/ark_test_interp.c -$tar $tarfile $distrobase/test/unit_tests/arkode/C_serial/ark_test_reset.c -$tar $tarfile $distrobase/test/unit_tests/arkode/CXX_serial/CMakeLists.txt -$tar $tarfile $distrobase/test/unit_tests/arkode/CXX_serial/ark_test_analytic_sys_mri.cpp -$tar $tarfile $distrobase/test/unit_tests/arkode/CXX_serial/ark_test_analytic_sys_mri_0.out -$tar $tarfile $distrobase/test/unit_tests/arkode/CXX_serial/ark_test_analytic_sys_mri_1.out -$tar $tarfile $distrobase/test/unit_tests/arkode/CXX_serial/ark_test_butcher.cpp -$tar $tarfile $distrobase/test/unit_tests/arkode/CXX_serial/ark_test_butcher.out -$tar $tarfile $distrobase/test/unit_tests/arkode/CXX_serial/ark_test_dahlquist_mri.cpp -$tar $tarfile $distrobase/test/unit_tests/arkode/CXX_serial/ark_test_dahlquist_mri.out -$tar $tarfile $distrobase/test/unit_tests/arkode/CXX_serial/ark_test_getjac.cpp -$tar $tarfile $distrobase/test/unit_tests/arkode/CXX_serial/ark_test_getjac.out -$tar $tarfile $distrobase/test/unit_tests/arkode/CXX_serial/ark_test_getjac_mri.cpp -$tar $tarfile $distrobase/test/unit_tests/arkode/CXX_serial/ark_test_getjac_mri.out -$tar $tarfile $distrobase/test/unit_tests/arkode/CXX_parallel/CMakeLists.txt -$tar $tarfile $distrobase/test/unit_tests/arkode/CXX_parallel/ark_test_heat2D_mri.cpp -$tar $tarfile $distrobase/test/unit_tests/arkode/F2003_serial/CMakeLists.txt -$tar $tarfile $distrobase/test/unit_tests/arkode/F2003_serial/ark_test_table_f2003.f90 +$tar $tarfile $distrobase/test/unit_tests/arkode diff --git a/scripts/cvode b/scripts/cvode index af97c77f74..2f83eb3ebf 100755 --- a/scripts/cvode +++ b/scripts/cvode @@ -272,22 +272,4 @@ $tar $tarfile $distrobase/examples/cvode/CXX_sycl/cvAdvDiff_kry_sycl.out echo " --- Add cvode unit tests to $tarfile" -$tar $tarfile $distrobase/test/unit_tests/cvode/CMakeLists.txt -$tar $tarfile $distrobase/test/unit_tests/cvode/C_serial/CMakeLists.txt -$tar $tarfile $distrobase/test/unit_tests/cvode/C_serial/cv_test_getuserdata.c -$tar $tarfile $distrobase/test/unit_tests/cvode/CXX_serial/CMakeLists.txt -$tar $tarfile $distrobase/test/unit_tests/cvode/CXX_serial/cv_test_getjac.cpp -$tar $tarfile $distrobase/test/unit_tests/cvode/CXX_serial/cv_test_getjac.out -$tar $tarfile $distrobase/test/unit_tests/cvode/CXX_serial/cv_test_kpr.cpp -$tar $tarfile $distrobase/test/unit_tests/cvode/CXX_serial/cv_test_kpr.hpp -$tar $tarfile $distrobase/test/unit_tests/cvode/CXX_serial/cv_test_kpr.out -$tar $tarfile $distrobase/test/unit_tests/cvode/CXX_serial/cv_test_kpr_--dgmax_jbad_1.0.out -$tar $tarfile $distrobase/test/unit_tests/cvode/CXX_serial/cv_test_kpr_--dgmax_lsetup_0.0.out -$tar $tarfile $distrobase/test/unit_tests/cvode/CXX_serial/cv_test_kpr_--eta_cf_0.5.out -$tar $tarfile $distrobase/test/unit_tests/cvode/CXX_serial/cv_test_kpr_--eta_max_ef_0.1_--small_nef_1.out -$tar $tarfile $distrobase/test/unit_tests/cvode/CXX_serial/cv_test_kpr_--eta_max_fs_2.out -$tar $tarfile $distrobase/test/unit_tests/cvode/CXX_serial/cv_test_kpr_--eta_min_ef_0.5.out -$tar $tarfile $distrobase/test/unit_tests/cvode/CXX_serial/cv_test_kpr_--eta_min_es_2_--small_nst_5.out -$tar $tarfile $distrobase/test/unit_tests/cvode/CXX_serial/cv_test_kpr_--eta_min_fx_1.0_--eta_max_fx_2.0.out -$tar $tarfile $distrobase/test/unit_tests/cvode/CXX_serial/cv_test_kpr_--eta_min_fx_1.0_--eta_min_0.5.out -$tar $tarfile $distrobase/test/unit_tests/cvode/CXX_serial/cv_test_kpr_--eta_min_gs_2.out +$tar $tarfile $distrobase/test/unit_tests/cvode diff --git a/scripts/cvodes b/scripts/cvodes index ae262ac1d0..cab37658ee 100755 --- a/scripts/cvodes +++ b/scripts/cvodes @@ -190,22 +190,4 @@ $tar $tarfile $distrobase/examples/cvodes/F2003_serial/cvsAdvDiff_FSA_non_f2003_ echo " --- Add cvodes unit tests to $tarfile" -$tar $tarfile $distrobase/test/unit_tests/cvodes/CMakeLists.txt -$tar $tarfile $distrobase/test/unit_tests/cvodes/C_serial/CMakeLists.txt -$tar $tarfile $distrobase/test/unit_tests/cvodes/C_serial/cvs_test_getuserdata.c -$tar $tarfile $distrobase/test/unit_tests/cvodes/CXX_serial/CMakeLists.txt -$tar $tarfile $distrobase/test/unit_tests/cvodes/CXX_serial/cvs_test_getjac.cpp -$tar $tarfile $distrobase/test/unit_tests/cvodes/CXX_serial/cvs_test_getjac.out -$tar $tarfile $distrobase/test/unit_tests/cvodes/CXX_serial/cvs_test_kpr.cpp -$tar $tarfile $distrobase/test/unit_tests/cvodes/CXX_serial/cvs_test_kpr.hpp -$tar $tarfile $distrobase/test/unit_tests/cvodes/CXX_serial/cvs_test_kpr.out -$tar $tarfile $distrobase/test/unit_tests/cvodes/CXX_serial/cvs_test_kpr_--dgmax_jbad_1.0.out -$tar $tarfile $distrobase/test/unit_tests/cvodes/CXX_serial/cvs_test_kpr_--dgmax_lsetup_0.0.out -$tar $tarfile $distrobase/test/unit_tests/cvodes/CXX_serial/cvs_test_kpr_--eta_cf_0.5.out -$tar $tarfile $distrobase/test/unit_tests/cvodes/CXX_serial/cvs_test_kpr_--eta_max_ef_0.1_--small_nef_1.out -$tar $tarfile $distrobase/test/unit_tests/cvodes/CXX_serial/cvs_test_kpr_--eta_max_fs_2.out -$tar $tarfile $distrobase/test/unit_tests/cvodes/CXX_serial/cvs_test_kpr_--eta_min_ef_0.5.out -$tar $tarfile $distrobase/test/unit_tests/cvodes/CXX_serial/cvs_test_kpr_--eta_min_es_2_--small_nst_5.out -$tar $tarfile $distrobase/test/unit_tests/cvodes/CXX_serial/cvs_test_kpr_--eta_min_fx_1.0_--eta_max_fx_2.0.out -$tar $tarfile $distrobase/test/unit_tests/cvodes/CXX_serial/cvs_test_kpr_--eta_min_fx_1.0_--eta_min_0.5.out -$tar $tarfile $distrobase/test/unit_tests/cvodes/CXX_serial/cvs_test_kpr_--eta_min_gs_2.out +$tar $tarfile $distrobase/test/unit_tests/cvodes diff --git a/scripts/ida b/scripts/ida index e616bf7a19..cc320c286b 100755 --- a/scripts/ida +++ b/scripts/ida @@ -162,19 +162,4 @@ $tar $tarfile $distrobase/examples/ida/F2003_serial/idaRoberts_dns_f2003.out echo " --- Add ida unit tests to $tarfile" -$tar $tarfile $distrobase/test/unit_tests/ida/CMakeLists.txt -$tar $tarfile $distrobase/test/unit_tests/ida/C_serial/CMakeLists.txt -$tar $tarfile $distrobase/test/unit_tests/ida/C_serial/ida_test_getuserdata.c -$tar $tarfile $distrobase/test/unit_tests/ida/CXX_serial/CMakeLists.txt -$tar $tarfile $distrobase/test/unit_tests/ida/CXX_serial/ida_test_getjac.cpp -$tar $tarfile $distrobase/test/unit_tests/ida/CXX_serial/ida_test_getjac.out -$tar $tarfile $distrobase/test/unit_tests/ida/CXX_serial/ida_test_kpr.cpp -$tar $tarfile $distrobase/test/unit_tests/ida/CXX_serial/ida_test_kpr.hpp -$tar $tarfile $distrobase/test/unit_tests/ida/CXX_serial/ida_test_kpr.out -$tar $tarfile $distrobase/test/unit_tests/ida/CXX_serial/ida_test_kpr_--dcj_0.9.out -$tar $tarfile $distrobase/test/unit_tests/ida/CXX_serial/ida_test_kpr_--eta_cf_0.5.out -$tar $tarfile $distrobase/test/unit_tests/ida/CXX_serial/ida_test_kpr_--eta_max_fs_2.out -$tar $tarfile $distrobase/test/unit_tests/ida/CXX_serial/ida_test_kpr_--eta_min_2.out -$tar $tarfile $distrobase/test/unit_tests/ida/CXX_serial/ida_test_kpr_--eta_min_ef_0.5.out -$tar $tarfile $distrobase/test/unit_tests/ida/CXX_serial/ida_test_kpr_--eta_min_fx_1.0_--eta_max_fx_2.0.out -$tar $tarfile $distrobase/test/unit_tests/ida/CXX_serial/ida_test_kpr_--eta_min_fx_1.0_--eta_min_0.5.out +$tar $tarfile $distrobase/test/unit_tests/ida diff --git a/scripts/idas b/scripts/idas index a373b1eeda..7604bb5983 100755 --- a/scripts/idas +++ b/scripts/idas @@ -151,18 +151,4 @@ $tar $tarfile $distrobase/examples/idas/F2003_serial/idasHeat2D_kry_f2003.out echo " --- Add idas unit tests to $tarfile" -$tar $tarfile $distrobase/test/unit_tests/idas/CMakeLists.txt -$tar $tarfile $distrobase/test/unit_tests/idas/C_serial/CMakeLists.txt -$tar $tarfile $distrobase/test/unit_tests/idas/C_serial/idas_test_getuserdata.c -$tar $tarfile $distrobase/test/unit_tests/idas/CXX_serial/CMakeLists.txt -$tar $tarfile $distrobase/test/unit_tests/idas/CXX_serial/idas_test_getjac.cpp -$tar $tarfile $distrobase/test/unit_tests/idas/CXX_serial/idas_test_getjac.out -$tar $tarfile $distrobase/test/unit_tests/idas/CXX_serial/idas_test_kpr.cpp -$tar $tarfile $distrobase/test/unit_tests/idas/CXX_serial/idas_test_kpr.hpp -$tar $tarfile $distrobase/test/unit_tests/idas/CXX_serial/idas_test_kpr.out -$tar $tarfile $distrobase/test/unit_tests/idas/CXX_serial/idas_test_kpr_--dcj_0.9.out -$tar $tarfile $distrobase/test/unit_tests/idas/CXX_serial/idas_test_kpr_--eta_cf_0.5.out -$tar $tarfile $distrobase/test/unit_tests/idas/CXX_serial/idas_test_kpr_--eta_min_2.out -$tar $tarfile $distrobase/test/unit_tests/idas/CXX_serial/idas_test_kpr_--eta_min_ef_0.5.out -$tar $tarfile $distrobase/test/unit_tests/idas/CXX_serial/idas_test_kpr_--eta_min_fx_1.0_--eta_max_fx_2.0.out -$tar $tarfile $distrobase/test/unit_tests/idas/CXX_serial/idas_test_kpr_--eta_min_fx_1.0_--eta_min_0.5.out +$tar $tarfile $distrobase/test/unit_tests/idas diff --git a/scripts/kinsol b/scripts/kinsol index cc081f8c2d..c7bf7dc752 100755 --- a/scripts/kinsol +++ b/scripts/kinsol @@ -145,9 +145,4 @@ $tar $tarfile $distrobase/examples/kinsol/F2003_serial/kinLaplace_picard_kry_f20 echo " --- Add kinsol unit tests to $tarfile" -$tar $tarfile $distrobase/test/unit_tests/kinsol/CMakeLists.txt -$tar $tarfile $distrobase/test/unit_tests/kinsol/C_serial/CMakeLists.txt -$tar $tarfile $distrobase/test/unit_tests/kinsol/C_serial/kin_test_getuserdata.c -$tar $tarfile $distrobase/test/unit_tests/kinsol/CXX_serial/CMakeLists.txt -$tar $tarfile $distrobase/test/unit_tests/kinsol/CXX_serial/kin_test_getjac.cpp -$tar $tarfile $distrobase/test/unit_tests/kinsol/CXX_serial/kin_test_getjac.out +$tar $tarfile $distrobase/test/unit_tests/kinsol diff --git a/scripts/shared b/scripts/shared index 2af50abff3..7304bc5df8 100755 --- a/scripts/shared +++ b/scripts/shared @@ -837,15 +837,4 @@ echo " --- Add unit tests files to $tarfile" $tar $tarfile $distrobase/test/unit_tests/CMakeLists.txt $tar $tarfile $distrobase/test/unit_tests/reductions -$tar $tarfile $distrobase/test/unit_tests/reductions/CMakeLists.txt -$tar $tarfile $distrobase/test/unit_tests/reductions/test_reduction_operators.cpp -$tar $tarfile $distrobase/test/unit_tests/sunmemory/CMakeLists.txt -$tar $tarfile $distrobase/test/unit_tests/sunmemory/sys -$tar $tarfile $distrobase/test/unit_tests/sunmemory/sys/CMakeLists.txt -$tar $tarfile $distrobase/test/unit_tests/sunmemory/sys/test_sunmemory_sys.cpp -$tar $tarfile $distrobase/test/unit_tests/sunmemory/cuda/CMakeLists.txt -$tar $tarfile $distrobase/test/unit_tests/sunmemory/cuda/test_sunmemory_cuda.cu -$tar $tarfile $distrobase/test/unit_tests/sunmemory/hip/CMakeLists.txt -$tar $tarfile $distrobase/test/unit_tests/sunmemory/hip/test_sunmemory_hip.cpp -$tar $tarfile $distrobase/test/unit_tests/sunmemory/sycl/CMakeLists.txt -$tar $tarfile $distrobase/test/unit_tests/sunmemory/sycl/test_sunmemory_sycl.cpp +$tar $tarfile $distrobase/test/unit_tests/sunmemory diff --git a/src/arkode/arkode.c b/src/arkode/arkode.c index 43a3920a18..601abca7ae 100644 --- a/src/arkode/arkode.c +++ b/src/arkode/arkode.c @@ -967,22 +967,31 @@ int arkEvolve(ARKodeMem ark_mem, realtype tout, N_Vector yout, } /* Check if tn is at tstop or near tstop */ - if ( ark_mem->tstopset ) { + if ( ark_mem->tstopset ) + { troundoff = FUZZ_FACTOR*ark_mem->uround * (SUNRabs(ark_mem->tcur) + SUNRabs(ark_mem->h)); - if ( SUNRabs(ark_mem->tcur - ark_mem->tstop) <= troundoff) { - if (ark_mem->tstopinterp) { - (void) arkGetDky(ark_mem, ark_mem->tstop, 0, yout); - } else { - N_VScale(ONE, ark_mem->yn, yout); + + if ( SUNRabs(ark_mem->tcur - ark_mem->tstop) <= troundoff) + { + /* Ensure tout >= tstop, otherwise check for tout return below */ + if ((tout - ark_mem->tstop) * ark_mem->h >= ZERO || + SUNRabs(tout - ark_mem->tstop) <= troundoff) + { + if (ark_mem->tstopinterp) { + (void) arkGetDky(ark_mem, ark_mem->tstop, 0, yout); + } else { + N_VScale(ONE, ark_mem->yn, yout); + } + ark_mem->tretlast = *tret = ark_mem->tstop; + ark_mem->tstopset = SUNFALSE; + istate = ARK_TSTOP_RETURN; + break; } - ark_mem->tretlast = *tret = ark_mem->tstop; - ark_mem->tstopset = SUNFALSE; - istate = ARK_TSTOP_RETURN; - break; } /* limit upcoming step if it will overcome tstop */ - if ( (ark_mem->tcur + ark_mem->hprime - ark_mem->tstop)*ark_mem->h > ZERO ) { + else if ( (ark_mem->tcur + ark_mem->hprime - ark_mem->tstop)*ark_mem->h > ZERO ) + { ark_mem->hprime = (ark_mem->tstop - ark_mem->tcur) * (ONE-FOUR*ark_mem->uround); ark_mem->eta = ark_mem->hprime/ark_mem->h; @@ -2105,24 +2114,35 @@ int arkStopTests(ARKodeMem ark_mem, realtype tout, N_Vector yout, } /* end of root stop check */ /* Test for tn at tstop or near tstop */ - if ( ark_mem->tstopset ) { - - if ( SUNRabs(ark_mem->tcur - ark_mem->tstop) <= troundoff) { - *ier = arkGetDky(ark_mem, ark_mem->tstop, 0, yout); - if (*ier != ARK_SUCCESS) { - arkProcessError(ark_mem, ARK_ILL_INPUT, "ARKODE", "arkStopTests", - MSG_ARK_BAD_TSTOP, ark_mem->tstop, ark_mem->tcur); - *ier = ARK_ILL_INPUT; + if ( ark_mem->tstopset ) + { + if ( SUNRabs(ark_mem->tcur - ark_mem->tstop) <= troundoff) + { + /* Ensure tout >= tstop, otherwise check for tout return below */ + if ((tout - ark_mem->tstop) * ark_mem->h >= ZERO || + SUNRabs(tout - ark_mem->tstop) <= troundoff) + { + if (ark_mem->tstopinterp) + { + *ier = arkGetDky(ark_mem, ark_mem->tstop, 0, yout); + if (*ier != ARK_SUCCESS) { + arkProcessError(ark_mem, ARK_ILL_INPUT, "ARKODE", "arkStopTests", + MSG_ARK_BAD_TSTOP, ark_mem->tstop, ark_mem->tcur); + *ier = ARK_ILL_INPUT; + return(1); + } + } else { + N_VScale(ONE, ark_mem->yn, yout); + } + ark_mem->tretlast = *tret = ark_mem->tstop; + ark_mem->tstopset = SUNFALSE; + *ier = ARK_TSTOP_RETURN; return(1); } - ark_mem->tretlast = *tret = ark_mem->tstop; - ark_mem->tstopset = SUNFALSE; - *ier = ARK_TSTOP_RETURN; - return(1); } - /* If next step would overtake tstop, adjust stepsize */ - if ( (ark_mem->tcur + ark_mem->hprime - ark_mem->tstop)*ark_mem->h > ZERO ) { + else if ( (ark_mem->tcur + ark_mem->hprime - ark_mem->tstop)*ark_mem->h > ZERO ) + { ark_mem->hprime = (ark_mem->tstop - ark_mem->tcur)*(ONE-FOUR*ark_mem->uround); ark_mem->eta = ark_mem->hprime/ark_mem->h; } diff --git a/src/cvode/cvode.c b/src/cvode/cvode.c index 2fd769b299..dddf19e171 100644 --- a/src/cvode/cvode.c +++ b/src/cvode/cvode.c @@ -1233,32 +1233,38 @@ int CVode(void *cvode_mem, realtype tout, N_Vector yout, } /* end of root stop check */ /* Test for tn at tstop or near tstop */ - if ( cv_mem->cv_tstopset ) { - - if ( SUNRabs(cv_mem->cv_tn - cv_mem->cv_tstop) <= troundoff ) { - if (cv_mem->cv_tstopinterp) { - ier = CVodeGetDky(cv_mem, cv_mem->cv_tstop, 0, yout); - if (ier != CV_SUCCESS) { - cvProcessError(cv_mem, CV_ILL_INPUT, "CVODE", "CVode", - MSGCV_BAD_TSTOP, cv_mem->cv_tstop, cv_mem->cv_tn); - SUNDIALS_MARK_FUNCTION_END(CV_PROFILER); - return(CV_ILL_INPUT); + if ( cv_mem->cv_tstopset ) + { + /* Test for tn at tstop */ + if ( SUNRabs(cv_mem->cv_tn - cv_mem->cv_tstop) <= troundoff ) + { + /* Ensure tout >= tstop, otherwise check for tout return below */ + if ((tout - cv_mem->cv_tstop) * cv_mem->cv_h >= ZERO || + SUNRabs(tout - cv_mem->cv_tstop) <= troundoff) + { + if (cv_mem->cv_tstopinterp) { + ier = CVodeGetDky(cv_mem, cv_mem->cv_tstop, 0, yout); + if (ier != CV_SUCCESS) { + cvProcessError(cv_mem, CV_ILL_INPUT, "CVODE", "CVode", + MSGCV_BAD_TSTOP, cv_mem->cv_tstop, cv_mem->cv_tn); + SUNDIALS_MARK_FUNCTION_END(CV_PROFILER); + return(CV_ILL_INPUT); + } + } else { + N_VScale(ONE, cv_mem->cv_zn[0], yout); } - } else { - N_VScale(ONE, cv_mem->cv_zn[0], yout); + cv_mem->cv_tretlast = *tret = cv_mem->cv_tstop; + cv_mem->cv_tstopset = SUNFALSE; + SUNDIALS_MARK_FUNCTION_END(CV_PROFILER); + return(CV_TSTOP_RETURN); } - cv_mem->cv_tretlast = *tret = cv_mem->cv_tstop; - cv_mem->cv_tstopset = SUNFALSE; - SUNDIALS_MARK_FUNCTION_END(CV_PROFILER); - return(CV_TSTOP_RETURN); } - /* If next step would overtake tstop, adjust stepsize */ - if ( (cv_mem->cv_tn + cv_mem->cv_hprime - cv_mem->cv_tstop)*cv_mem->cv_h > ZERO ) { + else if ( (cv_mem->cv_tn + cv_mem->cv_hprime - cv_mem->cv_tstop)*cv_mem->cv_h > ZERO ) + { cv_mem->cv_hprime = (cv_mem->cv_tstop - cv_mem->cv_tn)*(ONE-FOUR*cv_mem->cv_uround); cv_mem->cv_eta = cv_mem->cv_hprime / cv_mem->cv_h; } - } /* In CV_NORMAL mode, test if tout was reached */ @@ -1424,27 +1430,35 @@ int CVode(void *cvode_mem, realtype tout, N_Vector yout, } /* Check if tn is at tstop or near tstop */ - if ( cv_mem->cv_tstopset ) { - + if ( cv_mem->cv_tstopset ) + { troundoff = FUZZ_FACTOR * cv_mem->cv_uround * (SUNRabs(cv_mem->cv_tn) + SUNRabs(cv_mem->cv_h)); - if ( SUNRabs(cv_mem->cv_tn - cv_mem->cv_tstop) <= troundoff) { - if (cv_mem->cv_tstopinterp) { - (void) CVodeGetDky(cv_mem, cv_mem->cv_tstop, 0, yout); - } else { - N_VScale(ONE, cv_mem->cv_zn[0], yout); + + /* Test for tn at tstop */ + if ( SUNRabs(cv_mem->cv_tn - cv_mem->cv_tstop) <= troundoff) + { + /* Ensure tout >= tstop, otherwise check for tout return below */ + if ((tout - cv_mem->cv_tstop) * cv_mem->cv_h >= ZERO || + SUNRabs(tout - cv_mem->cv_tstop) <= troundoff) + { + if (cv_mem->cv_tstopinterp) { + (void) CVodeGetDky(cv_mem, cv_mem->cv_tstop, 0, yout); + } else { + N_VScale(ONE, cv_mem->cv_zn[0], yout); + } + cv_mem->cv_tretlast = *tret = cv_mem->cv_tstop; + cv_mem->cv_tstopset = SUNFALSE; + istate = CV_TSTOP_RETURN; + break; } - cv_mem->cv_tretlast = *tret = cv_mem->cv_tstop; - cv_mem->cv_tstopset = SUNFALSE; - istate = CV_TSTOP_RETURN; - break; } - - if ( (cv_mem->cv_tn + cv_mem->cv_hprime - cv_mem->cv_tstop)*cv_mem->cv_h > ZERO ) { + /* If next step would overtake tstop, adjust stepsize */ + else if ( (cv_mem->cv_tn + cv_mem->cv_hprime - cv_mem->cv_tstop)*cv_mem->cv_h > ZERO ) + { cv_mem->cv_hprime = (cv_mem->cv_tstop - cv_mem->cv_tn)*(ONE-FOUR*cv_mem->cv_uround); cv_mem->cv_eta = cv_mem->cv_hprime / cv_mem->cv_h; } - } /* In NORMAL mode, check if tout reached */ diff --git a/src/cvodes/cvodes.c b/src/cvodes/cvodes.c index 204d207fb0..cd1fabfd3d 100644 --- a/src/cvodes/cvodes.c +++ b/src/cvodes/cvodes.c @@ -3059,32 +3059,38 @@ int CVode(void *cvode_mem, realtype tout, N_Vector yout, } /* end of root stop check */ /* Test for tn at tstop or near tstop */ - if ( cv_mem->cv_tstopset ) { - - if ( SUNRabs(cv_mem->cv_tn - cv_mem->cv_tstop) <= troundoff ) { - if (cv_mem->cv_tstopinterp) { - ier = CVodeGetDky(cv_mem, cv_mem->cv_tstop, 0, yout); - if (ier != CV_SUCCESS) { - cvProcessError(cv_mem, CV_ILL_INPUT, "CVODES", "CVode", - MSGCV_BAD_TSTOP, cv_mem->cv_tstop, cv_mem->cv_tn); - SUNDIALS_MARK_FUNCTION_END(CV_PROFILER); - return(CV_ILL_INPUT); + if ( cv_mem->cv_tstopset ) + { + /* Test for tn at tstop */ + if ( SUNRabs(cv_mem->cv_tn - cv_mem->cv_tstop) <= troundoff ) + { + /* Ensure tout >= tstop, otherwise check for tout return below */ + if ((tout - cv_mem->cv_tstop) * cv_mem->cv_h >= ZERO || + SUNRabs(tout - cv_mem->cv_tstop) <= troundoff) + { + if (cv_mem->cv_tstopinterp) { + ier = CVodeGetDky(cv_mem, cv_mem->cv_tstop, 0, yout); + if (ier != CV_SUCCESS) { + cvProcessError(cv_mem, CV_ILL_INPUT, "CVODES", "CVode", + MSGCV_BAD_TSTOP, cv_mem->cv_tstop, cv_mem->cv_tn); + SUNDIALS_MARK_FUNCTION_END(CV_PROFILER); + return(CV_ILL_INPUT); + } + } else { + N_VScale(ONE, cv_mem->cv_zn[0], yout); } - } else { - N_VScale(ONE, cv_mem->cv_zn[0], yout); + cv_mem->cv_tretlast = *tret = cv_mem->cv_tstop; + cv_mem->cv_tstopset = SUNFALSE; + SUNDIALS_MARK_FUNCTION_END(CV_PROFILER); + return(CV_TSTOP_RETURN); } - cv_mem->cv_tretlast = *tret = cv_mem->cv_tstop; - cv_mem->cv_tstopset = SUNFALSE; - SUNDIALS_MARK_FUNCTION_END(CV_PROFILER); - return(CV_TSTOP_RETURN); } - /* If next step would overtake tstop, adjust stepsize */ - if ( (cv_mem->cv_tn + cv_mem->cv_hprime - cv_mem->cv_tstop)*cv_mem->cv_h > ZERO ) { + else if ( (cv_mem->cv_tn + cv_mem->cv_hprime - cv_mem->cv_tstop)*cv_mem->cv_h > ZERO ) + { cv_mem->cv_hprime = (cv_mem->cv_tstop - cv_mem->cv_tn)*(ONE-FOUR*cv_mem->cv_uround); cv_mem->cv_eta = cv_mem->cv_hprime / cv_mem->cv_h; } - } /* In CV_NORMAL mode, test if tout was reached */ @@ -3294,27 +3300,35 @@ int CVode(void *cvode_mem, realtype tout, N_Vector yout, } /* Check if tn is at tstop or near tstop */ - if ( cv_mem->cv_tstopset ) { - + if ( cv_mem->cv_tstopset ) + { troundoff = FUZZ_FACTOR * cv_mem->cv_uround * (SUNRabs(cv_mem->cv_tn) + SUNRabs(cv_mem->cv_h)); - if ( SUNRabs(cv_mem->cv_tn - cv_mem->cv_tstop) <= troundoff) { - if (cv_mem->cv_tstopinterp) { - (void) CVodeGetDky(cv_mem, cv_mem->cv_tstop, 0, yout); - } else { - N_VScale(ONE, cv_mem->cv_zn[0], yout); + + /* Test for tn at tstop */ + if ( SUNRabs(cv_mem->cv_tn - cv_mem->cv_tstop) <= troundoff) + { + /* Ensure tout >= tstop, otherwise check for tout return below */ + if ((tout - cv_mem->cv_tstop) * cv_mem->cv_h >= ZERO || + SUNRabs(tout - cv_mem->cv_tstop) <= troundoff) + { + if (cv_mem->cv_tstopinterp) { + (void) CVodeGetDky(cv_mem, cv_mem->cv_tstop, 0, yout); + } else { + N_VScale(ONE, cv_mem->cv_zn[0], yout); + } + cv_mem->cv_tretlast = *tret = cv_mem->cv_tstop; + cv_mem->cv_tstopset = SUNFALSE; + istate = CV_TSTOP_RETURN; + break; } - cv_mem->cv_tretlast = *tret = cv_mem->cv_tstop; - cv_mem->cv_tstopset = SUNFALSE; - istate = CV_TSTOP_RETURN; - break; } - - if ( (cv_mem->cv_tn + cv_mem->cv_hprime - cv_mem->cv_tstop)*cv_mem->cv_h > ZERO ) { + /* If next step would overtake tstop, adjust stepsize */ + else if ( (cv_mem->cv_tn + cv_mem->cv_hprime - cv_mem->cv_tstop)*cv_mem->cv_h > ZERO ) + { cv_mem->cv_hprime = (cv_mem->cv_tstop - cv_mem->cv_tn)*(ONE-FOUR*cv_mem->cv_uround); cv_mem->cv_eta = cv_mem->cv_hprime / cv_mem->cv_h; } - } /* In NORMAL mode, check if tout reached */ diff --git a/src/ida/ida.c b/src/ida/ida.c index 9e9b7c4b1d..2250bd6937 100644 --- a/src/ida/ida.c +++ b/src/ida/ida.c @@ -1977,28 +1977,42 @@ static int IDAStopTest1(IDAMem IDA_mem, realtype tout, realtype *tret, int ier; realtype troundoff; - if (IDA_mem->ida_tstopset) { - /* Test for tn past tstop, tn = tretlast, tn past tout, tn near tstop. */ - if ( (IDA_mem->ida_tn - IDA_mem->ida_tstop)*IDA_mem->ida_hh > ZERO) { + if (IDA_mem->ida_tstopset) + { + /* Test for tn past tstop */ + if ( (IDA_mem->ida_tn - IDA_mem->ida_tstop)*IDA_mem->ida_hh > ZERO) + { IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDA", "IDASolve", MSG_BAD_TSTOP, IDA_mem->ida_tstop, IDA_mem->ida_tn); return(IDA_ILL_INPUT); } troundoff = HUNDRED * IDA_mem->ida_uround * (SUNRabs(IDA_mem->ida_tn) + SUNRabs(IDA_mem->ida_hh)); - if (SUNRabs(IDA_mem->ida_tn - IDA_mem->ida_tstop) <= troundoff) { - ier = IDAGetSolution(IDA_mem, IDA_mem->ida_tstop, yret, ypret); - if (ier != IDA_SUCCESS) { - IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDA", "IDASolve", - MSG_BAD_TSTOP, IDA_mem->ida_tstop, IDA_mem->ida_tn); - return(IDA_ILL_INPUT); + + /* Test for tn at tstop */ + if (SUNRabs(IDA_mem->ida_tn - IDA_mem->ida_tstop) <= troundoff) + { + /* Ensure tout >= tstop, otherwise check for tout return below */ + if ((tout - IDA_mem->ida_tstop) * IDA_mem->ida_hh >= ZERO || + SUNRabs(tout - IDA_mem->ida_tstop) <= troundoff) + { + ier = IDAGetSolution(IDA_mem, IDA_mem->ida_tstop, yret, ypret); + if (ier != IDA_SUCCESS) + { + IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDA", "IDASolve", + MSG_BAD_TSTOP, IDA_mem->ida_tstop, IDA_mem->ida_tn); + return(IDA_ILL_INPUT); + } + *tret = IDA_mem->ida_tretlast = IDA_mem->ida_tstop; + IDA_mem->ida_tstopset = SUNFALSE; + return(IDA_TSTOP_RETURN); } - *tret = IDA_mem->ida_tretlast = IDA_mem->ida_tstop; - IDA_mem->ida_tstopset = SUNFALSE; - return(IDA_TSTOP_RETURN); } - if ((IDA_mem->ida_tn + IDA_mem->ida_hh - IDA_mem->ida_tstop)*IDA_mem->ida_hh > ZERO) + /* Test for tn approaching tstop */ + else if ((IDA_mem->ida_tn + IDA_mem->ida_hh - IDA_mem->ida_tstop)*IDA_mem->ida_hh > ZERO) + { IDA_mem->ida_hh = (IDA_mem->ida_tstop - IDA_mem->ida_tn)*(ONE - FOUR * IDA_mem->ida_uround); + } } switch (itask) { @@ -2065,17 +2079,28 @@ static int IDAStopTest2(IDAMem IDA_mem, realtype tout, realtype *tret, /* int ier; */ realtype troundoff; - if (IDA_mem->ida_tstopset) { - /* Test for tn at tstop and for tn near tstop */ + if (IDA_mem->ida_tstopset) + { troundoff = HUNDRED * IDA_mem->ida_uround * (SUNRabs(IDA_mem->ida_tn) + SUNRabs(IDA_mem->ida_hh)); - if (SUNRabs(IDA_mem->ida_tn - IDA_mem->ida_tstop) <= troundoff) { - /* ier = */ IDAGetSolution(IDA_mem, IDA_mem->ida_tstop, yret, ypret); - *tret = IDA_mem->ida_tretlast = IDA_mem->ida_tstop; - IDA_mem->ida_tstopset = SUNFALSE; - return(IDA_TSTOP_RETURN); + + /* Test for tn at tstop */ + if (SUNRabs(IDA_mem->ida_tn - IDA_mem->ida_tstop) <= troundoff) + { + /* Ensure tout >= tstop, otherwise check for tout return below */ + if ((tout - IDA_mem->ida_tstop) * IDA_mem->ida_hh >= ZERO || + SUNRabs(tout - IDA_mem->ida_tstop) <= troundoff) + { + /* ier = */ IDAGetSolution(IDA_mem, IDA_mem->ida_tstop, yret, ypret); + *tret = IDA_mem->ida_tretlast = IDA_mem->ida_tstop; + IDA_mem->ida_tstopset = SUNFALSE; + return(IDA_TSTOP_RETURN); + } } - if ((IDA_mem->ida_tn + IDA_mem->ida_hh - IDA_mem->ida_tstop)*IDA_mem->ida_hh > ZERO) + /* Test for tn approaching tstop */ + else if ((IDA_mem->ida_tn + IDA_mem->ida_hh - IDA_mem->ida_tstop)*IDA_mem->ida_hh > ZERO) + { IDA_mem->ida_hh = (IDA_mem->ida_tstop - IDA_mem->ida_tn)*(ONE - FOUR * IDA_mem->ida_uround); + } } switch (itask) { diff --git a/src/idas/idas.c b/src/idas/idas.c index a2b0874d03..0008a13375 100644 --- a/src/idas/idas.c +++ b/src/idas/idas.c @@ -4985,28 +4985,42 @@ static int IDAStopTest1(IDAMem IDA_mem, realtype tout, realtype *tret, int ier; realtype troundoff; - if (IDA_mem->ida_tstopset) { - /* Test for tn past tstop, tn past tretlast, and tn near tstop. */ - if ((IDA_mem->ida_tn - IDA_mem->ida_tstop)*IDA_mem->ida_hh > ZERO) { - IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDA", "IDASolve", + if (IDA_mem->ida_tstopset) + { + /* Test for tn past tstop */ + if ( (IDA_mem->ida_tn - IDA_mem->ida_tstop)*IDA_mem->ida_hh > ZERO) + { + IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDAS", "IDASolve", MSG_BAD_TSTOP, IDA_mem->ida_tstop, IDA_mem->ida_tn); return(IDA_ILL_INPUT); } troundoff = HUNDRED * IDA_mem->ida_uround * (SUNRabs(IDA_mem->ida_tn) + SUNRabs(IDA_mem->ida_hh)); - if (SUNRabs(IDA_mem->ida_tn - IDA_mem->ida_tstop) <= troundoff) { - ier = IDAGetSolution(IDA_mem, IDA_mem->ida_tstop, yret, ypret); - if (ier != IDA_SUCCESS) { - IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDA", "IDASolve", - MSG_BAD_TSTOP, IDA_mem->ida_tstop, IDA_mem->ida_tn); - return(IDA_ILL_INPUT); + + /* Test for tn at tstop */ + if (SUNRabs(IDA_mem->ida_tn - IDA_mem->ida_tstop) <= troundoff) + { + /* Ensure tout >= tstop, otherwise check for tout return below */ + if ((tout - IDA_mem->ida_tstop) * IDA_mem->ida_hh >= ZERO || + SUNRabs(tout - IDA_mem->ida_tstop) <= troundoff) + { + ier = IDAGetSolution(IDA_mem, IDA_mem->ida_tstop, yret, ypret); + if (ier != IDA_SUCCESS) + { + IDAProcessError(IDA_mem, IDA_ILL_INPUT, "IDAS", "IDASolve", + MSG_BAD_TSTOP, IDA_mem->ida_tstop, IDA_mem->ida_tn); + return(IDA_ILL_INPUT); + } + *tret = IDA_mem->ida_tretlast = IDA_mem->ida_tstop; + IDA_mem->ida_tstopset = SUNFALSE; + return(IDA_TSTOP_RETURN); } - *tret = IDA_mem->ida_tretlast = IDA_mem->ida_tstop; - IDA_mem->ida_tstopset = SUNFALSE; - return(IDA_TSTOP_RETURN); } - if ((IDA_mem->ida_tn + IDA_mem->ida_hh - IDA_mem->ida_tstop)*IDA_mem->ida_hh > ZERO) + /* Test for tn approaching tstop */ + else if ((IDA_mem->ida_tn + IDA_mem->ida_hh - IDA_mem->ida_tstop)*IDA_mem->ida_hh > ZERO) + { IDA_mem->ida_hh = (IDA_mem->ida_tstop - IDA_mem->ida_tn)*(ONE - FOUR * IDA_mem->ida_uround); + } } switch (itask) { @@ -5073,17 +5087,28 @@ static int IDAStopTest2(IDAMem IDA_mem, realtype tout, realtype *tret, /* int ier; */ realtype troundoff; - if (IDA_mem->ida_tstopset) { - /* Test for tn at tstop and for tn near tstop */ + if (IDA_mem->ida_tstopset) + { troundoff = HUNDRED * IDA_mem->ida_uround * (SUNRabs(IDA_mem->ida_tn) + SUNRabs(IDA_mem->ida_hh)); - if (SUNRabs(IDA_mem->ida_tn - IDA_mem->ida_tstop) <= troundoff) { - /* ier = */ IDAGetSolution(IDA_mem, IDA_mem->ida_tstop, yret, ypret); - *tret = IDA_mem->ida_tretlast = IDA_mem->ida_tstop; - IDA_mem->ida_tstopset = SUNFALSE; - return(IDA_TSTOP_RETURN); + + /* Test for tn at tstop */ + if (SUNRabs(IDA_mem->ida_tn - IDA_mem->ida_tstop) <= troundoff) + { + /* Ensure tout >= tstop, otherwise check for tout return below */ + if ((tout - IDA_mem->ida_tstop) * IDA_mem->ida_hh >= ZERO || + SUNRabs(tout - IDA_mem->ida_tstop) <= troundoff) + { + /* ier = */ IDAGetSolution(IDA_mem, IDA_mem->ida_tstop, yret, ypret); + *tret = IDA_mem->ida_tretlast = IDA_mem->ida_tstop; + IDA_mem->ida_tstopset = SUNFALSE; + return(IDA_TSTOP_RETURN); + } } - if ((IDA_mem->ida_tn + IDA_mem->ida_hh - IDA_mem->ida_tstop)*IDA_mem->ida_hh > ZERO) + /* Test for tn approaching tstop */ + else if ((IDA_mem->ida_tn + IDA_mem->ida_hh - IDA_mem->ida_tstop)*IDA_mem->ida_hh > ZERO) + { IDA_mem->ida_hh = (IDA_mem->ida_tstop - IDA_mem->ida_tn)*(ONE - FOUR * IDA_mem->ida_uround); + } } switch (itask) { diff --git a/test/answers b/test/answers index b47ad4f1f5..8f1d469a42 160000 --- a/test/answers +++ b/test/answers @@ -1 +1 @@ -Subproject commit b47ad4f1f5da5548b62f1933dad38294d9943fc5 +Subproject commit 8f1d469a426ffb562361ab2aa1702ad15194cb2c diff --git a/test/unit_tests/arkode/C_serial/CMakeLists.txt b/test/unit_tests/arkode/C_serial/CMakeLists.txt index 597196c228..2c4daa7d74 100644 --- a/test/unit_tests/arkode/C_serial/CMakeLists.txt +++ b/test/unit_tests/arkode/C_serial/CMakeLists.txt @@ -30,6 +30,7 @@ set(ARKODE_unit_tests "ark_test_interp\;-10000" "ark_test_interp\;-1000000" "ark_test_reset\;" + "ark_test_tstop\;" ) # Add the build and install targets for each test diff --git a/test/unit_tests/arkode/C_serial/ark_test_tstop.c b/test/unit_tests/arkode/C_serial/ark_test_tstop.c new file mode 100644 index 0000000000..66a17b5a46 --- /dev/null +++ b/test/unit_tests/arkode/C_serial/ark_test_tstop.c @@ -0,0 +1,231 @@ +/* ----------------------------------------------------------------------------- + * Programmer(s): David J. Gardner @ LLNL + * ----------------------------------------------------------------------------- + * SUNDIALS Copyright Start + * Copyright (c) 2002-2023, 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 setting stop time + * ---------------------------------------------------------------------------*/ + +#include +#include + +#include "nvector/nvector_serial.h" +#include "sundials/sundials_matrix.h" +#include "sundials/sundials_nvector.h" +#include "sunmatrix/sunmatrix_dense.h" +#include "sunlinsol/sunlinsol_dense.h" +#include "arkode/arkode_arkstep.h" + +#if defined(SUNDIALS_EXTENDED_PRECISION) +#define GSYM "Lg" +#else +#define GSYM "g" +#endif + +#define ZERO SUN_RCONST(0.0) +#define ONE SUN_RCONST(1.0) + + +int ode_rhs(sunrealtype t, N_Vector y, N_Vector ydot, void *user_data) +{ + sunrealtype* ydot_data = N_VGetArrayPointer(ydot); + ydot_data[0] = ONE; + return 0; +} + + +int ode_jac(sunrealtype t, N_Vector y, N_Vector f, SUNMatrix J, void *user_data, + N_Vector tempv1, N_Vector tempv2, N_Vector tempv3) +{ + sunrealtype* J_data = SUNDenseMatrix_Data(J); + J_data[0] = ZERO; + return 0; +} + + +int main(int argc, char *argv[]) +{ + SUNContext sunctx = NULL; + N_Vector y = NULL; + SUNMatrix A = NULL; + SUNLinearSolver LS = NULL; + void* arkode_mem = NULL; + + int flag = 0; + int arkode_flag = 0; + int i = 0; + sunrealtype tout = SUN_RCONST(0.10); + sunrealtype dt_tout = SUN_RCONST(0.25); + sunrealtype tstop = SUN_RCONST(0.30); + sunrealtype dt_tstop = SUN_RCONST(0.30); + sunrealtype tret = ZERO; + sunrealtype tcur = ZERO; + + /* -------------- + * Create context + * -------------- */ + + flag = SUNContext_Create(NULL, &sunctx); + if (flag) + { + fprintf(stderr, "SUNContext_Create returned %i\n", flag); + return 1; + } + + /* ----------------------- + * Setup initial condition + * ----------------------- */ + + y = N_VNew_Serial(1, sunctx); + if (!y) { return 1; } + N_VConst(ZERO, y); + + /* ----------- + * Setup ARKODE + * ----------- */ + + arkode_mem = ARKStepCreate(NULL, ode_rhs, ZERO, y, sunctx); + if (!arkode_mem) { return 1; } + + flag = ARKStepSStolerances(arkode_mem, SUN_RCONST(1.0e-4), SUN_RCONST(1.0e-8)); + if (flag) { return 1; } + + A = SUNDenseMatrix(1, 1, sunctx); + if (!A) { return 1; } + + LS = SUNLinSol_Dense(y, A, sunctx); + if (!LS) { return 1; } + + flag = ARKStepSetLinearSolver(arkode_mem, LS, A); + if (flag) { return 1; } + + flag = ARKStepSetJacFn(arkode_mem, ode_jac); + if (flag) { return 1; } + + flag = ARKStepSetOrder(arkode_mem, 2); + if (flag) { return 1; } + + flag = ARKStepSetStopTime(arkode_mem, tstop); + if (flag) { return 1; } + + /* --------------- + * Advance in time + * --------------- */ + + printf("0: tout = %" GSYM ", tstop = %" GSYM ", tret = %" GSYM ", tcur = %" GSYM "\n", + tout, tstop, tret, tcur); + + for (i = 1; i <= 6; i++) + { + arkode_flag = ARKStepEvolve(arkode_mem, tout, y, &tret, ARK_NORMAL); + if (arkode_flag < 0) { flag = 1; break; } + + flag = ARKStepGetCurrentTime(arkode_mem, &tcur); + if (flag) { break; } + + printf("%i: tout = %" GSYM ", tstop = %" GSYM ", tret = %" GSYM ", tcur = %" GSYM ", return = %i\n", + i, tout, tstop, tret, tcur, arkode_flag); + + /* First return: output time < stop time */ + if (i == 1 && arkode_flag != ARK_SUCCESS) + { + printf("ERROR: Expected output return!\n"); + flag = 1; + break; + } + + /* Second return: output time > stop time */ + if (i == 2) + { + if (arkode_flag != ARK_TSTOP_RETURN) + { + printf("ERROR: Expected stop return!\n"); + flag = 1; + break; + } + + /* Update stop time */ + tstop += dt_tstop; + flag = ARKStepSetStopTime(arkode_mem, tstop); + if (flag) { break; } + } + + /* Third return: output time = stop time */ + if (i == 3) + { + if (arkode_flag != ARK_TSTOP_RETURN) + { + printf("ERROR: Expected stop return!\n"); + flag = 1; + break; + } + + /* Update stop time */ + tstop += dt_tstop; + flag = ARKStepSetStopTime(arkode_mem, tstop); + if (flag) { break; } + } + + /* Fourth return: output time < stop time but both output time and the stop + time are overtaken in the same step */ + if (i == 4) + { + if (arkode_flag != ARK_SUCCESS) + { + printf("ERROR: Expected output return!\n"); + flag = 1; + break; + } + } + + /* Fifth return: output time > stop time after step where both output time + and the stop time were overtaken in the same step */ + if (i == 5) + { + if (arkode_flag != ARK_TSTOP_RETURN) + { + printf("ERROR: Expected stop return!\n"); + flag = 1; + break; + } + } + + /* Sixth return: output time < stop time (not updated) */ + if (i == 6 && arkode_flag != ARK_SUCCESS) + { + printf("ERROR: Expected output return!\n"); + flag = 1; + break; + } + + /* update output time */ + tout += dt_tout; + } + + /* -------- + * Clean up + * -------- */ + + ARKStepFree(&arkode_mem); + N_VDestroy(y); + SUNMatDestroy(A); + SUNLinSolFree(LS); + SUNContext_Free(&sunctx); + + if (!flag) + { + printf("SUCCESS\n"); + } + + return flag; +} + +/*---- end of file ----*/ diff --git a/test/unit_tests/cvode/C_serial/CMakeLists.txt b/test/unit_tests/cvode/C_serial/CMakeLists.txt index e576d75ddd..f396478a16 100644 --- a/test/unit_tests/cvode/C_serial/CMakeLists.txt +++ b/test/unit_tests/cvode/C_serial/CMakeLists.txt @@ -17,6 +17,7 @@ # List of test tuples of the form "name\;args" set(unit_tests "cv_test_getuserdata\;" + "cv_test_tstop\;" ) # Add the build and install targets for each test diff --git a/test/unit_tests/cvode/C_serial/cv_test_tstop.c b/test/unit_tests/cvode/C_serial/cv_test_tstop.c new file mode 100644 index 0000000000..50c7e053d6 --- /dev/null +++ b/test/unit_tests/cvode/C_serial/cv_test_tstop.c @@ -0,0 +1,234 @@ +/* ----------------------------------------------------------------------------- + * Programmer(s): David J. Gardner @ LLNL + * ----------------------------------------------------------------------------- + * SUNDIALS Copyright Start + * Copyright (c) 2002-2023, 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 setting stop time + * ---------------------------------------------------------------------------*/ + +#include +#include + +#include "nvector/nvector_serial.h" +#include "sundials/sundials_matrix.h" +#include "sundials/sundials_nvector.h" +#include "sunmatrix/sunmatrix_dense.h" +#include "sunlinsol/sunlinsol_dense.h" +#include "cvode/cvode.h" + +#if defined(SUNDIALS_EXTENDED_PRECISION) +#define GSYM "Lg" +#else +#define GSYM "g" +#endif + +#define ZERO SUN_RCONST(0.0) +#define ONE SUN_RCONST(1.0) + + +int ode_rhs(sunrealtype t, N_Vector y, N_Vector ydot, void *user_data) +{ + sunrealtype* ydot_data = N_VGetArrayPointer(ydot); + ydot_data[0] = ONE; + return 0; +} + + +int ode_jac(sunrealtype t, N_Vector y, N_Vector f, SUNMatrix J, void *user_data, + N_Vector tempv1, N_Vector tempv2, N_Vector tempv3) +{ + sunrealtype* J_data = SUNDenseMatrix_Data(J); + J_data[0] = ZERO; + return 0; +} + + +int main(int argc, char *argv[]) +{ + SUNContext sunctx = NULL; + N_Vector y = NULL; + SUNMatrix A = NULL; + SUNLinearSolver LS = NULL; + void* cvode_mem = NULL; + + int flag = 0; + int cvode_flag = 0; + int i = 0; + sunrealtype tout = SUN_RCONST(0.10); + sunrealtype dt_tout = SUN_RCONST(0.25); + sunrealtype tstop = SUN_RCONST(0.30); + sunrealtype dt_tstop = SUN_RCONST(0.30); + sunrealtype tret = ZERO; + sunrealtype tcur = ZERO; + + /* -------------- + * Create context + * -------------- */ + + flag = SUNContext_Create(NULL, &sunctx); + if (flag) + { + fprintf(stderr, "SUNContext_Create returned %i\n", flag); + return 1; + } + + /* ----------------------- + * Setup initial condition + * ----------------------- */ + + y = N_VNew_Serial(1, sunctx); + if (!y) { return 1; } + N_VConst(ZERO, y); + + /* ----------- + * Setup CVODE + * ----------- */ + + cvode_mem = CVodeCreate(CV_BDF, sunctx); + if (!cvode_mem) { return 1; } + + flag = CVodeInit(cvode_mem, ode_rhs, ZERO, y); + if (flag) { return 1; } + + flag = CVodeSStolerances(cvode_mem, SUN_RCONST(1.0e-4), SUN_RCONST(1.0e-8)); + if (flag) { return 1; } + + A = SUNDenseMatrix(1, 1, sunctx); + if (!A) { return 1; } + + LS = SUNLinSol_Dense(y, A, sunctx); + if (!LS) { return 1; } + + flag = CVodeSetLinearSolver(cvode_mem, LS, A); + if (flag) { return 1; } + + flag = CVodeSetJacFn(cvode_mem, ode_jac); + if (flag) { return 1; } + + flag = CVodeSetMaxOrd(cvode_mem, 1); + if (flag) { return 1; } + + flag = CVodeSetStopTime(cvode_mem, tstop); + if (flag) { return 1; } + + /* --------------- + * Advance in time + * --------------- */ + + printf("0: tout = %" GSYM ", tstop = %" GSYM ", tret = %" GSYM ", tcur = %" GSYM "\n", + tout, tstop, tret, tcur); + + for (i = 1; i <= 6; i++) + { + cvode_flag = CVode(cvode_mem, tout, y, &tret, CV_NORMAL); + if (cvode_flag < 0) { flag = 1; break; } + + flag = CVodeGetCurrentTime(cvode_mem, &tcur); + if (flag) { break; } + + printf("%i: tout = %" GSYM ", tstop = %" GSYM ", tret = %" GSYM ", tcur = %" GSYM ", return = %i\n", + i, tout, tstop, tret, tcur, cvode_flag); + + /* First return: output time < stop time */ + if (i == 1 && cvode_flag != CV_SUCCESS) + { + printf("ERROR: Expected output return!\n"); + flag = 1; + break; + } + + /* Second return: output time > stop time */ + if (i == 2) + { + if (cvode_flag != CV_TSTOP_RETURN) + { + printf("ERROR: Expected stop return!\n"); + flag = 1; + break; + } + + /* Update stop time */ + tstop += dt_tstop; + flag = CVodeSetStopTime(cvode_mem, tstop); + if (flag) { break; } + } + + /* Third return: output time = stop time */ + if (i == 3) + { + if (cvode_flag != CV_TSTOP_RETURN) + { + printf("ERROR: Expected stop return!\n"); + flag = 1; + break; + } + + /* Update stop time */ + tstop += dt_tstop; + flag = CVodeSetStopTime(cvode_mem, tstop); + if (flag) { break; } + } + + /* Fourth return: output time < stop time but both output time and the stop + time are overtaken in the same step */ + if (i == 4) + { + if (cvode_flag != CV_SUCCESS) + { + printf("ERROR: Expected output return!\n"); + flag = 1; + break; + } + } + + /* Fifth return: output time > stop time after step where both output time + and the stop time were overtaken in the same step */ + if (i == 5) + { + if (cvode_flag != CV_TSTOP_RETURN) + { + printf("ERROR: Expected stop return!\n"); + flag = 1; + break; + } + } + + /* Sixth return: output time < stop time (not updated) */ + if (i == 6 && cvode_flag != CV_SUCCESS) + { + printf("ERROR: Expected output return!\n"); + flag = 1; + break; + } + + /* update output time */ + tout += dt_tout; + } + + /* -------- + * Clean up + * -------- */ + + CVodeFree(&cvode_mem); + N_VDestroy(y); + SUNMatDestroy(A); + SUNLinSolFree(LS); + SUNContext_Free(&sunctx); + + if (!flag) + { + printf("SUCCESS\n"); + } + + return flag; +} + +/*---- end of file ----*/ diff --git a/test/unit_tests/cvodes/C_serial/CMakeLists.txt b/test/unit_tests/cvodes/C_serial/CMakeLists.txt index 0775ba2ab5..96c747becb 100644 --- a/test/unit_tests/cvodes/C_serial/CMakeLists.txt +++ b/test/unit_tests/cvodes/C_serial/CMakeLists.txt @@ -17,6 +17,7 @@ # List of test tuples of the form "name\;args" set(unit_tests "cvs_test_getuserdata\;" + "cvs_test_tstop\;" ) # Add the build and install targets for each test diff --git a/test/unit_tests/cvodes/C_serial/cvs_test_tstop.c b/test/unit_tests/cvodes/C_serial/cvs_test_tstop.c new file mode 100644 index 0000000000..5ce9c1c611 --- /dev/null +++ b/test/unit_tests/cvodes/C_serial/cvs_test_tstop.c @@ -0,0 +1,234 @@ +/* ----------------------------------------------------------------------------- + * Programmer(s): David J. Gardner @ LLNL + * ----------------------------------------------------------------------------- + * SUNDIALS Copyright Start + * Copyright (c) 2002-2023, 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 setting stop time + * ---------------------------------------------------------------------------*/ + +#include +#include + +#include "nvector/nvector_serial.h" +#include "sundials/sundials_matrix.h" +#include "sundials/sundials_nvector.h" +#include "sunmatrix/sunmatrix_dense.h" +#include "sunlinsol/sunlinsol_dense.h" +#include "cvodes/cvodes.h" + +#if defined(SUNDIALS_EXTENDED_PRECISION) +#define GSYM "Lg" +#else +#define GSYM "g" +#endif + +#define ZERO SUN_RCONST(0.0) +#define ONE SUN_RCONST(1.0) + + +int ode_rhs(sunrealtype t, N_Vector y, N_Vector ydot, void *user_data) +{ + sunrealtype* ydot_data = N_VGetArrayPointer(ydot); + ydot_data[0] = ONE; + return 0; +} + + +int ode_jac(sunrealtype t, N_Vector y, N_Vector f, SUNMatrix J, void *user_data, + N_Vector tempv1, N_Vector tempv2, N_Vector tempv3) +{ + sunrealtype* J_data = SUNDenseMatrix_Data(J); + J_data[0] = ZERO; + return 0; +} + + +int main(int argc, char *argv[]) +{ + SUNContext sunctx = NULL; + N_Vector y = NULL; + SUNMatrix A = NULL; + SUNLinearSolver LS = NULL; + void* cvode_mem = NULL; + + int flag = 0; + int cvode_flag = 0; + int i = 0; + sunrealtype tout = SUN_RCONST(0.10); + sunrealtype dt_tout = SUN_RCONST(0.25); + sunrealtype tstop = SUN_RCONST(0.30); + sunrealtype dt_tstop = SUN_RCONST(0.30); + sunrealtype tret = ZERO; + sunrealtype tcur = ZERO; + + /* -------------- + * Create context + * -------------- */ + + flag = SUNContext_Create(NULL, &sunctx); + if (flag) + { + fprintf(stderr, "SUNContext_Create returned %i\n", flag); + return 1; + } + + /* ----------------------- + * Setup initial condition + * ----------------------- */ + + y = N_VNew_Serial(1, sunctx); + if (!y) { return 1; } + N_VConst(ZERO, y); + + /* ----------- + * Setup CVODE + * ----------- */ + + cvode_mem = CVodeCreate(CV_BDF, sunctx); + if (!cvode_mem) { return 1; } + + flag = CVodeInit(cvode_mem, ode_rhs, ZERO, y); + if (flag) { return 1; } + + flag = CVodeSStolerances(cvode_mem, SUN_RCONST(1.0e-4), SUN_RCONST(1.0e-8)); + if (flag) { return 1; } + + A = SUNDenseMatrix(1, 1, sunctx); + if (!A) { return 1; } + + LS = SUNLinSol_Dense(y, A, sunctx); + if (!LS) { return 1; } + + flag = CVodeSetLinearSolver(cvode_mem, LS, A); + if (flag) { return 1; } + + flag = CVodeSetJacFn(cvode_mem, ode_jac); + if (flag) { return 1; } + + flag = CVodeSetMaxOrd(cvode_mem, 1); + if (flag) { return 1; } + + flag = CVodeSetStopTime(cvode_mem, tstop); + if (flag) { return 1; } + + /* --------------- + * Advance in time + * --------------- */ + + printf("0: tout = %" GSYM ", tstop = %" GSYM ", tret = %" GSYM ", tcur = %" GSYM "\n", + tout, tstop, tret, tcur); + + for (i = 1; i <= 6; i++) + { + cvode_flag = CVode(cvode_mem, tout, y, &tret, CV_NORMAL); + if (cvode_flag < 0) { flag = 1; break; } + + flag = CVodeGetCurrentTime(cvode_mem, &tcur); + if (flag) { break; } + + printf("%i: tout = %" GSYM ", tstop = %" GSYM ", tret = %" GSYM ", tcur = %" GSYM ", return = %i\n", + i, tout, tstop, tret, tcur, cvode_flag); + + /* First return: output time < stop time */ + if (i == 1 && cvode_flag != CV_SUCCESS) + { + printf("ERROR: Expected output return!\n"); + flag = 1; + break; + } + + /* Second return: output time > stop time */ + if (i == 2) + { + if (cvode_flag != CV_TSTOP_RETURN) + { + printf("ERROR: Expected stop return!\n"); + flag = 1; + break; + } + + /* Update stop time */ + tstop += dt_tstop; + flag = CVodeSetStopTime(cvode_mem, tstop); + if (flag) { break; } + } + + /* Third return: output time = stop time */ + if (i == 3) + { + if (cvode_flag != CV_TSTOP_RETURN) + { + printf("ERROR: Expected stop return!\n"); + flag = 1; + break; + } + + /* Update stop time */ + tstop += dt_tstop; + flag = CVodeSetStopTime(cvode_mem, tstop); + if (flag) { break; } + } + + /* Fourth return: output time < stop time but both output time and the stop + time are overtaken in the same step */ + if (i == 4) + { + if (cvode_flag != CV_SUCCESS) + { + printf("ERROR: Expected output return!\n"); + flag = 1; + break; + } + } + + /* Fifth return: output time > stop time after step where both output time + and the stop time were overtaken in the same step */ + if (i == 5) + { + if (cvode_flag != CV_TSTOP_RETURN) + { + printf("ERROR: Expected stop return!\n"); + flag = 1; + break; + } + } + + /* Sixth return: output time < stop time (not updated) */ + if (i == 6 && cvode_flag != CV_SUCCESS) + { + printf("ERROR: Expected output return!\n"); + flag = 1; + break; + } + + /* update output time */ + tout += dt_tout; + } + + /* -------- + * Clean up + * -------- */ + + CVodeFree(&cvode_mem); + N_VDestroy(y); + SUNMatDestroy(A); + SUNLinSolFree(LS); + SUNContext_Free(&sunctx); + + if (!flag) + { + printf("SUCCESS\n"); + } + + return flag; +} + +/*---- end of file ----*/ diff --git a/test/unit_tests/ida/C_serial/CMakeLists.txt b/test/unit_tests/ida/C_serial/CMakeLists.txt index f2060ee3ee..543b11c4f9 100644 --- a/test/unit_tests/ida/C_serial/CMakeLists.txt +++ b/test/unit_tests/ida/C_serial/CMakeLists.txt @@ -17,6 +17,7 @@ # List of test tuples of the form "name\;args" set(unit_tests "ida_test_getuserdata\;" + "ida_test_tstop\;" ) # Add the build and install targets for each test diff --git a/test/unit_tests/ida/C_serial/ida_test_tstop.c b/test/unit_tests/ida/C_serial/ida_test_tstop.c new file mode 100644 index 0000000000..491910ae1b --- /dev/null +++ b/test/unit_tests/ida/C_serial/ida_test_tstop.c @@ -0,0 +1,243 @@ +/* ----------------------------------------------------------------------------- + * Programmer(s): David J. Gardner @ LLNL + * ----------------------------------------------------------------------------- + * SUNDIALS Copyright Start + * Copyright (c) 2002-2023, 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 setting stop time + * ---------------------------------------------------------------------------*/ + +#include +#include + +#include "nvector/nvector_serial.h" +#include "sundials/sundials_matrix.h" +#include "sundials/sundials_nvector.h" +#include "sunmatrix/sunmatrix_dense.h" +#include "sunlinsol/sunlinsol_dense.h" +#include "ida/ida.h" + +#if defined(SUNDIALS_EXTENDED_PRECISION) +#define GSYM "Lg" +#else +#define GSYM "g" +#endif + +#define ZERO SUN_RCONST(0.0) +#define ONE SUN_RCONST(1.0) + + +int dae_res(sunrealtype t, N_Vector y, N_Vector ydot, N_Vector res, + void *user_data) +{ + sunrealtype* ydot_data = N_VGetArrayPointer(ydot); + sunrealtype* res_data = N_VGetArrayPointer(res); + res_data[0] = ydot_data[0] - ONE; + return 0; +} + + +int dae_jac(sunrealtype t, sunrealtype cj, N_Vector y, N_Vector yp, N_Vector rr, + SUNMatrix J, void *user_data, N_Vector tempv1, N_Vector tempv2, + N_Vector tempv3) +{ + sunrealtype* J_data = SUNDenseMatrix_Data(J); + J_data[0] = ONE; + return 0; +} + + +int main(int argc, char *argv[]) +{ + SUNContext sunctx = NULL; + N_Vector y = NULL; + N_Vector yp = NULL; + SUNMatrix A = NULL; + SUNLinearSolver LS = NULL; + void* ida_mem = NULL; + + int flag = 0; + int ida_flag = 0; + int i = 0; + sunrealtype tout = SUN_RCONST(0.10); + sunrealtype dt_tout = SUN_RCONST(0.25); + sunrealtype tstop = SUN_RCONST(0.30); + sunrealtype dt_tstop = SUN_RCONST(0.30); + sunrealtype tret = ZERO; + sunrealtype tcur = ZERO; + + /* -------------- + * Create context + * -------------- */ + + flag = SUNContext_Create(NULL, &sunctx); + if (flag) + { + fprintf(stderr, "SUNContext_Create returned %i\n", flag); + return 1; + } + + /* ----------------------- + * Setup initial condition + * ------------------------ */ + + y = N_VNew_Serial(1, sunctx); + if (!y) { return 1; } + N_VConst(ZERO, y); + + yp = N_VClone(y); + if (!yp) { return 1; } + N_VConst(ONE, yp); + + /* --------- + * Setup IDA + * --------- */ + + ida_mem = IDACreate(sunctx); + if (!ida_mem) { return 1; } + + flag = IDAInit(ida_mem, dae_res, ZERO, y, yp); + if (flag) { return 1; } + + flag = IDASStolerances(ida_mem, SUN_RCONST(1.0e-4), SUN_RCONST(1.0e-8)); + if (flag) { return 1; } + + A = SUNDenseMatrix(1, 1, sunctx); + if (!A) { return 1; } + + LS = SUNLinSol_Dense(y, A, sunctx); + if (!LS) { return 1; } + + flag = IDASetLinearSolver(ida_mem, LS, A); + if (flag) { return 1; } + + flag = IDASetJacFn(ida_mem, dae_jac); + if (flag) { return 1; } + + flag = IDASetMaxOrd(ida_mem, 1); + if (flag) { return 1; } + + flag = IDASetStopTime(ida_mem, tstop); + if (flag) { return 1; } + + /* --------------- + * Advance in time + * --------------- */ + + printf("0: tout = %" GSYM ", tstop = %" GSYM ", tret = %" GSYM ", tcur = %" GSYM "\n", + tout, tstop, tret, tcur); + + for (i = 1; i <= 6; i++) + { + ida_flag = IDASolve(ida_mem, tout, &tret, y, yp, IDA_NORMAL); + if (ida_flag < 0) { flag = 1; break; } + + flag = IDAGetCurrentTime(ida_mem, &tcur); + if (flag) { break; } + + printf("%i: tout = %" GSYM ", tstop = %" GSYM ", tret = %" GSYM ", tcur = %" GSYM ", return = %i\n", + i, tout, tstop, tret, tcur, ida_flag); + + /* First return: output time < stop time */ + if (i == 1 && ida_flag != IDA_SUCCESS) + { + printf("ERROR: Expected output return!\n"); + flag = 1; + break; + } + + /* Second return: output time > stop time */ + if (i == 2) + { + if (ida_flag != IDA_TSTOP_RETURN) + { + printf("ERROR: Expected stop return!\n"); + flag = 1; + break; + } + + /* Update stop time */ + tstop += dt_tstop; + flag = IDASetStopTime(ida_mem, tstop); + if (flag) { break; } + } + + /* Third return: output time = stop time */ + if (i == 3) + { + if (ida_flag != IDA_TSTOP_RETURN) + { + printf("ERROR: Expected stop return!\n"); + flag = 1; + break; + } + + /* Update stop time */ + tstop += dt_tstop; + flag = IDASetStopTime(ida_mem, tstop); + if (flag) { break; } + } + + /* Fourth return: output time < stop time but both output time and the stop + time are overtaken in the same step */ + if (i == 4) + { + if (ida_flag != IDA_SUCCESS) + { + printf("ERROR: Expected output return!\n"); + flag = 1; + break; + } + } + + /* Fifth return: output time > stop time after step where both output time + and the stop time were overtaken in the same step */ + if (i == 5) + { + if (ida_flag != IDA_TSTOP_RETURN) + { + printf("ERROR: Expected stop return!\n"); + flag = 1; + break; + } + } + + /* Sixth return: output time < stop time (not updated) */ + if (i == 6 && ida_flag != IDA_SUCCESS) + { + printf("ERROR: Expected output return!\n"); + flag = 1; + break; + } + + /* update output time */ + tout += dt_tout; + } + + /* -------- + * Clean up + * -------- */ + + IDAFree(&ida_mem); + N_VDestroy(y); + N_VDestroy(yp); + SUNMatDestroy(A); + SUNLinSolFree(LS); + SUNContext_Free(&sunctx); + + if (!flag) + { + printf("SUCCESS\n"); + } + + return flag; +} + +/*---- end of file ----*/ diff --git a/test/unit_tests/idas/C_serial/CMakeLists.txt b/test/unit_tests/idas/C_serial/CMakeLists.txt index 2514c73c1e..f928ff11ba 100644 --- a/test/unit_tests/idas/C_serial/CMakeLists.txt +++ b/test/unit_tests/idas/C_serial/CMakeLists.txt @@ -17,6 +17,7 @@ # List of test tuples of the form "name\;args" set(unit_tests "idas_test_getuserdata\;" + "idas_test_tstop\;" ) # Add the build and install targets for each test diff --git a/test/unit_tests/idas/C_serial/idas_test_tstop.c b/test/unit_tests/idas/C_serial/idas_test_tstop.c new file mode 100644 index 0000000000..6875fa4d79 --- /dev/null +++ b/test/unit_tests/idas/C_serial/idas_test_tstop.c @@ -0,0 +1,243 @@ +/* ----------------------------------------------------------------------------- + * Programmer(s): David J. Gardner @ LLNL + * ----------------------------------------------------------------------------- + * SUNDIALS Copyright Start + * Copyright (c) 2002-2023, 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 setting stop time + * ---------------------------------------------------------------------------*/ + +#include +#include + +#include "nvector/nvector_serial.h" +#include "sundials/sundials_matrix.h" +#include "sundials/sundials_nvector.h" +#include "sunmatrix/sunmatrix_dense.h" +#include "sunlinsol/sunlinsol_dense.h" +#include "idas/idas.h" + +#if defined(SUNDIALS_EXTENDED_PRECISION) +#define GSYM "Lg" +#else +#define GSYM "g" +#endif + +#define ZERO SUN_RCONST(0.0) +#define ONE SUN_RCONST(1.0) + + +int dae_res(sunrealtype t, N_Vector y, N_Vector ydot, N_Vector res, + void *user_data) +{ + sunrealtype* ydot_data = N_VGetArrayPointer(ydot); + sunrealtype* res_data = N_VGetArrayPointer(res); + res_data[0] = ydot_data[0] - ONE; + return 0; +} + + +int dae_jac(sunrealtype t, sunrealtype cj, N_Vector y, N_Vector yp, N_Vector rr, + SUNMatrix J, void *user_data, N_Vector tempv1, N_Vector tempv2, + N_Vector tempv3) +{ + sunrealtype* J_data = SUNDenseMatrix_Data(J); + J_data[0] = ONE; + return 0; +} + + +int main(int argc, char *argv[]) +{ + SUNContext sunctx = NULL; + N_Vector y = NULL; + N_Vector yp = NULL; + SUNMatrix A = NULL; + SUNLinearSolver LS = NULL; + void* ida_mem = NULL; + + int flag = 0; + int ida_flag = 0; + int i = 0; + sunrealtype tout = SUN_RCONST(0.10); + sunrealtype dt_tout = SUN_RCONST(0.25); + sunrealtype tstop = SUN_RCONST(0.30); + sunrealtype dt_tstop = SUN_RCONST(0.30); + sunrealtype tret = ZERO; + sunrealtype tcur = ZERO; + + /* -------------- + * Create context + * -------------- */ + + flag = SUNContext_Create(NULL, &sunctx); + if (flag) + { + fprintf(stderr, "SUNContext_Create returned %i\n", flag); + return 1; + } + + /* ----------------------- + * Setup initial condition + * ------------------------ */ + + y = N_VNew_Serial(1, sunctx); + if (!y) { return 1; } + N_VConst(ZERO, y); + + yp = N_VClone(y); + if (!yp) { return 1; } + N_VConst(ONE, yp); + + /* --------- + * Setup IDA + * --------- */ + + ida_mem = IDACreate(sunctx); + if (!ida_mem) { return 1; } + + flag = IDAInit(ida_mem, dae_res, ZERO, y, yp); + if (flag) { return 1; } + + flag = IDASStolerances(ida_mem, SUN_RCONST(1.0e-4), SUN_RCONST(1.0e-8)); + if (flag) { return 1; } + + A = SUNDenseMatrix(1, 1, sunctx); + if (!A) { return 1; } + + LS = SUNLinSol_Dense(y, A, sunctx); + if (!LS) { return 1; } + + flag = IDASetLinearSolver(ida_mem, LS, A); + if (flag) { return 1; } + + flag = IDASetJacFn(ida_mem, dae_jac); + if (flag) { return 1; } + + flag = IDASetMaxOrd(ida_mem, 1); + if (flag) { return 1; } + + flag = IDASetStopTime(ida_mem, tstop); + if (flag) { return 1; } + + /* --------------- + * Advance in time + * --------------- */ + + printf("0: tout = %" GSYM ", tstop = %" GSYM ", tret = %" GSYM ", tcur = %" GSYM "\n", + tout, tstop, tret, tcur); + + for (i = 1; i <= 6; i++) + { + ida_flag = IDASolve(ida_mem, tout, &tret, y, yp, IDA_NORMAL); + if (ida_flag < 0) { flag = 1; break; } + + flag = IDAGetCurrentTime(ida_mem, &tcur); + if (flag) { break; } + + printf("%i: tout = %" GSYM ", tstop = %" GSYM ", tret = %" GSYM ", tcur = %" GSYM ", return = %i\n", + i, tout, tstop, tret, tcur, ida_flag); + + /* First return: output time < stop time */ + if (i == 1 && ida_flag != IDA_SUCCESS) + { + printf("ERROR: Expected output return!\n"); + flag = 1; + break; + } + + /* Second return: output time > stop time */ + if (i == 2) + { + if (ida_flag != IDA_TSTOP_RETURN) + { + printf("ERROR: Expected stop return!\n"); + flag = 1; + break; + } + + /* Update stop time */ + tstop += dt_tstop; + flag = IDASetStopTime(ida_mem, tstop); + if (flag) { break; } + } + + /* Third return: output time = stop time */ + if (i == 3) + { + if (ida_flag != IDA_TSTOP_RETURN) + { + printf("ERROR: Expected stop return!\n"); + flag = 1; + break; + } + + /* Update stop time */ + tstop += dt_tstop; + flag = IDASetStopTime(ida_mem, tstop); + if (flag) { break; } + } + + /* Fourth return: output time < stop time but both output time and the stop + time are overtaken in the same step */ + if (i == 4) + { + if (ida_flag != IDA_SUCCESS) + { + printf("ERROR: Expected output return!\n"); + flag = 1; + break; + } + } + + /* Fifth return: output time > stop time after step where both output time + and the stop time were overtaken in the same step */ + if (i == 5) + { + if (ida_flag != IDA_TSTOP_RETURN) + { + printf("ERROR: Expected stop return!\n"); + flag = 1; + break; + } + } + + /* Sixth return: output time < stop time (not updated) */ + if (i == 6 && ida_flag != IDA_SUCCESS) + { + printf("ERROR: Expected output return!\n"); + flag = 1; + break; + } + + /* update output time */ + tout += dt_tout; + } + + /* -------- + * Clean up + * -------- */ + + IDAFree(&ida_mem); + N_VDestroy(y); + N_VDestroy(yp); + SUNMatDestroy(A); + SUNLinSolFree(LS); + SUNContext_Free(&sunctx); + + if (!flag) + { + printf("SUCCESS\n"); + } + + return flag; +} + +/*---- end of file ----*/