diff --git a/CHANGELOG.md b/CHANGELOG.md index 6aba1c0f50..aa56fad501 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -42,6 +42,21 @@ The build system has been updated to utilize the CMake LAPACK imported target which should ease building SUNDIALS with LAPACK libraries that require setting specific linker flags e.g., MKL. +Added support for multirate time step adaptivity controllers, based on the +recently introduced `SUNAdaptController` base class, to ARKODE's MRIStep module. +As a part of this, we added embeddings for existing MRI-GARK methods, as well as +support for embedded MERK and IMEX-MRI-SR methods. Added new default MRI methods +for temporally adaptive versus fixed-step runs. Added the function +`MRIStepGetNumInnerStepperFails` to retrieve the number of recoverable +failures reported by the MRIStepInnerStepper. + +Added functionality to ARKODE to accumulate a temporal error +estimate over multiple time steps. See the routines `ARKodeSetAccumulatedErrorType`, +`ARKodeResetAccumulatedError`, and `ARKodeGetAccumulatedError` for details. + +Added a utility routine to wrap any valid ARKODE integrator for use as an MRIStep +inner stepper object, `ARKodeCreateMRIStepInnerStepper`. + ### Bug Fixes Fixed a [bug](https://github.com/LLNL/sundials/issues/581) in the sparse matrix @@ -62,6 +77,15 @@ repeatedly. Fixed compilation errors when building the Trilinos Teptra NVector with CUDA support. +Fixed loading the default IMEX-MRI method if `ARKodeSetOrder` is used to specify +a third or fourth order method. Previously, the default second order method +was loaded in both cases. + +Fixed a bug in MRIStep where the data supplied to the Hermite interpolation module did +not include contributions from the fast right-hand side function. With this fix, users +will see one additional fast right-hand side function evaluation per slow step with the +Hermite interpolation option. + Fixed a CMake configuration issue related to aliasing an `ALIAS` target when using `ENABLE_KLU=ON` in combination with a static-only build of SuiteSparse. @@ -71,6 +95,10 @@ See details in GitHub Issue [#538](https://github.com/LLNL/sundials/issues/538). ### Deprecation Notices +Deprecated the ARKStep-specific utility routine for wrapping an ARKStep instance +as an MRIStep inner stepper object, `ARKStepCreateMRIStepInnerStepper`. Use +`ARKodeCreateMRIStepInnerStepper` instead. + The ARKODE stepper specific functions to retrieve the number of right-hand side function evaluations have been deprecated. Use `ARKodeGetNumRhsEvals` instead. diff --git a/doc/arkode/guide/source/Constants.rst b/doc/arkode/guide/source/Constants.rst index fc300c802a..46f4e143b6 100644 --- a/doc/arkode/guide/source/Constants.rst +++ b/doc/arkode/guide/source/Constants.rst @@ -64,7 +64,7 @@ contains the ARKODE output constants. +-----------------------------------------------+------------------------------------------------------------+ | | | +-----------------------------------------------+------------------------------------------------------------+ - | **Relaxtion module input constants** | | + | **Relaxation module input constants** | | +-----------------------------------------------+------------------------------------------------------------+ | :index:`ARK_RELAX_BRENT` | Specifies Brent's method as the relaxation nonlinear | | | solver. | @@ -350,13 +350,13 @@ contains the ARKODE output constants. +-----------------------------------------------+------------------------------------------------------------+ | :index:`ARKODE_MRI_GARK_FORWARD_EULER` | Use the forward Euler MRI-GARK method. | +-----------------------------------------------+------------------------------------------------------------+ - | :index:`ARKODE_MRI_GARK_ERK22b` | Use the ERK22b MRI-GARK method. | - +-----------------------------------------------+------------------------------------------------------------+ | :index:`ARKODE_MRI_GARK_ERK22a` | Use the ERK22a MRI-GARK method. | +-----------------------------------------------+------------------------------------------------------------+ + | :index:`ARKODE_MRI_GARK_ERK22b` | Use the ERK22b MRI-GARK method. | + +-----------------------------------------------+------------------------------------------------------------+ | :index:`ARKODE_MRI_GARK_RALSTON2` | Use the second order Ralston MRI-GARK method. | +-----------------------------------------------+------------------------------------------------------------+ - | :index:`ARKODE_MIS_MW3` | Use the Knoth-Wolke-3 MIS method. | + | :index:`ARKODE_MIS_KW3` | Use the Knoth-Wolke-3 MIS method (non-embedded). | +-----------------------------------------------+------------------------------------------------------------+ | :index:`ARKODE_MRI_GARK_ERK33a` | Use the ERK33a MRI-GARK method. | +-----------------------------------------------+------------------------------------------------------------+ @@ -364,6 +364,14 @@ contains the ARKODE output constants. +-----------------------------------------------+------------------------------------------------------------+ | :index:`ARKODE_MRI_GARK_ERK45a` | Use the ERK45a MRI-GARK method. | +-----------------------------------------------+------------------------------------------------------------+ + | :index:`ARKODE_MERK21` | Use the MERK21 method. | + +-----------------------------------------------+------------------------------------------------------------+ + | :index:`ARKODE_MERK32` | Use the MERK32 method. | + +-----------------------------------------------+------------------------------------------------------------+ + | :index:`ARKODE_MERK43` | Use the MERK43 method. | + +-----------------------------------------------+------------------------------------------------------------+ + | :index:`ARKODE_MERK54` | Use the MERK54 method. | + +-----------------------------------------------+------------------------------------------------------------+ | :index:`ARKODE_MRI_GARK_BACKWARD_EULER` | Use the backward Euler MRI-GARK method. | +-----------------------------------------------+------------------------------------------------------------+ | :index:`ARKODE_MRI_GARK_IRK21a` | Use the IRK21a MRI-GARK method. | @@ -380,47 +388,74 @@ contains the ARKODE output constants. +-----------------------------------------------+------------------------------------------------------------+ | :index:`ARKODE_IMEX_MRI_GARK_MIDPOINT` | Use the midpoint rule IMEX-MRI-GARK method. | +-----------------------------------------------+------------------------------------------------------------+ - | :index:`ARKODE_IMEX_MRI_GARK3a` | Use the IMEX-MRI-GARK3a method. | + | :index:`ARKODE_IMEX_MRI_GARK3a` | Use the IMEX-MRI-GARK3a method (non-embedded). | + +-----------------------------------------------+------------------------------------------------------------+ + | :index:`ARKODE_IMEX_MRI_GARK3b` | Use the IMEX-MRI-GARK3b method (non-embedded). | +-----------------------------------------------+------------------------------------------------------------+ - | :index:`ARKODE_IMEX_MRI_GARK3b` | Use the IMEX-MRI-GARK3b method. | + | :index:`ARKODE_IMEX_MRI_GARK4` | Use the IMEX-MRI-GARK4 method (non-embedded). | +-----------------------------------------------+------------------------------------------------------------+ - | :index:`ARKODE_IMEX_MRI_GARK4` | Use the IMEX-MRI-GARK4 method. | + | :index:`ARKODE_IMEX_MRI_SR21` | Use the IMEX-MRI-SR21 method. | +-----------------------------------------------+------------------------------------------------------------+ - | :index:`MRISTEP_DEFAULT_EXPL_TABLE_1` | Use MRIStep's default 1st-order explicit method | - | | (MRI_GARK_FORWARD_EULER). | + | :index:`ARKODE_IMEX_MRI_SR32` | Use the IMEX-MRI-SR32 method. | +-----------------------------------------------+------------------------------------------------------------+ - | :index:`MRISTEP_DEFAULT_EXPL_TABLE_2` | Use MRIStep's default 2nd-order explicit method | - | | (MRI_GARK_ERK22b). | + | :index:`ARKODE_IMEX_MRI_SR43` | Use the IMEX-MRI-SR43 method. | +-----------------------------------------------+------------------------------------------------------------+ - | :index:`MRISTEP_DEFAULT_EXPL_TABLE_3` | Use MRIStep's default 3rd-order explicit method | - | | (MIS_MW3). | + | :index:`MRISTEP_DEFAULT_EXPL_1` | Use MRIStep's default 1st-order explicit method | + | | (ARKODE_MRI_GARK_FORWARD_EULER). | +-----------------------------------------------+------------------------------------------------------------+ - | :index:`MRISTEP_DEFAULT_EXPL_TABLE_4` | Use MRIStep's default 4th-order explicit method | - | | (MRI_GARK_ERK45a). | + | :index:`MRISTEP_DEFAULT_EXPL_2` | Use MRIStep's default 2nd-order explicit method | + | | (ARKODE_MRI_GARK_ERK22b). | +-----------------------------------------------+------------------------------------------------------------+ - | :index:`MRISTEP_DEFAULT_IMPL_SD_TABLE_1` | Use MRIStep's default 1st-order solve-decoupled implicit | - | | method (MRI_GARK_BACKWARD_EULER). | + | :index:`MRISTEP_DEFAULT_EXPL_3` | Use MRIStep's default 3rd-order explicit method | + | | (ARKODE_MIS_KW3). | +-----------------------------------------------+------------------------------------------------------------+ - | :index:`MRISTEP_DEFAULT_IMPL_SD_TABLE_2` | Use MRIStep's default 2nd-order solve-decoupled implicit | - | | method (MRI_GARK_IRK21a). | + | :index:`MRISTEP_DEFAULT_EXPL_4` | Use MRIStep's default 4th-order explicit method | + | | (ARKODE_MRI_GARK_ERK45a). | +-----------------------------------------------+------------------------------------------------------------+ - | :index:`MRISTEP_DEFAULT_IMPL_SD_TABLE_3` | Use MRIStep's default 3rd-order solve-decoupled implicit | - | | method (MRI_GARK_ESDIRK34a). | + | :index:`MRISTEP_DEFAULT_EXPL_2_AD` | Use MRIStep's default 2nd-order adaptive explicit method | + | | (ARKODE_MRI_GARK_ERK22a). | +-----------------------------------------------+------------------------------------------------------------+ - | :index:`MRISTEP_DEFAULT_IMPL_SD_TABLE_4` | Use MRIStep's default 4th-order solve-decoupled implicit | - | | method (MRI_GARK_ESDIRK46a). | + | :index:`MRISTEP_DEFAULT_EXPL_3_AD` | Use MRIStep's default 3rd-order adaptive explicit method | + | | (ARKODE_MRI_GARK_ERK33a). | +-----------------------------------------------+------------------------------------------------------------+ - | :index:`MRISTEP_DEFAULT_IMEX_SD_TABLE_1` | Use MRIStep's default 1st-order solve-decoupled ImEx | - | | method (IMEX_MRI_GARK_EULER). | + | :index:`MRISTEP_DEFAULT_EXPL_4_AD` | Use MRIStep's default 4th-order adaptive explicit method | + | | (ARKODE_MRI_GARK_ERK45a). | +-----------------------------------------------+------------------------------------------------------------+ - | :index:`MRISTEP_DEFAULT_IMEX_SD_TABLE_2` | Use MRIStep's default 2nd-order solve-decoupled ImEx | + | :index:`MRISTEP_DEFAULT_EXPL_5_AD` | Use MRIStep's default 5th-order adaptive explicit method | + | | (ARKODE_MERK54). | + +-----------------------------------------------+------------------------------------------------------------+ + | :index:`MRISTEP_DEFAULT_IMPL_SD_1` | Use MRIStep's default 1st-order solve-decoupled implicit | + | | method (ARKODE_MRI_GARK_BACKWARD_EULER). | + +-----------------------------------------------+------------------------------------------------------------+ + | :index:`MRISTEP_DEFAULT_IMPL_SD_2` | Use MRIStep's default 2nd-order solve-decoupled implicit | + | | method (ARKODE_MRI_GARK_IRK21a). | + +-----------------------------------------------+------------------------------------------------------------+ + | :index:`MRISTEP_DEFAULT_IMPL_SD_3` | Use MRIStep's default 3rd-order solve-decoupled implicit | + | | method (ARKODE_MRI_GARK_ESDIRK34a). | + +-----------------------------------------------+------------------------------------------------------------+ + | :index:`MRISTEP_DEFAULT_IMPL_SD_4` | Use MRIStep's default 4th-order solve-decoupled implicit | + | | method (ARKODE_MRI_GARK_ESDIRK46a). | + +-----------------------------------------------+------------------------------------------------------------+ + | :index:`MRISTEP_DEFAULT_IMEX_SD_1` | Use MRIStep's default 1st-order solve-decoupled ImEx | + | | method (ARKODE_IMEX_MRI_GARK_EULER). | + +-----------------------------------------------+------------------------------------------------------------+ + | :index:`MRISTEP_DEFAULT_IMEX_SD_2` | Use MRIStep's default 2nd-order solve-decoupled ImEx | | | method (ARKODE_IMEX_MRI_GARK_TRAPEZOIDAL). | +-----------------------------------------------+------------------------------------------------------------+ - | :index:`MRISTEP_DEFAULT_IMEX_SD_TABLE_3` | Use MRIStep's default 3rd-order solve-decoupled ImEx | - | | method (IMEX_MRI_GARK3b). | + | :index:`MRISTEP_DEFAULT_IMEX_SD_3` | Use MRIStep's default 3rd-order solve-decoupled ImEx | + | | method (ARKODE_IMEX_MRI_GARK3b). | + +-----------------------------------------------+------------------------------------------------------------+ + | :index:`MRISTEP_DEFAULT_IMEX_SD_4` | Use MRIStep's default 4th-order solve-decoupled ImEx | + | | method (ARKODE_IMEX_MRI_GARK4). | + +-----------------------------------------------+------------------------------------------------------------+ + | :index:`MRISTEP_DEFAULT_IMEX_SD_2_AD` | Use MRIStep's default 2nd-order solve-decoupled adaptive | + | | ImEx method (ARKODE_IMEX_MRI_SR21). | + +-----------------------------------------------+------------------------------------------------------------+ + | :index:`MRISTEP_DEFAULT_IMEX_SD_3_AD` | Use MRIStep's default 3rd-order solve-decoupled adaptive | + | | ImEx method (ARKODE_IMEX_MRI_SR32). | +-----------------------------------------------+------------------------------------------------------------+ - | :index:`MRISTEP_DEFAULT_IMEX_SD_TABLE_4` | Use MRIStep's default 4th-order solve-decoupled ImEx | - | | method (IMEX_MRI_GARK4). | + | :index:`MRISTEP_DEFAULT_IMEX_SD_4_AD` | Use MRIStep's default 4th-order solve-decoupled adaptive | + | | ImEx method (ARKODE_IMEX_MRI_SR43). | +-----------------------------------------------+------------------------------------------------------------+ diff --git a/doc/arkode/guide/source/Mathematics.rst b/doc/arkode/guide/source/Mathematics.rst index 10a053b879..d550d65635 100644 --- a/doc/arkode/guide/source/Mathematics.rst +++ b/doc/arkode/guide/source/Mathematics.rst @@ -606,129 +606,231 @@ an identity mass matrix, :math:`M(t)=I`. The slow time scale may consist of only nonstiff terms (:math:`f^I \equiv 0`), only stiff terms (:math:`f^E \equiv 0`), or both nonstiff and stiff terms. -For cases with only a single slow right-hand side function (i.e., -:math:`f^E \equiv 0` or :math:`f^I \equiv 0`), MRIStep provides fixed-slow-step -multirate infinitesimal step (MIS) :cite:p:`Schlegel:09, Schlegel:12a, -Schlegel:12b` and multirate infinitesimal GARK (MRI-GARK) :cite:p:`Sandu:19` -methods. For problems with an additively split slow right-hand side MRIStep -provides fixed-slow-step implicit-explicit MRI-GARK (IMEX-MRI-GARK) -:cite:p:`ChiRen:21` methods. The slow (outer) method derives from an :math:`s` -stage Runge--Kutta method for MIS and MRI-GARK methods or an additive Runge--Kutta -method for IMEX-MRI-GARK methods. In either case, the stage values and the new -solution are computed by solving an auxiliary ODE with a fast (inner) time -integration method. This corresponds to the following algorithm for a single -step: +For cases with only a single slow right-hand side function (i.e., :math:`f^E +\equiv 0` or :math:`f^I \equiv 0`), MRIStep provides multirate infinitesimal +step (MIS) :cite:p:`Schlegel:09, Schlegel:12a, Schlegel:12b`, first through +fourth order multirate infinitesimal GARK (MRI-GARK) :cite:p:`Sandu:19`, and +second through fifth order multirate exponential Runge--Kutta (MERK) +:cite:p:`Luan:20` methods. For problems with an additively split slow right-hand +side, MRIStep provides first through fourth order implicit-explicit MRI-GARK +(IMEX-MRI-GARK) :cite:p:`ChiRen:21` and second through fourth order +implicit-explicit multirate infinitesimal stage-restart (IMEX-MRI-SR) +:cite:p:`Fish:24` methods. For a complete list of the methods available in +MRIStep see :numref:`ARKODE.Usage.MRIStep.MRIStepCoupling.Tables`. Additionally, +users may supply their own method by defining and attaching a coupling table, +see :numref:`ARKODE.Usage.MRIStep.MRIStepCoupling` for more information. + +Generally, the slow (outer) method for each family derives from a single-rate +method: MIS and MRI-GARK methods derive from explicit or +diagonally-implicit Runge--Kutta methods, MERK methods derive from exponential +Runge--Kutta methods, while IMEX-MRI-GARK and IMEX-MRI-SR methods derive from +additive Runge--Kutta methods. In each case, the "infinitesimal" nature of the +multirate methods derives from the fact that slow stages are computed by solving +a set of auxiliary ODEs with a fast (inner) time integration method. Generally +speaking, an :math:`s`-stage method from of each family adheres to the following +algorithm for a single step: #. Set :math:`z_1 = y_{n-1}`. -#. For :math:`i = 2,\ldots,s+1` do: +#. For :math:`i = 2,\ldots,s`, compute the stage solutions, :math:`z_i`, by + evolving the fast IVP - #. Let :math:`t_{n,i-1}^S = t_{n-1} + c_{i-1}^S h^S` and - :math:`v(t_{n,i-1}^S) = z_{i-1}`. + .. math:: + {v}_i'(t) = f^F(t, v_i) + r_i(t) \quad\text{for}\quad t \in [t_{0,i},t_{F,i}] \quad\text{with}\quad v_i(t_{0,i}) = v_{0,i} + :label: MRI_fast_IVP - #. Let :math:`r_i(t) = - \frac{1}{\Delta c_i^S} - \sum\limits_{j=1}^{i-1} \omega_{i,j}(\tau) f^E(t_{n,j}^I, z_j) + - \frac{1}{\Delta c_i^S} - \sum\limits_{j=1}^i \gamma_{i,j}(\tau) f^I(t_{n,j}^I, z_j)` - where :math:`\Delta c_i^S=\left(c^S_i - c^S_{i-1}\right)` and the - normalized time is :math:`\tau = (t - t_{n,i-1}^S)/(h^S \Delta c_i^S)`. + and setting :math:`z_i = v(t_{F,i})`, and/or performing a standard explicit, + diagonally-implicit, or additive Runge--Kutta stage update, - #. For :math:`t \in [t_{n,i-1}^S, t_{n,i}^S]` solve - :math:`\dot{v}(t) = f^F(t, v) + r_i(t)`. + .. math:: + z_i - \theta_{i,i} h^S f^I(t_{n,i}^S, z_i) = a_i. + :label: MRI_implicit_solve - #. Set :math:`z_i = v(t_{n,i}^S)`. + where :math:`t_{n,j}^S = t_{n-1} + h^S c^S_j`. -#. Set :math:`y_{n} = z_{s+1}`. +#. Set :math:`y_{n} = z_{s}`. -The fast (inner) IVP solve can be carried out using either the ARKStep module -(allowing for explicit, implicit, or ImEx treatments of the fast time scale with -fixed or adaptive steps), or a user-defined integration method (see section +#. If the method has an embedding, compute the embedded solution, + :math:`\tilde{y}`, by evolving the fast IVP + + .. math:: + \tilde{v}'(t) = f^F(t, \tilde{v}) + \tilde{r}(t) \quad\text{for}\quad t \in [\tilde{t}_{0},\tilde{t}_{F}] \quad\text{with}\quad \tilde{v}(\tilde{t}_{0}) = \tilde{v}_{0} + :label: MRI_embedding_fast_IVP + + and setting :math:`\tilde{y}_{n} = \tilde{v}(\tilde{t}_{F})`, and/or + performing a standard explicit, diagonally-implicit, or additive Runge--Kutta + stage update, + + .. math:: + \tilde{y}_n - \tilde{\theta} h^S f^I(t_n, \tilde{y}_n) = \tilde{a}. + :label: MRI_embedding_implicit_solve + +Whether a fast IVP evolution or a stage update (or both) is needed depends on +the method family (MRI-GARK, MERK, etc.). The specific aspects of the fast IVP +forcing function (:math:`r_i(t)` or :math:`\tilde{r}(t)`), the interval over +which the IVP must be evolved (:math:`[t_{0,i},t_{F,i}])`, the Runge--Kutta +coefficients (:math:`\theta_{i,i}` and :math:`\tilde{\theta}`), and the +Runge--Kutta data (:math:`a_i` and :math:`\tilde{a}`), are also determined by +the method family. Generally, the forcing functions and data, are constructed +using evaluations of the slow RHS functions, :math:`f^E` and :math:`f^I`, at +preceding stages, :math:`z_j`. The fast IVP solves can be carried out using any +valid ARKODE integrator or a user-defined integration method (see section :numref:`ARKODE.Usage.MRIStep.CustomInnerStepper`). -The final abscissa is :math:`c^S_{s+1}=1` and the coefficients -:math:`\omega_{i,j}` and :math:`\gamma_{i,j}` are polynomials in time that -dictate the couplings from the slow to the fast time scale; these can be -expressed as in :cite:p:`ChiRen:21` and :cite:p:`Sandu:19` as +Below we summarize the details for each method family. For additional +information, please see the references listed above. -.. math:: - \omega_{i,j}(\tau) = \sum_{k\geq 0} \omega_{i,j}^{\{k\}} \tau^k - \quad\text{and}\quad - \gamma_{i,j}(\tau) = \sum_{k\geq 0} \gamma_{i,j}^{\{k\}} \tau^k, - :label: ARKODE_MRI_coupling -and where the tables :math:`\Omega^{\{k\}}\in\mathbb{R}^{(s+1)\times(s+1)}` and -:math:`\Gamma^{\{k\}}\in\mathbb{R}^{(s+1)\times(s+1)}` define the slow-to-fast -coupling for the explicit and implicit components respectively. +MIS, MRI-GARK, and IMEX-MRI-GARK Methods +---------------------------------------- -For traditional MIS methods, the coupling coefficients are uniquely defined -based on a slow Butcher table :math:`(A^S,b^S,c^S)` having an explicit first -stage (i.e., :math:`c^S_1=0` and :math:`A^S_{1,j}=0` for :math:`1\le j\le s`), -sorted abscissae (i.e., :math:`c^S_{i} \ge c^S_{i-1}` for :math:`2\le i\le s`), -and the final abscissa is :math:`c^S_s \leq 1`. With these properties met, the -coupling coefficients for an explicit-slow method are given as +The methods in IMEX-MRI-GARK family, which includes MIS and MRI-GARK methods, +are defined by a vector of slow stage time abscissae, :math:`c^S \in +\mathbb{R}^{s}`, and a set of coupling tensors, +:math:`\Omega\in\mathbb{R}^{(s+1)\times s \times k}` and +:math:`\Gamma\in\mathbb{R}^{(s+1)\times s \times k}`, that specify the +slow-to-fast coupling for the explicit and implicit components, respectively. + +The fast stage IVPs, :eq:`MRI_fast_IVP`, are evolved over non-overlapping +intervals :math:`[t_{0,i},t_{F,i}] = [t_{n,i-1}^S, t_{n,i}^S]` with +the initial condition :math:`v_{0,i}=z_{i-1}`. The fast IVP forcing function is +given by .. math:: - \omega_{i,j}^{\{0\}} = \begin{cases} - 0, & \text{if}\; i=1,\\ - A^S_{i,j} - A^S_{i-1,j}, & \text{if}\; 2\le i\le s,\\ - b^S_j - A^S_{s,j}, & \text{if}\; i=s+1. - \end{cases} - :label: ARKODE_MIS_to_MRI + r_i(t) = \frac{1}{\Delta c_i^S} \sum\limits_{j=1}^{i-1} \omega_{i,j}(\tau) f^E(t_{n,j}^S, z_j) + + \frac{1}{\Delta c_i^S} \sum\limits_{j=1}^i \gamma_{i,j}(\tau) f^I(t_{n,j}^S, z_j) -For general slow tables :math:`(A^S,b^S,c^S)` with at least second-order -accuracy, the corresponding MIS method will be second order. However, if this -slow table is at least third order and satisfies the additional condition +where :math:`\Delta c_i^S=\left(c^S_i - c^S_{i-1}\right)`, :math:`\tau = (t - +t_{n,i-1}^S)/(h^S \Delta c_i^S)` is the normalized time, the coefficients +:math:`\omega_{i,j}` and :math:`\gamma_{i,j}` are polynomials in time of degree +:math:`k-1` given by .. math:: - \sum_{i=2}^{s} \left(c_i^S-c_{i-1}^S\right) - \left(\mathbf{e}_i+\mathbf{e}_{i-1}\right)^T A^S c^S - + \left(1-c_{s}^S\right) \left( \frac12+\mathbf{e}_{s}^T A^S c^S \right) - = \frac13, - :label: ARKODE_MIS_order3 - -where :math:`\mathbf{e}_j` corresponds to the :math:`j`-th column from the -:math:`s \times s` identity matrix, then the overall MIS method will be third -order. + \omega_{i,j}(\tau) = \sum_{\ell = 1}^{k} \Omega_{i,j,\ell} \, \tau^{\ell-1} + \quad\text{and}\quad + \gamma_{i,j}(\tau) = \sum_{\ell = 1}^{k} \Gamma_{i,j,\ell} \, \tau^{\ell-1}. + :label: ARKODE_MRI_coupling -In the above algorithm, when the slow (outer) method has repeated abscissa, i.e. -:math:`\Delta c_i^S = 0` for stage :math:`i`, the fast (inner) IVP can be -rescaled and integrated analytically. In this case the stage is computed as +When the slow abscissa are repeated, i.e. :math:`\Delta c_i^S = 0`, the fast IVP +can be rescaled and integrated analytically leading to the Runge--Kutta update +:eq:`MRI_implicit_solve` instead of the fast IVP evolution. In this case the +stage is computed as .. math:: z_i = z_{i-1} - + h^S \sum_{j=1}^{i-1} \left(\sum_{k\geq 0} - \frac{\omega_{i,j}^{\{k\}}}{k+1}\right) f^E(t_{n,j}^S, z_j) - + h^S \sum_{j=1}^i \left(\sum_{k\geq 0} - \frac{\gamma_{i,j}^{\{k\}}}{k+1}\right) f^I(t_{n,j}^S, z_j), + + h^S \sum_{j=1}^{i-1} \left(\sum_{\ell = 1}^{k} + \frac{\Omega_{i,j,\ell}}{\ell}\right) f^E(t_{n,j}^S, z_j) + + h^S \sum_{j=1}^i \left(\sum_{\ell = 1}^{k} + \frac{\Gamma_{i,j,\ell}}{\ell}\right) f^I(t_{n,j}^S, z_j). :label: ARKODE_MRI_delta_c_zero -which corresponds to a standard ARK, DIRK, or ERK stage computation depending on -whether the summations over :math:`k` are zero or nonzero. +Similarly, the embedded solution IVP, :eq:`MRI_embedding_fast_IVP`, is evolved +over the interval :math:`[\tilde{t}_{0},\tilde{t}_{F}] = [t_{n,s-1}^S, t_{n}]` +with the initial condition :math:`\tilde{v}_0=z_{s-1}`. As with standard ARK and DIRK methods, implicitness at the slow time scale is -characterized by nonzero values on or above the diagonal of the matrices -:math:`\Gamma^{\{k\}}`. Typically, MRI-GARK and IMEX-MRI-GARK methods are at -most diagonally-implicit (i.e., :math:`\gamma_{i,j}^{\{k\}}=0` for all +characterized by nonzero values on or above the diagonal of the :math:`k` +matrices in :math:`\Gamma`. Typically, MRI-GARK and IMEX-MRI-GARK methods are at +most diagonally-implicit (i.e., :math:`\Gamma_{i,j,\ell}=0` for all :math:`\ell` and :math:`j>i`). Furthermore, diagonally-implicit stages are characterized as being -"solve-decoupled" if :math:`\Delta c_i^S = 0` when :math:`\gamma_{i,i}^{\{k\}} \ne 0`, -in which case the stage is computed as standard ARK or DIRK update. Alternately, +"solve-decoupled" if :math:`\Delta c_i^S = 0` when :math:`\Gamma_{i,i,\ell} \ne 0`, +in which case the stage is computed as a standard ARK or DIRK update. Alternately, a diagonally-implicit stage :math:`i` is considered "solve-coupled" if -:math:`\Delta c^S_i \gamma_{i,j}^{\{k\}} \ne 0`, in which -case the stage solution :math:`z_i` is *both* an input to :math:`r(t)` and the +:math:`\Delta c^S_i \, \Gamma_{i,j,\ell} \ne 0`, in which +case the stage solution :math:`z_i` is *both* an input to :math:`r_i(t)` and the result of time-evolution of the fast IVP, necessitating an implicit solve that -is coupled to the fast (inner) solver. At present, only "solve-decoupled" +is coupled to the fast evolution. At present, only "solve-decoupled" diagonally-implicit MRI-GARK and IMEX-MRI-GARK methods are supported. -For problems with only a slow-nonstiff term (:math:`f^I \equiv 0`), MRIStep -provides third and fourth order explicit MRI-GARK methods. In cases with only a -slow-stiff term (:math:`f^E \equiv 0`), MRIStep supplies second, third, and -fourth order implicit solve-decoupled MRI-GARK methods. For applications -with both stiff and nonstiff slow terms, MRIStep implements third and fourth -order IMEX-MRI-GARK methods. For a complete list of the methods available in -MRIStep see :numref:`ARKODE.Usage.MRIStep.MRIStepCoupling.Tables`. Additionally, users -may supply their own method by defining and attaching a coupling table, see -:numref:`ARKODE.Usage.MRIStep.MRIStepCoupling` for more information. + +IMEX-MRI-SR Methods +------------------- + +The IMEX-MRI-SR family of methods perform *both* the fast IVP evolution, +:eq:`MRI_fast_IVP` or :eq:`MRI_embedding_fast_IVP`, *and* stage update, +:eq:`MRI_implicit_solve` or :eq:`MRI_embedding_implicit_solve`, in every stage +(but these methods typically have far fewer stages than implicit MRI-GARK or +IMEX-MRI-GARK methods). These methods are defined by a vector of slow stage +time abscissae :math:`c^S \in \mathbb{R}^{s}`, a set of coupling tensors +:math:`\Omega\in\mathbb{R}^{(s+1)\times s\times k}`, and a Butcher table of +slow-implicit coefficients, :math:`\Gamma\in\mathbb{R}^{(s+1) \times s}`. + +The fast stage IVPs, :eq:`MRI_fast_IVP`, are evolved on overlapping +intervals :math:`[t_{0,i},t_{F,i}] = [t_{n-1}, t_{n,i}^S]` with +the initial condition :math:`v_{0,i}=y_{n-1}`. The fast IVP forcing function is +given by + +.. math:: + r_i(t) = \frac{1}{c_i^S} \sum\limits_{j=1}^{i-1} \omega_{i,j}(\tau) \left( f^E(t_{n,j}^S, z_j) + f^I(t_{n,j}^S, z_j)\right), + :label: IMEXMRISR_forcing + +where :math:`\tau = (t - t_n)/(h^S c_i^S)` is the normalized time, and the coefficients +:math:`\omega_{i,j}` are polynomials in time of degree :math:`k-1` that are also given by +:eq:`ARKODE_MRI_coupling`. The solution of these fast IVPs defines an intermediate stage +solution, :math:`\tilde{z}_i`. + +The implicit solve that follows each fast IVP must solve the algebraic equation for :math:`z_i` + +.. math:: + z_i = \tilde{z}_i + h^S \sum_{j=1}^{i} \gamma_{i,j} f^I(t_{n,j}^S, z_j). + :label: ARKODE_MRISR_implicit + +We note that IMEX-MRI-SR methods are solve-decoupled by construction, and thus the structure +of a given stage never needs to be deduced based on :math:`\Delta c_i^S`. However, ARKODE +still checks the value of :math:`\gamma_{i,i}`, since if it zero then the stage update +equation :eq:`ARKODE_MRISR_implicit` simplifies to a simple explicit Runge--Kutta-like stage +update. + +The overall time step solution is given by the final internal stage solution, +i.e., :math:`y_{n} = z_{s}`. The embedded solution is computing using the above +algorithm for stage index :math:`s+1`, under the definition that :math:`c_{s+1}^S=1` +(and thus the fast IVP portion is evolved over the full time step, +:math:`[\tilde{t}_{0}, \tilde{t}_{F}] = [t_{n-1}, t_{n}]`). + + + +MERK Methods +------------ + +The MERK family of methods are only defined for multirate applications that +are explicit at the slow time scale, i.e., :math:`f^I=0`, but otherwise they are +nearly identical to IMEX-MRI-SR methods. Specifically, like IMEX-MRI-SR methods, +these evolve the fast IVPs +:eq:`MRI_fast_IVP` and :eq:`MRI_embedding_fast_IVP` over the intervals +:math:`[t_{0,i},t_{F,i}] = [t_{n-1}, t_{n,i}^S]` and +:math:`[\tilde{t}_{0}, \tilde{t}_{F}] = [t_{n-1}, t_{n}]`, respectively, and begin +with the initial condition :math:`v_{0,i}=y_{n-1}`. Furthermore, the fast IVP +forcing functions are given by :eq:`IMEXMRISR_forcing` with :math:`f^I=0`. +As MERK-based applications lack the implicit slow operator, they do not require +the solution of implicit algebraic equations. + +However, unlike other MRI families, MERK methods were designed to admit a useful +efficiency improvement. Since each fast IVP begins with the same initial condition, +:math:`v_{0,i}=y_{n-1}`, if multiple stages share the same forcing function +:math:`r_i(t)`, then they may be "grouped" together. This is achieved by sorting the +final IVP solution time for each stage, :math:`t_{n,i}^S`, and then evolving the inner +solver to each of these stage times in order, storing the corresponding inner solver +solutions at these times as the stages :math:`z_i`. For example, the +:index:`ARKODE_MERK54` method involves 11 stages, that may be combined into 5 distinct +groups. The fourth group contains stages 7, 8, 9, and the embedding, corresponding to +the :math:`c_i^S` values :math:`7/10`, :math:`1/2`, :math:`2/3`, and :math:`1`. +Sorting these, a single fast IVP for this group must be evolved over the interval +:math:`[t_{0,i},t_{F,i}] = [t_{n-1}, t_{n}]`, first pausing at :math:`t_{n-1}+\frac12 h^S` +to store :math:`z_8`, then pausing at :math:`t_{n-1}+\frac{2}{3} h^S` to store +:math:`z_9`, then pausing at :math:`t_{n-1}+\frac{7}{10} h^S` to store :math:`z_7`, +and finally finishing the IVP solve to :math:`t_{n-1}+h^S` to obtain :math:`\tilde{y}_n`. + +.. note:: + + Although all MERK methods were derived in :cite:p:`Luan:20` under an assumption that + the fast function :math:`f^F(t,y)` is linear in :math:`y`, in :cite:p:`Fish:24` it + was proven that MERK methods also satisfy all nonlinear order conditions up through + their linear order. The lone exception is :index:`ARKODE_MERK54`, where it was only + proven to satisfy all nonlinear conditions up to order 4 (since :cite:p:`Fish:24` did + not establish the formulas for the order 5 conditions). All our numerical tests to + date have shown :index:`ARKODE_MERK54` to achieve fifth order for nonlinear problems, + and so we conjecture that it also satisfies the nonlinear fifth order conditions. + .. _ARKODE.Mathematics.LSRK: @@ -737,11 +839,11 @@ LSRKStep -- Low-Storage Runge--Kutta methods ============================================ The LSRKStep time-stepping module in ARKODE supports a variety of so-called -"low-storage" Runge--Kutta (LSRK) methods, :cite:p:`VSH:04, MBA:14, K:08, FCS:22`. This category includes traditional explicit -fixed-step and low-storage Runge--Kutta methods, adaptive +"low-storage" Runge--Kutta (LSRK) methods, :cite:p:`VSH:04, MBA:14, K:08, FCS:22`. This category includes traditional explicit +fixed-step and low-storage Runge--Kutta methods, adaptive low-storage Runge--Kutta methods, and others. These are characterized by coefficient tables that have an exploitable structure, such that their implementation does not require -that all stages be stored simultaneously. At present, this module supports explicit, +that all stages be stored simultaneously. At present, this module supports explicit, adaptive "super-time-stepping" (STS) and "strong-stability-preserving" (SSP) methods. The LSRK time-stepping module in ARKODE currently supports IVP @@ -750,7 +852,7 @@ requires that problems have an identity mass matrix (i.e., :math:`M(t)=I`) and that the right-hand side function is not split into separate components. -LSRKStep currently supports two families of second-order, explicit, and temporally adaptive STS methods: +LSRKStep currently supports two families of second-order, explicit, and temporally adaptive STS methods: Runge--Kutta--Chebyshev (RKC), :cite:p:`VSH:04` and Runge--Kutta--Legendre (RKL), :cite:p:`MBA:14`. These methods have the form .. math:: @@ -762,15 +864,15 @@ Runge--Kutta--Chebyshev (RKC), :cite:p:`VSH:04` and Runge--Kutta--Legendre (RKL) The corresponding coefficients can be found in :cite:p:`VSH:04` and :cite:p:`MBA:14`, respectively. -LSRK methods of STS type are designed for stiff problems characterized by -having Jacobians with eigenvalues that have large real and small imaginary parts. +LSRK methods of STS type are designed for stiff problems characterized by +having Jacobians with eigenvalues that have large real and small imaginary parts. While those problems are traditionally treated using implicit methods, STS methods -are explicit. To achieve stability for these stiff problems, STS methods use more stages than -conventional Runge-Kutta methods to extend the stability region along the negative -real axis. The extent of this stability region is proportional to the square of the number +are explicit. To achieve stability for these stiff problems, STS methods use more stages than +conventional Runge-Kutta methods to extend the stability region along the negative +real axis. The extent of this stability region is proportional to the square of the number of stages used. -LSRK methods of the SSP type are designed to preserve the so-called "strong-stability" properties of advection-type equations. +LSRK methods of the SSP type are designed to preserve the so-called "strong-stability" properties of advection-type equations. For details, see :cite:p:`K:08`. The SSPRK methods in ARKODE use the following Shu--Osher representation :cite:p:`SO:88` of explicit Runge--Kutta methods: @@ -781,9 +883,9 @@ The SSPRK methods in ARKODE use the following Shu--Osher representation :cite:p: :label: ARKODE_SSP The coefficients of the Shu--Osher representation are not uniquely determined by the Butcher table :cite:p:`SR:02`. -In particular, the methods SSP(s,2), SSP(s,3), and SSP(10,4) implemented herein and presented in -:cite:p:`K:08` have "almost" all zero coefficients appearing in :math:`\alpha_{i,i-1}` and -:math:`\beta_{i,i-1}`. This feature facilitates their implementation in a low-storage manner. The +In particular, the methods SSP(s,2), SSP(s,3), and SSP(10,4) implemented herein and presented in +:cite:p:`K:08` have "almost" all zero coefficients appearing in :math:`\alpha_{i,i-1}` and +:math:`\beta_{i,i-1}`. This feature facilitates their implementation in a low-storage manner. The corresponding coefficients and embedding weights can be found in :cite:p:`K:08` and :cite:p:`FCS:22`, respectively. .. _ARKODE.Mathematics.Error.Norm: @@ -847,13 +949,14 @@ time-steppers) is their adaptive control of local truncation error (LTE). At every step, we estimate the local error, and ensure that it satisfies tolerance conditions. If this local error test fails, then the step is recomputed with a reduced step size. To this end, the -Runge--Kutta methods packaged within both the ARKStep and ERKStep -modules admit an embedded solution :math:`\tilde{y}_n`, as shown in -equations :eq:`ARKODE_ARK` and :eq:`ARKODE_ERK`. Generally, these embedded -solutions attain a slightly lower order of accuracy than the computed -solution :math:`y_n`. Denoting the order of accuracy for :math:`y_n` -as :math:`q` and for :math:`\tilde{y}_n` as :math:`p`, most of these -embedded methods satisfy :math:`p = q-1`. These values of :math:`q` +majority of the Runge--Kutta methods and many of the MRI methods in ARKODE +admit an embedded solution :math:`\tilde{y}_n`, as shown in +equations :eq:`ARKODE_ARK`, :eq:`ARKODE_ERK`, and +:eq:`MRI_embedding_fast_IVP`-:eq:`MRI_embedding_implicit_solve`. Generally, +these embedded solutions attain a slightly lower order of accuracy than the +computed solution :math:`y_n`. Denoting the order of accuracy for +:math:`y_n` as :math:`q` and for :math:`\tilde{y}_n` as :math:`p`, most of +these embedded methods satisfy :math:`p = q-1`. These values of :math:`q` and :math:`p` correspond to the *global* orders of accuracy for the method and embedding, hence each admit local truncation errors satisfying :cite:p:`HWN:87` @@ -983,6 +1086,238 @@ support has been deprecated in favor of the SUNAdaptController class, and will be removed in a future release. +.. _ARKODE.Mathematics.MultirateAdaptivity: + +Multirate time step adaptivity (MRIStep) +---------------------------------------- + +Since multirate applications evolve on multiple time scales, +MRIStep supports additional forms of temporal adaptivity. Specifically, +we consider time steps at two adjacent levels, :math:`h^S > h^F`, where +:math:`h^S` is the step size used by MRIStep, and :math:`h^F` is the +step size used to solve the corresponding fast-time-scale IVPs in +MRIStep, :eq:`MRI_fast_IVP` and :eq:`MRI_embedding_fast_IVP`. + + +.. _ARKODE.Mathematics.MultirateControllers: + +Multirate temporal controls +^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +We consider two categories of temporal controllers that may be used within MRI +methods. The first (and simplest), are "decoupled" controllers, that consist of +two separate single-rate temporal controllers: one that adapts the slow time scale +step size, :math:`h^S`, and the other that adapts the fast time scale step size, +:math:`h^F`. As these ignore any coupling between the two time scales, these +methods should work well for multirate problems where the time scales are somewhat +decoupled, and that errors introduced at one scale do not "pollute" the other. + +The second category of controllers that we provide are :math:`h^S`-:math:`Tol` multirate +controllers. The basic idea is that an adaptive time integration method will +attempt to adapt step sizes to control the *local error* within each step to +achieve a requested tolerance. However, MRI methods must ask an adaptive "inner" +solver to produce the stage solutions :math:`v_i(t_{F,i})` and +:math:`\tilde{v}(\tilde{t}_{F})`, that result from sub-stepping over intervals +:math:`[t_{0,i},t_{F,i}]` or :math:`[\tilde{t}_{0},\tilde{t}_{F}]`, respectively. +Local errors within the inner integrator may accumulate, resulting in an overall +inner solver error :math:`\varepsilon^F_n` that exceeds the requested tolerance. +If that inner solver can produce *both* :math:`v_i(t_{F,i})` and +an estimation of the accumulated error, :math:`\varepsilon^F_{n,approx}`, then the +tolerances provided to that inner solver can be adjusted accordingly to +ensure stage solutions that are within the overall tolerances requested of the outer +MRI method. + +To this end, we assume that the inner solver will provide accumulated errors +over each fast interval having the form + +.. math:: + \varepsilon^F_{n} = c(t_n) h^S_n \left(\text{RTOL}_n^F\right), + :label: fast_error_accumulation_assumption + +where :math:`c(t)` is independent of the tolerance or step size, but may vary in time. +Single-scale adaptive controllers assume that the local error at a step :math:`n` with step +size :math:`h_n` has order :math:`p`, i.e., + +.. math:: + LTE_n = c(t_n) (h_n)^{p+1}, + +to predict candidate values :math:`h_{n+1}`. We may therefore repurpose an existing +single-scale controller to predict candidate values :math:`\text{RTOL}^F_{n+1}` by +supplying an "order" :math:`p=0` and a "control parameter" +:math:`h_n=\left(\text{RTOL}_n^F\right)`. + +Thus to construct an :math:`h^S`-:math:`Tol` controller, we require three separate single-rate +adaptivity controllers: + +* scontrol-H -- this is a single-rate controller that adapts :math:`h^S_n` within the + slow integrator to achieve user-requested solution tolerances. + +* scontrol-Tol -- this is a single-rate controller that adapts :math:`\text{RTOL}^F_n` + using the strategy described above. + +* fcontrol -- this adapts time steps :math:`h^F` within the fast integrator to achieve + the current tolerance, :math:`\text{RTOL}^F_n`. + +We note that both the decoupled and :math:`h^S`-:math:`Tol` controller families may be used in +multirate calculations with an arbitrary number of time scales, since these focus on only +one scale at a time, or on how a given time scale relates to the next-faster scale. + + +.. _ARKODE.Mathematics.MultirateFastError: + +Fast temporal error estimation +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +MRI temporal adaptivity requires estimation of the temporal errors that +arise at *both* the slow and fast time scales, which we denote here as +:math:`\varepsilon^S` and :math:`\varepsilon^F`, respectively. While the +slow error may be estimated as :math:`\varepsilon^S = \|y_n - \tilde{y}_n\|`, +non-intrusive approaches for estimating :math:`\varepsilon^F` are more +challenging. ARKODE provides several strategies to help provide this estimate, all +of which assume the fast integrator is temporally adaptive and, at each of its +:math:`m` steps to reach :math:`t_n`, computes an estimate of the local +temporal error, :math:`\varepsilon^F_{n,m}`. In this case, we assume that the +fast integrator was run with the same absolute tolerances as the slow integrator, but +that it may have used a potentially different relative solution tolerance, +:math:`\text{RTOL}^F`. The fast integrator then accumulates these local error +estimates using either a "maximum accumulation" strategy, + +.. math:: + \varepsilon^F_{max} = \text{RTOL}^F \max_{m\in \mathcal{S}} \|\varepsilon^F_{n,m}\|_{WRMS}, + :label: maximum_accumulation + +an "additive accumulation" strategy, + +.. math:: + \varepsilon^F_{sum} = \text{RTOL}^F \sum_{m\in \mathcal{S}} \|\varepsilon^F_{n,m}\|_{WRMS}, + :label: additive_accumulation + +or using an "averaged accumulation" strategy, + +.. math:: + \varepsilon^F_{avg} = \frac{\text{RTOL}^F}{\Delta t_{\mathcal{S}}} \sum_{m\in \mathcal{S}} h_{n,m} \|\varepsilon^F_{n,m}\|_{WRMS}, + :label: average_accumulation + +where :math:`h_{n,m}` is the step size that gave rise to :math:`\varepsilon^F_{n,m}`, +:math:`\Delta t_{\mathcal{S}}` denotes the elapsed time over which :math:`\mathcal{S}` +is taken, and the norms are taken using the tolerance-informed error-weight vector. In +each case, the sum or the maximum is taken over the set of all steps :math:`\mathcal{S}` +since the fast error accumulator has been reset. + + + +.. _ARKODE.Mathematics.InitialStep: + +Initial step size estimation +============================== + +Before time step adaptivity can be accomplished, an initial step must be taken. These +values may always be provided by the user; however, if these are not provided then +ARKODE will estimate a suitable choice. Typically +with adaptive methods, the first step should be chosen conservatively to ensure +that it succeeds both in its internal solver algorithms, and its eventual temporal error +test. However, if this initial step is too conservative then its computational cost will +essentially be wasted. We thus strive to construct a conservative step that will succeed +while also progressing toward the eventual solution. + +Before commenting on the specifics of ARKODE, we first summarize two common +approaches to initial step size selection. To this end, consider a simple +single-time-scale ODE, + +.. math:: + y'(t) = f(t,y), \quad y(t_0) = y_0 + :label: IVP_single + +For this, we may consider two Taylor series expansions of :math:`y(t_0+h)` around the +initial time, + +.. math:: + y(t_0+h) = y_0 + h f(t_0,y_0) + \frac{h^2}{2} \frac{\mathrm d}{\mathrm dt} f(t_0+\tau,y_0+\eta),\\ + :label: TSExp1 + +and + +.. math:: + y(t_0+h) = y_0 + h f(t_0+\tau,y_0+\eta), + :label: TSExp0 + +where :math:`t_0+\tau` is between :math:`t_0` and :math:`t_0+h`, and :math:`y_0+\eta` +is on the line segment connecting :math:`y_0` and :math:`y(t_0+h)`. + +Initial step size estimation based on the first-order Taylor expansion :eq:`TSExp1` +typically attempts to determine a step size such that an explicit Euler method +for :eq:`IVP_single` would be sufficiently accurate, i.e., + +.. math:: + \|y(t_0+h_0) - \left(y_0 + h_0 f(t_0,y_0)\right)\| \approx \left\|\frac{h^2}{2} \frac{\mathrm d}{\mathrm dt} f(t_0,y_0)\right\| < 1, + +where we have assumed that :math:`y(t)` is sufficiently differentiable, and that the +norms include user-specified tolerances such that an error with norm less than one is +deemed "acceptable." Satisfying this inequality with a value of :math:`\frac12` and +solving for :math:`h_0`, we have + +.. math:: + |h_0| = \frac{1}{\left\|\frac{\mathrm d}{\mathrm dt} f(t_0,y_0)\right\|^{1/2}}. + +Finally, by estimating the time derivative with finite-differences, + +.. math:: + \frac{\mathrm d}{\mathrm dt} f(t_0,y_0) \approx \frac{1}{\delta t} \left(f(t_0+\delta t,y_0+\delta t f(t_0,y_0)) - f(t_0,y_0)\right), + +we obtain + +.. math:: + |h_0| = \frac{{\delta t}^{1/2}}{\|f(t_0+\delta t,y_0+\delta t f(t_0,y_0)) - f(t_0,y_0)\|^{1/2}}. + :label: H0_TSExp1 + +Initial step size estimation based on the simpler Taylor expansion :eq:`TSExp0` +instead assumes that the first calculated time step should be "close" to the +initial state, + +.. math:: + \|y(t_0+h_0) - y_0 \| \approx \left\|h_0 f(t_0,y_0)\right\| < 1, + +where we again satisfy the inequality with a value of :math:`\frac12` to obtain + +.. math:: + |h_0| = \frac{1}{2\left\| f(t_0,y_0)\right\|}. + :label: H0_TSExp0 + + + +Comparing the two estimates :eq:`H0_TSExp1` and :eq:`H0_TSExp0`, we see that the +former has double the number of :math:`f` evaluations, but that it has a less +conservative estimate of :math:`h_0`, particularly since we expect any valid +time integration method to have at least :math:`\mathcal{O}(h)` accuracy. + +Of these two approaches, for calculations at a single time scale (e.g., using ARKStep), +formula :eq:`H0_TSExp1` is used, due to its more aggressive estimate for :math:`h_0`. + + +.. _ARKODE.Mathematics.MultirateInitialSteps: + +Initial multirate step sizes +------------------------------ + +In MRI methods, initial time step selection is complicated by the fact that not only must +an initial slow step size, :math:`h_0^S`, be chosen, but a smaller initial step, +:math:`h_0^F`, must also be selected. Additionally, it is typically assumed that within +MRI methods, evaluation of :math:`f^S` is significantly more costly than evaluation of +:math:`f^F`, and thus we wish to construct these initial steps accordingly. + +Under an assumption that conservative steps will be selected for both time scales, +the error arising from temporal coupling between the slow and fast methods may be +negligible. Thus, we estimate initial values of :math:`h^S_0` and :math:`h^F_0` +independently. Due to our assumed higher cost of :math:`f^S`, then for the slow +time scale we employ the initial estimate :eq:`H0_TSExp0` for :math:`h^S_0` using +:math:`f = f^S`. Since the function :math:`f^F` is assumed to be cheaper, we +instead apply the estimate :eq:`H0_TSExp1` for :math:`h^F_0` using :math:`f=f^F`, +and enforce an upper bound :math:`|h^F_0| \le \frac{|h^S_0|}{10}`. + +.. note:: + + If the fast integrator does not supply its "full RHS function" :math:`f^F` + for the MRI method to call, then we simply initialize :math:`h^F_0 = \frac{h^S_0}{100}`. @@ -1048,10 +1383,10 @@ Here the explicit stability step factor :math:`c>0` (often called the Fixed time stepping =================== -While both the ARKStep and ERKStep time-stepping modules are +While most of the time-stepping modules are designed for tolerance-based time step adaptivity, they additionally support a "fixed-step" mode. This mode is typically used for debugging -purposes, for verification against hand-coded Runge--Kutta methods, or for +purposes, for verification against hand-coded methods, or for problems where the time steps should be chosen based on other problem-specific information. In this mode, all internal time step adaptivity is disabled: @@ -1068,7 +1403,7 @@ information. In this mode, all internal time step adaptivity is disabled: size by default. .. note:: - Fixed-step mode is currently required for the slow time scale in the MRIStep module. + Any methods that do not provide an embedding are required to be run in fixed-step mode. Additional information on this mode is provided in the section @@ -1104,17 +1439,14 @@ Nonlinear solver methods ------------------------------------ -For the DIRK and ARK methods corresponding to :eq:`ARKODE_IMEX_IVP` and -:eq:`ARKODE_IVP_implicit` in ARKStep, and the solve-decoupled implicit slow -stages :eq:`ARKODE_MRI_delta_c_zero` in MRIStep, an implicit system +Methods with an implicit partition require solving implicit systems of the form .. math:: - G(z_i) = 0 + G(z_i) = 0. :label: ARKODE_Residual -must be solved for each implicit stage :math:`z_i`. In order to -maximize solver efficiency, we define this root-finding problem differently -based on the type of mass-matrix supplied by the user. +In order to maximize solver efficiency, we define this root-finding problem +differently based on the type of mass-matrix supplied by the user. * In the case that :math:`M=I` within ARKStep, we define the residual as @@ -1170,18 +1502,30 @@ based on the type of mass-matrix supplied by the user. As above, this form of the residual is chosen to remove excessive mass-matrix solves from the nonlinear solve process. -* Similarly, in MRIStep (that always assumes :math:`M=I`), we have the residual +* Similarly, in MRIStep (that always assumes :math:`M=I`), MRI-GARK and IMEX-MRI-GARK methods + have the residual .. math:: - G(z_i) \equiv z_i - h^S \left(\sum_{k\geq 0} \frac{\gamma_{i,i}^{\{k\}}}{k+1}\right) + G(z_i) \equiv z_i - h^S \left(\sum_{k\geq 1} \frac{\Gamma_{i,i,k}}{k}\right) f^I(t_{n,i}^S, z_i) - a_i = 0 - :label: ARKODE_MRIStep_Residual + :label: ARKODE_IMEX-MRI-GARK_Residual + + where + + .. math:: + a_i \equiv z_{i-1} + h^S \sum_{j=1}^{i-1} \left(\sum_{k\geq 1} + \frac{\Gamma_{i,j,k}}{k}\right)f^I(t_{n,j}^S, z_j). + + IMEX-MRI-SR methods have the residual + + .. math:: + G(z_i) \equiv z_i - h^S \Gamma_{i,i} f^I(t_{n,i}^S, z_i) - a_i = 0 + :label: ARKODE_IMEX-MRI-SR_Residual where .. math:: - a_i \equiv z_{i-1} + h^S \sum_{j=1}^{i-1} \left(\sum_{k\geq 0} - \frac{\gamma_{i,j}^{\{k\}}}{k+1}\right)f^I(t_{n,j}^S, z_j). + a_i \equiv z_{i-1} + h^S \sum_{j=1}^{i-1} \Gamma_{i,j} f^I(t_{n,j}^S, z_j). Upon solving for :math:`z_i`, method stages must store @@ -1240,7 +1584,7 @@ within ARKStep, or .. math:: {\mathcal A}(t,z) \approx I - \gamma J(t,z), \quad J(t,z) = \frac{\partial f^I(t,z)}{\partial z}, \quad\text{and}\quad - \gamma = h^S \sum_{k\geq 0} \frac{\gamma_{i,i}^{\{k\}}}{k+1} + \gamma = h^S \sum_{k\geq 1} \frac{\Gamma_{i,i,k}}{k} :label: ARKODE_NewtonMatrix_MRIStep within MRIStep. @@ -1335,7 +1679,7 @@ or .. math:: \tilde{\mathcal A}(\tilde{t},\tilde{z}) \approx I - \tilde{\gamma} J(\tilde{t},\tilde{z}), \quad\text{and}\quad - \tilde{\gamma} = \tilde{h} \sum_{k\geq 0} \frac{\gamma_{i,i}^{\{k\}}}{k+1}\quad\text{(MRIStep)}. + \tilde{\gamma} = \tilde{h} \sum_{k\geq 1} \frac{\Gamma_{i,i,k}}{k}\quad\text{(MRIStep)}. :label: ARKODE_modified_NewtonMatrix_MRI Here, the solution :math:`\tilde{z}`, time :math:`\tilde{t}`, and step @@ -1349,7 +1693,7 @@ but may be modified by the user. When using the dense and band SUNMatrix objects for the linear systems :eq:`ARKODE_modified_Newton_system`, the Jacobian :math:`J` may be supplied -by a user routine, or approximated internally by finite-differences. +by a user routine, or approximated internally with finite-differences. In the case of differencing, we use the standard approximation .. math:: diff --git a/doc/arkode/guide/source/Usage/ARKStep/User_callable.rst b/doc/arkode/guide/source/Usage/ARKStep/User_callable.rst index ae01be6b25..65cbe33287 100644 --- a/doc/arkode/guide/source/Usage/ARKStep/User_callable.rst +++ b/doc/arkode/guide/source/Usage/ARKStep/User_callable.rst @@ -4404,7 +4404,11 @@ wrap an ARKStep memory block as an :c:type:`MRIStepInnerStepper`. /* create an MRIStep object, setting the slow (outer) right-hand side functions and the initial condition */ - outer_arkode_mem = MRIStepCreate(fse, fsi, t0, y0, stepper, sunctx) + outer_arkode_mem = MRIStepCreate(fse, fsi, t0, y0, stepper, sunctx); **Example codes:** * ``examples/arkode/CXX_parallel/ark_diffusion_reaction_p.cpp`` + + .. deprecated:: x.y.z + + Use :c:func:`ARKodeCreateMRIStepInnerStepper` instead. diff --git a/doc/arkode/guide/source/Usage/ERKStep/User_callable.rst b/doc/arkode/guide/source/Usage/ERKStep/User_callable.rst index 865e4c3e25..4d9506ff76 100644 --- a/doc/arkode/guide/source/Usage/ERKStep/User_callable.rst +++ b/doc/arkode/guide/source/Usage/ERKStep/User_callable.rst @@ -33,7 +33,7 @@ ERKStep supports the following categories: * temporal adaptivity * relaxation Runge--Kutta methods -ERKStep does not have forcing function support when converted to a +ERKStep also has forcing function support when converted to a :c:type:`SUNStepper` or :c:type:`MRIStepInnerStepper`. See :c:func:`ARKodeCreateSUNStepper` and :c:func:`ARKStepCreateMRIStepInnerStepper` for additional details. @@ -1787,9 +1787,9 @@ Main solver optional output functions typedef struct ARKodeButcherTableMem { - int q; /* method order of accuracy */ - int p; /* embedding order of accuracy */ - int stages; /* number of stages */ + int q; /* method order of accuracy */ + int p; /* embedding order of accuracy */ + int stages; /* number of stages */ sunrealtype **A; /* Butcher table coefficients */ sunrealtype *c; /* canopy node coefficients */ sunrealtype *b; /* root node coefficients */ diff --git a/doc/arkode/guide/source/Usage/LSRKStep/User_callable.rst b/doc/arkode/guide/source/Usage/LSRKStep/User_callable.rst index a08e5918b4..0f9d53f581 100644 --- a/doc/arkode/guide/source/Usage/LSRKStep/User_callable.rst +++ b/doc/arkode/guide/source/Usage/LSRKStep/User_callable.rst @@ -31,6 +31,10 @@ LSRKStep supports the following categories: * temporal adaptivity +LSRKStep does not have forcing function support when converted to a +:c:type:`SUNStepper` or :c:type:`MRIStepInnerStepper`. See +:c:func:`ARKodeCreateSUNStepper` and :c:func:`ARKStepCreateMRIStepInnerStepper` +for additional details. .. _ARKODE.Usage.LSRKStep.Initialization: @@ -85,7 +89,7 @@ Optional input functions .. c:function:: int LSRKStepSetSTSMethod(void* arkode_mem, ARKODE_LSRKMethodType method); - This function selects the LSRK STS method that should be used. The list of allowable + This function selects the LSRK STS method that should be used. The list of allowable values for this input is below. :c:func:`LSRKStepCreateSTS` defaults to using :c:enumerator:`ARKODE_LSRK_RKC_2`. @@ -100,7 +104,7 @@ Optional input functions .. c:function:: int LSRKStepSetSSPMethod(void* arkode_mem, ARKODE_LSRKMethodType method); - This function selects the LSRK SSP method that should be used. The list of allowable + This function selects the LSRK SSP method that should be used. The list of allowable values for this input is below. :c:func:`LSRKStepCreateSSP` defaults to using :c:enumerator:`ARKODE_LSRK_SSP_S_2`. @@ -123,20 +127,20 @@ Allowable Method Families .. c:enumerator:: ARKODE_LSRK_RKL_2 - Second order Runge--Kutta--Legendre method + Second order Runge--Kutta--Legendre method .. c:enumerator:: ARKODE_LSRK_SSP_S_2 - Second order, s-stage SSP(s,2) method + Second order, s-stage SSP(s,2) method .. c:enumerator:: ARKODE_LSRK_SSP_S_3 - Third order, s-stage SSP(s,3) method + Third order, s-stage SSP(s,3) method .. c:enumerator:: ARKODE_LSRK_SSP_10_4 Fourth order, 10-stage SSP(10,4) method - + .. c:function:: int LSRKStepSetSTSMethodByName(void* arkode_mem, const char* emethod); @@ -199,7 +203,7 @@ Allowable Method Families * *ARK_SUCCESS* if successful * *ARKLS_MEM_NULL* if ``arkode_mem`` was ``NULL``. -.. note:: If LSRKStepSetDomEigFrequency routine is not called, then the default ``nsteps`` is set to :math:`25` as recommended in :cite:p:`VSH:04`. +.. note:: If LSRKStepSetDomEigFrequency routine is not called, then the default ``nsteps`` is set to :math:`25` as recommended in :cite:p:`VSH:04`. Calling this function with ``nsteps < 0`` resets the default value while ``nsteps = 0`` refers to constant dominant eigenvalue. @@ -217,16 +221,16 @@ Allowable Method Families * *ARKLS_MEM_NULL* if ``arkode_mem`` was ``NULL``. .. note:: If LSRKStepSetMaxNumStages routine is not called, then the default ``stage_max_limit`` is - set to :math:`200`. Calling this function with ``stage_max_limit < 2`` resets the default value. - This limit should be chosen with consideration of the following proportionality: :math:`s^2 \sim - h\lambda`, + set to :math:`200`. Calling this function with ``stage_max_limit < 2`` resets the default value. + This limit should be chosen with consideration of the following proportionality: :math:`s^2 \sim - h\lambda`, where :math:`s` is the number of stages used, :math:`h` is the current step size and :math:`\lambda` is the dominant eigenvalue. .. c:function:: int LSRKStepSetDomEigSafetyFactor(void* arkode_mem, sunrealtype dom_eig_safety); - Specifies a safety factor to use for the result of the dominant eigenvalue estimation function. - This value is used to scale the magnitude of the dominant eigenvalue, in the hope of ensuring - a sufficient number of stages for the method to be stable. This input is only used for RKC + Specifies a safety factor to use for the result of the dominant eigenvalue estimation function. + This value is used to scale the magnitude of the dominant eigenvalue, in the hope of ensuring + a sufficient number of stages for the method to be stable. This input is only used for RKC and RKL methods. **Arguments:** @@ -244,7 +248,7 @@ Allowable Method Families .. c:function:: int LSRKStepSetSSPStageNum(void* arkode_mem, int num_of_stages); Sets the number of stages, ``s`` in ``SSP(s, p)`` methods. This input is only utilized by SSPRK methods. - + * :c:enumerator:`ARKODE_LSRK_SSP_S_2` -- ``num_of_stages`` must be greater than or equal to 2 * :c:enumerator:`ARKODE_LSRK_SSP_S_3` -- ``num_of_stages`` must be a perfect-square greater than or equal to 4 * :c:enumerator:`ARKODE_LSRK_SSP_10_4` -- ``num_of_stages`` cannot be modified from 10, so this function should not be called. @@ -259,8 +263,8 @@ Allowable Method Families * *ARK_ILL_INPUT* if an argument had an illegal value (e.g. SSP method is not declared) .. note:: If LSRKStepSetSSPStageNum routine is not called, then the default ``num_of_stages`` is - set. Calling this function with ``num_of_stages <= 0`` resets the default values: - + set. Calling this function with ``num_of_stages <= 0`` resets the default values: + * ``num_of_stages = 10`` for :c:enumerator:`ARKODE_LSRK_SSP_S_2` * ``num_of_stages = 9`` for :c:enumerator:`ARKODE_LSRK_SSP_S_3` * ``num_of_stages = 10`` for :c:enumerator:`ARKODE_LSRK_SSP_10_4` @@ -301,36 +305,36 @@ LSRKStep re-initialization function ------------------------------------- To reinitialize the LSRKStep module for the solution of a new problem, -where a prior call to :c:func:`LSRKStepCreateSTS` or :c:func:`LSRKStepCreateSSP` -has been made, the user must call the function :c:func:`LSRKStepReInitSTS()` -or :c:func:`LSRKStepReInitSSP()`, accordingly. The new problem must have -the same size as the previous one. This routine retains the current settings -for all LSRKstep module options and performs the same input checking and -initializations that are done in :c:func:`LSRKStepCreateSTS` or +where a prior call to :c:func:`LSRKStepCreateSTS` or :c:func:`LSRKStepCreateSSP` +has been made, the user must call the function :c:func:`LSRKStepReInitSTS()` +or :c:func:`LSRKStepReInitSSP()`, accordingly. The new problem must have +the same size as the previous one. This routine retains the current settings +for all LSRKstep module options and performs the same input checking and +initializations that are done in :c:func:`LSRKStepCreateSTS` or :c:func:`LSRKStepCreateSSP`, but it performs no memory allocation as it -assumes that the existing internal memory is sufficient for the new problem. -A call to this re-initialization routine deletes the solution history that -was stored internally during the previous integration, and deletes any -previously-set *tstop* value specified via a call to +assumes that the existing internal memory is sufficient for the new problem. +A call to this re-initialization routine deletes the solution history that +was stored internally during the previous integration, and deletes any +previously-set *tstop* value specified via a call to :c:func:`ARKodeSetStopTime()`. Following a successful call to -:c:func:`LSRKStepReInitSTS()` or :c:func:`LSRKStepReInitSSP()`, +:c:func:`LSRKStepReInitSTS()` or :c:func:`LSRKStepReInitSSP()`, call :c:func:`ARKodeEvolve()` again for the solution of the new problem. -One important use of the :c:func:`LSRKStepReInitSTS()` and -:c:func:`LSRKStepReInitSSP()` function is in the treating of jump -discontinuities in the RHS function. Except in cases of fairly small -jumps, it is usually more efficient to stop at each point of discontinuity -and restart the integrator with a readjusted ODE model, using a call to this -routine. To stop when the location of the discontinuity is known, simply -make that location a value of ``tout``. To stop when the location of -the discontinuity is determined by the solution, use the rootfinding feature. +One important use of the :c:func:`LSRKStepReInitSTS()` and +:c:func:`LSRKStepReInitSSP()` function is in the treating of jump +discontinuities in the RHS function. Except in cases of fairly small +jumps, it is usually more efficient to stop at each point of discontinuity +and restart the integrator with a readjusted ODE model, using a call to this +routine. To stop when the location of the discontinuity is known, simply +make that location a value of ``tout``. To stop when the location of +the discontinuity is determined by the solution, use the rootfinding feature. In either case, it is critical that the RHS function *not* incorporate the -discontinuity, but rather have a smooth extension over the discontinuity, -so that the step across it (and subsequent rootfinding, if used) can be done -efficiently. Then use a switch within the RHS function (communicated through -``user_data``) that can be flipped between the stopping of the integration -and the restart, so that the restarted problem uses the new values (which -have jumped). Similar comments apply if there is to be a jump in the +discontinuity, but rather have a smooth extension over the discontinuity, +so that the step across it (and subsequent rootfinding, if used) can be done +efficiently. Then use a switch within the RHS function (communicated through +``user_data``) that can be flipped between the stopping of the integration +and the restart, so that the restarted problem uses the new values (which +have jumped). Similar comments apply if there is to be a jump in the dependent variable vector. diff --git a/doc/arkode/guide/source/Usage/MRIStep/Custom_Inner_Stepper/Description.rst b/doc/arkode/guide/source/Usage/MRIStep/Custom_Inner_Stepper/Description.rst index f327d5a76c..9a9590bb9b 100644 --- a/doc/arkode/guide/source/Usage/MRIStep/Custom_Inner_Stepper/Description.rst +++ b/doc/arkode/guide/source/Usage/MRIStep/Custom_Inner_Stepper/Description.rst @@ -19,17 +19,19 @@ The MRIStepInnerStepper Class As with other SUNDIALS classes, the :c:type:`MRIStepInnerStepper` abstract base class is implemented using a C structure containing a ``content`` pointer to the -derived class member data and a structure of function pointers the derived class -implementations of the virtual methods. +derived class member data and a structure of function pointers (vtable) to the +derived class implementations of the base class virtual methods. .. c:type:: MRIStepInnerStepper An object for solving the fast (inner) ODE in an MRI method. - The actual definition of the ``MRIStepInnerStepper`` structure is kept - private to allow for the object internals to change without impacting user - code. The following sections describe the base class methods and the virtual - methods that a must be provided by a derived class. +The actual definitions of the structure and the +corresponding operations structure are kept private to allow for the object +internals to change without impacting user code. The following sections describe +the base (:numref:`ARKODE.Usage.MRIStep.CustomInnerStepper.Description.BaseMethods`) +and virtual methods (:numref:`ARKODE.Usage.MRIStep.CustomInnerStepper.Description.ImplMethods`) +that a must be provided by a derived class. .. _ARKODE.Usage.MRIStep.CustomInnerStepper.Description.BaseMethods: @@ -53,13 +55,11 @@ Creating and Destroying an Object This function creates an :c:type:`MRIStepInnerStepper` object to which a user should attach the member data (content) pointer and method function pointers. - **Arguments:** - * ``sunctx`` -- the SUNDIALS simulation context. - * ``stepper`` -- a pointer to an inner stepper object. + :param sunctx: the SUNDIALS simulation context. + :param stepper: a pointer to an inner stepper object. - **Return value:** - * ARK_SUCCESS if successful - * ARK_MEM_FAIL if a memory allocation error occurs + :retval ARK_SUCCESS: if successful + :retval ARK_MEM_FAIL: if a memory allocation error occurs **Example usage:** @@ -109,11 +109,9 @@ Creating and Destroying an Object This function destroys an :c:type:`MRIStepInnerStepper` object. - **Arguments:** - * *stepper* -- a pointer to an inner stepper object. + :param stepper: a pointer to an inner stepper object. - **Return value:** - * ARK_SUCCESS if successful + :retval ARK_SUCCESS: if successful **Example usage:** @@ -141,13 +139,11 @@ Attaching and Accessing the Content Pointer This function attaches a member data (content) pointer to an :c:type:`MRIStepInnerStepper` object. - **Arguments:** - * *stepper* -- an inner stepper object. - * *content* -- a pointer to the stepper member data. + :param stepper: an inner stepper object. + :param content: a pointer to the stepper member data. - **Return value:** - * ARK_SUCCESS if successful - * ARK_ILL_INPUT if the stepper is ``NULL`` + :retval ARK_SUCCESS: if successful + :retval ARK_ILL_INPUT: if the stepper is ``NULL`` **Example usage:** @@ -166,13 +162,11 @@ Attaching and Accessing the Content Pointer This function retrieves the member data (content) pointer from an :c:type:`MRIStepInnerStepper` object. - **Arguments:** - * *stepper* -- an inner stepper object. - * *content* -- a pointer to set to the stepper member data pointer. + :param stepper: an inner stepper object. + :param content: a pointer to set to the stepper member data pointer. - **Return value:** - * ARK_SUCCESS if successful - * ARK_ILL_INPUT if the stepper is ``NULL`` + :retval ARK_SUCCESS: if successful + :retval ARK_ILL_INPUT: if the stepper is ``NULL`` **Example usage:** @@ -199,13 +193,11 @@ Setting Member Functions This function attaches an :c:type:`MRIStepInnerEvolveFn` function to an :c:type:`MRIStepInnerStepper` object. - **Arguments:** - * *stepper* -- an inner stepper object. - * *fn* -- the :c:type:`MRIStepInnerStepper` function to attach. + :param stepper: an inner stepper object. + :param fn: the :c:type:`MRIStepInnerStepper` function to attach. - **Return value:** - * ARK_SUCCESS if successful - * ARK_ILL_INPUT if the stepper is ``NULL`` + :retval ARK_SUCCESS: if successful + :retval ARK_ILL_INPUT: if the stepper is ``NULL`` **Example usage:** @@ -223,13 +215,11 @@ Setting Member Functions This function attaches an :c:type:`MRIStepInnerFullRhsFn` function to an :c:type:`MRIStepInnerStepper` object. - **Arguments:** - * *stepper* -- an inner stepper object. - * *fn* -- the :c:type:`MRIStepInnerFullRhsFn` function to attach. + :param stepper: an inner stepper object. + :param fn: the :c:type:`MRIStepInnerFullRhsFn` function to attach. - **Return value:** - * ARK_SUCCESS if successful - * ARK_ILL_INPUT if the stepper is ``NULL`` + :retval ARK_SUCCESS: if successful + :retval ARK_ILL_INPUT: if the stepper is ``NULL`` **Example usage:** @@ -247,13 +237,11 @@ Setting Member Functions This function attaches an :c:type:`MRIStepInnerResetFn` function to an :c:type:`MRIStepInnerStepper` object. - **Arguments:** - * *stepper* -- an inner stepper object. - * *fn* -- the :c:type:`MRIStepInnerResetFn` function to attach. + :param stepper: an inner stepper object. + :param fn: the :c:type:`MRIStepInnerResetFn` function to attach. - **Return value:** - * ARK_SUCCESS if successful - * ARK_ILL_INPUT if the stepper is ``NULL`` + :retval ARK_SUCCESS: if successful + :retval ARK_ILL_INPUT: if the stepper is ``NULL`` **Example usage:** @@ -265,6 +253,49 @@ Setting Member Functions **Example codes:** * ``examples/arkode/CXX_parallel/ark_diffusion_reaction_p.cpp`` +.. c:function:: int MRIStepInnerStepper_SetAccumulatedErrorGetFn(MRIStepInnerStepper stepper, MRIStepInnerGetAccumulatedError fn) + + This function attaches an :c:type:`MRIStepInnerGetAccumulatedError` function to an + :c:type:`MRIStepInnerStepper` object. + + :param stepper: an inner stepper object. + :param fn: the :c:type:`MRIStepInnerGetAccumulatedError` function to attach. + + :retval ARK_SUCCESS: if successful + :retval ARK_ILL_INPUT: if the stepper is ``NULL`` + + .. versionadded: x.y.z + + +.. c:function:: int MRIStepInnerStepper_SetAccumulatedErrorResetFn(MRIStepInnerStepper stepper, MRIStepInnerResetAccumulatedError fn) + + This function attaches an :c:type:`MRIStepInnerResetAccumulatedError` function to an + :c:type:`MRIStepInnerStepper` object. + + :param stepper: an inner stepper object. + :param fn: the :c:type:`MRIStepInnerResetAccumulatedError` function to attach. + + :retval ARK_SUCCESS: if successful + :retval ARK_ILL_INPUT: if the stepper is ``NULL`` + + .. versionadded: x.y.z + + +.. c:function:: int MRIStepInnerStepper_SetRTolFn(MRIStepInnerStepper stepper, MRIStepInnerSetRTol fn) + + This function attaches an :c:type:`MRIStepInnerSetRTol` function to an + :c:type:`MRIStepInnerStepper` object. + + :param stepper: an inner stepper object. + :param fn: the :c:type:`MRIStepInnerSetRTol` function to attach. + + :retval ARK_SUCCESS: if successful + :retval ARK_ILL_INPUT: if the stepper is ``NULL`` + + .. versionadded: x.y.z + + + .. _ARKODE.Usage.MRIStep.CustomInnerStepper.Description.BaseMethods.Forcing: Applying and Accessing Forcing Data @@ -275,7 +306,10 @@ responsible for evaluating ODE right-hand side function :math:`f^F(t,v)` as well as computing and applying the forcing term :eq:`ARKODE_MRI_forcing_poly` to obtain the full right-hand side of the inner (fast) ODE :eq:`ARKODE_MRI_IVP`. The functions in this section can be used to either apply the inner (fast) forcing or access the -data necessary to construct the inner (fast) forcing polynomial. +data necessary to construct the inner (fast) forcing polynomial. While the first of +these is less intrusive and may be used to package an existing black-box IVP solver +as an MRIStepInnerStepper, the latter may be more computationally efficient since it +does not traverse the data directly. .. c:function:: int MRIStepInnerStepper_AddForcing(MRIStepInnerStepper stepper, sunrealtype t, N_Vector ff) @@ -284,46 +318,36 @@ data necessary to construct the inner (fast) forcing polynomial. time *t* and adds it to input vector *ff*, i.e., the inner (fast) right-hand side vector. - **Arguments:** - * *stepper* -- an inner stepper object. - * *t* -- the time at which the forcing should be evaluated. - * *f* -- the vector to which the forcing should be applied. - - **Return value:** - * ARK_SUCCESS if successful - * ARK_ILL_INPUT if the stepper is ``NULL`` - - **Example usage:** + :param stepper: an inner stepper object. + :param t: the time at which the forcing should be evaluated. + :param f: the vector to which the forcing should be applied. - .. code-block:: C - - /* compute the forcing term and add it the fast RHS vector */ - flag = MRIStepInnerStepper_AddForcing(inner_stepper, t, f_fast); + :retval ARK_SUCCESS: if successful + :retval ARK_ILL_INPUT: if the stepper is ``NULL`` **Example codes:** * ``examples/arkode/CXX_parallel/ark_diffusion_reaction_p.cpp`` + .. c:function:: int MRIStepInnerStepper_GetForcingData(MRIStepInnerStepper stepper, sunrealtype *tshift, sunrealtype *tscale, N_Vector **forcing, int *nforcing) This function provides access to data necessary to compute the forcing term :eq:`ARKODE_MRI_forcing_poly`. This includes the shift and scaling factors for the normalized time :math:`\tau = (t - t_{n,i-1}^S)/(h^S \Delta c_i^S)` and the - array of polynomial coefficient vectors :math:`\hat{\gamma}^{\{k\}}_i`. + array of polynomial coefficient vectors :math:`\hat{\gamma}^{i,k}`. - **Arguments:** - * *stepper* -- an inner stepper object. - * *tshift* -- the time shift to apply to the current time when computing the + :param stepper: an inner stepper object. + :param tshift: the time shift to apply to the current time when computing the forcing, :math:`t_{n,i-1}^S`. - * *tscale* -- the time scaling to apply to the current time when computing + :param tscale: the time scaling to apply to the current time when computing the forcing, :math:`h^S \Delta c_i^S`. - * *forcing* -- a pointer to an array of forcing vectors, - :math:`\hat{\gamma}^{\{k\}}_i`. - * *nforcing* -- the number of forcing vectors. + :param forcing: a pointer to an array of forcing vectors, + :math:`\hat{\gamma}_{i,k}`. + :param nforcing: the number of forcing vectors. - **Return value:** - * ARK_SUCCESS if successful - * ARK_ILL_INPUT if the stepper is ``NULL`` + :retval ARK_SUCCESS: if successful + :retval ARK_ILL_INPUT: if the stepper is ``NULL`` **Example usage:** @@ -384,8 +408,9 @@ member functions: **Return value:** An :c:type:`MRIStepInnerEvolveFn` should return 0 if successful, a positive - value if a recoverable error occurred, or a negative value if it failed - unrecoverably. + value if a recoverable error occurred (i.e., the function could be successful if + called over a smaller time interval :math:`[t0,tout]`), or a negative value if + it failed unrecoverably. **Example codes:** * ``examples/arkode/CXX_parallel/ark_diffusion_reaction_p.cpp`` @@ -400,7 +425,8 @@ following member functions: This function computes the full right-hand side function of the inner (fast) ODE, :math:`f^F(t,v)` in :eq:`ARKODE_MRI_IVP` for a given value of the independent - variable *t* and state vector *y*. + variable *t* and state vector *y*. We note that this routine should *not* include + contributions from the forcing term :eq:`ARKODE_MRI_forcing_poly`. **Arguments:** * *stepper* -- the inner stepper object. @@ -416,9 +442,8 @@ following member functions: * ``ARK_FULLRHS_OTHER`` -- called elsewhere e.g., for dense output **Return value:** - An :c:type:`MRIStepInnerFullRhsFn` should return 0 if successful, a positive - value if a recoverable error occurred, or a negative value if it failed - unrecoverably. + An :c:type:`MRIStepInnerFullRhsFn` should return 0 if successful, or + a nonzero value upon failure. **Example codes:** * ``examples/arkode/CXX_parallel/ark_diffusion_reaction_p.cpp`` @@ -432,15 +457,94 @@ following member functions: This function resets the inner (fast) stepper state to the provided independent variable value and dependent variable vector. + If provided, the :c:type:`MRIStepInnerResetFn` function will be called + *before* a call to :c:type:`MRIStepInnerEvolveFn` when the state was + updated at the slow timescale. + **Arguments:** * *stepper* -- the inner stepper object. * *tR* -- the value of the independent variable :math:`t_R`. * *vR* -- the value of the dependent variable vector :math:`v(t_R)`. **Return value:** - An :c:type:`MRIStepInnerResetFn` should return 0 if successful, a positive - value if a recoverable error occurred, or a negative value if it failed - unrecoverably. + An :c:type:`MRIStepInnerResetFn` should return 0 if successful, or a nonzero + value upon failure. **Example codes:** * ``examples/arkode/CXX_parallel/ark_diffusion_reaction_p.cpp`` + + +.. c:type:: int (*MRIStepInnerGetAccumulatedError)(MRIStepInnerStepper stepper, sunrealtype* accum_error) + + This function returns an estimate of the accumulated solution error arising from the + inner stepper. Both the :c:type:`MRIStepInnerGetAccumulatedError` and + :c:type:`MRIStepInnerResetAccumulatedError` functions should be provided, or not; if only + one is provided then MRIStep will disable multirate temporal adaptivity and call neither. + + + **Arguments:** + * *stepper* -- the inner stepper object. + * *accum_error* -- estimation of the accumulated solution error. + + **Return value:** + An :c:type:`MRIStepInnerGetAccumulatedError` should return 0 if successful, a positive + value if a recoverable error occurred (i.e., the function could be successful if + called over a smaller time interval :math:`[t0,tout]`), or a negative value if it + failed unrecoverably. + + .. note:: + + This function is required when multirate temporal adaptivity has been enabled, + using a :c:type:`SUNAdaptController` module having type :c:enumerator:`SUN_ADAPTCONTROLLER_MRI_H_TOL`. + + If provided, the :c:type:`MRIStepInnerGetAccumulatedError` function will always + be called *after* a preceding call to the :c:type:`MRIStepInnerResetAccumulatedError` + function. + + +.. c:type:: int (*MRIStepInnerResetAccumulatedError)(MRIStepInnerStepper stepper) + + This function resets the inner stepper's accumulated solution error to zero. + This function performs a different role within MRIStep than the + :c:type:`MRIStepInnerResetFn`, and thus an implementation should make no + assumptions about the frequency/ordering of calls to either. + + **Arguments:** + * *stepper* -- the inner stepper object. + + **Return value:** + An :c:type:`MRIStepInnerResetAccumulatedError` should return 0 if successful, or + a nonzero value upon failure. + + .. note:: + + This function is required when multirate temporal adaptivity has been enabled, + using a :c:type:`SUNAdaptController` module having type :c:enumerator:`SUN_ADAPTCONTROLLER_MRI_H_TOL`. + + The :c:type:`MRIStepInnerResetAccumulatedError` function will always be called + *before* any calls to the :c:type:`MRIStepInnerGetAccumulatedError` function. + + Both the :c:type:`MRIStepInnerGetAccumulatedError` and + :c:type:`MRIStepInnerResetAccumulatedError` functions should be provided, or not; if only + one is provided then MRIStep will disable multirate temporal adaptivity and call neither. + + +.. c:type:: int (*MRIStepInnerSetRTol)(MRIStepInnerStepper stepper, sunrealtype rtol) + + This function accepts a relative tolerance for the inner stepper to use in its + upcoming adaptive solve. It is assumed that if the inner stepper supports absolute + tolerances as well, then these have been set up directly by the user to indicate the + "noise" level for solution components. + + **Arguments:** + * *stepper* -- the inner stepper object. + * *rtol* -- relative tolerance to use on the upcoming solve. + + **Return value:** + An :c:type:`MRIStepInnerSetRTol` should return 0 if successful, or a nonzero value + upon failure. + + .. note:: + + This function is required when multirate temporal adaptivity has been enabled + using a :c:type:`SUNAdaptController` module having type :c:enumerator:`SUN_ADAPTCONTROLLER_MRI_H_TOL`. diff --git a/doc/arkode/guide/source/Usage/MRIStep/Custom_Inner_Stepper/index.rst b/doc/arkode/guide/source/Usage/MRIStep/Custom_Inner_Stepper/index.rst index 9ce5b94aa9..a1f5272aae 100644 --- a/doc/arkode/guide/source/Usage/MRIStep/Custom_Inner_Stepper/index.rst +++ b/doc/arkode/guide/source/Usage/MRIStep/Custom_Inner_Stepper/index.rst @@ -17,36 +17,41 @@ MRIStep Custom Inner Steppers ============================= -Recall, MIS and MRI-GARK methods require solving the auxiliary IVP +Recall that infinitesimal multirate methods require solving a set of auxiliary IVPs .. math:: - \dot{v}(t) = f^F(t, v) + r_i(t), \qquad v(t_{n,i-1}^S) = z_{i-1} + \dot{v}(t) = f^F(t, v) + r_i(t), \qquad v(t_{i,0}) = v_{i,0}, :label: ARKODE_MRI_IVP -for :math:`i \geq 2` on the interval :math:`t \in [t_{n,i-1}^S, t_{n,i}^S]` -where :math:`t_{n,i-1}^S = t_{n-1} + c_{i-1}^S h^S`. The forcing term -:math:`r_i(t)` presented in :numref:`ARKODE.Mathematics.MRIStep` can be equivalently -written as +on intervals :math:`t \in [t_{i,0}, t_{i,f}]`. For the MIS, MRI-GARK and IMEX-MRI-GARK +methods implemented in MRIStep, the forcing term :math:`r_i(t)` +presented in :numref:`ARKODE.Mathematics.MRIStep` can be equivalently written as .. math:: r_i(t) = - \sum\limits_{k \geq 0} \hat{\omega}^{\{k\}}_i \tau^k + \sum\limits_{k \geq 1} \hat{\omega}_{i,k} \tau^{k-1} + - \sum\limits_{k \geq 0} \hat{\gamma}^{\{k\}}_i \tau^k + \sum\limits_{k \geq 1} \hat{\gamma}_{i,k} \tau^{k-1} :label: ARKODE_MRI_forcing_poly where :math:`\tau = (t - t_{n,i-1}^S)/(h^S \Delta c_i^S)` is the normalized time -with :math:`\Delta c_i^S=\left(c^S_i - c^S_{i-1}\right)` and the polynomial -coefficient vectors are +with :math:`\Delta c_i^S=\left(c^S_i - c^S_{i-1}\right)`, the slow stage times are +:math:`t_{n,i-1}^S = t_{n-1} + c_{i-1}^S h^S`, and the polynomial coefficient +vectors are .. math:: - \hat{\omega}^{\{k\}}_i = \frac{1}{\Delta c_i^S} \sum\limits_{j=1}^{i-1} - \omega^{\{k\}}_{i,j} f^E(t_{n,j}^S, z_j) + \hat{\omega}_{i,k} = \frac{1}{\Delta c_i^S} \sum\limits_{j=1}^{i-1} + \Omega_{i,j,k} f^E(t_{n,j}^S, z_j) \quad\text{and}\quad - \hat{\gamma}^{\{k\}}_i = \frac{1}{\Delta c_i^S} \sum\limits_{j=1}^i - \gamma^{\{k\}}_{i,j} f^I(t_{n,j}^S, z_j). + \hat{\gamma}_{i,k} = \frac{1}{\Delta c_i^S} \sum\limits_{j=1}^i + \Gamma_{i,j,k} f^I(t_{n,j}^S, z_j). :label: ARKODE_MRI_forcing_coefficients +The MERK and IMEX-MRI-SR methods included in MRIStep compute the forcing polynomial +:eq:`ARKODE_MRI_forcing_poly` similarly, with appropriate modifications to +:math:`\Delta c_i^S`, :math:`t_{n,i-1}^S`, and the coefficients +:eq:`ARKODE_MRI_forcing_coefficients`. + To evolve the IVP :eq:`ARKODE_MRI_IVP` MRIStep utilizes a generic time integrator interface defined by the :c:type:`MRIStepInnerStepper` base class. This section presents the :c:type:`MRIStepInnerStepper` base class and methods that define diff --git a/doc/arkode/guide/source/Usage/MRIStep/MRIStepCoupling.rst b/doc/arkode/guide/source/Usage/MRIStep/MRIStepCoupling.rst index 53d5a8c7d5..6da195368f 100644 --- a/doc/arkode/guide/source/Usage/MRIStep/MRIStepCoupling.rst +++ b/doc/arkode/guide/source/Usage/MRIStep/MRIStepCoupling.rst @@ -22,7 +22,36 @@ MRIStep supplies several built-in MIS, MRI-GARK, and IMEX-MRI-GARK methods, see coupling tables and their corresponding identifiers. Additionally, a user may supply a custom set of slow-to-fast time scale coupling coefficients by constructing a coupling table and attaching it with -:c:func:`MRIStepSetCoupling`. The MRI coupling tables are stored in an +:c:func:`MRIStepSetCoupling`. A given MRI coupling table can encode any of +the MRI methods supported by MRIStep. The family of MRI method encoded +by the table is determined by an enumerated type, :c:enum:`MRISTEP_METHOD_TYPE`: + +.. c:enum:: MRISTEP_METHOD_TYPE + + The MRI method family encoded by a :c:type:`MRIStepCoupling` table + + .. c:enumerator:: MRISTEP_EXPLICIT + + An explicit MRI-GARK method (does not support a slow implicit operator, :math:`f^I`). + + .. c:enumerator:: MRISTEP_IMPLICIT + + An implicit MRI-GARK method (does not support a slow explicit operator, :math:`f^E`). + + .. c:enumerator:: MRISTEP_IMEX + + An IMEX-MRK-GARK method. + + .. c:enumerator:: MRISTEP_MERK + + A explicit MERK method (does not support a slow implicit operator, :math:`f^I`). + + .. c:enumerator:: MRISTEP_SR + + An IMEX-MRI-SR method. + + +The MRI coupling tables themselves are stored in an :c:func:`MRIStepCoupling` object which is a pointer to a :c:struct:`MRIStepCouplingMem` structure: @@ -36,43 +65,57 @@ constructing a coupling table and attaching it with As described in :numref:`ARKODE.Mathematics.MRIStep`, the coupling from the slow time scale to the fast time scale is encoded by a vector of slow stage time abscissae, :math:`c^S \in \mathbb{R}^{s+1}` and a set of coupling - matrices :math:`\Gamma^{\{k\}}\in\mathbb{R}^{(s+1)\times(s+1)}` and - :math:`\Omega^{\{k\}}\in\mathbb{R}^{(s+1)\times(s+1)}`. + tensors :math:`\Gamma\in\mathbb{R}^{(s+1)\times(s+1)\times k}` and + :math:`\Omega\in\mathbb{R}^{(s+1)\times(s+1)\times k}`. + + .. c:member:: MRISTEP_METHOD_TYPE type + + Flag indicating the type of MRI method encoded by this table. .. c:member:: int nmat - The number of coupling matrices :math:`\Omega^{\{k\}}` for the - slow-nonstiff terms and/or :math:`\Gamma^{\{k\}}` for the slow-stiff terms - in :eq:`ARKODE_IVP_two_rate`, + The value of :math:`k` above i.e., number of coupling matrices in + :math:`\Omega` for the slow-nonstiff terms and/or in :math:`\Gamma` for + the slow-stiff terms in :eq:`ARKODE_IVP_two_rate`. .. c:member:: int stages - The number of abscissae i.e., :math:`s+1` above + The number of abscissae i.e., :math:`s+1` above. .. c:member:: int q - The method order of accuracy + The method order of accuracy. .. c:member:: int p - The embedding order of accuracy + The embedding order of accuracy. + + .. c:member:: sunrealtype* c + + An array of length ``[stages]`` containing the slow abscissae :math:`c^S` + for the method. .. c:member:: sunrealtype*** W - A three-dimensional array with dimensions ``[nmat][stages][stages]`` - containing the method's :math:`\Omega^{\{k\}}` coupling matrices for the - slow-nonstiff (explicit) terms in :eq:`ARKODE_IVP_two_rate` + A three-dimensional array with dimensions ``[nmat][stages+1][stages]`` + containing the method's :math:`\Omega` coupling coefficients for the + slow-nonstiff (explicit) terms in :eq:`ARKODE_IVP_two_rate`. .. c:member:: sunrealtype*** G - A three-dimensional array with dimensions ``[nmat][stages][stages]`` - containing the method's :math:`\Gamma^{\{k\}}` coupling matrices for the - slow-stiff (implicit) terms in :eq:`ARKODE_IVP_two_rate` + A three-dimensional array with dimensions ``[nmat][stages+1][stages]`` + containing the method's :math:`\Gamma` coupling coefficients for the + slow-stiff (implicit) terms in :eq:`ARKODE_IVP_two_rate`. - .. c:member:: sunrealtype* c + .. c:member:: int ngroup - An array of length ``[stages]`` containing the slow abscissae :math:`c^S` - for the method + Number of stage groups for the method (only relevant for MERK methods). + + .. c:member:: int** group + + A two-dimensional array with dimensions ``[stages][stages]`` that encodes + which stages should be combined together within fast integration groups + (only relevant for MERK methods). .. _ARKODE.Usage.MRIStep.MRIStepCoupling.Functions: @@ -87,27 +130,27 @@ are defined ``arkode/arkode_mristep.h``. .. _ARKODE.Usage.MRIStep.MRIStepCoupling.Functions.Table: .. table:: MRIStepCoupling functions - +---------------------------------------------+--------------------------------------------------------------------+ - | Function name | Description | - +---------------------------------------------+--------------------------------------------------------------------+ - | :c:func:`MRIStepCoupling_LoadTable()` | Loads a pre-defined MRIStepCoupling table by ID | - +---------------------------------------------+--------------------------------------------------------------------+ - | :c:func:`MRIStepCoupling_LoadTableByName()` | Loads a pre-defined MRIStepCoupling table by name | - +---------------------------------------------+--------------------------------------------------------------------+ - | :c:func:`MRIStepCoupling_Alloc()` | Allocate an empty MRIStepCoupling table | - +---------------------------------------------+--------------------------------------------------------------------+ - | :c:func:`MRIStepCoupling_Create()` | Create a new MRIStepCoupling table from coefficients | - +---------------------------------------------+--------------------------------------------------------------------+ - | :c:func:`MRIStepCoupling_MIStoMRI()` | Create a new MRIStepCoupling table from a slow Butcher table | - +---------------------------------------------+--------------------------------------------------------------------+ - | :c:func:`MRIStepCoupling_Copy()` | Create a copy of a MRIStepCoupling table | - +---------------------------------------------+--------------------------------------------------------------------+ - | :c:func:`MRIStepCoupling_Space()` | Get the MRIStepCoupling table real and integer workspace sizes | - +---------------------------------------------+--------------------------------------------------------------------+ - | :c:func:`MRIStepCoupling_Free()` | Deallocate a MRIStepCoupling table | - +---------------------------------------------+--------------------------------------------------------------------+ - | :c:func:`MRIStepCoupling_Write()` | Write the MRIStepCoupling table to an output file | - +---------------------------------------------+--------------------------------------------------------------------+ + +-------------------------------------------+--------------------------------------------------------------------+ + | Function name | Description | + +===========================================+====================================================================+ + | :c:func:`MRIStepCoupling_LoadTable` | Loads a pre-defined MRIStepCoupling table by ID | + +-------------------------------------------+--------------------------------------------------------------------+ + | :c:func:`MRIStepCoupling_LoadTableByName` | Loads a pre-defined MRIStepCoupling table by name | + +-------------------------------------------+--------------------------------------------------------------------+ + | :c:func:`MRIStepCoupling_Alloc` | Allocate an empty MRIStepCoupling table | + +-------------------------------------------+--------------------------------------------------------------------+ + | :c:func:`MRIStepCoupling_Create` | Create a new MRIStepCoupling table from coefficients | + +-------------------------------------------+--------------------------------------------------------------------+ + | :c:func:`MRIStepCoupling_MIStoMRI` | Create a new MRIStepCoupling table from a Butcher table | + +-------------------------------------------+--------------------------------------------------------------------+ + | :c:func:`MRIStepCoupling_Copy` | Create a copy of a MRIStepCoupling table | + +-------------------------------------------+--------------------------------------------------------------------+ + | :c:func:`MRIStepCoupling_Space` | Get the MRIStepCoupling table real and integer workspace sizes | + +-------------------------------------------+--------------------------------------------------------------------+ + | :c:func:`MRIStepCoupling_Free` | Deallocate a MRIStepCoupling table | + +-------------------------------------------+--------------------------------------------------------------------+ + | :c:func:`MRIStepCoupling_Write` | Write the MRIStepCoupling table to an output file | + +-------------------------------------------+--------------------------------------------------------------------+ .. c:function:: MRIStepCoupling MRIStepCoupling_LoadTable(ARKODE_MRITableID method) @@ -116,160 +159,215 @@ are defined ``arkode/arkode_mristep.h``. set of coupling tables and their corresponding identifiers, see :numref:`ARKODE.Usage.MRIStep.MRIStepCoupling.Tables`. + :param method: the coupling table identifier. - **Arguments:** - * ``method`` -- the coupling table identifier. - - **Return value:** - * An :c:type:`MRIStepCoupling` structure if successful. - * A ``NULL`` pointer if *method* was invalid or an allocation error occurred. + :returns: An :c:type:`MRIStepCoupling` structure if successful. A ``NULL`` + pointer if *method* was invalid or an allocation error occurred. -.. c:function:: MRIStepCoupling MRIStepCoupling_LoadTableByName(const char *method) +.. c:function:: MRIStepCoupling MRIStepCoupling_LoadTableByName(const char* method) Retrieves a specified coupling table. For further information on the current set of coupling tables and their corresponding name, see :numref:`ARKODE.Usage.MRIStep.MRIStepCoupling.Tables`. + :param method: the coupling table name. - **Arguments:** - * ``method`` -- the coupling table name. - - **Return value:** - * An :c:type:`MRIStepCoupling` structure if successful. - * A ``NULL`` pointer if *method* was invalid, *method* was - ``"ARKODE_MRI_NONE"``, or an allocation error occurred. + :returns: An :c:type:`MRIStepCoupling` structure if successful. + A ``NULL`` pointer if *method* was invalid, *method* was + ``"ARKODE_MRI_NONE"``, or an allocation error occurred. .. note:: This function is case sensitive. -.. c:function:: MRIStepCoupling MRIStepCoupling_Alloc(int nmat, int stages, int type) +.. c:function:: MRIStepCoupling MRIStepCoupling_Alloc(int nmat, int stages, MRISTEP_METHOD_TYPE type) Allocates an empty MRIStepCoupling table. - **Arguments:** - * ``nmat`` -- number of :math:`\Omega^{\{k\}}` and/or :math:`\Gamma^{\{k\}}` - matrices in the coupling table. - * ``stages`` -- number of stages in the coupling table. - * ``type`` -- the method type: explicit (0), implicit (1), or ImEx (2). + :param nmat: the value of :math:`k` i.e., number of number of coupling + matrices in :math:`\Omega` for the slow-nonstiff terms and/or in + :math:`\Gamma` for the slow-stiff terms in :eq:`ARKODE_IVP_two_rate`. + :param stages: number of stages in the coupling table. + :param type: the type of MRI method the table will encode. - **Return value:** - * An :c:type:`MRIStepCoupling` structure if successful. - * A ``NULL`` pointer if *stages* or *type* was invalid or an allocation error - occurred. + :returns: An :c:type:`MRIStepCoupling` structure if successful. + A ``NULL`` pointer if *stages* or *type* was invalid or an allocation error + occurred. .. note:: - For explicit methods only the W array is allocated, with implicit methods - only the G array is allocated, and for ImEx methods both W and G are - allocated. + For :c:enumerator:`MRISTEP_EXPLICIT` tables, the *G* and *group* arrays are not allocated. + + For :c:enumerator:`MRISTEP_IMPLICIT` tables, the *W* and *group* arrays are not allocated. + + For :c:enumerator:`MRISTEP_IMEX` tables, the *group* array is not allocated. + + For :c:enumerator:`MRISTEP_MERK` tables, the *G* array is not allocated. + + For :c:enumerator:`MRISTEP_SR` tables, the *group* array is not allocated. + + When allocated, both :math:`\Omega` and :math:`\Gamma` + are initialized to all zeros, so only nonzero coefficients need to be provided. + + When allocated, all entries in *group* are initialized to ``-1``, + indicating an unused group and/or the end of a stage group. Users who + supply a custom MRISTEP_MERK table should overwrite all active stages in + each group. For example the ``ARKODE_MERK32`` method has 4 stages that + are evolved in 3 groups -- the first group consists of stage 1, the second + group consists of stages 2 and 4, while the third group consists of + stage 3. Thus *ngroup* should equal 3, and *group* should have + non-default entries + + .. code-block:: C + + C->group[0][0] = 1; + C->group[1][0] = 2; + C->group[1][1] = 4; + C->group[2][0] = 3; + + .. versionchanged:: x.y.z + + This function now supports a broader range of MRI method types. + .. c:function:: MRIStepCoupling MRIStepCoupling_Create(int nmat, int stages, int q, int p, sunrealtype *W, sunrealtype *G, sunrealtype *c) Allocates a coupling table and fills it with the given values. - **Arguments:** - * ``nmat`` -- number of :math:`\Omega^{\{k\}}` and/or :math:`\Gamma^{\{k\}}` - matrices in the coupling table. - * ``stages`` -- number of stages in the method. - * ``q`` -- global order of accuracy for the method. - * ``p`` -- global order of accuracy for the embedded method. - * ``W`` -- array of coefficients defining the explicit coupling matrices - :math:`\Omega^{\{k\}}`. The entries should be stored as a 1D array of size - ``nmat * stages * stages``, in row-major order. If the slow method is - implicit pass ``NULL``. - * ``G`` -- array of coefficients defining the implicit coupling matrices - :math:`\Gamma^{\{k\}}`. The entries should be stored as a 1D array of size - ``nmat * stages * stages``, in row-major order. If the slow method is - explicit pass ``NULL``. - * ``c`` -- array of slow abscissae for the MRI method. The entries should be - stored as a 1D array of length ``stages``. - - **Return value:** - * An :c:type:`MRIStepCoupling` structure if successful. - * A ``NULL`` pointer if ``stages`` was invalid, an allocation error occurred, - or the input data arrays are inconsistent with the method type. - - .. note:: + This routine can only be used to create coupling tables with type + ``MRISTEP_EXPLICIT``, ``MRISTEP_IMPLICIT``, or ``MRISTEP_IMEX``. The + routine determines the relevant type based on whether either of the + arguments *W* and *G* are ``NULL``. Users who wish to create MRI + methods of type ``MRISTEP_MERK`` or ``MRISTEP_SR`` must currently + do so manually. + + The assumed size of the input arrays *W* and *G* depends on the + input value for the embedding order of accuracy, *p*. + + * Non-embedded methods should be indicated by an input *p=0*, in which + case *W* and/or *G* should have entries stored as a 1D array of size + ``nmat * stages * stages``, in row-major order. + + * Embedded methods should be indicated by an input *p>0*, in which + case *W* and/or *G* should have entries stored as a 1D array of size + ``nmat * (stages+1) * stages``, in row-major order. The additional + "row" is assumed to hold the embedding coefficients. + + :param nmat: the value of :math:`k` i.e., number of number of coupling + matrices in :math:`\Omega` for the slow-nonstiff terms and/or in + :math:`\Gamma` for the slow-stiff terms in :eq:`ARKODE_IVP_two_rate`. + :param stages: number of stages in the method. + :param q: global order of accuracy for the method. + :param p: global order of accuracy for the embedded method. + :param W: array of values defining the explicit coupling coefficients + :math:`\Omega`. If the slow method is implicit pass ``NULL``. + :param G: array of values defining the implicit coupling coefficients + :math:`\Gamma`. If the slow method is explicit pass ``NULL``. + :param c: array of slow abscissae for the MRI method. The entries should be + stored as a 1D array of length ``stages``. + + :returns: An :c:type:`MRIStepCoupling` structure if successful. + A ``NULL`` pointer if ``stages`` was invalid, an allocation error occurred, + or the input data arrays are inconsistent with the method type. - As embeddings are not currently supported in MRIStep, ``p`` should be - equal to zero. .. c:function:: MRIStepCoupling MRIStepCoupling_MIStoMRI(ARKodeButcherTable B, int q, int p) Creates an MRI coupling table for a traditional MIS method based on the slow - Butcher table *B*, following the formula shown in :eq:`ARKODE_MIS_to_MRI` + Butcher table *B*. - **Arguments:** - * ``B`` -- the :c:type:`ARKodeButcherTable` for the 'slow' MIS method. - * ``q`` -- the overall order of the MIS/MRI method. - * ``p`` -- the overall order of the MIS/MRI embedding. + The :math:`s`-stage slow Butcher table must have an explicit first stage + (i.e., :math:`c_1=0` and :math:`A_{1,j}=0` for :math:`1\le j\le s`), + sorted abscissae (i.e., :math:`c_{i} \ge c_{i-1}` for :math:`2\le i\le s`), + and a final abscissa value :math:`c_s \le 1`. In this case, the + :math:`(s+1)`-stage coupling table is computed as - **Return value:** - * An :c:type:`MRIStepCoupling` structure if successful. - * A ``NULL`` pointer if an allocation error occurred. + .. math:: - .. note:: + \Omega_{i,j,1} \;\text{or}\; \Gamma_{i,j,1} = + \begin{cases} + 0, & \text{if}\; i=1,\\ + A_{i,j}-A_{i-1,j}, & \text{if}\; 2\le i\le s,\\ + b_{j}-A_{s,j}, & \text{if}\; i= s+1. + \end{cases} + + and the embedding coefficients (if applicable) are computed as + + .. math:: - The :math:`s`-stage slow Butcher table must have an explicit first stage - (i.e., :math:`c_1=0` and :math:`A_{1,j}=0` for :math:`1\le j\le s`) and - sorted abscissae (i.e., :math:`c_{i} \ge c_{i-1}` for :math:`2\le i\le s`). + \tilde{\Omega}_{i,j,1} \;\text{or}\; \tilde{\Gamma}_{i,j,1} = \tilde{b}_{j}-A_{s,j}. - Since an MIS method is at most third order accurate, and even then only if - it meets certain compatibility criteria (see :eq:`ARKODE_MIS_order3`), the values - of *q* and *p* may differ from the method and embedding orders of accuracy - for the Runge--Kutta method encoded in *B*, which is why these arguments - should be supplied separately. + We note that only one of :math:`\Omega` or :math:`\Gamma` will + be filled in. If *B* corresponded to an explicit method, then this routine + fills :math:`\Omega`; if *B* is diagonally-implicit, then this routine + inserts redundant "padding" stages to ensure a solve-decoupled structure and + then uses the above formula to fill :math:`\Gamma`. - As embeddings are not currently supported in MRIStep, then *p* should be - equal to zero. + For general slow tables with at least second-order accuracy, the MIS method will + be second order. However, if the slow table is at least third order and + additionally satisfies + + .. math:: + + \sum_{i=2}^s (c_i-c_{i-1})(\mathbf{e}_i+\mathbf{e}_{i-1})^T A c + (1-c_s) \left(\frac12 + \mathbf{e}_s^T A c\right) = \frac13, + + where :math:`\mathbf{e}_j` corresponds to the :math:`j`-th column from the + :math:`s \times s` identity matrix, then the overall MIS method will be third order. + + As a result, the values of *q* and *p* may differ from the method and + embedding orders of accuracy for the Runge--Kutta method encoded in *B*, + which is why these arguments should be supplied separately. + + If *p>0* is input, then the table *B* must include embedding coefficients. + + + :param B: the :c:type:`ARKodeButcherTable` for the "slow" MIS method. + :param q: the overall order of the MIS/MRI method. + :param p: the overall order of the MIS/MRI embedding. + + :returns: An :c:type:`MRIStepCoupling` structure if successful. + A ``NULL`` pointer if an allocation error occurred. .. c:function:: MRIStepCoupling MRIStepCoupling_Copy(MRIStepCoupling C) Creates copy of the given coupling table. - **Arguments:** - * ``C`` -- the coupling table to copy. + :param C: the coupling table to copy. - **Return value:** - * An :c:type:`MRIStepCoupling` structure if successful. - * A ``NULL`` pointer if an allocation error occurred. + :returns: An :c:type:`MRIStepCoupling` structure if successful. + A ``NULL`` pointer if an allocation error occurred. .. c:function:: void MRIStepCoupling_Space(MRIStepCoupling C, sunindextype *liw, sunindextype *lrw) Get the real and integer workspace size for a coupling table. - **Arguments:** - * ``C`` -- the coupling table. - * ``lenrw`` -- the number of ``sunrealtype`` values in the coupling table - workspace. - * ``leniw`` -- the number of integer values in the coupling table workspace. + :param C: the coupling table. + :param lenrw: the number of ``sunrealtype`` values in the coupling table + workspace. + :param leniw: the number of integer values in the coupling table workspace. - **Return value:** - * *ARK_SUCCESS* if successful. - * *ARK_MEM_NULL* if the Butcher table memory was ``NULL``. + :retval ARK_SUCCESS: if successful. + :retval ARK_MEM_NULL: if the Butcher table memory was ``NULL``. .. c:function:: void MRIStepCoupling_Free(MRIStepCoupling C) Deallocate the coupling table memory. - **Arguments:** - * ``C`` -- the coupling table. + :param C: the coupling table. .. c:function:: void MRIStepCoupling_Write(MRIStepCoupling C, FILE *outfile) Write the coupling table to the provided file pointer. - **Arguments:** - * ``C`` -- the coupling table. - * ``outfile`` -- pointer to use for printing the table. + :param C: the coupling table. + :param outfile: pointer to use for printing the table. .. note:: @@ -303,49 +401,82 @@ with values specified for each method below (e.g., ``ARKODE_MIS_KW3``). -.. table:: Explicit MRI-GARK coupling tables. The default method for each order - is marked with an asterisk (:math:`^*`). +.. table:: Explicit MRIStep coupling tables. + + ====================================== ================== =============== ============== ===================== + Table name Method Order Embedding Order Slow RHS Calls Reference + ====================================== ================== =============== ============== ===================== + :index:`ARKODE_MRI_GARK_FORWARD_EULER` :math:`1^*` -- 1 + :index:`ARKODE_MRI_GARK_ERK22a` 2 1 2 :cite:p:`Sandu:19` + :index:`ARKODE_MRI_GARK_ERK22b` :math:`2^{*\circ}` 1 2 :cite:p:`Sandu:19` + :index:`ARKODE_MRI_GARK_RALSTON2` 2 1 2 :cite:p:`Roberts:22` + :index:`ARKODE_MERK21` 2 1 2 :cite:p:`Luan:20` + :index:`ARKODE_MIS_KW3` :math:`3^*` -- 3 :cite:p:`Schlegel:09` + :index:`ARKODE_MRI_GARK_ERK33a` :math:`3^{\circ}` 2 3 :cite:p:`Sandu:19` + :index:`ARKODE_MRI_GARK_RALSTON3` 3 2 3 :cite:p:`Roberts:22` + :index:`ARKODE_MERK32` 3 2 3 :cite:p:`Luan:20` + :index:`ARKODE_MRI_GARK_ERK45a` :math:`4^{*\circ}` 3 5 :cite:p:`Sandu:19` + :index:`ARKODE_MERK43` 4 3 6 :cite:p:`Luan:20` + :index:`ARKODE_MERK54` :math:`5^{A}` 4 10 :cite:p:`Luan:20` + ====================================== ================== =============== ============== ===================== + + +Notes regarding the above table: + +#. The default method for each order when using fixed step sizes is marked with an + asterisk (:math:`^*`). + +#. The default method for each order when using adaptive time stepping is marked + with a circle (:math:`^\circ`). + +#. The "Slow RHS Calls" column corresponds to the number of calls to the slow + right-hand side function, :math:`f^E`, per time step. - ================================= =========== ===================== - Table name Order Reference - ================================= =========== ===================== - ``ARKODE_MRI_GARK_FORWARD_EULER`` :math:`1^*` - ``ARKODE_MRI_GARK_ERK22b`` :math:`2^*` :cite:p:`Sandu:19` - ``ARKODE_MRI_GARK_ERK22a`` 2 :cite:p:`Sandu:19` - ``ARKODE_MRI_GARK_RALSTON2`` 2 :cite:p:`Roberts:22` - ``ARKODE_MIS_KW3`` :math:`3^*` :cite:p:`Schlegel:09` - ``ARKODE_MRI_GARK_ERK33a`` 3 :cite:p:`Sandu:19` - ``ARKODE_MRI_GARK_RALSTON3`` 3 :cite:p:`Roberts:22` - ``ARKODE_MRI_GARK_ERK45a`` :math:`4^*` :cite:p:`Sandu:19` - ================================= =========== ===================== +#. Note A: although all MERK methods were derived in :cite:p:`Luan:20` under an assumption + that the fast function :math:`f^F(t,y)` is linear in :math:`y`, in :cite:p:`Fish:24` it + was proven that MERK methods also satisfy all nonlinear order conditions up through + their linear order. The lone exception is :index:`ARKODE_MERK54`, where it was only + proven to satisfy all nonlinear conditions up to order 4 (since :cite:p:`Fish:24` did + not establish the formulas for the order 5 conditions). All our numerical tests to + date have shown :index:`ARKODE_MERK54` to achieve fifth order for nonlinear problems, + and so we conjecture that it also satisfies the nonlinear fifth order conditions. -.. table:: Diagonally-implicit, solve-decoupled MRI-GARK coupling tables. The - default method for each order is marked with an asterisk - (:math:`^*`). +.. table:: Diagonally-implicit, solve-decoupled MRI-GARK coupling tables. The default + method for each order when using fixed step sizes is marked with an asterisk + (:math:`^*`); the default method for each order when using adaptive time + stepping is marked with a circle (:math:`^\circ`). The "Implicit Solves" + column corresponds to the number of slow implicit (non)linear solves required + per time step. - ===================================== =========== =============== ================== - Table name Order Implicit Solves Reference - ===================================== =========== =============== ================== - ``ARKODE_MRI_GARK_BACKWARD_EULER`` :math:`1^*` 1 - ``ARKODE_MRI_GARK_IRK21a`` :math:`2^*` 1 :cite:p:`Sandu:19` - ``ARKODE_MRI_GARK_IMPLICIT_MIDPOINT`` 2 2 - ``ARKODE_MRI_GARK_ESDIRK34a`` :math:`3^*` 3 :cite:p:`Sandu:19` - ``ARKODE_MRI_GARK_ESDIRK46a`` :math:`4^*` 5 :cite:p:`Sandu:19` - ===================================== =========== =============== ================== + ========================================== ================== =============== =============== ================== + Table name Method Order Embedding Order Implicit Solves Reference + ========================================== ================== =============== =============== ================== + :index:`ARKODE_MRI_GARK_BACKWARD_EULER` :math:`1^{*\circ}` -- 1 + :index:`ARKODE_MRI_GARK_IRK21a` :math:`2^{*\circ}` 1 1 :cite:p:`Sandu:19` + :index:`ARKODE_MRI_GARK_IMPLICIT_MIDPOINT` 2 -- 2 + :index:`ARKODE_MRI_GARK_ESDIRK34a` :math:`3^{*\circ}` 2 3 :cite:p:`Sandu:19` + :index:`ARKODE_MRI_GARK_ESDIRK46a` :math:`4^{*\circ}` 3 5 :cite:p:`Sandu:19` + ========================================== ================== =============== =============== ================== .. table:: Diagonally-implicit, solve-decoupled IMEX-MRI-GARK coupling tables. - The default method for each order is marked with an asterisk - (:math:`^*`). - - ==================================== =========== =============== =================== - Table name Order Implicit Solves Reference - ==================================== =========== =============== =================== - ``ARKODE_IMEX_MRI_GARK_EULER`` :math:`1^*` 1 - ``ARKODE_IMEX_MRI_GARK_TRAPEZOIDAL`` :math:`2^*` 1 - ``ARKODE_IMEX_MRI_GARK_MIDPOINT`` 2 2 - ``ARKODE_IMEX_MRI_GARK3a`` :math:`3^*` 2 :cite:p:`ChiRen:21` - ``ARKODE_IMEX_MRI_GARK3b`` 3 2 :cite:p:`ChiRen:21` - ``ARKODE_IMEX_MRI_GARK4`` :math:`4^*` 5 :cite:p:`ChiRen:21` - ==================================== =========== =============== =================== + The default method for each order when using fixed step sizes is marked + with an asterisk (:math:`^*`); the default method for each order when using + adaptive time stepping is marked with a circle (:math:`^\circ`). The + "Implicit Solves" column corresponds to the number of slow implicit + (non)linear solves required per time step. + + ========================================= ================= =============== =============== =================== + Table name Method Order Embedding Order Implicit Solves Reference + ========================================= ================= =============== =============== =================== + :index:`ARKODE_IMEX_MRI_GARK_EULER` :math:`1^*` -- 1 + :index:`ARKODE_IMEX_MRI_GARK_TRAPEZOIDAL` :math:`2^*` -- 1 + :index:`ARKODE_IMEX_MRI_GARK_MIDPOINT` 2 -- 2 + :index:`ARKODE_IMEX_MRI_SR21` :math:`2^{\circ}` 1 3 :cite:p:`Fish:24` + :index:`ARKODE_IMEX_MRI_GARK3a` :math:`3^*` -- 2 :cite:p:`ChiRen:21` + :index:`ARKODE_IMEX_MRI_GARK3b` 3 -- 2 :cite:p:`ChiRen:21` + :index:`ARKODE_IMEX_MRI_SR32` :math:`3^{\circ}` 2 4 :cite:p:`Fish:24` + :index:`ARKODE_IMEX_MRI_GARK4` :math:`4^*` -- 5 :cite:p:`ChiRen:21` + :index:`ARKODE_IMEX_MRI_SR43` :math:`4^{\circ}` 3 5 :cite:p:`Fish:24` + ========================================= ================= =============== =============== =================== diff --git a/doc/arkode/guide/source/Usage/MRIStep/Skeleton.rst b/doc/arkode/guide/source/Usage/MRIStep/Skeleton.rst index f1275b0ae3..c8e239086c 100644 --- a/doc/arkode/guide/source/Usage/MRIStep/Skeleton.rst +++ b/doc/arkode/guide/source/Usage/MRIStep/Skeleton.rst @@ -39,15 +39,12 @@ unchanged from the skeleton program presented in #. Create an inner stepper object to solve the fast (inner) IVP - * If using ARKStep as the fast (inner) integrator, create the ARKStep object - with :c:func:`ARKStepCreate` and configure the integrator as desired for - evolving the fast time scale. See sections :numref:`ARKODE.Usage.Skeleton`, - :numref:`ARKODE.Usage.OptionalInputs`, and - :numref:`ARKODE.Usage.ARKStep.OptionalInputs` for details on configuring - ARKStep. + * If using an ARKODE stepper module for the fast integrator, create and configure + the stepper as normal following the steps detailed in the section for the desired + stepper. - Once the ARKStep object is setup, create an ``MRIStepInnerStepper`` object - with :c:func:`ARKStepCreateMRIStepInnerStepper`. + Once the ARKODE stepper object is setup, create an ``MRIStepInnerStepper`` object + with :c:func:`ARKodeCreateMRIStepInnerStepper`. * If supplying a user-defined fast (inner) integrator, create the ``MRIStepInnerStepper`` object as described in section @@ -88,11 +85,16 @@ unchanged from the skeleton program presented in inputs to :c:func:`MRIStepCreate` is the ``MRIStepInnerStepper`` object for solving the fast (inner) IVP created in the previous step. -#. Set the slow step size - - Call :c:func:`ARKodeSetFixedStep()` on the MRIStep object to specify the +#. If using fixed step sizes, then set the slow step size by calling + :c:func:`ARKodeSetFixedStep()` on the MRIStep object to specify the slow time step size. + If using adaptive slow steps, then specify the desired integration tolerances + as normal. By default, MRIStep will use a "decoupled" (see + :numref:`ARKODE.Mathematics.MultirateControllers`) I controller (see + :numref:`SUNAdaptController.Soderlind`), Alternately, create and attach a + multirate temporal controller (see :numref:`SUNAdaptController.MRIHTol`). + #. Create and configure implicit solvers (*as appropriate*) Specifically, if MRIStep is configured with an implicit slow right-hand side diff --git a/doc/arkode/guide/source/Usage/MRIStep/User_callable.rst b/doc/arkode/guide/source/Usage/MRIStep/User_callable.rst index 695c28ad5c..08cd106970 100644 --- a/doc/arkode/guide/source/Usage/MRIStep/User_callable.rst +++ b/doc/arkode/guide/source/Usage/MRIStep/User_callable.rst @@ -31,9 +31,10 @@ As discussed in the main :ref:`ARKODE user-callable function introduction clarifies the categories of user-callable functions that it supports. MRIStep supports the following categories: +* temporal adaptivity * implicit nonlinear and/or linear solvers -MRIStep does not have forcing function support when converted to a +MRIStep also has forcing function support when converted to a :c:type:`SUNStepper` or :c:type:`MRIStepInnerStepper`. See :c:func:`ARKodeCreateSUNStepper` and :c:func:`ARKStepCreateMRIStepInnerStepper` for additional details. @@ -50,24 +51,22 @@ MRIStep initialization and deallocation functions This function allocates and initializes memory for a problem to be solved using the MRIStep time-stepping module in ARKODE. - **Arguments:** - * *fse* -- the name of the function (of type :c:func:`ARKRhsFn()`) - defining the explicit slow portion of the right-hand side function in - :math:`\dot{y} = f^E(t,y) + f^I(t,y) + f^F(t,y)`. - * *fsi* -- the name of the function (of type :c:func:`ARKRhsFn()`) - defining the implicit slow portion of the right-hand side function in - :math:`\dot{y} = f^E(t,y) + f^I(t,y) + f^F(t,y)`. - * *t0* -- the initial value of :math:`t`. - * *y0* -- the initial condition vector :math:`y(t_0)`. - * *stepper* -- an :c:type:`MRIStepInnerStepper` for integrating the fast - time scale. - * *sunctx* -- the :c:type:`SUNContext` object (see :numref:`SUNDIALS.SUNContext`) - - **Return value:** - If successful, a pointer to initialized problem memory of type ``void*``, to - be passed to all user-facing MRIStep routines listed below. If unsuccessful, - a ``NULL`` pointer will be returned, and an error message will be printed to - ``stderr``. + :param fse: the name of the function (of type :c:func:`ARKRhsFn()`) + defining the explicit slow portion of the right-hand side function in + :math:`\dot{y} = f^E(t,y) + f^I(t,y) + f^F(t,y)`. + :param fsi: the name of the function (of type :c:func:`ARKRhsFn()`) + defining the implicit slow portion of the right-hand side function in + :math:`\dot{y} = f^E(t,y) + f^I(t,y) + f^F(t,y)`. + :param t0: the initial value of :math:`t`. + :param y0: the initial condition vector :math:`y(t_0)`. + :param stepper: an :c:type:`MRIStepInnerStepper` for integrating the fast + time scale. + :param sunctx: the :c:type:`SUNContext` object (see :numref:`SUNDIALS.SUNContext`) + + :returns: If successful, a pointer to initialized problem memory of type ``void*``, to + be passed to all user-facing MRIStep routines listed below. If unsuccessful, + a ``NULL`` pointer will be returned, and an error message will be printed to + ``stderr``. **Example usage:** @@ -77,18 +76,18 @@ MRIStep initialization and deallocation functions void *inner_arkode_mem = NULL; void *outer_arkode_mem = NULL; - /* MRIStepInnerStepper to wrap the inner (fast) ARKStep object */ + /* MRIStepInnerStepper to wrap the inner (fast) object */ MRIStepInnerStepper stepper = NULL; - /* create an ARKStep object, setting fast (inner) right-hand side + /* create an ARKODE object, setting fast (inner) right-hand side functions and the initial condition */ - inner_arkode_mem = ARKStepCreate(ffe, ffi, t0, y0, sunctx); + inner_arkode_mem = *StepCreate(...); - /* setup ARKStep */ - . . . + /* configure the inner integrator */ + retval = ARKodeSet*(inner_arkode_mem, ...); - /* create MRIStepInnerStepper wrapper for the ARKStep memory block */ - flag = ARKStepCreateMRIStepInnerStepper(inner_arkode_mem, &stepper); + /* create MRIStepInnerStepper wrapper for the ARKODE integrator */ + flag = ARKodeCreateMRIStepInnerStepper(inner_arkode_mem, &stepper); /* create an MRIStep object, setting the slow (outer) right-hand side functions and the initial condition */ @@ -102,6 +101,8 @@ MRIStep initialization and deallocation functions * ``examples/arkode/C_serial/ark_reaction_diffusion_mri.c`` * ``examples/arkode/C_serial/ark_kpr_mri.c`` * ``examples/arkode/CXX_parallel/ark_diffusion_reaction_p.cpp`` + * ``examples/arkode/CXX_serial/ark_test_kpr_nestedmri.cpp`` + (uses MRIStep within itself) .. c:function:: void MRIStepFree(void** arkode_mem) @@ -109,10 +110,8 @@ MRIStep initialization and deallocation functions This function frees the problem memory *arkode_mem* created by :c:func:`MRIStepCreate`. - **Arguments:** - * *arkode_mem* -- pointer to the MRIStep memory block. + :param arkode_mem: pointer to the MRIStep memory block. - **Return value:** None .. deprecated:: 6.1.0 @@ -129,16 +128,14 @@ MRIStep tolerance specification functions This function specifies scalar relative and absolute tolerances. - **Arguments:** - * *arkode_mem* -- pointer to the MRIStep memory block. - * *reltol* -- scalar relative tolerance. - * *abstol* -- scalar absolute tolerance. + :param arkode_mem: pointer to the MRIStep memory block. + :param reltol: scalar relative tolerance. + :param abstol: scalar absolute tolerance. - **Return value:** - * *ARK_SUCCESS* if successful - * *ARK_MEM_NULL* if the MRIStep memory was ``NULL`` - * *ARK_NO_MALLOC* if the MRIStep memory was not allocated by the time-stepping module - * *ARK_ILL_INPUT* if an argument had an illegal value (e.g. a negative tolerance). + :retval ARK_SUCCESS: if successful + :retval ARK_MEM_NULL: if the MRIStep memory was ``NULL`` + :retval ARK_NO_MALLOC: if the MRIStep memory was not allocated by the time-stepping module + :retval ARK_ILL_INPUT: if an argument had an illegal value (e.g. a negative tolerance). .. deprecated:: 6.1.0 @@ -152,17 +149,15 @@ MRIStep tolerance specification functions absolute tolerance (a potentially different absolute tolerance for each vector component). - **Arguments:** - * *arkode_mem* -- pointer to the MRIStep memory block. - * *reltol* -- scalar relative tolerance. - * *abstol* -- vector containing the absolute tolerances for each - solution component. + :param arkode_mem: pointer to the MRIStep memory block. + :param reltol: scalar relative tolerance. + :param abstol: vector containing the absolute tolerances for each + solution component. - **Return value:** - * *ARK_SUCCESS* if successful - * *ARK_MEM_NULL* if the MRIStep memory was ``NULL`` - * *ARK_NO_MALLOC* if the MRIStep memory was not allocated by the time-stepping module - * *ARK_ILL_INPUT* if an argument had an illegal value (e.g. a negative tolerance). + :retval ARK_SUCCESS: if successful + :retval ARK_MEM_NULL: if the MRIStep memory was ``NULL`` + :retval ARK_NO_MALLOC: if the MRIStep memory was not allocated by the time-stepping module + :retval ARK_ILL_INPUT: if an argument had an illegal value (e.g. a negative tolerance). .. deprecated:: 6.1.0 @@ -175,15 +170,13 @@ MRIStep tolerance specification functions This function specifies a user-supplied function *efun* to compute the error weight vector ``ewt``. - **Arguments:** - * *arkode_mem* -- pointer to the MRIStep memory block. - * *efun* -- the name of the function (of type :c:func:`ARKEwtFn()`) - that implements the error weight vector computation. + :param arkode_mem: pointer to the MRIStep memory block. + :param efun: the name of the function (of type :c:func:`ARKEwtFn()`) + that implements the error weight vector computation. - **Return value:** - * *ARK_SUCCESS* if successful - * *ARK_MEM_NULL* if the MRIStep memory was ``NULL`` - * *ARK_NO_MALLOC* if the MRIStep memory was not allocated by the time-stepping module + :retval ARK_SUCCESS: if successful + :retval ARK_MEM_NULL: if the MRIStep memory was ``NULL`` + :retval ARK_NO_MALLOC: if the MRIStep memory was not allocated by the time-stepping module .. deprecated:: 6.1.0 @@ -191,6 +184,7 @@ MRIStep tolerance specification functions + .. _ARKODE.Usage.MRIStep.LinearSolvers: Linear solver interface functions @@ -202,40 +196,40 @@ Linear solver interface functions should use, as well as a template Jacobian ``SUNMatrix`` object (if applicable). - **Arguments:** - * *arkode_mem* -- pointer to the MRIStep memory block. - * *LS* -- the ``SUNLinearSolver`` object to use. - * *J* -- the template Jacobian ``SUNMatrix`` object to use (or - ``NULL`` if not applicable). - - **Return value:** - * *ARKLS_SUCCESS* if successful - * *ARKLS_MEM_NULL* if the MRIStep memory was ``NULL`` - * *ARKLS_MEM_FAIL* if there was a memory allocation failure - * *ARKLS_ILL_INPUT* if ARKLS is incompatible with the - provided *LS* or *J* input objects, or the current - ``N_Vector`` module. - - **Notes:** If *LS* is a matrix-free linear solver, then the *J* - argument should be ``NULL``. - - If *LS* is a matrix-based linear solver, then the template Jacobian - matrix *J* will be used in the solve process, so if additional - storage is required within the ``SUNMatrix`` object (e.g. for - factorization of a banded matrix), ensure that the input object is - allocated with sufficient size (see the documentation of - the particular SUNMATRIX type in :numref:`SUNMatrix` for - further information). - - When using sparse linear solvers, it is typically much more - efficient to supply *J* so that it includes the full sparsity - pattern of the Newton system matrices :math:`\mathcal{A} = - I-\gamma J`, even if *J* itself has zeros in nonzero - locations of :math:`I`. The reasoning for this is - that :math:`\mathcal{A}` is constructed in-place, on top of the - user-specified values of *J*, so if the sparsity pattern in *J* is - insufficient to store :math:`\mathcal{A}` then it will need to be - resized internally by MRIStep. + :param arkode_mem: pointer to the MRIStep memory block. + :param LS: the ``SUNLinearSolver`` object to use. + :param J: the template Jacobian ``SUNMatrix`` object to use (or + ``NULL`` if not applicable). + + :retval ARKLS_SUCCESS: if successful + :retval ARKLS_MEM_NULL: if the MRIStep memory was ``NULL`` + :retval ARKLS_MEM_FAIL: if there was a memory allocation failure + :retval ARKLS_ILL_INPUT: if ARKLS is incompatible with the + provided *LS* or *J* input objects, or the current + ``N_Vector`` module. + + .. note:: + + If *LS* is a matrix-free linear solver, then the *J* + argument should be ``NULL``. + + If *LS* is a matrix-based linear solver, then the template Jacobian + matrix *J* will be used in the solve process, so if additional + storage is required within the ``SUNMatrix`` object (e.g. for + factorization of a banded matrix), ensure that the input object is + allocated with sufficient size (see the documentation of + the particular SUNMATRIX type in :numref:`SUNMatrix` for + further information). + + When using sparse linear solvers, it is typically much more + efficient to supply *J* so that it includes the full sparsity + pattern of the Newton system matrices :math:`\mathcal{A} = + I-\gamma J`, even if *J* itself has zeros in nonzero + locations of :math:`I`. The reasoning for this is + that :math:`\mathcal{A}` is constructed in-place, on top of the + user-specified values of *J*, so if the sparsity pattern in *J* is + insufficient to store :math:`\mathcal{A}` then it will need to be + resized internally by MRIStep. .. deprecated:: 6.1.0 @@ -253,20 +247,20 @@ Nonlinear solver interface functions This function specifies the ``SUNNonlinearSolver`` object that MRIStep should use for implicit stage solves. - **Arguments:** - * *arkode_mem* -- pointer to the MRIStep memory block. - * *NLS* -- the ``SUNNonlinearSolver`` object to use. + :param arkode_mem: pointer to the MRIStep memory block. + :param NLS: the ``SUNNonlinearSolver`` object to use. - **Return value:** - * *ARK_SUCCESS* if successful - * *ARK_MEM_NULL* if the MRIStep memory was ``NULL`` - * *ARK_MEM_FAIL* if there was a memory allocation failure - * *ARK_ILL_INPUT* if MRIStep is incompatible with the - provided *NLS* input object. + :retval ARK_SUCCESS: if successful + :retval ARK_MEM_NULL: if the MRIStep memory was ``NULL`` + :retval ARK_MEM_FAIL: if there was a memory allocation failure + :retval ARK_ILL_INPUT: if MRIStep is incompatible with the + provided *NLS* input object. - **Notes:** MRIStep will use the Newton ``SUNNonlinearSolver`` module by - default; a call to this routine replaces that module with the - supplied *NLS* object. + .. note:: + + MRIStep will use the Newton ``SUNNonlinearSolver`` module by + default; a call to this routine replaces that module with the + supplied *NLS* object. .. deprecated:: 6.1.0 @@ -285,29 +279,29 @@ Rootfinding initialization function integration of the ODE system. It must be called after :c:func:`MRIStepCreate()`, and before :c:func:`MRIStepEvolve()`. - **Arguments:** - * *arkode_mem* -- pointer to the MRIStep memory block. - * *nrtfn* -- number of functions :math:`g_i`, an integer :math:`\ge` 0. - * *g* -- name of user-supplied function, of type :c:func:`ARKRootFn()`, - defining the functions :math:`g_i` whose roots are sought. + :param arkode_mem: pointer to the MRIStep memory block. + :param nrtfn: number of functions :math:`g_i`, an integer :math:`\ge` 0. + :param g: name of user-supplied function, of type :c:func:`ARKRootFn()`, + defining the functions :math:`g_i` whose roots are sought. + + :retval ARK_SUCCESS: if successful + :retval ARK_MEM_NULL: if the MRIStep memory was ``NULL`` + :retval ARK_MEM_FAIL: if there was a memory allocation failure + :retval ARK_ILL_INPUT: if *nrtfn* is greater than zero but *g* = ``NULL``. - **Return value:** - * *ARK_SUCCESS* if successful - * *ARK_MEM_NULL* if the MRIStep memory was ``NULL`` - * *ARK_MEM_FAIL* if there was a memory allocation failure - * *ARK_ILL_INPUT* if *nrtfn* is greater than zero but *g* = ``NULL``. + .. note:: - **Notes:** To disable the rootfinding feature after it has already - been initialized, or to free memory associated with MRIStep's - rootfinding module, call *MRIStepRootInit* with *nrtfn = 0*. + To disable the rootfinding feature after it has already + been initialized, or to free memory associated with MRIStep's + rootfinding module, call *MRIStepRootInit* with *nrtfn = 0*. - Similarly, if a new IVP is to be solved with a call to - :c:func:`MRIStepReInit()`, where the new IVP has no rootfinding - problem but the prior one did, then call *MRIStepRootInit* with - *nrtfn = 0*. + Similarly, if a new IVP is to be solved with a call to + :c:func:`MRIStepReInit()`, where the new IVP has no rootfinding + problem but the prior one did, then call *MRIStepRootInit* with + *nrtfn = 0*. - Rootfinding is only supported for the slow (outer) integrator and should not - be activated for the fast (inner) integrator. + Rootfinding is only supported for the slow (outer) integrator and should not + be activated for the fast (inner) integrator. .. deprecated:: 6.1.0 @@ -324,72 +318,73 @@ MRIStep solver function Integrates the ODE over an interval in :math:`t`. - **Arguments:** - * *arkode_mem* -- pointer to the MRIStep memory block. - * *tout* -- the next time at which a computed solution is desired. - * *yout* -- the computed solution vector. - * *tret* -- the time corresponding to *yout* (output). - * *itask* -- a flag indicating the job of the solver for the next - user step. - - The *ARK_NORMAL* option causes the solver to take internal - steps until it has just overtaken a user-specified output - time, *tout*, in the direction of integration, - i.e. :math:`t_{n-1} <` *tout* :math:`\le t_{n}` for forward - integration, or :math:`t_{n} \le` *tout* :math:`< t_{n-1}` for - backward integration. It will then compute an approximation - to the solution :math:`y(tout)` by interpolation (as described - in :numref:`ARKODE.Mathematics.Interpolation`). - - The *ARK_ONE_STEP* option tells the solver to only take a - single internal step, :math:`y_{n-1} \to y_{n}`, and return the solution - at that point, :math:`y_{n}`, in the vector *yout*. - - **Return value:** - * *ARK_SUCCESS* if successful. - * *ARK_ROOT_RETURN* if :c:func:`MRIStepEvolve()` succeeded, and - found one or more roots. If the number of root functions, - *nrtfn*, is greater than 1, call - :c:func:`MRIStepGetRootInfo()` to see which :math:`g_i` were - found to have a root at (*\*tret*). - * *ARK_TSTOP_RETURN* if :c:func:`MRIStepEvolve()` succeeded and - returned at *tstop*. - * *ARK_MEM_NULL* if the *arkode_mem* argument was ``NULL``. - * *ARK_NO_MALLOC* if *arkode_mem* was not allocated. - * *ARK_ILL_INPUT* if one of the inputs to - :c:func:`MRIStepEvolve()` is illegal, or some other input to - the solver was either illegal or missing. Details will be - provided in the error message. Typical causes of this failure: - - (a) A component of the error weight vector became zero during - internal time-stepping. - - (b) The linear solver initialization function (called by the - user after calling :c:func:`MRIStepCreate`) failed to set - the linear solver-specific *lsolve* field in - *arkode_mem*. - - (c) A root of one of the root functions was found both at a - point :math:`t` and also very near :math:`t`. - - * *ARK_TOO_MUCH_WORK* if the solver took *mxstep* internal steps - but could not reach *tout*. The default value for *mxstep* is - *MXSTEP_DEFAULT = 500*. - * *ARK_CONV_FAILURE* if convergence test failures occurred - too many times (*ark_maxncf*) during one internal time step. - * *ARK_LINIT_FAIL* if the linear solver's initialization - function failed. - * *ARK_LSETUP_FAIL* if the linear solver's setup routine failed in - an unrecoverable manner. - * *ARK_LSOLVE_FAIL* if the linear solver's solve routine failed in - an unrecoverable manner. - * *ARK_VECTOROP_ERR* a vector operation error occurred. - * *ARK_INNERSTEP_FAILED* if the inner stepper returned with an - unrecoverable error. The value returned from the inner stepper can be - obtained with :c:func:`MRIStepGetLastInnerStepFlag()`. - * *ARK_INVALID_TABLE* if an invalid coupling table was provided. - - **Notes:** + :param arkode_mem: pointer to the MRIStep memory block. + :param tout: the next time at which a computed solution is desired. + :param yout: the computed solution vector. + :param tret: the time corresponding to *yout* (output). + :param itask: a flag indicating the job of the solver for the next + user step. + + The *ARK_NORMAL* option causes the solver to take internal + steps until it has just overtaken a user-specified output + time, *tout*, in the direction of integration, + i.e. :math:`t_{n-1} <` *tout* :math:`\le t_{n}` for forward + integration, or :math:`t_{n} \le` *tout* :math:`< t_{n-1}` for + backward integration. It will then compute an approximation + to the solution :math:`y(tout)` by interpolation (as described + in :numref:`ARKODE.Mathematics.Interpolation`). + + The *ARK_ONE_STEP* option tells the solver to only take a + single internal step, :math:`y_{n-1} \to y_{n}`, and return the + solution at that point, :math:`y_{n}`, in the vector *yout*. + + :retval ARK_SUCCESS: if successful. + :retval ARK_ROOT_RETURN: if :c:func:`MRIStepEvolve()` succeeded, and + found one or more roots. If the number of root + functions, *nrtfn*, is greater than 1, call + :c:func:`ARKodeGetRootInfo()` to see which + :math:`g_i` were found to have a root at (*\*tret*). + :retval ARK_TSTOP_RETURN: if :c:func:`MRIStepEvolve()` succeeded and + returned at *tstop*. + :retval ARK_MEM_NULL: if the *arkode_mem* argument was ``NULL``. + :retval ARK_NO_MALLOC: if *arkode_mem* was not allocated. + :retval ARK_ILL_INPUT: if one of the inputs to + :c:func:`MRIStepEvolve()` is illegal, or some other + input to the solver was either illegal or missing. + Details will be provided in the error message. + Typical causes of this failure: + + (a) A component of the error weight vector became + zero during internal time-stepping. + + (b) The linear solver initialization function + (called by the user after calling + :c:func:`ARKStepCreate`) failed to set + the linear solver-specific *lsolve* field in + *arkode_mem*. + + (c) A root of one of the root functions was found both + at a point :math:`t` and also very near :math:`t`. + + :retval ARK_TOO_MUCH_WORK: if the solver took *mxstep* internal steps + but could not reach *tout*. The default value for + *mxstep* is *MXSTEP_DEFAULT = 500*. + :retval ARK_CONV_FAILURE: if convergence test failures occurred too many + times (*ark_maxncf*) during one internal time step. + :retval ARK_LINIT_FAIL: if the linear solver's initialization function failed. + :retval ARK_LSETUP_FAIL: if the linear solver's setup routine failed in + an unrecoverable manner. + :retval ARK_LSOLVE_FAIL: if the linear solver's solve routine failed in + an unrecoverable manner. + :retval ARK_VECTOROP_ERR: a vector operation error occurred. + :retval ARK_INNERSTEP_FAILED: if the inner stepper returned with an + unrecoverable error. The value returned from the + inner stepper can be obtained with + :c:func:`MRIStepGetLastInnerStepFlag()`. + :retval ARK_INVALID_TABLE: if an invalid coupling table was provided. + + .. note:: + The input vector *yout* can use the same memory as the vector *y0* of initial conditions that was passed to :c:func:`MRIStepCreate`. @@ -441,22 +436,18 @@ Optional inputs for MRIStep Resets all optional input parameters to MRIStep's original default values. - **Arguments:** - - * *arkode_mem* -- pointer to the MRIStep memory block. + :param arkode_mem: pointer to the MRIStep memory block. - **Return value:** + :retval ARK_SUCCESS: if successful + :retval ARK_MEM_NULL: if the MRIStep memory is ``NULL`` + :retval ARK_ILL_INPUT: if an argument has an illegal value - * *ARK_SUCCESS* if successful - - * *ARK_MEM_NULL* if the MRIStep memory is ``NULL`` - - * *ARK_ILL_INPUT* if an argument had an illegal value + .. note:: - **Notes:** This function does not change problem-defining function pointers - *fs* and *ff* or the *user_data* pointer. It also does not affect any data - structures or options related to root-finding (those can be reset using - :c:func:`MRIStepRootInit()`). + This function does not change problem-defining function pointers + *fs* and *ff* or the *user_data* pointer. It also does not affect any data + structures or options related to root-finding (those can be reset using + :c:func:`MRIStepRootInit()`). .. deprecated:: 6.1.0 @@ -479,39 +470,32 @@ Optional inputs for MRIStep used for dense output (i.e. interpolation of solution output values and implicit method predictors). - **Arguments:** - - * *arkode_mem* -- pointer to the MRIStep memory block. - - * *degree* -- requested polynomial degree. + :param arkode_mem: pointer to the MRIStep memory block. + :param degree: requested polynomial degree. - **Return value:** + :retval ARK_SUCCESS: if successful + :retval ARK_MEM_NULL: if the MRIStep memory or interpolation module are ``NULL`` + :retval ARK_INTERP_FAIL: if this is called after :c:func:`MRIStepEvolve()` + :retval ARK_ILL_INPUT: if an argument has an illegal value or the + interpolation module has already been initialized - * *ARK_SUCCESS* if successful - - * *ARK_MEM_NULL* if the MRIStep memory or interpolation module are ``NULL`` - - * *ARK_INTERP_FAIL* if this is called after :c:func:`MRIStepEvolve()` - - * *ARK_ILL_INPUT* if an argument had an illegal value or the - interpolation module has already been initialized - - **Notes:** Allowed values are between 0 and 5. + .. note:: - This routine should be called *after* :c:func:`MRIStepCreate()` and *before* - :c:func:`MRIStepEvolve()`. After the first call to :c:func:`MRIStepEvolve()` - the interpolation degree may not be changed without first calling - :c:func:`MRIStepReInit()`. + Allowed values are between 0 and 5. + This routine should be called *after* :c:func:`MRIStepCreate()` and *before* + :c:func:`MRIStepEvolve()`. After the first call to :c:func:`MRIStepEvolve()` + the interpolation degree may not be changed without first calling + :c:func:`MRIStepReInit()`. - If a user calls both this routine and :c:func:`MRIStepSetInterpolantType()`, then - :c:func:`MRIStepSetInterpolantType()` must be called first. + If a user calls both this routine and :c:func:`MRIStepSetInterpolantType()`, then + :c:func:`MRIStepSetInterpolantType()` must be called first. - Since the accuracy of any polynomial interpolant is limited by the accuracy - of the time-step solutions on which it is based, the *actual* polynomial - degree that is used by MRIStep will be the minimum of :math:`q-1` and the - input *degree*, for :math:`q > 1` where :math:`q` is the order of accuracy - for the time integration method. + Since the accuracy of any polynomial interpolant is limited by the accuracy + of the time-step solutions on which it is based, the *actual* polynomial + degree that is used by MRIStep will be the minimum of :math:`q-1` and the + input *degree*, for :math:`q > 1` where :math:`q` is the order of accuracy + for the time integration method. .. versionchanged:: 5.5.1 @@ -536,28 +520,23 @@ Optional inputs for MRIStep Specifies the file pointer for a diagnostics file where all MRIStep step adaptivity and solver information is written. - **Arguments:** + :param arkode_mem: pointer to the MRIStep memory block. + :param diagfp: pointer to the diagnostics output file. - * *arkode_mem* -- pointer to the MRIStep memory block. + :retval ARK_SUCCESS: if successful + :retval ARK_MEM_NULL: if the MRIStep memory is ``NULL`` + :retval ARK_ILL_INPUT: if an argument has an illegal value - * *diagfp* -- pointer to the diagnostics output file. - - **Return value:** - - * *ARK_SUCCESS* if successful - - * *ARK_MEM_NULL* if the MRIStep memory is ``NULL`` - - * *ARK_ILL_INPUT* if an argument had an illegal value + .. note:: - **Notes:** This parameter can be ``stdout`` or ``stderr``, although the - suggested approach is to specify a pointer to a unique file opened - by the user and returned by ``fopen``. If not called, or if called - with a ``NULL`` file pointer, all diagnostics output is disabled. + This parameter can be ``stdout`` or ``stderr``, although the + suggested approach is to specify a pointer to a unique file opened + by the user and returned by ``fopen``. If not called, or if called + with a ``NULL`` file pointer, all diagnostics output is disabled. - When run in parallel, only one process should set a non-NULL value - for this pointer, since statistics from all processes would be - identical. + When run in parallel, only one process should set a non-NULL value + for this pointer, since statistics from all processes would be + identical. .. deprecated:: 5.2.0 @@ -569,24 +548,17 @@ Optional inputs for MRIStep Set the slow step size used within MRIStep for the following internal step(s). - **Arguments:** + :param arkode_mem: pointer to the MRIStep memory block. + :param hs: value of the outer (slow) step size. - * *arkode_mem* -- pointer to the MRIStep memory block. + :retval ARK_SUCCESS: if successful + :retval ARK_MEM_NULL: if the MRIStep memory is ``NULL`` + :retval ARK_ILL_INPUT: if an argument has an illegal value - * *hs* -- value of the outer (slow) step size. - - **Return value:** - - * *ARK_SUCCESS* if successful - - * *ARK_MEM_NULL* if the MRIStep memory is ``NULL`` - - * *ARK_ILL_INPUT* if an argument had an illegal value - - **Notes:** + .. note:: - The step sizes used by the inner (fast) stepper may be controlled through calling the - appropriate "Set" routines on the inner integrator. + The step sizes used by the inner (fast) stepper may be controlled through calling the + appropriate "Set" routines on the inner integrator. .. deprecated:: 6.1.0 @@ -600,24 +572,18 @@ Optional inputs for MRIStep solver to warn that :math:`t+h=t` on the next internal step, before MRIStep will instead return with an error. - **Arguments:** - - * *arkode_mem* -- pointer to the MRIStep memory block. - - * *mxhnil* -- maximum allowed number of warning messages :math:`(>0)`. - - **Return value:** + :param arkode_mem: pointer to the MRIStep memory block. + :param mxhnil: maximum allowed number of warning messages :math:`(>0)`. - * *ARK_SUCCESS* if successful + :retval ARK_SUCCESS: if successful + :retval ARK_MEM_NULL: if the MRIStep memory is ``NULL`` + :retval ARK_ILL_INPUT: if an argument has an illegal value - * *ARK_MEM_NULL* if the MRIStep memory is ``NULL`` - - * *ARK_ILL_INPUT* if an argument had an illegal value + .. note:: - **Notes:** The default value is 10; set *mxhnil* to zero to specify - this default. + The default value is 10; set *mxhnil* to zero to specify this default. - A negative value indicates that no warning messages should be issued. + A negative value indicates that no warning messages should be issued. .. deprecated:: 6.1.0 @@ -631,24 +597,19 @@ Optional inputs for MRIStep solver in its attempt to reach the next output time, before MRIStep will return with an error. - **Arguments:** - - * *arkode_mem* -- pointer to the MRIStep memory block. - - * *mxsteps* -- maximum allowed number of internal steps. - - **Return value:** + :param arkode_mem: pointer to the MRIStep memory block. + :param mxsteps: maximum allowed number of internal steps. - * *ARK_SUCCESS* if successful + :retval ARK_SUCCESS: if successful + :retval ARK_MEM_NULL: if the MRIStep memory is ``NULL`` + :retval ARK_ILL_INPUT: if an argument has an illegal value - * *ARK_MEM_NULL* if the MRIStep memory is ``NULL`` - - * *ARK_ILL_INPUT* if an argument had an illegal value + .. note:: - **Notes:** Passing *mxsteps* = 0 results in MRIStep using the - default value (500). + Passing *mxsteps* = 0 results in MRIStep using the + default value (500). - Passing *mxsteps* < 0 disables the test (not recommended). + Passing *mxsteps* < 0 disables the test (not recommended). .. deprecated:: 6.1.0 @@ -661,21 +622,14 @@ Optional inputs for MRIStep Specifies the value of the independent variable :math:`t` past which the solution is not to proceed. - **Arguments:** - - * *arkode_mem* -- pointer to the MRIStep memory block. - - * *tstop* -- stopping time for the integrator. - - **Return value:** + :param arkode_mem: pointer to the MRIStep memory block. + :param tstop: stopping time for the integrator. - * *ARK_SUCCESS* if successful + :retval ARK_SUCCESS: if successful + :retval ARK_MEM_NULL: if the MRIStep memory is ``NULL`` + :retval ARK_ILL_INPUT: if an argument has an illegal value - * *ARK_MEM_NULL* if the MRIStep memory is ``NULL`` - - * *ARK_ILL_INPUT* if an argument had an illegal value - - **Notes:** + .. note:: The default is that no stop time is imposed. @@ -699,13 +653,11 @@ Optional inputs for MRIStep :math:`t` equals the specified ``tstop`` (instead of merely copying the internal solution :math:`y_n`). - **Arguments:** - * *arkode_mem* -- pointer to the MRIStep memory block. - * *interp* -- flag indicating to use interpolation (1) or copy (0). + :param arkode_mem: pointer to the MRIStep memory block. + :param interp: flag indicating to use interpolation (1) or copy (0). - **Return value:** - * *ARK_SUCCESS* if successful - * *ARK_MEM_NULL* if the MRIStep memory is ``NULL`` + :retval ARK_SUCCESS: if successful + :retval ARK_MEM_NULL: if the MRIStep memory is ``NULL`` .. versionadded:: 5.6.0 @@ -719,14 +671,13 @@ Optional inputs for MRIStep Disables the stop time set with :c:func:`MRIStepSetStopTime`. - **Arguments:** - * *arkode_mem* -- pointer to the MRIStep memory block. + :param arkode_mem: pointer to the MRIStep memory block. - **Return value:** - * *ARK_SUCCESS* if successful - * *ARK_MEM_NULL* if the MRIStep memory is ``NULL`` + :retval ARK_SUCCESS: if successful + :retval ARK_MEM_NULL: if the MRIStep memory is ``NULL`` + + .. note:: - **Notes:** The stop time can be re-enabled though a new call to :c:func:`MRIStepSetStopTime`. @@ -743,28 +694,24 @@ Optional inputs for MRIStep Specifies the user data block *user_data* for the outer integrator and attaches it to the main MRIStep memory block. - **Arguments:** + :param arkode_mem: pointer to the MRIStep memory block. + :param user_data: pointer to the user data. - * *arkode_mem* -- pointer to the MRIStep memory block. + :retval ARK_SUCCESS: if successful + :retval ARK_MEM_NULL: if the MRIStep memory is ``NULL`` + :retval ARK_ILL_INPUT: if an argument has an illegal value - * *user_data* -- pointer to the user data. - - **Return value:** - - * *ARK_SUCCESS* if successful - - * *ARK_MEM_NULL* if the MRIStep memory is ``NULL`` - - * *ARK_ILL_INPUT* if an argument had an illegal value + .. note:: - **Notes:** If specified, the pointer to *user_data* is passed to all - user-supplied functions called by the outer integrator for which it is an - argument; otherwise ``NULL`` is passed. + If specified, the pointer to *user_data* is passed to all + user-supplied functions called by the outer integrator for which it is an + argument; otherwise ``NULL`` is passed. - To attach a user data block to the inner integrator call :c:func:`ARKodeSetUserData` - for the inner integrator memory structure. This pointer may be the same as or - different from the pointer attached to the outer integrator depending on what is - required by the user code. + To attach a user data block to the inner integrator call the appropriate + *SetUserData* function for the inner integrator memory structure (e.g., + :c:func:`ARKStepSetUserData()` if the inner stepper is ARKStep). This pointer + may be the same as or different from the pointer attached to the outer + integrator depending on what is required by the user code. .. deprecated:: 6.1.0 @@ -776,18 +723,12 @@ Optional inputs for MRIStep Specifies the function called *before* each inner integration. - **Arguments:** + :param arkode_mem: pointer to the MRIStep memory block. + :param prefn: the name of the C function (of type :c:func:`MRIStepPreInnerFn()`) + defining pre inner integration function. - * *arkode_mem* -- pointer to the MRIStep memory block. - - * *prefn* -- the name of the C function (of type :c:func:`MRIStepPreInnerFn()`) - defining pre inner integration function. - - **Return value:** - - * *ARK_SUCCESS* if successful - - * *ARK_MEM_NULL* if the MRIStep memory is ``NULL`` + :retval ARK_SUCCESS: if successful + :retval ARK_MEM_NULL: if the MRIStep memory is ``NULL`` @@ -795,18 +736,13 @@ Optional inputs for MRIStep Specifies the function called *after* each inner integration. - **Arguments:** - - * *arkode_mem* -- pointer to the MRIStep memory block. + :param arkode_mem: pointer to the MRIStep memory block. + :param postfn: the name of the C function (of type :c:func:`MRIStepPostInnerFn()`) + defining post inner integration function. - * *postfn* -- the name of the C function (of type :c:func:`MRIStepPostInnerFn()`) - defining post inner integration function. + :retval ARK_SUCCESS: if successful + :retval ARK_MEM_NULL: if the MRIStep memory is ``NULL`` - **Return value:** - - * *ARK_SUCCESS* if successful - - * *ARK_MEM_NULL* if the MRIStep memory is ``NULL`` @@ -821,7 +757,7 @@ Optional inputs for IVP method selection +--------------------------------+-------------------------------------+----------+ | Optional input | Function name | Default | - +--------------------------------+-------------------------------------+----------+ + +================================+=====================================+==========+ | Select the default MRI method | :c:func:`MRIStepSetOrder()` | 3 | | of a given order | | | +--------------------------------+-------------------------------------+----------+ @@ -833,20 +769,14 @@ Optional inputs for IVP method selection Select the default MRI method of a given order. - The default order is 3. An order less than 1 or greater than 4 will result in + The default order is 3. An order less than 1 will result in using the default. - **Arguments:** - - * *arkode_mem* -- pointer to the MRIStep memory block. - - * *ord* -- the method order. + :param arkode_mem: pointer to the MRIStep memory block. + :param ord: the method order. - **Return value:** - - * *ARK_SUCCESS* if successful - - * *ARK_MEM_NULL* if the MRIStep memory is ``NULL`` + :retval ARK_SUCCESS: if successful + :retval ARK_MEM_NULL: if the MRIStep memory is ``NULL`` .. deprecated:: 6.1.0 @@ -858,28 +788,21 @@ Optional inputs for IVP method selection Specifies a customized set of slow-to-fast coupling coefficients for the MRI method. - **Arguments:** - - * *arkode_mem* -- pointer to the MRIStep memory block. - - * *C* -- the table of coupling coefficients for the MRI method. - - **Return value:** + :param arkode_mem: pointer to the MRIStep memory block. + :param C: the table of coupling coefficients for the MRI method. - * *ARK_SUCCESS* if successful + :retval ARK_SUCCESS: if successful + :retval ARK_MEM_NULL: if the MRIStep memory is ``NULL`` + :retval ARK_ILL_INPUT: if an argument has an illegal value - * *ARK_MEM_NULL* if the MRIStep memory is ``NULL`` - - * *ARK_ILL_INPUT* if an argument had an illegal value - - **Notes:** + .. note:: - For a description of the :c:type:`MRIStepCoupling` type and related - functions for creating Butcher tables see :numref:`ARKODE.Usage.MRIStep.MRIStepCoupling`. + For a description of the :c:type:`MRIStepCoupling` type and related + functions for creating Butcher tables see :numref:`ARKODE.Usage.MRIStep.MRIStepCoupling`. - **Warning:** + .. warning:: - This should not be used with :c:func:`ARKodeSetOrder`. + This should not be used with :c:func:`ARKodeSetOrder`. @@ -893,28 +816,28 @@ Optional inputs for implicit stage solves Specifies that the implicit slow right-hand side function, :math:`f^I(t,y)` is linear in :math:`y`. - **Arguments:** - * *arkode_mem* -- pointer to the MRIStep memory block. - * *timedepend* -- flag denoting whether the Jacobian of - :math:`f^I(t,y)` is time-dependent (1) or not (0). - Alternately, when using a matrix-free iterative linear solver - this flag denotes time dependence of the preconditioner. + :param arkode_mem: pointer to the MRIStep memory block. + :param timedepend: flag denoting whether the Jacobian of + :math:`f^I(t,y)` is time-dependent (1) or not (0). + Alternately, when using a matrix-free iterative linear solver + this flag denotes time dependence of the preconditioner. - **Return value:** - * *ARK_SUCCESS* if successful - * *ARK_MEM_NULL* if the MRIStep memory is ``NULL`` - * *ARK_ILL_INPUT* if an argument had an illegal value + :retval ARK_SUCCESS: if successful + :retval ARK_MEM_NULL: if the MRIStep memory is ``NULL`` + :retval ARK_ILL_INPUT: if an argument has an illegal value - **Notes:** Tightens the linear solver tolerances and takes only a - single Newton iteration. Calls :c:func:`MRIStepSetDeltaGammaMax()` - to enforce Jacobian recomputation when the step size ratio changes - by more than 100 times the unit roundoff (since nonlinear - convergence is not tested). Only applicable when used in - combination with the modified or inexact Newton iteration (not the - fixed-point solver). + .. note:: + + Tightens the linear solver tolerances and takes only a + single Newton iteration. Calls :c:func:`MRIStepSetDeltaGammaMax()` + to enforce Jacobian recomputation when the step size ratio changes + by more than 100 times the unit roundoff (since nonlinear + convergence is not tested). Only applicable when used in + combination with the modified or inexact Newton iteration (not the + fixed-point solver). - The only SUNDIALS-provided SUNNonlinearSolver module that is compatible - with the :c:func:`MRIStepSetLinear()` option is the Newton solver. + The only SUNDIALS-provided SUNNonlinearSolver module that is compatible + with the :c:func:`MRIStepSetLinear()` option is the Newton solver. .. deprecated:: 6.1.0 @@ -927,19 +850,19 @@ Optional inputs for implicit stage solves Specifies that the implicit slow right-hand side function, :math:`f^I(t,y)` is nonlinear in :math:`y`. - **Arguments:** - * *arkode_mem* -- pointer to the MRIStep memory block. + :param arkode_mem: pointer to the MRIStep memory block. - **Return value:** - * *ARK_SUCCESS* if successful - * *ARK_MEM_NULL* if the MRIStep memory is ``NULL`` - * *ARK_ILL_INPUT* if an argument had an illegal value + :retval ARK_SUCCESS: if successful + :retval ARK_MEM_NULL: if the MRIStep memory is ``NULL`` + :retval ARK_ILL_INPUT: if an argument has an illegal value - **Notes:** This is the default behavior of MRIStep, so the function - is primarily useful to undo a previous call to - :c:func:`MRIStepSetLinear()`. Calls - :c:func:`MRIStepSetDeltaGammaMax()` to reset the step size ratio - threshold to the default value. + .. note:: + + This is the default behavior of MRIStep, so the function + is primarily useful to undo a previous call to + :c:func:`MRIStepSetLinear()`. Calls + :c:func:`MRIStepSetDeltaGammaMax()` to reset the step size ratio + threshold to the default value. .. deprecated:: 6.1.0 @@ -951,35 +874,37 @@ Optional inputs for implicit stage solves Specifies the method to use for predicting implicit solutions. - **Arguments:** - * *arkode_mem* -- pointer to the MRIStep memory block. - * *method* -- method choice (0 :math:`\le` *method* :math:`\le` 4): + :param arkode_mem: pointer to the MRIStep memory block. + :param method: the predictor method + + * 0 is the trivial predictor, - * 0 is the trivial predictor, + * 1 is the maximum order (dense output) predictor, - * 1 is the maximum order (dense output) predictor, + * 2 is the variable order predictor, that decreases the + polynomial degree for more distant RK stages, - * 2 is the variable order predictor, that decreases the - polynomial degree for more distant RK stages, + * 3 is the cutoff order predictor, that uses the maximum order + for early RK stages, and a first-order predictor for distant + RK stages, - * 3 is the cutoff order predictor, that uses the maximum order - for early RK stages, and a first-order predictor for distant - RK stages, + * 4 is the bootstrap predictor, that uses a second-order + predictor based on only information within the current step. + **deprecated** - * 4 is the bootstrap predictor, that uses a second-order - predictor based on only information within the current step. - **deprecated** + :retval ARK_SUCCESS: if successful + :retval ARK_MEM_NULL: if the MRIStep memory is ``NULL`` + :retval ARK_ILL_INPUT: if an argument has an illegal value - **Return value:** - * *ARK_SUCCESS* if successful - * *ARK_MEM_NULL* if the MRIStep memory is ``NULL`` - * *ARK_ILL_INPUT* if an argument had an illegal value + .. note:: + + The default value is 0. If *method* is set to an + undefined value, this default predictor will be used. - **Notes:** The default value is 0. If *method* is set to an - undefined value, this default predictor will be used. + .. warning:: - **The "bootstrap" predictor (option 4 above) has been deprecated, and - will be removed from a future release.** + The "bootstrap" predictor (option 4 above) has been deprecated, and + will be removed from a future release. .. deprecated:: 6.1.0 @@ -992,18 +917,17 @@ Optional inputs for implicit stage solves Specifies the maximum number of nonlinear solver iterations permitted per slow MRI stage within each time step. - **Arguments:** - * *arkode_mem* -- pointer to the MRIStep memory block. - * *maxcor* -- maximum allowed solver iterations per stage :math:`(>0)`. + :param arkode_mem: pointer to the MRIStep memory block. + :param maxcor: maximum allowed solver iterations per stage :math:`(>0)`. - **Return value:** - * *ARK_SUCCESS* if successful - * *ARK_MEM_NULL* if the MRIStep memory is ``NULL`` - * *ARK_ILL_INPUT* if an argument had an illegal value or if the SUNNONLINSOL module is ``NULL`` - * *ARK_NLS_OP_ERR* if the SUNNONLINSOL object returned a failure flag + :retval ARK_SUCCESS: if successful + :retval ARK_MEM_NULL: if the MRIStep memory is ``NULL`` + :retval ARK_ILL_INPUT: if an argument has an illegal value or if the SUNNONLINSOL module is ``NULL`` + :retval ARK_NLS_OP_ERR: if the SUNNONLINSOL object returned a failure flag + + .. note:: - **Notes:** The default value is 3; set *maxcor* :math:`\le 0` - to specify this default. + The default value is 3; set *maxcor* :math:`\le 0` to specify this default. .. deprecated:: 6.1.0 @@ -1015,17 +939,16 @@ Optional inputs for implicit stage solves Specifies the safety factor used within the nonlinear solver convergence test. - **Arguments:** - * *arkode_mem* -- pointer to the MRIStep memory block. - * *nlscoef* -- coefficient in nonlinear solver convergence test :math:`(>0.0)`. + :param arkode_mem: pointer to the MRIStep memory block. + :param nlscoef: coefficient in nonlinear solver convergence test :math:`(>0.0)`. - **Return value:** - * *ARK_SUCCESS* if successful - * *ARK_MEM_NULL* if the MRIStep memory is ``NULL`` - * *ARK_ILL_INPUT* if an argument had an illegal value + :retval ARK_SUCCESS: if successful + :retval ARK_MEM_NULL: if the MRIStep memory is ``NULL`` + :retval ARK_ILL_INPUT: if an argument has an illegal value - **Notes:** The default value is 0.1; set *nlscoef* :math:`\le 0` - to specify this default. + .. note:: + + The default value is 0.1; set *nlscoef* :math:`\le 0` to specify this default. .. deprecated:: 6.1.0 @@ -1037,16 +960,16 @@ Optional inputs for implicit stage solves Specifies the constant used in estimating the nonlinear solver convergence rate. - **Arguments:** - * *arkode_mem* -- pointer to the MRIStep memory block. - * *crdown* -- nonlinear convergence rate estimation constant (default is 0.3). + :param arkode_mem: pointer to the MRIStep memory block. + :param crdown: nonlinear convergence rate estimation constant (default is 0.3). - **Return value:** - * *ARK_SUCCESS* if successful - * *ARK_MEM_NULL* if the MRIStep memory is ``NULL`` - * *ARK_ILL_INPUT* if an argument had an illegal value + :retval ARK_SUCCESS: if successful + :retval ARK_MEM_NULL: if the MRIStep memory is ``NULL`` + :retval ARK_ILL_INPUT: if an argument has an illegal value - **Notes:** Any non-positive parameter will imply a reset to the default value. + .. note:: + + Any non-positive parameter will imply a reset to the default value. .. deprecated:: 6.1.0 @@ -1059,17 +982,17 @@ Optional inputs for implicit stage solves Specifies the nonlinear correction threshold beyond which the iteration will be declared divergent. - **Arguments:** - * *arkode_mem* -- pointer to the MRIStep memory block. - * *rdiv* -- tolerance on nonlinear correction size ratio to - declare divergence (default is 2.3). + :param arkode_mem: pointer to the MRIStep memory block. + :param rdiv: tolerance on nonlinear correction size ratio to + declare divergence (default is 2.3). + + :retval ARK_SUCCESS: if successful + :retval ARK_MEM_NULL: if the MRIStep memory is ``NULL`` + :retval ARK_ILL_INPUT: if an argument has an illegal value - **Return value:** - * *ARK_SUCCESS* if successful - * *ARK_MEM_NULL* if the MRIStep memory is ``NULL`` - * *ARK_ILL_INPUT* if an argument had an illegal value + .. note:: - **Notes:** Any non-positive parameter will imply a reset to the default value. + Any non-positive parameter will imply a reset to the default value. .. deprecated:: 6.1.0 @@ -1082,17 +1005,17 @@ Optional inputs for implicit stage solves Sets the user-supplied function to update the implicit stage predictor prior to execution of the nonlinear or linear solver algorithms that compute the implicit stage solution. - **Arguments:** - * *arkode_mem* -- pointer to the MRIStep memory block. - * *PredictStage* -- name of user-supplied predictor function. If ``NULL``, then any - previously-provided stage prediction function will be disabled. + :param arkode_mem: pointer to the MRIStep memory block. + :param PredictStage: name of user-supplied predictor function. If ``NULL``, then any + previously-provided stage prediction function will be disabled. + + :retval ARK_SUCCESS: if successful + :retval ARK_MEM_NULL: if the MRIStep memory is ``NULL`` - **Return value:** - * *ARK_SUCCESS* if successful - * *ARK_MEM_NULL* if the MRIStep memory is ``NULL`` + .. note:: - **Notes:** See :numref:`ARKODE.Usage.StagePredictFn` for more information on - this user-supplied routine. + See :numref:`ARKODE.Usage.StagePredictFn` for more information on + this user-supplied routine. .. deprecated:: 6.1.0 @@ -1105,22 +1028,22 @@ Optional inputs for implicit stage solves Specifies an alternative implicit slow right-hand side function for evaluating :math:`f^I(t,y)` within nonlinear system function evaluations. - **Arguments:** - * *arkode_mem* -- pointer to the MRIStep memory block. - * *nls_fs* -- the alternative C function for computing the right-hand side - function :math:`f^I(t,y)` in the ODE. + :param arkode_mem: pointer to the MRIStep memory block. + :param nls_fs: the alternative C function for computing the right-hand side + function :math:`f^I(t,y)` in the ODE. - **Return value:** - * *ARK_SUCCESS* if successful. - * *ARK_MEM_NULL* if the MRIStep memory was ``NULL``. + :retval ARK_SUCCESS: if successful. + :retval ARK_MEM_NULL: if the MRIStep memory was ``NULL``. + + .. note:: - **Notes:** The default is to use the implicit slow right-hand side function - provided to :c:func:`MRIStepCreate()` in nonlinear system functions. If the - input implicit slow right-hand side function is ``NULL``, the default is - used. + The default is to use the implicit slow right-hand side function + provided to :c:func:`MRIStepCreate()` in nonlinear system functions. If the + input implicit slow right-hand side function is ``NULL``, the default is + used. - When using a non-default nonlinear solver, this function must be called - *after* :c:func:`MRIStepSetNonlinearSolver()`. + When using a non-default nonlinear solver, this function must be called + *after* :c:func:`MRIStepSetNonlinearSolver()`. .. deprecated:: 6.1.0 @@ -1133,16 +1056,14 @@ Optional inputs for implicit stage solves Specifies if implicit stage derivatives are deduced without evaluating :math:`f^I`. See :numref:`ARKODE.Mathematics.Nonlinear` for more details. - **Arguments:** - * *arkode_mem* -- pointer to the MRIStep memory block. - * *deduce* -- If ``SUNFALSE`` (default), the stage derivative is obtained - by evaluating :math:`f^I` with the stage solution returned from the - nonlinear solver. If ``SUNTRUE``, the stage derivative is deduced - without an additional evaluation of :math:`f^I`. + :param arkode_mem: pointer to the MRIStep memory block. + :param deduce: If ``SUNFALSE`` (default), the stage derivative is obtained + by evaluating :math:`f^I` with the stage solution returned from the + nonlinear solver. If ``SUNTRUE``, the stage derivative is deduced + without an additional evaluation of :math:`f^I`. - **Return value:** - * *ARK_SUCCESS* if successful - * *ARK_MEM_NULL* if the MRIStep memory is ``NULL`` + :retval ARK_SUCCESS: if successful + :retval ARK_MEM_NULL: if the MRIStep memory is ``NULL`` .. versionadded:: 5.2.0 @@ -1168,17 +1089,17 @@ Optional inputs for the ARKLS linear solver interface Specifies a scaled step size ratio tolerance, beyond which the linear solver setup routine will be signaled. - **Arguments:** - * *arkode_mem* -- pointer to the MRIStep memory block. - * *dgmax* -- tolerance on step size ratio change before calling - linear solver setup routine (default is 0.2). + :param arkode_mem: pointer to the MRIStep memory block. + :param dgmax: tolerance on step size ratio change before calling + linear solver setup routine (default is 0.2). - **Return value:** - * *ARK_SUCCESS* if successful - * *ARK_MEM_NULL* if the MRIStep memory is ``NULL`` - * *ARK_ILL_INPUT* if an argument had an illegal value + :retval ARK_SUCCESS: if successful + :retval ARK_MEM_NULL: if the MRIStep memory is ``NULL`` + :retval ARK_ILL_INPUT: if an argument has an illegal value - **Notes:** Any non-positive parameter will imply a reset to the default value. + .. note:: + + Any non-positive parameter will imply a reset to the default value. .. deprecated:: 6.1.0 @@ -1191,20 +1112,19 @@ Optional inputs for the ARKLS linear solver interface Specifies the frequency of calls to the linear solver setup routine. - **Arguments:** - * *arkode_mem* -- pointer to the MRIStep memory block. - * *msbp* -- the linear solver setup frequency. + :param arkode_mem: pointer to the MRIStep memory block. + :param msbp: the linear solver setup frequency. - **Return value:** - * *ARK_SUCCESS* if successful - * *ARK_MEM_NULL* if the MRIStep memory is ``NULL`` + :retval ARK_SUCCESS: if successful + :retval ARK_MEM_NULL: if the MRIStep memory is ``NULL`` - **Notes:** - Positive values of **msbp** specify the linear solver setup frequency. For - example, an input of 1 means the setup function will be called every time - step while an input of 2 means it will be called called every other time - step. If **msbp** is 0, the default value of 20 will be used. A negative - value forces a linear solver step at each implicit stage. + .. note:: + + Positive values of **msbp** specify the linear solver setup frequency. For + example, an input of 1 means the setup function will be called every time + step while an input of 2 means it will be called called every other time + step. If **msbp** is 0, the default value of 20 will be used. A negative + value forces a linear solver step at each implicit stage. .. deprecated:: 6.1.0 @@ -1217,27 +1137,26 @@ Optional inputs for the ARKLS linear solver interface Specifies the frequency for recomputing the Jacobian or recommending a preconditioner update. - **Arguments:** - * *arkode_mem* -- pointer to the MRIStep memory block. - * *msbj* -- the Jacobian re-computation or preconditioner update frequency. + :param arkode_mem: pointer to the MRIStep memory block. + :param msbj: the Jacobian re-computation or preconditioner update frequency. + + :retval ARKLS_SUCCESS: if successful. + :retval ARKLS_MEM_NULL: if the MRIStep memory was ``NULL``. + :retval ARKLS_LMEM_NULL: if the linear solver memory was ``NULL``. - **Return value:** - * *ARKLS_SUCCESS* if successful. - * *ARKLS_MEM_NULL* if the MRIStep memory was ``NULL``. - * *ARKLS_LMEM_NULL* if the linear solver memory was ``NULL``. + .. note:: - **Notes:** - The Jacobian update frequency is only checked *within* calls to the linear - solver setup routine, as such values of *msbj* :math:`<` *msbp* will result - in recomputing the Jacobian every *msbp* steps. See - :c:func:`MRIStepSetLSetupFrequency()` for setting the linear solver setup - frequency *msbp*. + The Jacobian update frequency is only checked *within* calls to the linear + solver setup routine, as such values of *msbj* :math:`<` *msbp* will result + in recomputing the Jacobian every *msbp* steps. See + :c:func:`MRIStepSetLSetupFrequency()` for setting the linear solver setup + frequency *msbp*. - Passing a value *msbj* :math:`\le 0` indicates to use the - default value of 50. + Passing a value *msbj* :math:`\le 0` indicates to use the + default value of 50. - This function must be called *after* the ARKLS system solver interface has - been initialized through a call to :c:func:`MRIStepSetLinearSolver()`. + This function must be called *after* the ARKLS system solver interface has + been initialized through a call to :c:func:`MRIStepSetLinearSolver()`. .. deprecated:: 6.1.0 @@ -1256,26 +1175,26 @@ Optional inputs for matrix-based ``SUNLinearSolver`` modules Specifies the Jacobian approximation routine to be used for the matrix-based solver with the ARKLS interface. - **Arguments:** - * *arkode_mem* -- pointer to the MRIStep memory block. - * *jac* -- name of user-supplied Jacobian approximation function. + :param arkode_mem: pointer to the MRIStep memory block. + :param jac: name of user-supplied Jacobian approximation function. + + :retval ARKLS_SUCCESS: if successful + :retval ARKLS_MEM_NULL: if the MRIStep memory was ``NULL`` + :retval ARKLS_LMEM_NULL: if the linear solver memory was ``NULL`` - **Return value:** - * *ARKLS_SUCCESS* if successful - * *ARKLS_MEM_NULL* if the MRIStep memory was ``NULL`` - * *ARKLS_LMEM_NULL* if the linear solver memory was ``NULL`` + .. note:: - **Notes:** This routine must be called after the ARKLS linear - solver interface has been initialized through a call to - :c:func:`MRIStepSetLinearSolver()`. + This routine must be called after the ARKLS linear + solver interface has been initialized through a call to + :c:func:`MRIStepSetLinearSolver()`. - By default, ARKLS uses an internal difference quotient function for - dense and band matrices. If ``NULL`` is passed in for *jac*, this - default is used. An error will occur if no *jac* is supplied when - using other matrix types. + By default, ARKLS uses an internal difference quotient function for + dense and band matrices. If ``NULL`` is passed in for *jac*, this + default is used. An error will occur if no *jac* is supplied when + using other matrix types. - The function type :c:func:`ARKLsJacFn()` is described in - :numref:`ARKODE.Usage.UserSupplied`. + The function type :c:func:`ARKLsJacFn()` is described in + :numref:`ARKODE.Usage.UserSupplied`. .. deprecated:: 6.1.0 @@ -1288,25 +1207,25 @@ Optional inputs for matrix-based ``SUNLinearSolver`` modules Specifies the linear system approximation routine to be used for the matrix-based solver with the ARKLS interface. - **Arguments:** - * *arkode_mem* -- pointer to the MRIStep memory block. - * *linsys* -- name of user-supplied linear system approximation function. + :param arkode_mem: pointer to the MRIStep memory block. + :param linsys: name of user-supplied linear system approximation function. - **Return value:** - * *ARKLS_SUCCESS* if successful - * *ARKLS_MEM_NULL* if the MRIStep memory was ``NULL`` - * *ARKLS_LMEM_NULL* if the linear solver memory was ``NULL`` + :retval ARKLS_SUCCESS: if successful + :retval ARKLS_MEM_NULL: if the MRIStep memory was ``NULL`` + :retval ARKLS_LMEM_NULL: if the linear solver memory was ``NULL`` + + .. note:: - **Notes:** This routine must be called after the ARKLS linear - solver interface has been initialized through a call to - :c:func:`MRIStepSetLinearSolver()`. + This routine must be called after the ARKLS linear + solver interface has been initialized through a call to + :c:func:`MRIStepSetLinearSolver()`. - By default, ARKLS uses an internal linear system function that leverages the - SUNMATRIX API to form the system :math:`I - \gamma J`. If ``NULL`` is passed - in for *linsys*, this default is used. + By default, ARKLS uses an internal linear system function that leverages the + SUNMATRIX API to form the system :math:`I - \gamma J`. If ``NULL`` is passed + in for *linsys*, this default is used. - The function type :c:func:`ARKLsLinSysFn()` is described in - :numref:`ARKODE.Usage.UserSupplied`. + The function type :c:func:`ARKLsLinSysFn()` is described in + :numref:`ARKODE.Usage.UserSupplied`. .. deprecated:: 6.1.0 @@ -1320,18 +1239,18 @@ Optional inputs for matrix-based ``SUNLinearSolver`` modules change in :math:`\gamma` in the linear system. For more details see :numref:`SUNLinSol.Lagged_matrix`. - **Arguments:** - * *arkode_mem* -- pointer to the MRIStep memory block. - * *onoff* -- flag to enable (``SUNTRUE``) or disable (``SUNFALSE``) - scaling + :param arkode_mem: pointer to the MRIStep memory block. + :param onoff: flag to enable (``SUNTRUE``) or disable (``SUNFALSE``) + scaling - **Return value:** - * *ARKLS_SUCCESS* if successful - * *ARKLS_MEM_NULL* if the MRIStep memory was ``NULL`` - * *ARKLS_ILL_INPUT* if the attached linear solver is not matrix-based + :retval ARKLS_SUCCESS: if successful + :retval ARKLS_MEM_NULL: if the MRIStep memory was ``NULL`` + :retval ARKLS_ILL_INPUT: if the attached linear solver is not matrix-based - **Notes:** Linear solution scaling is enabled by default when a matrix-based - linear solver is attached. + .. note:: + + Linear solution scaling is enabled by default when a matrix-based + linear solver is attached. .. deprecated:: 6.1.0 @@ -1348,33 +1267,33 @@ Optional inputs for matrix-free ``SUNLinearSolver`` modules Specifies the Jacobian-times-vector setup and product functions. - **Arguments:** - * *arkode_mem* -- pointer to the MRIStep memory block. - * *jtsetup* -- user-defined Jacobian-vector setup function. - Pass ``NULL`` if no setup is necessary. - * *jtimes* -- user-defined Jacobian-vector product function. + :param arkode_mem: pointer to the MRIStep memory block. + :param jtsetup: user-defined Jacobian-vector setup function. + Pass ``NULL`` if no setup is necessary. + :param jtimes: user-defined Jacobian-vector product function. - **Return value:** - * *ARKLS_SUCCESS* if successful. - * *ARKLS_MEM_NULL* if the MRIStep memory was ``NULL``. - * *ARKLS_LMEM_NULL* if the linear solver memory was ``NULL``. - * *ARKLS_ILL_INPUT* if an input has an illegal value. - * *ARKLS_SUNLS_FAIL* if an error occurred when setting up - the Jacobian-vector product in the ``SUNLinearSolver`` - object used by the ARKLS interface. + :retval ARKLS_SUCCESS: if successful. + :retval ARKLS_MEM_NULL: if the MRIStep memory was ``NULL``. + :retval ARKLS_LMEM_NULL: if the linear solver memory was ``NULL``. + :retval ARKLS_ILL_INPUT: if an input has an illegal value. + :retval ARKLS_SUNLS_FAIL: if an error occurred when setting up + the Jacobian-vector product in the ``SUNLinearSolver`` + object used by the ARKLS interface. - **Notes:** The default is to use an internal finite difference - quotient for *jtimes* and to leave out *jtsetup*. If ``NULL`` is - passed to *jtimes*, these defaults are used. A user may - specify non-``NULL`` *jtimes* and ``NULL`` *jtsetup* inputs. + .. note:: - This function must be called *after* the ARKLS system solver - interface has been initialized through a call to - :c:func:`MRIStepSetLinearSolver()`. + The default is to use an internal finite difference + quotient for *jtimes* and to leave out *jtsetup*. If ``NULL`` is + passed to *jtimes*, these defaults are used. A user may + specify non-``NULL`` *jtimes* and ``NULL`` *jtsetup* inputs. - The function types :c:type:`ARKLsJacTimesSetupFn` and - :c:type:`ARKLsJacTimesVecFn` are described in - :numref:`ARKODE.Usage.UserSupplied`. + This function must be called *after* the ARKLS system solver + interface has been initialized through a call to + :c:func:`MRIStepSetLinearSolver()`. + + The function types :c:type:`ARKLsJacTimesSetupFn` and + :c:type:`ARKLsJacTimesVecFn` are described in + :numref:`ARKODE.Usage.UserSupplied`. .. deprecated:: 6.1.0 @@ -1386,23 +1305,23 @@ Optional inputs for matrix-free ``SUNLinearSolver`` modules Specifies an alternative implicit right-hand side function for use in the internal Jacobian-vector product difference quotient approximation. - **Arguments:** - * *arkode_mem* -- pointer to the MRIStep memory block. - * *jtimesRhsFn* -- the name of the C function (of type - :c:func:`ARKRhsFn()`) defining the alternative right-hand side function. + :param arkode_mem: pointer to the MRIStep memory block. + :param jtimesRhsFn: the name of the C function defining the alternative + right-hand side function. - **Return value:** - * *ARKLS_SUCCESS* if successful. - * *ARKLS_MEM_NULL* if the MRIStep memory was ``NULL``. - * *ARKLS_LMEM_NULL* if the linear solver memory was ``NULL``. - * *ARKLS_ILL_INPUT* if an input has an illegal value. + :retval ARKLS_SUCCESS: if successful. + :retval ARKLS_MEM_NULL: if the MRIStep memory was ``NULL``. + :retval ARKLS_LMEM_NULL: if the linear solver memory was ``NULL``. + :retval ARKLS_ILL_INPUT: if an input has an illegal value. - **Notes:** The default is to use the implicit right-hand side function - provided to :c:func:`MRIStepCreate()` in the internal difference quotient. If - the input implicit right-hand side function is ``NULL``, the default is used. + .. note:: - This function must be called *after* the ARKLS system solver interface has - been initialized through a call to :c:func:`MRIStepSetLinearSolver()`. + The default is to use the implicit right-hand side function provided + to :c:func:`MRIStepCreate()` in the internal difference quotient. If + the input implicit right-hand side function is ``NULL``, the default is used. + + This function must be called *after* the ARKLS system solver interface has + been initialized through a call to :c:func:`MRIStepSetLinearSolver()`. .. deprecated:: 6.1.0 @@ -1421,31 +1340,31 @@ Optional inputs for iterative ``SUNLinearSolver`` modules Specifies the user-supplied preconditioner setup and solve functions. - **Arguments:** - * *arkode_mem* -- pointer to the MRIStep memory block. - * *psetup* -- user defined preconditioner setup function. Pass - ``NULL`` if no setup is needed. - * *psolve* -- user-defined preconditioner solve function. + :param arkode_mem: pointer to the MRIStep memory block. + :param psetup: user defined preconditioner setup function. Pass + ``NULL`` if no setup is needed. + :param psolve: user-defined preconditioner solve function. + + :retval ARKLS_SUCCESS: if successful. + :retval ARKLS_MEM_NULL: if the MRIStep memory was ``NULL``. + :retval ARKLS_LMEM_NULL: if the linear solver memory was ``NULL``. + :retval ARKLS_ILL_INPUT: if an input has an illegal value. + :retval ARKLS_SUNLS_FAIL: if an error occurred when setting up + preconditioning in the ``SUNLinearSolver`` object used + by the ARKLS interface. - **Return value:** - * *ARKLS_SUCCESS* if successful. - * *ARKLS_MEM_NULL* if the MRIStep memory was ``NULL``. - * *ARKLS_LMEM_NULL* if the linear solver memory was ``NULL``. - * *ARKLS_ILL_INPUT* if an input has an illegal value. - * *ARKLS_SUNLS_FAIL* if an error occurred when setting up - preconditioning in the ``SUNLinearSolver`` object used - by the ARKLS interface. + .. note:: - **Notes:** The default is ``NULL`` for both arguments (i.e., no - preconditioning). + The default is ``NULL`` for both arguments (i.e., no + preconditioning). - This function must be called *after* the ARKLS system solver - interface has been initialized through a call to - :c:func:`MRIStepSetLinearSolver()`. + This function must be called *after* the ARKLS system solver + interface has been initialized through a call to + :c:func:`MRIStepSetLinearSolver()`. - Both of the function types :c:func:`ARKLsPrecSetupFn()` and - :c:func:`ARKLsPrecSolveFn()` are described in - :numref:`ARKODE.Usage.UserSupplied`. + Both of the function types :c:func:`ARKLsPrecSetupFn()` and + :c:func:`ARKLsPrecSolveFn()` are described in + :numref:`ARKODE.Usage.UserSupplied`. .. deprecated:: 6.1.0 @@ -1459,22 +1378,22 @@ Optional inputs for iterative ``SUNLinearSolver`` modules iteration is multiplied to get a tolerance on the linear iteration. - **Arguments:** - * *arkode_mem* -- pointer to the MRIStep memory block. - * *eplifac* -- linear convergence safety factor. + :param arkode_mem: pointer to the MRIStep memory block. + :param eplifac: linear convergence safety factor. - **Return value:** - * *ARKLS_SUCCESS* if successful. - * *ARKLS_MEM_NULL* if the MRIStep memory was ``NULL``. - * *ARKLS_LMEM_NULL* if the linear solver memory was ``NULL``. - * *ARKLS_ILL_INPUT* if an input has an illegal value. + :retval ARKLS_SUCCESS: if successful. + :retval ARKLS_MEM_NULL: if the MRIStep memory was ``NULL``. + :retval ARKLS_LMEM_NULL: if the linear solver memory was ``NULL``. + :retval ARKLS_ILL_INPUT: if an input has an illegal value. - **Notes:** Passing a value *eplifac* :math:`\le 0` indicates to use the - default value of 0.05. + .. note:: - This function must be called *after* the ARKLS system solver - interface has been initialized through a call to - :c:func:`MRIStepSetLinearSolver()`. + Passing a value *eplifac* :math:`\le 0` indicates to use the + default value of 0.05. + + This function must be called *after* the ARKLS system solver + interface has been initialized through a call to + :c:func:`MRIStepSetLinearSolver()`. .. deprecated:: 6.1.0 @@ -1488,26 +1407,25 @@ Optional inputs for iterative ``SUNLinearSolver`` modules (WRMS norm) to the linear solver tolerance (L2 norm) for Newton linear system solves e.g., ``tol_L2 = fac * tol_WRMS``. - **Arguments:** - * *arkode_mem* -- pointer to the MRIStep memory block. - * *nrmfac* -- the norm conversion factor. If *nrmfac* is: + :param arkode_mem: pointer to the MRIStep memory block. + :param nrmfac: the norm conversion factor. If *nrmfac* is: + + :math:`> 0` then the provided value is used. - :math:`> 0` then the provided value is used. + :math:`= 0` then the conversion factor is computed using the vector + length i.e., ``nrmfac = sqrt(N_VGetLength(y))`` (*default*). - :math:`= 0` then the conversion factor is computed using the vector - length i.e., ``nrmfac = sqrt(N_VGetLength(y))`` (*default*). + :math:`< 0` then the conversion factor is computed using the vector dot + product i.e., ``nrmfac = sqrt(N_VDotProd(v,v))`` where all the entries + of ``v`` are one. - :math:`< 0` then the conversion factor is computed using the vector dot - product i.e., ``nrmfac = sqrt(N_VDotProd(v,v))`` where all the entries - of ``v`` are one. + :retval ARK_SUCCESS: if successful. + :retval ARK_MEM_NULL: if the MRIStep memory was ``NULL``. - **Return value:** - * *ARK_SUCCESS* if successful. - * *ARK_MEM_NULL* if the MRIStep memory was ``NULL``. + .. note:: - **Notes:** - This function must be called *after* the ARKLS system solver interface has - been initialized through a call to :c:func:`MRIStepSetLinearSolver()`. + This function must be called *after* the ARKLS system solver interface has + been initialized through a call to :c:func:`MRIStepSetLinearSolver()`. .. deprecated:: 6.1.0 @@ -1524,22 +1442,22 @@ Rootfinding optional input functions Specifies the direction of zero-crossings to be located and returned. - **Arguments:** - * *arkode_mem* -- pointer to the MRIStep memory block. - * *rootdir* -- state array of length *nrtfn*, the number of root - functions :math:`g_i` (the value of *nrtfn* was supplied in - the call to :c:func:`MRIStepRootInit()`). If ``rootdir[i] == - 0`` then crossing in either direction for :math:`g_i` should be - reported. A value of +1 or -1 indicates that the solver - should report only zero-crossings where :math:`g_i` is - increasing or decreasing, respectively. + :param arkode_mem: pointer to the MRIStep memory block. + :param rootdir: state array of length *nrtfn*, the number of root + functions :math:`g_i` (the value of *nrtfn* was supplied in + the call to :c:func:`MRIStepRootInit()`). If + ``rootdir[i] == 0`` then crossing in either direction for + :math:`g_i` should be reported. A value of +1 or -1 indicates + that the solver should report only zero-crossings where + :math:`g_i` is increasing or decreasing, respectively. - **Return value:** - * *ARK_SUCCESS* if successful - * *ARK_MEM_NULL* if the MRIStep memory is ``NULL`` - * *ARK_ILL_INPUT* if an argument had an illegal value + :retval ARK_SUCCESS: if successful + :retval ARK_MEM_NULL: if the MRIStep memory is ``NULL`` + :retval ARK_ILL_INPUT: if an argument has an illegal value + + .. note:: - **Notes:** The default behavior is to monitor for both zero-crossing directions. + The default behavior is to monitor for both zero-crossing directions. .. deprecated:: 6.1.0 @@ -1552,20 +1470,20 @@ Rootfinding optional input functions Disables issuing a warning if some root function appears to be identically zero at the beginning of the integration. - **Arguments:** - * *arkode_mem* -- pointer to the MRIStep memory block. + :param arkode_mem: pointer to the MRIStep memory block. - **Return value:** - * *ARK_SUCCESS* if successful - * *ARK_MEM_NULL* if the MRIStep memory is ``NULL`` + :retval ARK_SUCCESS: if successful + :retval ARK_MEM_NULL: if the MRIStep memory is ``NULL`` - **Notes:** MRIStep will not report the initial conditions as a - possible zero-crossing (assuming that one or more components - :math:`g_i` are zero at the initial time). However, if it appears - that some :math:`g_i` is identically zero at the initial time - (i.e., :math:`g_i` is zero at the initial time *and* after the - first step), MRIStep will issue a warning which can be disabled with - this optional input function. + .. note:: + + MRIStep will not report the initial conditions as a + possible zero-crossing (assuming that one or more components + :math:`g_i` are zero at the initial time). However, if it appears + that some :math:`g_i` is identically zero at the initial time + (i.e., :math:`g_i` is zero at the initial time *and* after the + first step), MRIStep will issue a warning which can be disabled with + this optional input function. .. deprecated:: 6.1.0 @@ -1593,35 +1511,26 @@ Interpolated output function interpolation module. For Hermite interpolants *kmax = 5* and for Lagrange interpolants *kmax = 3*. - **Arguments:** - - * *arkode_mem* -- pointer to the MRIStep memory block. - - * *t* -- the value of the independent variable at which the - derivative is to be evaluated. - - * *k* -- the derivative order requested. + :param arkode_mem: pointer to the MRIStep memory block. + :param t: the value of the independent variable at which the + derivative is to be evaluated. + :param k: the derivative order requested. + :param dky: output vector (must be allocated by the user). - * *dky* -- output vector (must be allocated by the user). + :retval ARK_SUCCESS: if successful + :retval ARK_BAD_K: if *k* is not in the range {0,..., *min(degree, kmax)*}. + :retval ARK_BAD_T: if *t* is not in the interval :math:`[t_n-h_n, t_n]` + :retval ARK_BAD_DKY: if the *dky* vector was ``NULL`` + :retval ARK_MEM_NULL: if the MRIStep memory is ``NULL`` - **Return value:** - - * *ARK_SUCCESS* if successful - - * *ARK_BAD_K* if *k* is not in the range {0,..., *min(degree, kmax)*}. - - * *ARK_BAD_T* if *t* is not in the interval :math:`[t_n-h_n, t_n]` - - * *ARK_BAD_DKY* if the *dky* vector was ``NULL`` - - * *ARK_MEM_NULL* if the MRIStep memory is ``NULL`` + .. note:: - **Notes:** It is only legal to call this function after a successful - return from :c:func:`MRIStepEvolve()`. + It is only legal to call this function after a successful + return from :c:func:`MRIStepEvolve()`. - A user may access the values :math:`t_n` and :math:`h_n` via the - functions :c:func:`MRIStepGetCurrentTime()` and - :c:func:`MRIStepGetLastStep()`, respectively. + A user may access the values :math:`t_n` and :math:`h_n` via the + functions :c:func:`MRIStepGetCurrentTime()` and + :c:func:`MRIStepGetLastStep()`, respectively. .. deprecated:: 6.1.0 @@ -1641,23 +1550,29 @@ Main solver optional output functions ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -.. c:function:: int MRIStepGetWorkSpace(void* arkode_mem, long int* lenrw, long int* leniw) +.. c:function:: int MRIStepGetNumInnerStepperFails(void* arkode_mem, long int* inner_fails) - Returns the MRIStep real and integer workspace sizes. + Returns the number of recoverable failures reported by the inner stepper (so far). + + :param arkode_mem: pointer to the MRIStep memory block. + :param inner_fails: number of failed fast (inner) integrations. - **Arguments:** + :retval ARK_SUCCESS: if successful + :retval ARK_MEM_NULL: if the MRIStep memory was ``NULL`` - * *arkode_mem* -- pointer to the MRIStep memory block. + .. versionadded:: x.y.z - * *lenrw* -- the number of ``sunrealtype`` values in the MRIStep workspace. - * *leniw* -- the number of integer values in the MRIStep workspace. +.. c:function:: int MRIStepGetWorkSpace(void* arkode_mem, long int* lenrw, long int* leniw) - **Return value:** + Returns the MRIStep real and integer workspace sizes. - * *ARK_SUCCESS* if successful + :param arkode_mem: pointer to the MRIStep memory block. + :param lenrw: the number of ``realtype`` values in the MRIStep workspace. + :param leniw: the number of integer values in the MRIStep workspace. - * *ARK_MEM_NULL* if the MRIStep memory was ``NULL`` + :retval ARK_SUCCESS: if successful + :retval ARK_MEM_NULL: if the MRIStep memory was ``NULL`` .. deprecated:: 6.1.0 @@ -1670,19 +1585,12 @@ Main solver optional output functions Returns the cumulative number of slow and fast internal steps taken by the solver (so far). - **Arguments:** - - * *arkode_mem* -- pointer to the MRIStep memory block. - - * *nssteps* -- number of slow steps taken in the solver. - - * *nfsteps* -- number of fast steps taken in the solver. + :param arkode_mem: pointer to the MRIStep memory block. + :param nssteps: number of slow steps taken in the solver. + :param nfsteps: number of fast steps taken in the solver. - **Return value:** - - * *ARK_SUCCESS* if successful - - * *ARK_MEM_NULL* if the MRIStep memory was ``NULL`` + :retval ARK_SUCCESS: if successful + :retval ARK_MEM_NULL: if the MRIStep memory was ``NULL`` .. deprecated:: 6.1.0 @@ -1695,17 +1603,11 @@ Main solver optional output functions Returns the integration step size taken on the last successful internal step. - **Arguments:** - - * *arkode_mem* -- pointer to the MRIStep memory block. - - * *hlast* -- step size taken on the last internal step. - - **Return value:** + :param arkode_mem: pointer to the MRIStep memory block. + :param hlast: step size taken on the last internal step. - * *ARK_SUCCESS* if successful - - * *ARK_MEM_NULL* if the MRIStep memory was ``NULL`` + :retval ARK_SUCCESS: if successful + :retval ARK_MEM_NULL: if the MRIStep memory was ``NULL`` .. deprecated:: 6.1.0 @@ -1717,17 +1619,11 @@ Main solver optional output functions Returns the current internal time reached by the solver. - **Arguments:** - - * *arkode_mem* -- pointer to the MRIStep memory block. - - * *tcur* -- current internal time reached. - - **Return value:** - - * *ARK_SUCCESS* if successful + :param arkode_mem: pointer to the MRIStep memory block. + :param tcur: current internal time reached. - * *ARK_MEM_NULL* if the MRIStep memory was ``NULL`` + :retval ARK_SUCCESS: if successful + :retval ARK_MEM_NULL: if the MRIStep memory was ``NULL`` .. deprecated:: 6.1.0 @@ -1738,21 +1634,17 @@ Main solver optional output functions Returns the current internal solution reached by the solver. - **Arguments:** + :param arkode_mem: pointer to the MRIStep memory block. + :param ycur: current internal solution. - * *arkode_mem* -- pointer to the MRIStep memory block. + :retval ARK_SUCCESS: if successful + :retval ARK_MEM_NULL: if the MRIStep memory was ``NULL`` - * *ycur* -- current internal solution. - - **Return value:** - - * *ARK_SUCCESS* if successful - - * *ARK_MEM_NULL* if the MRIStep memory was ``NULL`` + .. note:: - **Notes:** Users should exercise extreme caution when using this function, - as altering values of *ycur* may lead to undesirable behavior, depending - on the particular use case and on when this routine is called. + Users should exercise extreme caution when using this function, + as altering values of *ycur* may lead to undesirable behavior, depending + on the particular use case and on when this routine is called. .. deprecated:: 6.1.0 @@ -1764,17 +1656,11 @@ Main solver optional output functions Returns the current internal value of :math:`\gamma` used in the implicit solver Newton matrix (see equation :eq:`ARKODE_NewtonMatrix`). - **Arguments:** + :param arkode_mem: pointer to the MRIStep memory block. + :param gamma: current step size scaling factor in the Newton system. - * *arkode_mem* -- pointer to the MRIStep memory block. - - * *gamma* -- current step size scaling factor in the Newton system. - - **Return value:** - - * *ARK_SUCCESS* if successful - - * *ARK_MEM_NULL* if the MRIStep memory was ``NULL`` + :retval ARK_SUCCESS: if successful + :retval ARK_MEM_NULL: if the MRIStep memory was ``NULL`` .. deprecated:: 6.1.0 @@ -1787,17 +1673,11 @@ Main solver optional output functions tolerances should be scaled when too much accuracy has been requested for some internal step. - **Arguments:** - - * *arkode_mem* -- pointer to the MRIStep memory block. + :param arkode_mem: pointer to the MRIStep memory block. + :param tolsfac: suggested scaling factor for user-supplied tolerances. - * *tolsfac* -- suggested scaling factor for user-supplied tolerances. - - **Return value:** - - * *ARK_SUCCESS* if successful - - * *ARK_MEM_NULL* if the MRIStep memory was ``NULL`` + :retval ARK_SUCCESS: if successful + :retval ARK_MEM_NULL: if the MRIStep memory was ``NULL`` .. deprecated:: 6.1.0 @@ -1808,20 +1688,16 @@ Main solver optional output functions Returns the current error weight vector. - **Arguments:** - - * *arkode_mem* -- pointer to the MRIStep memory block. - - * *eweight* -- solution error weights at the current time. + :param arkode_mem: pointer to the MRIStep memory block. + :param eweight: solution error weights at the current time. - **Return value:** + :retval ARK_SUCCESS: if successful + :retval ARK_MEM_NULL: if the MRIStep memory was ``NULL`` - * *ARK_SUCCESS* if successful - - * *ARK_MEM_NULL* if the MRIStep memory was ``NULL`` + .. note:: - **Notes:** The user must allocate space for *eweight*, that will be - filled in by this function. + The user must allocate space for *eweight*, that will be + filled in by this function. .. deprecated:: 6.1.0 @@ -1833,19 +1709,18 @@ Main solver optional output functions Outputs all of the integrator, nonlinear solver, linear solver, and other statistics. - **Arguments:** - * *arkode_mem* -- pointer to the MRIStep memory block. - * *outfile* -- pointer to output file. - * *fmt* -- the output format: + :param arkode_mem: pointer to the MRIStep memory block. + :param outfile: pointer to output file. + :param fmt: the output format: + + * :c:enumerator:`SUN_OUTPUTFORMAT_TABLE` -- prints a table of values - * :c:enumerator:`SUN_OUTPUTFORMAT_TABLE` -- prints a table of values - * :c:enumerator:`SUN_OUTPUTFORMAT_CSV` -- prints a comma-separated list - of key and value pairs e.g., ``key1,value1,key2,value2,...`` + * :c:enumerator:`SUN_OUTPUTFORMAT_CSV` -- prints a comma-separated list + of key and value pairs e.g., ``key1,value1,key2,value2,...`` - **Return value:** - * *ARK_SUCCESS* -- if the output was successfully. - * *CV_MEM_NULL* -- if the MRIStep memory was ``NULL``. - * *CV_ILL_INPUT* -- if an invalid formatting option was provided. + :retval ARK_SUCCESS: if the output was successfully. + :retval ARK_MEM_NULL: if the MRIStep memory was ``NULL``. + :retval ARK_ILL_INPUT: if an invalid formatting option was provided. .. note:: @@ -1865,13 +1740,9 @@ Main solver optional output functions Returns the name of the MRIStep constant corresponding to *flag*. See :ref:`ARKODE.Constants`. - **Arguments:** + :param flag: a return flag from an MRIStep function. - * *flag* -- a return flag from an MRIStep function. - - **Return value:** - The return value is a string containing the name of - the corresponding constant. + :returns: A string containing the name of the corresponding constant. .. deprecated:: 6.1.0 @@ -1884,19 +1755,12 @@ Main solver optional output functions Returns the number of calls to the user's outer (slow) right-hand side functions, :math:`f^E` and :math:`f^I`, so far. - **Arguments:** - - * *arkode_mem* -- pointer to the MRIStep memory block. + :param arkode_mem: pointer to the MRIStep memory block. + :param nfse_evals: number of calls to the user's :math:`f^E(t,y)` function. + :param nfsi_evals: number of calls to the user's :math:`f^I(t,y)` function. - * *nfse_evals* -- number of calls to the user's :math:`f^E(t,y)` function. - - * *nfsi_evals* -- number of calls to the user's :math:`f^I(t,y)` function. - - **Return value:** - - * *ARK_SUCCESS* if successful - - * *ARK_MEM_NULL* if the MRIStep memory was ``NULL`` + :retval ARK_SUCCESS: if successful + :retval ARK_MEM_NULL: if the MRIStep memory was ``NULL`` .. deprecated:: x.y.z @@ -1907,17 +1771,11 @@ Main solver optional output functions Returns the number of failed steps due to a nonlinear solver failure (so far). - **Arguments:** - - * *arkode_mem* -- pointer to the MRIStep memory block. + :param arkode_mem: pointer to the MRIStep memory block. + :param ncnf: number of step failures. - * *ncnf* -- number of step failures. - - **Return value:** - - * *ARK_SUCCESS* if successful - - * *ARK_MEM_NULL* if the MRIStep memory was ``NULL`` + :retval ARK_SUCCESS: if successful + :retval ARK_MEM_NULL: if the MRIStep memory was ``NULL`` .. deprecated:: 6.1.0 @@ -1928,54 +1786,29 @@ Main solver optional output functions Returns the MRI coupling table currently in use by the solver. - **Arguments:** - - * *arkode_mem* -- pointer to the MRIStep memory block. - - * *C* -- pointer to slow-to-fast MRI coupling structure. - - **Return value:** - - * *ARK_SUCCESS* if successful - - * *ARK_MEM_NULL* if the MRIStep memory was ``NULL`` - - **Notes:** The *MRIStepCoupling* data structure is defined in - the header file ``arkode/arkode_mristep.h``. It is defined as a - pointer to the following C structure: - - .. code-block:: c + :param arkode_mem: pointer to the MRIStep memory block. + :param C: pointer to slow-to-fast MRI coupling structure. - struct MRIStepCouplingMem { + :retval ARK_SUCCESS: if successful + :retval ARK_MEM_NULL: if the MRIStep memory was ``NULL`` - int nmat; /* number of MRI coupling matrices */ - int stages; /* size of coupling matrices (stages * stages) */ - int q; /* method order of accuracy */ - int p; /* embedding order of accuracy */ - sunrealtype ***G; /* coupling matrices [nmat][stages][stages] */ - sunrealtype *c; /* abscissae */ - - }; - typedef MRIStepCouplingMem *MRIStepCoupling; + .. note:: - For more details see :numref:`ARKODE.Usage.MRIStep.MRIStepCoupling`. + The *MRIStepCoupling* data structure is defined in + the header file ``arkode/arkode_mristep.h``. For more details + see :numref:`ARKODE.Usage.MRIStep.MRIStepCoupling`. .. c:function:: int MRIStepGetLastInnerStepFlag(void* arkode_mem, int* flag) Returns the last return value from the inner stepper. - **Arguments:** - - * *arkode_mem* -- pointer to the MRIStep memory block. - - * *flag* -- inner stepper return value. - - **Return value:** + :param arkode_mem: pointer to the MRIStep memory block. + :param flag: inner stepper return value. - * *ARK_SUCCESS* if successful + :retval ARK_SUCCESS: if successful + :retval ARK_MEM_NULL: if the MRIStep memory was ``NULL`` - * *ARK_MEM_NULL* if the MRIStep memory was ``NULL`` .. c:function:: int MRIStepGetUserData(void* arkode_mem, void** user_data) @@ -1983,17 +1816,11 @@ Main solver optional output functions Returns the user data pointer previously set with :c:func:`MRIStepSetUserData`. - **Arguments:** - - * *arkode_mem* -- pointer to the MRIStep memory block. - - * *user_data* -- memory reference to a user data pointer - - **Return value:** - - * *ARK_SUCCESS* if successful + :param arkode_mem: pointer to the MRIStep memory block. + :param user_data: memory reference to a user data pointer - * *ARK_MEM_NULL* if the MRIStep memory was ``NULL`` + :retval ARK_SUCCESS: if successful + :retval ARK_MEM_NULL: if the ARKStep memory was ``NULL`` .. versionadded:: 5.3.0 @@ -2013,21 +1840,17 @@ Implicit solver optional output functions Returns the number of calls made to the linear solver's setup routine (so far). - **Arguments:** + :param arkode_mem: pointer to the MRIStep memory block. + :param nlinsetups: number of linear solver setup calls made. - * *arkode_mem* -- pointer to the MRIStep memory block. + :retval ARK_SUCCESS: if successful + :retval ARK_MEM_NULL: if the MRIStep memory was ``NULL`` - * *nlinsetups* -- number of linear solver setup calls made. - - **Return value:** - - * *ARK_SUCCESS* if successful - - * *ARK_MEM_NULL* if the MRIStep memory was ``NULL`` + .. note:: - **Notes:** This is only accumulated for the "life" of the nonlinear - solver object; the counter is reset whenever a new nonlinear solver - module is "attached" to MRIStep, or when MRIStep is resized. + This is only accumulated for the "life" of the nonlinear + solver object; the counter is reset whenever a new nonlinear solver + module is "attached" to MRIStep, or when MRIStep is resized. .. deprecated:: 6.1.0 @@ -2038,23 +1861,18 @@ Implicit solver optional output functions Returns the number of nonlinear solver iterations performed (so far). - **Arguments:** - - * *arkode_mem* -- pointer to the MRIStep memory block. + :param arkode_mem: pointer to the MRIStep memory block. + :param nniters: number of nonlinear iterations performed. - * *nniters* -- number of nonlinear iterations performed. + :retval ARK_SUCCESS: if successful + :retval ARK_MEM_NULL: if the MRIStep memory was ``NULL`` + :retval ARK_NLS_OP_ERR: if the SUNNONLINSOL object returned a failure flag - **Return value:** - - * *ARK_SUCCESS* if successful - - * *ARK_MEM_NULL* if the MRIStep memory was ``NULL`` - - * *ARK_NLS_OP_ERR* if the SUNNONLINSOL object returned a failure flag + .. note:: - **Notes:** This is only accumulated for the "life" of the nonlinear - solver object; the counter is reset whenever a new nonlinear solver - module is "attached" to MRIStep, or when MRIStep is resized. + This is only accumulated for the "life" of the nonlinear + solver object; the counter is reset whenever a new nonlinear solver + module is "attached" to MRIStep, or when MRIStep is resized. .. deprecated:: 6.1.0 @@ -2067,21 +1885,17 @@ Implicit solver optional output functions Returns the number of nonlinear solver convergence failures that have occurred (so far). - **Arguments:** - - * *arkode_mem* -- pointer to the MRIStep memory block. + :param arkode_mem: pointer to the MRIStep memory block. + :param nncfails: number of nonlinear convergence failures. - * *nncfails* -- number of nonlinear convergence failures. + :retval ARK_SUCCESS: if successful + :retval ARK_MEM_NULL: if the MRIStep memory was ``NULL`` - **Return value:** - - * *ARK_SUCCESS* if successful - - * *ARK_MEM_NULL* if the MRIStep memory was ``NULL`` + .. note:: - **Notes:** This is only accumulated for the "life" of the nonlinear - solver object; the counter is reset whenever a new nonlinear solver - module is "attached" to MRIStep, or when MRIStep is resized. + This is only accumulated for the "life" of the nonlinear + solver object; the counter is reset whenever a new nonlinear solver + module is "attached" to MRIStep, or when MRIStep is resized. .. deprecated:: 6.1.0 @@ -2093,25 +1907,19 @@ Implicit solver optional output functions Returns all of the nonlinear solver statistics in a single call. - **Arguments:** - - * *arkode_mem* -- pointer to the MRIStep memory block. - - * *nniters* -- number of nonlinear iterations performed. + :param arkode_mem: pointer to the MRIStep memory block. + :param nniters: number of nonlinear iterations performed. + :param nncfails: number of nonlinear convergence failures. - * *nncfails* -- number of nonlinear convergence failures. + :retval ARK_SUCCESS: if successful + :retval ARK_MEM_NULL: if the MRIStep memory was ``NULL`` + :retval ARK_NLS_OP_ERR: if the SUNNONLINSOL object returned a failure flag - **Return value:** - - * *ARK_SUCCESS* if successful - - * *ARK_MEM_NULL* if the MRIStep memory was ``NULL`` - - * *ARK_NLS_OP_ERR* if the SUNNONLINSOL object returned a failure flag + .. note:: - **Notes:** These are only accumulated for the "life" of the - nonlinear solver object; the counters are reset whenever a new - nonlinear solver module is "attached" to MRIStep, or when MRIStep is resized. + These are only accumulated for the "life" of the + nonlinear solver object; the counters are reset whenever a new + nonlinear solver module is "attached" to MRIStep, or when MRIStep is resized. .. deprecated:: 6.1.0 @@ -2129,26 +1937,26 @@ Rootfinding optional output functions Returns an array showing which functions were found to have a root. - **Arguments:** - * *arkode_mem* -- pointer to the MRIStep memory block. - * *rootsfound* -- array of length *nrtfn* with the indices of the - user functions :math:`g_i` found to have a root (the value of - *nrtfn* was supplied in the call to - :c:func:`MRIStepRootInit()`). For :math:`i = 0 \ldots` - *nrtfn*-1, ``rootsfound[i]`` is nonzero if :math:`g_i` has a - root, and 0 if not. + :param arkode_mem: pointer to the MRIStep memory block. + :param rootsfound: array of length *nrtfn* with the indices of the + user functions :math:`g_i` found to have a root (the value of + *nrtfn* was supplied in the call to + :c:func:`MRIStepRootInit()`). For :math:`i = 0 \ldots` + *nrtfn*-1, ``rootsfound[i]`` is nonzero if :math:`g_i` has a + root, and 0 if not. - **Return value:** - * *ARK_SUCCESS* if successful - * *ARK_MEM_NULL* if the MRIStep memory was ``NULL`` + :retval ARK_SUCCESS: if successful + :retval ARK_MEM_NULL: if the MRIStep memory was ``NULL`` - **Notes:** The user must allocate space for *rootsfound* prior to - calling this function. + .. note:: + + The user must allocate space for *rootsfound* prior to + calling this function. - For the components of :math:`g_i` for which a root was found, the - sign of ``rootsfound[i]`` indicates the direction of - zero-crossing. A value of +1 indicates that :math:`g_i` is - increasing, while a value of -1 indicates a decreasing :math:`g_i`. + For the components of :math:`g_i` for which a root was found, the + sign of ``rootsfound[i]`` indicates the direction of + zero-crossing. A value of +1 indicates that :math:`g_i` is + increasing, while a value of -1 indicates a decreasing :math:`g_i`. .. deprecated:: 6.1.0 @@ -2161,13 +1969,11 @@ Rootfinding optional output functions Returns the cumulative number of calls made to the user's root function :math:`g`. - **Arguments:** - * *arkode_mem* -- pointer to the MRIStep memory block. - * *ngevals* -- number of calls made to :math:`g` so far. + :param arkode_mem: pointer to the MRIStep memory block. + :param ngevals: number of calls made to :math:`g` so far. - **Return value:** - * *ARK_SUCCESS* if successful - * *ARK_MEM_NULL* if the MRIStep memory was ``NULL`` + :retval ARK_SUCCESS: if successful + :retval ARK_MEM_NULL: if the MRIStep memory was ``NULL`` .. deprecated:: 6.1.0 @@ -2241,30 +2047,24 @@ Linear solver interface optional output functions Returns the real and integer workspace used by the ARKLS linear solver interface. - **Arguments:** - - * *arkode_mem* -- pointer to the MRIStep memory block. - - * *lenrwLS* -- the number of ``sunrealtype`` values in the ARKLS workspace. - - * *leniwLS* -- the number of integer values in the ARKLS workspace. + :param arkode_mem: pointer to the MRIStep memory block. + :param lenrwLS: the number of ``realtype`` values in the ARKLS workspace. + :param leniwLS: the number of integer values in the ARKLS workspace. - **Return value:** + :retval ARKLS_SUCCESS: if successful + :retval ARKLS_MEM_NULL: if the MRIStep memory was ``NULL`` + :retval ARKLS_LMEM_NULL: if the linear solver memory was ``NULL`` - * *ARKLS_SUCCESS* if successful - - * *ARKLS_MEM_NULL* if the MRIStep memory was ``NULL`` - - * *ARKLS_LMEM_NULL* if the linear solver memory was ``NULL`` + .. note:: - **Notes:** The workspace requirements reported by this routine - correspond only to memory allocated within this interface and to - memory allocated by the ``SUNLinearSolver`` object attached - to it. The template Jacobian matrix allocated by the user outside - of ARKLS is not included in this report. + The workspace requirements reported by this routine + correspond only to memory allocated within this interface and to + memory allocated by the ``SUNLinearSolver`` object attached + to it. The template Jacobian matrix allocated by the user outside + of ARKLS is not included in this report. - In a parallel setting, the above values are global (i.e., summed over all - processors). + In a parallel setting, the above values are global (i.e., summed over all + processors). .. deprecated:: 6.1.0 @@ -2275,23 +2075,18 @@ Linear solver interface optional output functions Returns the number of Jacobian evaluations. - **Arguments:** - - * *arkode_mem* -- pointer to the MRIStep memory block. - - * *njevals* -- number of Jacobian evaluations. + :param arkode_mem: pointer to the MRIStep memory block. + :param njevals: number of Jacobian evaluations. - **Return value:** + :retval ARKLS_SUCCESS: if successful + :retval ARKLS_MEM_NULL: if the MRIStep memory was ``NULL`` + :retval ARKLS_LMEM_NULL: if the linear solver memory was ``NULL`` - * *ARKLS_SUCCESS* if successful - - * *ARKLS_MEM_NULL* if the MRIStep memory was ``NULL`` - - * *ARKLS_LMEM_NULL* if the linear solver memory was ``NULL`` + .. note:: - **Notes:** This is only accumulated for the "life" of the linear - solver object; the counter is reset whenever a new linear solver - module is "attached" to MRIStep, or when MRIStep is resized. + This is only accumulated for the "life" of the linear + solver object; the counter is reset whenever a new linear solver + module is "attached" to MRIStep, or when MRIStep is resized. .. deprecated:: 6.1.0 @@ -2304,23 +2099,18 @@ Linear solver interface optional output functions i.e., the number of calls made to *psetup* with ``jok`` = ``SUNFALSE`` and that returned ``*jcurPtr`` = ``SUNTRUE``. - **Arguments:** - - * *arkode_mem* -- pointer to the MRIStep memory block. - - * *npevals* -- the current number of calls to *psetup*. + :param arkode_mem: pointer to the MRIStep memory block. + :param npevals: the current number of calls to *psetup*. - **Return value:** + :retval ARKLS_SUCCESS: if successful + :retval ARKLS_MEM_NULL: if the MRIStep memory was ``NULL`` + :retval ARKLS_LMEM_NULL: if the linear solver memory was ``NULL`` - * *ARKLS_SUCCESS* if successful - - * *ARKLS_MEM_NULL* if the MRIStep memory was ``NULL`` - - * *ARKLS_LMEM_NULL* if the linear solver memory was ``NULL`` + .. note:: - **Notes:** This is only accumulated for the "life" of the linear - solver object; the counter is reset whenever a new linear solver - module is "attached" to MRIStep, or when MRIStep is resized. + This is only accumulated for the "life" of the linear + solver object; the counter is reset whenever a new linear solver + module is "attached" to MRIStep, or when MRIStep is resized. .. deprecated:: 6.1.0 @@ -2332,23 +2122,18 @@ Linear solver interface optional output functions Returns the number of calls made to the preconditioner solve function, *psolve*. - **Arguments:** - - * *arkode_mem* -- pointer to the MRIStep memory block. + :param arkode_mem: pointer to the MRIStep memory block. + :param npsolves: the number of calls to *psolve*. - * *npsolves* -- the number of calls to *psolve*. + :retval ARKLS_SUCCESS: if successful + :retval ARKLS_MEM_NULL: if the MRIStep memory was ``NULL`` + :retval ARKLS_LMEM_NULL: if the linear solver memory was ``NULL`` - **Return value:** - - * *ARKLS_SUCCESS* if successful - - * *ARKLS_MEM_NULL* if the MRIStep memory was ``NULL`` - - * *ARKLS_LMEM_NULL* if the linear solver memory was ``NULL`` + .. note:: - **Notes:** This is only accumulated for the "life" of the linear - solver object; the counter is reset whenever a new linear solver - module is "attached" to MRIStep, or when MRIStep is resized. + This is only accumulated for the "life" of the linear + solver object; the counter is reset whenever a new linear solver + module is "attached" to MRIStep, or when MRIStep is resized. .. deprecated:: 6.1.0 @@ -2359,23 +2144,18 @@ Linear solver interface optional output functions Returns the cumulative number of linear iterations. - **Arguments:** - - * *arkode_mem* -- pointer to the MRIStep memory block. + :param arkode_mem: pointer to the MRIStep memory block. + :param nliters: the current number of linear iterations. - * *nliters* -- the current number of linear iterations. + :retval ARKLS_SUCCESS: if successful + :retval ARKLS_MEM_NULL: if the MRIStep memory was ``NULL`` + :retval ARKLS_LMEM_NULL: if the linear solver memory was ``NULL`` - **Return value:** - - * *ARKLS_SUCCESS* if successful - - * *ARKLS_MEM_NULL* if the MRIStep memory was ``NULL`` - - * *ARKLS_LMEM_NULL* if the linear solver memory was ``NULL`` + .. note:: - **Notes:** This is only accumulated for the "life" of the linear - solver object; the counter is reset whenever a new linear solver - module is "attached" to MRIStep, or when MRIStep is resized. + This is only accumulated for the "life" of the linear + solver object; the counter is reset whenever a new linear solver + module is "attached" to MRIStep, or when MRIStep is resized. .. deprecated:: 6.1.0 @@ -2386,23 +2166,18 @@ Linear solver interface optional output functions Returns the cumulative number of linear convergence failures. - **Arguments:** - - * *arkode_mem* -- pointer to the MRIStep memory block. + :param arkode_mem: pointer to the MRIStep memory block. + :param nlcfails: the current number of linear convergence failures. - * *nlcfails* -- the current number of linear convergence failures. + :retval ARKLS_SUCCESS: if successful + :retval ARKLS_MEM_NULL: if the MRIStep memory was ``NULL`` + :retval ARKLS_LMEM_NULL: if the linear solver memory was ``NULL`` - **Return value:** - - * *ARKLS_SUCCESS* if successful - - * *ARKLS_MEM_NULL* if the MRIStep memory was ``NULL`` - - * *ARKLS_LMEM_NULL* if the linear solver memory was ``NULL`` + .. note:: - **Notes:** This is only accumulated for the "life" of the linear - solver object; the counter is reset whenever a new linear solver - module is "attached" to MRIStep, or when MRIStep is resized. + This is only accumulated for the "life" of the linear + solver object; the counter is reset whenever a new linear solver + module is "attached" to MRIStep, or when MRIStep is resized. .. deprecated:: 6.1.0 @@ -2414,23 +2189,18 @@ Linear solver interface optional output functions Returns the cumulative number of calls made to the user-supplied Jacobian-vector setup function, *jtsetup*. - **Arguments:** - - * *arkode_mem* -- pointer to the MRIStep memory block. + :param arkode_mem: pointer to the MRIStep memory block. + :param njtsetup: the current number of calls to *jtsetup*. - * *njtsetup* -- the current number of calls to *jtsetup*. + :retval ARKLS_SUCCESS: if successful + :retval ARKLS_MEM_NULL: if the MRIStep memory was ``NULL`` + :retval ARKLS_LMEM_NULL: if the linear solver memory was ``NULL`` - **Return value:** - - * *ARKLS_SUCCESS* if successful - - * *ARKLS_MEM_NULL* if the MRIStep memory was ``NULL`` - - * *ARKLS_LMEM_NULL* if the linear solver memory was ``NULL`` + .. note:: - **Notes:** This is only accumulated for the "life" of the linear - solver object; the counter is reset whenever a new linear solver - module is "attached" to MRIStep, or when MRIStep is resized. + This is only accumulated for the "life" of the linear + solver object; the counter is reset whenever a new linear solver + module is "attached" to MRIStep, or when MRIStep is resized. .. deprecated:: 6.1.0 @@ -2442,23 +2212,18 @@ Linear solver interface optional output functions Returns the cumulative number of calls made to the Jacobian-vector product function, *jtimes*. - **Arguments:** - - * *arkode_mem* -- pointer to the MRIStep memory block. + :param arkode_mem: pointer to the MRIStep memory block. + :param njvevals: the current number of calls to *jtimes*. - * *njvevals* -- the current number of calls to *jtimes*. + :retval ARKLS_SUCCESS: if successful + :retval ARKLS_MEM_NULL: if the MRIStep memory was ``NULL`` + :retval ARKLS_LMEM_NULL: if the linear solver memory was ``NULL`` - **Return value:** - - * *ARKLS_SUCCESS* if successful - - * *ARKLS_MEM_NULL* if the MRIStep memory was ``NULL`` - - * *ARKLS_LMEM_NULL* if the linear solver memory was ``NULL`` + .. note:: - **Notes:** This is only accumulated for the "life" of the linear - solver object; the counter is reset whenever a new linear solver - module is "attached" to MRIStep, or when MRIStep is resized. + This is only accumulated for the "life" of the linear + solver object; the counter is reset whenever a new linear solver + module is "attached" to MRIStep, or when MRIStep is resized. .. deprecated:: 6.1.0 @@ -2471,27 +2236,22 @@ Linear solver interface optional output functions right-hand side function :math:`f^I` for finite difference Jacobian or Jacobian-vector product approximation. - **Arguments:** - - * *arkode_mem* -- pointer to the MRIStep memory block. + :param arkode_mem: pointer to the MRIStep memory block. + :param nfevalsLS: the number of calls to the user implicit + right-hand side function. - * *nfevalsLS* -- the number of calls to the user implicit - right-hand side function. + :retval ARKLS_SUCCESS: if successful + :retval ARKLS_MEM_NULL: if the MRIStep memory was ``NULL`` + :retval ARKLS_LMEM_NULL: if the linear solver memory was ``NULL`` - **Return value:** - - * *ARKLS_SUCCESS* if successful - - * *ARKLS_MEM_NULL* if the MRIStep memory was ``NULL`` - - * *ARKLS_LMEM_NULL* if the linear solver memory was ``NULL`` + .. note:: - **Notes:** The value *nfevalsLS* is incremented only if the default - internal difference quotient function is used. + The value *nfevalsLS* is incremented only if the default + internal difference quotient function is used. - This is only accumulated for the "life" of the linear - solver object; the counter is reset whenever a new linear solver - module is "attached" to MRIStep, or when MRIStep is resized. + This is only accumulated for the "life" of the linear + solver object; the counter is reset whenever a new linear solver + module is "attached" to MRIStep, or when MRIStep is resized. .. deprecated:: 6.1.0 @@ -2502,55 +2262,58 @@ Linear solver interface optional output functions Returns the last return value from an ARKLS routine. - **Arguments:** + :param arkode_mem: pointer to the MRIStep memory block. + :param lsflag: the value of the last return flag from an + ARKLS function. - * *arkode_mem* -- pointer to the MRIStep memory block. + :retval ARKLS_SUCCESS: if successful + :retval ARKLS_MEM_NULL: if the MRIStep memory was ``NULL`` + :retval ARKLS_LMEM_NULL: if the linear solver memory was ``NULL`` - * *lsflag* -- the value of the last return flag from an - ARKLS function. + .. note:: - **Return value:** + If the ARKLS setup function failed when using the + ``SUNLINSOL_DENSE`` or ``SUNLINSOL_BAND`` modules, then the value + of *lsflag* is equal to the column index (numbered from one) at + which a zero diagonal element was encountered during the LU + factorization of the (dense or banded) Jacobian matrix. For all + other failures, *lsflag* is negative. - * *ARKLS_SUCCESS* if successful + Otherwise, if the ARKLS setup function failed + (:c:func:`MRIStepEvolve()` returned *ARK_LSETUP_FAIL*), then + *lsflag* will be *SUNLS_PSET_FAIL_UNREC*, *SUNLS_ASET_FAIL_UNREC* + or *SUNLS_PACKAGE_FAIL_UNREC*. - * *ARKLS_MEM_NULL* if the MRIStep memory was ``NULL`` + If the ARKLS solve function failed (:c:func:`MRIStepEvolve()` + returned *ARK_LSOLVE_FAIL*), then *lsflag* contains the error + return flag from the ``SUNLinearSolver`` object, which will + be one of: - * *ARKLS_LMEM_NULL* if the linear solver memory was ``NULL`` + * *SUNLS_MEM_NULL*, indicating that the ``SUNLinearSolver`` + memory is ``NULL``; - **Notes:** If the ARKLS setup function failed when using the - ``SUNLINSOL_DENSE`` or ``SUNLINSOL_BAND`` modules, then the value - of *lsflag* is equal to the column index (numbered from one) at - which a zero diagonal element was encountered during the LU - factorization of the (dense or banded) Jacobian matrix. For all - other failures, *lsflag* is negative. + * *SUNLS_ATIMES_NULL*, indicating that a matrix-free iterative solver + was provided, but is missing a routine for the matrix-vector product + approximation, - Otherwise, if the ARKLS setup function failed - (:c:func:`MRIStepEvolve()` returned *ARK_LSETUP_FAIL*), then - *lsflag* will be *SUNLS_PSET_FAIL_UNREC*, *SUNLS_ASET_FAIL_UNREC* - or *SUN_ERR_EXT_FAIL*. + * *SUNLS_ATIMES_FAIL_UNREC*, indicating an unrecoverable failure in + the :math:`Jv` function; - If the ARKLS solve function failed (:c:func:`MRIStepEvolve()` - returned *ARK_LSOLVE_FAIL*), then *lsflag* contains the error - return flag from the ``SUNLinearSolver`` object, which will - be one of: - *SUN_ERR_ARG_CORRUPTRRUPT*, indicating that the ``SUNLinearSolver`` - memory is ``NULL``; - *SUNLS_ATIMES_NULL*, indicating that a matrix-free iterative solver - was provided, but is missing a routine for the matrix-vector product - approximation, - *SUNLS_ATIMES_FAIL_UNREC*, indicating an unrecoverable failure in - the :math:`Jv` function; - *SUNLS_PSOLVE_NULL*, indicating that an iterative linear solver was - configured to use preconditioning, but no preconditioner solve - routine was provided, - *SUNLS_PSOLVE_FAIL_UNREC*, indicating that the preconditioner solve - function failed unrecoverably; - *SUNLS_GS_FAIL*, indicating a failure in the Gram-Schmidt procedure - (SPGMR and SPFGMR only); - *SUNLS_QRSOL_FAIL*, indicating that the matrix :math:`R` was found - to be singular during the QR solve phase (SPGMR and SPFGMR only); or - *SUN_ERR_EXT_FAIL*, indicating an unrecoverable failure in - an external iterative linear solver package. + * *SUNLS_PSOLVE_NULL*, indicating that an iterative linear solver was + configured to use preconditioning, but no preconditioner solve + routine was provided, + + * *SUNLS_PSOLVE_FAIL_UNREC*, indicating that the preconditioner solve + function failed unrecoverably; + + * *SUNLS_GS_FAIL*, indicating a failure in the Gram-Schmidt procedure + (SPGMR and SPFGMR only); + + * *SUNLS_QRSOL_FAIL*, indicating that the matrix :math:`R` was found + to be singular during the QR solve phase (SPGMR and SPFGMR only); or + + * *SUNLS_PACKAGE_FAIL_UNREC*, indicating an unrecoverable failure in + an external iterative linear solver package. .. deprecated:: 6.1.0 @@ -2561,14 +2324,13 @@ Linear solver interface optional output functions Returns the name of the ARKLS constant corresponding to *lsflag*. - **Arguments:** - - * *lsflag* -- a return flag from an ARKLS function. + :param lsflag: a return flag from an ARKLS function. - **Return value:** The return value is a string containing the name of - the corresponding constant. If using the ``SUNLINSOL_DENSE`` or - ``SUNLINSOL_BAND`` modules, then if 1 :math:`\le` `lsflag` - :math:`\le n` (LU factorization failed), this routine returns "NONE". + :returns: The return value is a string containing the name of + the corresponding constant. If using the ``SUNLINSOL_DENSE`` + or ``SUNLINSOL_BAND`` modules, then if 1 :math:`\le` `lsflag` + :math:`\le n` (LU factorization failed), this routine returns + "NONE". .. deprecated:: 6.1.0 @@ -2586,24 +2348,20 @@ General usability functions Outputs all MRIStep solver parameters to the provided file pointer. - **Arguments:** + :param arkode_mem: pointer to the MRIStep memory block. + :param fp: pointer to use for printing the solver parameters. - * *arkode_mem* -- pointer to the MRIStep memory block. + :retval ARKS_SUCCESS: if successful + :retval ARKS_MEM_NULL: if the MRIStep memory was ``NULL`` - * *fp* -- pointer to use for printing the solver parameters. - - **Return value:** - - * *ARKS_SUCCESS* if successful - - * *ARKS_MEM_NULL* if the MRIStep memory was ``NULL`` + .. note:: - **Notes:** The *fp* argument can be ``stdout`` or ``stderr``, or it - may point to a specific file created using ``fopen``. + The *fp* argument can be ``stdout`` or ``stderr``, or it + may point to a specific file created using ``fopen``. - When run in parallel, only one process should set a non-NULL value - for this pointer, since parameters for all processes would be - identical. + When run in parallel, only one process should set a non-NULL value + for this pointer, since parameters for all processes would be + identical. .. deprecated:: 6.1.0 @@ -2614,24 +2372,20 @@ General usability functions Outputs the current MRI coupling table to the provided file pointer. - **Arguments:** + :param arkode_mem: pointer to the MRIStep memory block. + :param fp: pointer to use for printing the Butcher tables. - * *arkode_mem* -- pointer to the MRIStep memory block. + :retval ARK_SUCCESS: if successful + :retval ARK_MEM_NULL: if the MRIStep memory was ``NULL`` - * *fp* -- pointer to use for printing the Butcher tables. - - **Return value:** - - * *ARK_SUCCESS* if successful - - * *ARK_MEM_NULL* if the MRIStep memory was ``NULL`` + .. note:: - **Notes:** The *fp* argument can be ``stdout`` or ``stderr``, or it - may point to a specific file created using ``fopen``. + The *fp* argument can be ``stdout`` or ``stderr``, or it + may point to a specific file created using ``fopen``. - When run in parallel, only one process should set a non-NULL value - for this pointer, since tables for all processes would be - identical. + When run in parallel, only one process should set a non-NULL value + for this pointer, since tables for all processes would be + identical. .. deprecated:: 6.1.0 @@ -2687,42 +2441,32 @@ vector. Provides required problem specifications and re-initializes the MRIStep outer (slow) stepper. - **Arguments:** - - * *arkode_mem* -- pointer to the MRIStep memory block. - - * *fse* -- the name of the function (of type :c:func:`ARKRhsFn()`) - defining the explicit slow portion of the right-hand side function in - :math:`\dot{y} = f^E(t,y) + f^I(t,y) + f^F(t,y)`. - - * *fsi* -- the name of the function (of type :c:func:`ARKRhsFn()`) - defining the implicit slow portion of the right-hand side function in - :math:`\dot{y} = f^E(t,y) + f^I(t,y) + f^F(t,y)`. - - * *t0* -- the initial value of :math:`t`. - - * *y0* -- the initial condition vector :math:`y(t_0)`. - - **Return value:** + :param arkode_mem: pointer to the MRIStep memory block. + :param fse: the name of the function (of type :c:func:`ARKRhsFn()`) + defining the explicit slow portion of the right-hand side function in + :math:`\dot{y} = f^E(t,y) + f^I(t,y) + f^F(t,y)`. + :param fsi: the name of the function (of type :c:func:`ARKRhsFn()`) + defining the implicit slow portion of the right-hand side function in + :math:`\dot{y} = f^E(t,y) + f^I(t,y) + f^F(t,y)`. + :param t0: the initial value of :math:`t`. + :param y0: the initial condition vector :math:`y(t_0)`. + + :retval ARK_SUCCESS: if successful + :retval ARK_MEM_NULL: if the MRIStep memory was ``NULL`` + :retval ARK_MEM_FAIL: if a memory allocation failed + :retval ARK_ILL_INPUT: if an argument has an illegal value. - * *ARK_SUCCESS* if successful - - * *ARK_MEM_NULL* if the MRIStep memory was ``NULL`` - - * *ARK_MEM_FAIL* if a memory allocation failed - - * *ARK_ILL_INPUT* if an argument had an illegal value. + .. note:: - **Notes:** - If the inner (fast) stepper also needs to be reinitialized, its - reinitialization function should be called before calling - :c:func:`MRIStepReInit()` to reinitialize the outer stepper. + If the inner (fast) stepper also needs to be reinitialized, its + reinitialization function should be called before calling + :c:func:`MRIStepReInit()` to reinitialize the outer stepper. - All previously set options are retained but may be updated by calling - the appropriate "Set" functions. + All previously set options are retained but may be updated by calling + the appropriate "Set" functions. - If an error occurred, :c:func:`MRIStepReInit()` also - sends an error message to the error handler function. + If an error occurred, :c:func:`MRIStepReInit()` also + sends an error message to the error handler function. @@ -2736,33 +2480,25 @@ MRIStep reset function Resets the current MRIStep outer (slow) time-stepper module state to the provided independent variable value and dependent variable vector. - **Arguments:** - - * *arkode_mem* -- pointer to the MRIStep memory block. - - * *tR* -- the value of the independent variable :math:`t`. - - * *yR* -- the value of the dependent variable vector :math:`y(t_R)`. - - **Return value:** - - * *ARK_SUCCESS* if successful + :param arkode_mem: pointer to the MRIStep memory block. + :param tR: the value of the independent variable :math:`t`. + :param yR: the value of the dependent variable vector :math:`y(t_R)`. - * *ARK_MEM_NULL* if the MRIStep memory was ``NULL`` + :retval ARK_SUCCESS: if successful + :retval ARK_MEM_NULL: if the MRIStep memory was ``NULL`` + :retval ARK_MEM_FAIL: if a memory allocation failed + :retval ARK_ILL_INPUT: if an argument has an illegal value. - * *ARK_MEM_FAIL* if a memory allocation failed - - * *ARK_ILL_INPUT* if an argument had an illegal value. + .. note:: - **Notes:** - If the inner (fast) stepper also needs to be reset, its reset function should - be called before calling :c:func:`MRIStepReset()` to reset the outer stepper. + If the inner (fast) stepper also needs to be reset, its reset function should + be called before calling :c:func:`MRIStepReset()` to reset the outer stepper. - All previously set options are retained but may be updated by calling - the appropriate "Set" functions. + All previously set options are retained but may be updated by calling + the appropriate "Set" functions. - If an error occurred, :c:func:`MRIStepReset()` also sends an error message to - the error handler function. + If an error occurred, :c:func:`MRIStepReset()` also sends an error message to + the error handler function. .. versionchanged:: 5.3.0 @@ -2776,6 +2512,7 @@ MRIStep reset function + .. _ARKODE.Usage.MRIStep.Resizing: MRIStep system resize function @@ -2785,68 +2522,58 @@ MRIStep system resize function Re-initializes MRIStep with a different state vector. - **Arguments:** - - * *arkode_mem* -- pointer to the MRIStep memory block. - - * *yR* -- the newly-sized solution vector, holding the current - dependent variable values :math:`y(t_R)`. - - * *tR* -- the current value of the independent variable - :math:`t_R` (this must be consistent with *yR*). - - * *resize* -- the user-supplied vector resize function (of type - :c:func:`ARKVecResizeFn()`. - - * *resize_data* -- the user-supplied data structure to be passed - to *resize* when modifying internal MRIStep vectors. - - **Return value:** - - * *ARK_SUCCESS* if successful + :param arkode_mem: pointer to the MRIStep memory block. + :param yR: the newly-sized solution vector, holding the current + dependent variable values :math:`y(t_R)`. + :param tR: the current value of the independent variable + :math:`t_R` (this must be consistent with *yR*). + :param resize: the user-supplied vector resize function (of type + :c:func:`ARKVecResizeFn()`. + :param resize_data: the user-supplied data structure to be passed + to *resize* when modifying internal MRIStep vectors. + + :retval ARK_SUCCESS: if successful + :retval ARK_MEM_NULL: if the MRIStep memory was ``NULL`` + :retval ARK_NO_MALLOC: if *arkode_mem* was not allocated. + :retval ARK_ILL_INPUT: if an argument has an illegal value. - * *ARK_MEM_NULL* if the MRIStep memory was ``NULL`` - - * *ARK_NO_MALLOC* if *arkode_mem* was not allocated. - - * *ARK_ILL_INPUT* if an argument had an illegal value. - - **Notes:** If an error occurred, :c:func:`MRIStepResize()` also sends an error - message to the error handler function. - - **Resizing the linear solver:** - When using any of the SUNDIALS-provided linear solver modules, the - linear solver memory structures must also be resized. At present, - none of these include a solver-specific "resize" function, so the linear - solver memory must be destroyed and re-allocated **following** each - call to :c:func:`MRIStepResize()`. Moreover, the existing ARKLS - interface should then be deleted and recreated by attaching the - updated ``SUNLinearSolver`` (and possibly ``SUNMatrix``) object(s) - through calls to :c:func:`MRIStepSetLinearSolver()`. - - If any user-supplied routines are provided to aid the linear solver - (e.g. Jacobian construction, Jacobian-vector product, - mass-matrix-vector product, preconditioning), then the corresponding - "set" routines must be called again **following** the solver - re-specification. - - **Resizing the absolute tolerance array:** - If using array-valued absolute tolerances, the absolute tolerance - vector will be invalid after the call to :c:func:`MRIStepResize()`, so - the new absolute tolerance vector should be re-set **following** each - call to :c:func:`MRIStepResize()` through a new call to - :c:func:`MRIStepSVtolerances()`. - - If scalar-valued tolerances or a tolerance function was specified - through either :c:func:`MRIStepSStolerances()` or - :c:func:`MRIStepWFtolerances()`, then these will remain valid and no - further action is necessary. - - .. note:: + .. note:: - For an example showing usage of the similar :c:func:`ARKStepResize()` - routine, see the supplied serial C example problem, - ``ark_heat1D_adapt.c``. + If an error occurred, :c:func:`MRIStepResize()` also sends an error + message to the error handler function. + + **Resizing the linear solver:** + When using any of the SUNDIALS-provided linear solver modules, the + linear solver memory structures must also be resized. At present, + none of these include a solver-specific "resize" function, so the linear + solver memory must be destroyed and re-allocated **following** each + call to :c:func:`MRIStepResize()`. Moreover, the existing ARKLS + interface should then be deleted and recreated by attaching the + updated ``SUNLinearSolver`` (and possibly ``SUNMatrix``) object(s) + through calls to :c:func:`MRIStepSetLinearSolver()`. + + If any user-supplied routines are provided to aid the linear solver + (e.g. Jacobian construction, Jacobian-vector product, + mass-matrix-vector product, preconditioning), then the corresponding + "set" routines must be called again **following** the solver + re-specification. + + **Resizing the absolute tolerance array:** + If using array-valued absolute tolerances, the absolute tolerance + vector will be invalid after the call to :c:func:`MRIStepResize()`, so + the new absolute tolerance vector should be re-set **following** each + call to :c:func:`MRIStepResize()` through a new call to + :c:func:`MRIStepSVtolerances()`. + + If scalar-valued tolerances or a tolerance function was specified + through either :c:func:`MRIStepSStolerances()` or + :c:func:`MRIStepWFtolerances()`, then these will remain valid and no + further action is necessary. + + **Example codes:** + For an example showing usage of the similar :c:func:`ARKStepResize()` + routine, see the supplied serial C example problem, + ``ark_heat1D_adapt.c``. .. deprecated:: 6.1.0 diff --git a/doc/arkode/guide/source/Usage/User_callable.rst b/doc/arkode/guide/source/Usage/User_callable.rst index d147c1560c..fc11496f61 100644 --- a/doc/arkode/guide/source/Usage/User_callable.rst +++ b/doc/arkode/guide/source/Usage/User_callable.rst @@ -790,9 +790,9 @@ the user has set a stop time (with a call to the optional input function :retval ARK_MASSSETUP_FAIL: the mass matrix solver's setup routine failed. :retval ARK_MASSSOLVE_FAIL: the mass matrix solver's solve routine failed. :retval ARK_VECTOROP_ERR: a vector operation error occurred. - :retval ARK_DOMEIG_FAIL: the dominant eigenvalue function failed. It is either + :retval ARK_DOMEIG_FAIL: the dominant eigenvalue function failed. It is either not provided or returns an illegal value. - :retval ARK_MAX_STAGE_LIMIT_FAIL: stepper failed to achieve stable results. Either + :retval ARK_MAX_STAGE_LIMIT_FAIL: stepper failed to achieve stable results. Either reduce the step size or increase the stage_max_limit .. note:: @@ -974,8 +974,8 @@ Set max number of constraint failures :c:func:`ARKodeSetMaxNumConstr Disabling interpolation will reduce the memory footprint of an integrator by two or more state vectors (depending on the interpolant type and degree) which can be beneficial when interpolation is not needed e.g., when - integrating to a final time without output in between or using ARKStep as an - explicit fast time scale integrator with MRI methods. + integrating to a final time without output in between or using a solver from + ARKODE as a fast time scale integrator with MRI methods. This routine frees any previously-allocated interpolation module, and re-creates one according to the specified argument. @@ -992,16 +992,14 @@ Set max number of constraint failures :c:func:`ARKodeSetMaxNumConstr .. versionchanged:: 6.1.0 + This function replaces stepper specific versions in ARKStep, ERKStep, + MRIStep, and SPRKStep. + Added the ``ARK_INTERP_NONE`` option to disable interpolation. Values set by a previous call to :c:func:`ARKStepSetInterpolantDegree` are no longer nullified by a call to :c:func:`ARKStepSetInterpolantType`. - .. versionadded:: 6.1.0 - - This function replaces stepper specific versions in ARKStep, ERKStep, - MRIStep, and SPRKStep. - .. c:function:: int ARKodeSetInterpolantDegree(void* arkode_mem, int degree) @@ -1418,7 +1416,7 @@ the code, is provided in :numref:`ARKODE.Mathematics.Adaptivity`. Optional input Function name Default ========================================================= ========================================== ======== Provide a :c:type:`SUNAdaptController` for ARKODE to use :c:func:`ARKodeSetAdaptController` PID -Adjust the method order used in the controller :c:func:`ERKStepSetAdaptivityAdjustment` -1 +Adjust the method order used in the controller :c:func:`ARKodeSetAdaptivityAdjustment` -1 Explicit stability safety factor :c:func:`ARKodeSetCFLFraction` 0.5 Time step error bias factor :c:func:`ARKodeSetErrorBias` 1.5 Bounds determining no change in step size :c:func:`ARKodeSetFixedStepBounds` 1.0 1.5 @@ -1428,8 +1426,10 @@ Maximum first step growth factor :c:func:`ARKodeSetMa Maximum allowed general step growth factor :c:func:`ARKodeSetMaxGrowth` 20.0 Minimum allowed step reduction factor on error test fail :c:func:`ARKodeSetMinReduction` 0.1 Time step safety factor :c:func:`ARKodeSetSafetyFactor` 0.96 -Error fails before MaxEFailGrowth takes effect :c:func:`ARKodeSetSmallNumEFails` 2 +Error fails before ``MaxEFailGrowth`` takes effect :c:func:`ARKodeSetSmallNumEFails` 2 Explicit stability function :c:func:`ARKodeSetStabilityFn` none +Set accumulated error estimation type :c:func:`ARKodeSetAccumulatedErrorType` none +Reset accumulated error :c:func:`ARKodeResetAccumulatedError` ========================================================= ========================================== ======== @@ -1439,8 +1439,7 @@ Explicit stability function :c:func:`ARKodeSetSt Sets a user-supplied time-step controller object. :param arkode_mem: pointer to the ARKODE memory block. - :param C: user-supplied time adaptivity controller. If ``NULL`` then the PID controller - will be created (see :numref:`SUNAdaptController.Soderlind`). + :param C: user-supplied time adaptivity controller. :retval ARK_SUCCESS: the function exited successfully. :retval ARK_MEM_NULL: ``arkode_mem`` was ``NULL``. @@ -1450,9 +1449,16 @@ Explicit stability function :c:func:`ARKodeSetSt .. note:: + If *C* is ``NULL`` then the PID controller will be created (see :numref:`SUNAdaptController.Soderlind`). + This is only compatible with time-stepping modules that support temporal adaptivity. - .. versionadded:: 6.1.0 + Not all time-stepping modules are compatible with all types of :c:type:`SUNAdaptController` + objects. While all steppers that support temporal adaptivity support controllers with + :c:type:`SUNAdaptController_Type` type ``SUN_ADAPTCONTROLLER_H``, only MRIStep supports + inputs with type ``SUN_ADAPTCONTROLLER_MRI_H_TOL``. + + .. versionadded:: 6.1.0 .. c:function:: int ARKodeSetAdaptivityAdjustment(void* arkode_mem, int adjust) @@ -1755,6 +1761,84 @@ Explicit stability function :c:func:`ARKodeSetSt .. versionadded:: 6.1.0 +The following routines are used to control algorithms that ARKODE can use to estimate +the accumulated temporal error over multiple time steps. While these may be informational +for users on their applications, this functionality is required when using multirate +temporal adaptivity in MRIStep via the :ref:`SUNAdaptController_MRIHTol ` +module. For time-stepping modules that compute both a solution and embedding, :math:`y_n` +and :math:`\tilde{y}_n`, these may be combined to create a vector-valued local temporal error +estimate for the current internal step, :math:`y_n - \tilde{y}_n`. These local errors may be +accumulated by ARKODE in a variety of ways, as determined by the enumerated type +:c:enum:`ARKAccumError`. In each of the cases below, the accumulation is taken over all steps +since the most recent call to either :c:func:`ARKodeSetAccumulatedErrorType` or +:c:func:`ARKodeResetAccumulatedError`. Below the set :math:`\mathcal{S}` contains +the indices of the steps since the last call to either of the aforementioned functions. +The norm is taken using the tolerance-informed error-weight vector (see +:c:func:`ARKodeGetErrWeights`), and ``reltol`` is the user-specified relative solution +tolerance. + +.. c:enum:: ARKAccumError + + The type of error accumulation that ARKODE should use. + + .. versionadded:: x.y.z + + .. c:enumerator:: ARK_ACCUMERROR_NONE + + No accumulation should be performed + + .. c:enumerator:: ARK_ACCUMERROR_MAX + + Computes :math:`\text{reltol} \max\limits_{i \in \mathcal{S}} \|y_i - \tilde{y}_i\|_{WRMS}` + + .. c:enumerator:: ARK_ACCUMERROR_SUM + + Computes :math:`\text{reltol} \sum\limits_{i \in \mathcal{S}} \|y_i - \tilde{y}_i\|_{WRMS}` + + .. c:enumerator:: ARK_ACCUMERROR_AVG + + Computes :math:`\frac{\text{reltol}}{\Delta t_{\mathcal{S}}} \sum\limits_{i \in \mathcal{S}} h_i \|y_i - \tilde{y}_i\|_{WRMS}`, + where :math:`h_i` is the step size used when computing :math:`y_i`, and + :math:`\Delta t_{\mathcal{S}}` denotes the elapsed time over which + :math:`\mathcal{S}` is taken. + + +.. c:function:: int ARKodeSetAccumulatedErrorType(void* arkode_mem, ARKAccumError accum_type) + + Sets the strategy to use for accumulating a temporal error estimate + over multiple time steps. By default, ARKODE will not accumulate any + local error estimates (i.e., the default *accum_type* is ``ARK_ACCUMERROR_NONE``). + + A non-default error accumulation strategy can be disabled by calling + :c:func:`ARKodeSetAccumulatedErrorType` with the argument ``ARK_ACCUMERROR_NONE``. + + + :param arkode_mem: pointer to the ARKODE memory block. + :param accum_type: accumulation strategy. + + :retval ARK_SUCCESS: the function exited successfully. + :retval ARK_MEM_NULL: ``arkode_mem`` was ``NULL`` + :retval ARK_STEPPER_UNSUPPORTED: temporal error estimation is not supported + by the current time-stepping module. + + .. versionadded:: x.y.z + + +.. c:function:: int ARKodeResetAccumulatedError(void* arkode_mem) + + Resets the accumulated temporal error estimate, that was triggered by a previous call to + :c:func:`ARKodeSetAccumulatedErrorType`. + + :param arkode_mem: pointer to the ARKODE memory block. + + :retval ARK_SUCCESS: the function exited successfully. + :retval ARK_MEM_NULL: ``arkode_mem`` was ``NULL`` + :retval ARK_STEPPER_UNSUPPORTED: temporal error estimation is not supported + by the current time-stepping module. + + .. versionadded:: x.y.z + + .. _ARKODE.Usage.ARKodeSolverInputTable: @@ -3175,6 +3259,7 @@ No. of failed steps due to a nonlinear solver failure :c:func:`ARKodeGetNumStep Estimated local truncation error vector :c:func:`ARKodeGetEstLocalErrors` Number of constraint test failures :c:func:`ARKodeGetNumConstrFails` Retrieve a pointer for user data :c:func:`ARKodeGetUserData` +Retrieve the accumulated temporal error estimate :c:func:`ARKodeGetAccumulatedError` ===================================================== ============================================ @@ -3425,8 +3510,8 @@ Retrieve a pointer for user data :c:func:`ARKodeGetUserDat .. c:function:: int ARKodeGetNumExpSteps(void* arkode_mem, long int* expsteps) Returns the cumulative number of stability-limited steps - taken by the solver (so far). If the combination of the maximum number of stages - and the current time step size in the LSRKStep module will not allow for a stable + taken by the solver (so far). If the combination of the maximum number of stages + and the current time step size in the LSRKStep module will not allow for a stable step, the counter also accounts for such returns. :param arkode_mem: pointer to the ARKODE memory block. @@ -3611,6 +3696,25 @@ Retrieve a pointer for user data :c:func:`ARKodeGetUserDat .. versionadded:: 6.1.0 +.. c:function:: int ARKodeGetAccumulatedError(void* arkode_mem, sunrealtype* accum_error) + + Returns the accumulated temporal error estimate. + + :param arkode_mem: pointer to the ARKODE memory block. + :param accum_error: pointer to accumulated error estimate. + + :retval ARK_SUCCESS: the function exited successfully. + :retval ARK_MEM_NULL: ``arkode_mem`` was ``NULL``. + :retval ARK_WARNING: accumulated error estimation is currently disabled. + :retval ARK_STEPPER_UNSUPPORTED: temporal error estimation is not supported + by the current time-stepping module. + + .. versionadded:: x.y.z + + + + + .. _ARKODE.Usage.ARKodeImplicitSolverOutputs: Implicit solver optional output functions @@ -4728,6 +4832,57 @@ rescale the upcoming time step by the specified factor. If a value +.. _ARKODE.Usage.MRIStepInterface: + +Using an ARKODE solver as an MRIStep "inner" solver +--------------------------------------------------- + +When using an integrator from ARKODE as the inner (fast) integrator with MRIStep, the +utility function :c:func:`ARKodeCreateMRIStepInnerStepper` should be used to +wrap the ARKODE memory block as an :c:type:`MRIStepInnerStepper`. + +.. c:function:: int ARKodeCreateMRIStepInnerStepper(void *inner_arkode_mem, MRIStepInnerStepper *stepper) + + Wraps an ARKODE integrator as an :c:type:`MRIStepInnerStepper` for use + with MRIStep. + + :param arkode_mem: pointer to the ARKODE memory block. + :param stepper: the :c:type:`MRIStepInnerStepper` object to create. + + :retval ARK_SUCCESS: the function exited successfully. + :retval ARK_MEM_FAIL: a memory allocation failed. + :retval ARK_STEPPER_UNSUPPORTED: the time-stepping module does not currently support use as an inner stepper. + + .. note:: + + Currently, ARKODE integrators based on ARKStep, ERKStep, and MRIStep + support use as an MRIStep inner stepper. + + **Example usage:** + + .. code-block:: C + + /* fast (inner) and slow (outer) ARKODE objects */ + void *inner_arkode_mem = NULL; + void *outer_arkode_mem = NULL; + + /* MRIStepInnerStepper to wrap the inner (fast) object */ + MRIStepInnerStepper stepper = NULL; + + /* create an ARKODE object, setting fast (inner) right-hand side + functions and the initial condition */ + inner_arkode_mem = *StepCreate(...); + + /* configure the inner integrator */ + retval = ARKodeSet*(inner_arkode_mem, ...); + + /* create MRIStepInnerStepper wrapper for the ARKODE integrator */ + flag = ARKodeCreateMRIStepInnerStepper(inner_arkode_mem, &stepper); + + /* create an MRIStep object, setting the slow (outer) right-hand side + functions and the initial condition */ + outer_arkode_mem = MRIStepCreate(fse, fsi, t0, y0, stepper, sunctx) + .. _ARKODE.Usage.SUNStepperInterface: Using an ARKODE solver as a SUNStepper @@ -4750,6 +4905,6 @@ block as a :c:type:`SUNStepper`. .. warning:: Currently, ``stepper`` will be equipped with an implementation for the :c:func:`SUNStepper_SetForcing` function only if ``inner_arkode_mem`` is - an ARKStep integrator. + an ARKStep, ERKStep, or MRIStep integrator. .. versionadded:: x.y.z diff --git a/doc/arkode/guide/source/sunadaptcontroller/SUNAdaptController_links.rst b/doc/arkode/guide/source/sunadaptcontroller/SUNAdaptController_links.rst index 081cb80650..9c90434a0c 100644 --- a/doc/arkode/guide/source/sunadaptcontroller/SUNAdaptController_links.rst +++ b/doc/arkode/guide/source/sunadaptcontroller/SUNAdaptController_links.rst @@ -13,3 +13,4 @@ .. include:: ../../../../shared/sunadaptcontroller/SUNAdaptController_Description.rst .. include:: ../../../../shared/sunadaptcontroller/SUNAdaptController_Soderlind.rst .. include:: ../../../../shared/sunadaptcontroller/SUNAdaptController_ImExGus.rst +.. include:: ../../../../shared/sunadaptcontroller/SUNAdaptController_MRIHTol.rst diff --git a/doc/shared/RecentChanges.rst b/doc/shared/RecentChanges.rst index c13e19c596..9885baca5a 100644 --- a/doc/shared/RecentChanges.rst +++ b/doc/shared/RecentChanges.rst @@ -45,6 +45,22 @@ The build system has been updated to utilize the CMake LAPACK imported target which should ease building SUNDIALS with LAPACK libraries that require setting specific linker flags e.g., MKL. +Added support for multirate time step adaptivity controllers, based on the +recently introduced :c:type:`SUNAdaptController` base class, to ARKODE's MRIStep module. +As a part of this, we added embeddings for existing MRI-GARK methods, as well as +support for embedded MERK and IMEX-MRI-SR methods. Added new default MRI methods +for temporally adaptive versus fixed-step runs. Added the function +:c:func:`MRIStepGetNumInnerStepperFails` to retrieve the number of recoverable +failures reported by the MRIStepInnerStepper. + +Added functionality to ARKODE to accumulate a temporal error +estimate over multiple time steps. See the routines +:c:func:`ARKodeSetAccumulatedErrorType`, :c:func:`ARKodeResetAccumulatedError`, +and :c:func:`ARKodeGetAccumulatedError` for details. + +Added a utility routine to wrap any valid ARKODE integrator for use as an MRIStep +inner stepper object, :c:func:`ARKodeCreateMRIStepInnerStepper`. + **Bug Fixes** Fixed a `bug `__ in the sparse @@ -65,6 +81,15 @@ repeatedly. Fixed compilation errors when building the Trilinos Teptra NVector with CUDA support. +Fixed loading the default IMEX-MRI method if :c:func:`ARKodeSetOrder` is used to +specify a third or fourth order method. Previously, the default second order method +was loaded in both cases. + +Fixed a bug in MRIStep where the data supplied to the Hermite interpolation module did +not include contributions from the fast right-hand side function. With this fix, users +will see one additional fast right-hand side function evaluation per slow step with the +Hermite interpolation option. + Fixed a CMake configuration issue related to aliasing an ``ALIAS`` target when using ``ENABLE_KLU=ON`` in combination with a static-only build of SuiteSparse. @@ -74,6 +99,10 @@ See details in GitHub Issue `#538 ` **Deprecation Notices** +Deprecated the ARKStep-specific utility routine for wrapping an ARKStep instance +as an MRIStep inner stepper object, :c:func:`ARKStepCreateMRIStepInnerStepper`. Use +:c:func:`ARKodeCreateMRIStepInnerStepper` instead. + The ARKODE stepper specific functions to retrieve the number of right-hand side function evaluations have been deprecated. Use :c:func:`ARKodeGetNumRhsEvals` instead. diff --git a/doc/shared/sunadaptcontroller/SUNAdaptController_Description.rst b/doc/shared/sunadaptcontroller/SUNAdaptController_Description.rst index 91e94abbf0..3407edc9f4 100644 --- a/doc/shared/sunadaptcontroller/SUNAdaptController_Description.rst +++ b/doc/shared/sunadaptcontroller/SUNAdaptController_Description.rst @@ -18,6 +18,10 @@ The SUNAdaptController API .. versionadded:: 6.7.0 +.. versionchanged:: x.y.z + + Added support multirate time step adaptivity controllers + The SUNAdaptController base class provides a common API for accuracy-based adaptivity controllers to be used by SUNDIALS integrators. These controllers estimate step sizes (among other things) such that the next step solution satisfies a desired @@ -75,10 +79,16 @@ The virtual table structure is defined as The function implementing :c:func:`SUNAdaptController_Destroy` - .. c:member:: SUNErrCode (*estimatestep)(SUNAdaptController C, sunrealtype h, int p, sunrealtype dsm, sunrealtype* hnew); + .. c:member:: SUNErrCode (*estimatestep)(SUNAdaptController C, sunrealtype h, int p, sunrealtype dsm, sunrealtype* hnew) The function implementing :c:func:`SUNAdaptController_EstimateStep` + .. c:member:: SUNErrCode (*estimatesteptol)(SUNAdaptController C, sunrealtype H, sunrealtype tolfac, int P, sunrealtype DSM, sunrealtype dsm, sunrealtype* Hnew, sunrealtype* tolfacnew) + + The function implementing :c:func:`SUNAdaptController_EstimateStepTol` + + .. versionadded:: x.y.z + .. c:member:: SUNErrCode (*reset)(SUNAdaptController C) The function implementing :c:func:`SUNAdaptController_Reset` @@ -99,6 +109,12 @@ The virtual table structure is defined as The function implementing :c:func:`SUNAdaptController_UpdateH` + .. c:member:: SUNErrCode (*updatemritol)(SUNAdaptController C, sunrealtype H, sunrealtype tolfac, sunrealtype DSM, sunrealtype dsm) + + The function implementing :c:func:`SUNAdaptController_UpdateMRIHTol` + + .. versionadded:: x.y.z + .. c:member:: SUNErrCode (*space)(SUNAdaptController C, long int *lenrw, long int *leniw) The function implementing :c:func:`SUNAdaptController_Space` @@ -128,6 +144,13 @@ following set of SUNAdaptController types: Controls a single-rate step size. +.. c:enumerator:: SUN_ADAPTCONTROLLER_MRI_H_TOL + + Controls both a slow time step and a tolerance factor to apply on the next-faster + time scale within a multirate simulation that has an arbitrary number of time scales. + + .. versionadded:: x.y.z + .. _SUNAdaptController.Description.operations: @@ -168,11 +191,6 @@ note these requirements below. Additionally, we note the behavior of the base SU :param C: the :c:type:`SUNAdaptController` object. :return: :c:type:`SUNErrCode` indicating success or failure. - Usage: - - .. code-block:: c - - retval = SUNAdaptController_DestroyEmpty(C); .. c:function:: SUNAdaptController_Type SUNAdaptController_GetType(SUNAdaptController C) @@ -182,11 +200,6 @@ note these requirements below. Additionally, we note the behavior of the base SU :param C: the :c:type:`SUNAdaptController` object. :return: :c:type:`SUNAdaptController_Type` type identifier. - Usage: - - .. code-block:: c - - SUNAdaptController_Type id = SUNAdaptController_GetType(C); .. c:function:: SUNErrCode SUNAdaptController_Destroy(SUNAdaptController C) @@ -200,11 +213,6 @@ note these requirements below. Additionally, we note the behavior of the base SU :param C: the :c:type:`SUNAdaptController` object. :return: :c:type:`SUNErrCode` indicating success or failure. - Usage: - - .. code-block:: c - - retval = SUNAdaptController_Destroy(C); .. c:function:: SUNErrCode SUNAdaptController_EstimateStep(SUNAdaptController C, sunrealtype h, int p, sunrealtype dsm, sunrealtype* hnew) @@ -219,25 +227,41 @@ note these requirements below. Additionally, we note the behavior of the base SU :param hnew: (output) the estimated step size. :return: :c:type:`SUNErrCode` indicating success or failure. - Usage: - .. code-block:: c +.. c:function:: SUNErrCode SUNAdaptController_EstimateStepTol(SUNAdaptController C, sunrealtype H, sunrealtype tolfac, int P, sunrealtype DSM, sunrealtype dsm, sunrealtype* Hnew, sunrealtype* tolfacnew) + + Estimates a slow step size and a fast tolerance multiplication factor + for two adjacent time scales within a multirate application. + + This routine is required for controllers of type :c:enumerator`SUN_ADAPTCONTROLLER_MRI_H_TOL`. + If the current time scale has relative tolerance ``rtol``, then the + next-faster time scale will be called with relative tolerance ``tolfac * rtol``. + If this is not provided by the implementation, the base class method will set + ``*Hnew = H`` and ``*tolfacnew = tolfac`` and return. + + :param C: the :c:type:`SUNAdaptController` object. + :param H: the slow step size from the previous step attempt. + :param tolfac: the current relative tolerance factor for the next-faster time scale. + :param P: the current order of accuracy for the slow time scale integration method. + :param DSM: the slow time scale local temporal estimate from the previous step attempt. + :param dsm: the fast time scale local temporal estimate from the previous step attempt. + :param Hnew: (output) the estimated slow step size. + :param tolfacnew: (output) the estimated relative tolerance factor. + :return: :c:type:`SUNErrCode` indicating success or failure. + + .. versionadded:: x.y.z - retval = SUNAdaptController_EstimateStep(C, hcur, p, dsm, &hnew); .. c:function:: SUNErrCode SUNAdaptController_Reset(SUNAdaptController C) Resets the controller to its initial state, e.g., if it stores a small number - of previous *dsm* or *h* values. + of previous ``dsm`` or ``h`` values. :param C: the :c:type:`SUNAdaptController` object. :return: :c:type:`SUNErrCode` indicating success or failure. - Usage: + .. versionadded:: x.y.z - .. code-block:: c - - retval = SUNAdaptController_Reset(C); .. c:function:: SUNErrCode SUNAdaptController_SetDefaults(SUNAdaptController C) @@ -246,11 +270,8 @@ note these requirements below. Additionally, we note the behavior of the base SU :param C: the :c:type:`SUNAdaptController` object. :return: :c:type:`SUNErrCode` indicating success or failure. - Usage: - - .. code-block:: c + .. versionadded:: x.y.z - retval = SUNAdaptController_SetDefaults(C); .. c:function:: SUNErrCode SUNAdaptController_Write(SUNAdaptController C, FILE* fptr) @@ -260,11 +281,6 @@ note these requirements below. Additionally, we note the behavior of the base SU :param fptr: the output stream to write the parameters to. :return: :c:type:`SUNErrCode` indicating success or failure. - Usage: - - .. code-block:: c - - retval = SUNAdaptController_Write(C, stdout); .. c:function:: SUNErrCode SUNAdaptController_SetErrorBias(SUNAdaptController C, sunrealtype bias) @@ -277,15 +293,10 @@ note these requirements below. Additionally, we note the behavior of the base SU the default value for the controller. :return: :c:type:`SUNErrCode` indicating success or failure. - Usage: - - .. code-block:: c - - retval = SUNAdaptController_SetErrorBias(C, 1.2); .. c:function:: SUNErrCode SUNAdaptController_UpdateH(SUNAdaptController C, sunrealtype h, sunrealtype dsm) - Notifies a controller of type SUN_ADAPTCONTROLLER_H that a successful time step + Notifies a controller of type ``SUN_ADAPTCONTROLLER_H`` that a successful time step was taken with stepsize *h* and local error factor *dsm*, indicating that these can be saved for subsequent controller functions. This is typically relevant for controllers that store a history of either step sizes or error estimates for @@ -296,11 +307,24 @@ note these requirements below. Additionally, we note the behavior of the base SU :param dsm: the successful temporal error estimate. :return: :c:type:`SUNErrCode` indicating success or failure. - Usage: - .. code-block:: c +.. c:function:: SUNErrCode SUNAdaptController_UpdateMRIHTol(SUNAdaptController C, sunrealtype H, sunrealtype tolfac, sunrealtype DSM, sunrealtype dsm) + + Notifies a controller of type :c:enumerator:`SUN_ADAPTCONTROLLER_MRI_H_TOL` that a successful time step + was taken with slow stepsize ``H`` and fast relative tolerance factor ``tolfac``, and that the + step had slow and fast local error factors ``DSM`` and ``dsm``, indicating that these can be + saved for subsequent controller functions. This is typically relevant for controllers that + store a history of either step sizes or error estimates for performing the estimation process. + + :param C: the :c:type:`SUNAdaptController` object. + :param H: the successful slow step size. + :param tolfac: the successful fast time scale relative tolerance factor. + :param DSM: the successful slow temporal error estimate. + :param dsm: the successful fast temporal error estimate. + :return: :c:type:`SUNErrCode` indicating success or failure. + + .. versionadded:: x.y.z - retval = SUNAdaptController_UpdateH(C, h, dsm); .. c:function:: SUNErrCode SUNAdaptController_Space(SUNAdaptController C, long int *lenrw, long int *leniw) @@ -315,11 +339,6 @@ note these requirements below. Additionally, we note the behavior of the base SU `long int` words. :return: :c:type:`SUNErrCode` indicating success or failure. - Usage: - - .. code-block:: c - - retval = SUNAdaptController_Space(C, &lenrw, &leniw); diff --git a/doc/shared/sunadaptcontroller/SUNAdaptController_MRIHTol.rst b/doc/shared/sunadaptcontroller/SUNAdaptController_MRIHTol.rst new file mode 100644 index 0000000000..5d1e4c4fc6 --- /dev/null +++ b/doc/shared/sunadaptcontroller/SUNAdaptController_MRIHTol.rst @@ -0,0 +1,215 @@ +.. + Programmer(s): Daniel R. Reynolds @ SMU + ---------------------------------------------------------------- + SUNDIALS Copyright Start + Copyright (c) 2002-2024, Lawrence Livermore National Security + and Southern Methodist University. + All rights reserved. + + See the top-level LICENSE and NOTICE files for details. + + SPDX-License-Identifier: BSD-3-Clause + SUNDIALS Copyright End + ---------------------------------------------------------------- + +.. _SUNAdaptController.MRIHTol: + +The SUNAdaptController_MRIHTol Module +====================================== + +.. versionadded:: x.y.z + +Mathematical motivation +----------------------- + +The MRIHTol implementation of the SUNAdaptController class, +SUNAdaptController_MRIHTol, implements a general structure for telescopic +multirate temporal control. A SUNAdaptController_MRIHTol object is constructed +using two single-rate controller objects, *HControl* and *TolControl*. The +MRIHTol controller assumes that overall solution error at a given time scale +results from two types of error: + +#. "Slow" temporal errors introduced at the current time scale, + + .. math:: + \varepsilon^S_{n} = C(t_n) \left(h_n^S\right)^{P+1}, + :label: slow_error_assumption + + where :math:`C(t)` is independent of the current time scale step size :math:`h_n^S` + but may vary in time. + +#. "Fast" errors introduced through calls to the next-fastest ("inner") solver, + :math:`\varepsilon^F_{n}`. If this inner solver is called to evolve IVPs over + time intervals :math:`[t_{0,i}, t_{F,i}]` with a relative tolerance + :math:`\text{RTOL}_n^F`, then it will result in accumulated errors over these + intervals of the form + + .. math:: + \varepsilon^F_{n} = c(t_n) h_n^S \left(\text{RTOL}_n^F\right), + + where :math:`c(t)` is independent of the tolerance or subinterval width but may vary in + time, or equivalently, + + .. math:: + \varepsilon^F_{n} = \kappa(t_n) \left(\text{tolfac}_n^F\right), + :label: inner_solver_assumption + + where :math:`\text{RTOL}_n^F = \text{RTOL}^S \text{tolfac}_n^F`, + the relative tolerance that was supplied to the current time scale + solver is :math:`\text{RTOL}^S`, and + :math:`\kappa(t_n) = c(t_n) h_n^S \text{RTOL}^S` is + independent of the relative tolerance factor, :math:`\text{tolfac}_n^F`. + +Single-rate controllers are constructed to adapt a single parameter, e.g., +:math:`\delta`, under an assumption that solution error :math:`\varepsilon` depends +asymptotically on this parameter via the form + +.. math:: + \varepsilon = \mathcal{O}(\delta^{q+1}). + +Both :eq:`slow_error_assumption` and :eq:`inner_solver_assumption` fit this form, +with control parameters :math:`h_n^S` and :math:`\text{tolfac}^F_n`, and "orders" +:math:`P` and :math:`0`, respectively. Thus an MRIHTol controller employs +*HControl* to adapt :math:`h_n^S` to control the current time scale error +:math:`\varepsilon^S_n`, and it employs *TolControl* to adapt +:math:`\text{tolfac}_n^F` to control the accumulated inner solver error +:math:`\varepsilon^F_n`. + +To avoid overly large changes in calls to the inner solver, we apply bounds on the +results from *TolControl*. If *TolControl* predicts a control parameter +:math:`\text{tolfac}'`, we obtain the eventual tolerance factor via +enforcing the following bounds: + +.. math:: + \frac{\text{tolfac}_{n}^F}{\text{tolfac}'} &\le relch_{\text{max}},\\ + \frac{\text{tolfac}'}{\text{tolfac}_{n}^F} &\le relch_{\text{max}},\\ + \text{tolfac}_{min} &\le \text{tolfac}' \le \text{tolfac}_{max}. + +The default values for these bounds are :math:`relch_{\text{max}} = 20`, +:math:`\text{tolfac}_{min} = 10^{-5}`, and :math:`\text{tolfac}_{max} = 1`. + + +Implementation +-------------- + +The SUNAdaptController_MRIHTol controller is implemented as a derived +:c:type:`SUNAdaptController` class, and its *content* field is defined by +the :c:struct:`SUNAdaptControllerContent_MRIHTol_` structure: + +.. c:struct:: SUNAdaptControllerContent_MRIHTol_ + + The member data structure for an MRIHTol controller + + .. c:member:: SUNAdaptController HControl + + A single time-scale controller to adapt the current step size, :math:`h^S_n`. + + .. c:member:: SUNAdaptController TolControl + + A single time-scale controller to adapt the inner solver relative tolerance + factor, :math:`\text{reltol}^F_n`. + + .. c:member:: sunrealtype inner_max_relch + + The parameter :math:`relch_{\text{max}}` above. + + .. c:member:: sunrealtype inner_min_tolfac + + The parameter :math:`\text{tolfac}_{min}` above. + + .. c:member:: sunrealtype inner_max_tolfac + + The parameter :math:`\text{tolfac}_{max}` above. + +The header file to be included when using this module is +``sunadaptcontroller/sunadaptcontroller_mrihtol.h``. + +The SUNAdaptController_MRIHTol class provides implementations of all operations +relevant to a :c:enumerator:`SUN_ADAPTCONTROLLER_MRI_H_TOL` controller listed in +:numref:`SUNAdaptController.Description.operations`. This class +also provides the following additional user-callable routines: + + +.. c:function:: SUNAdaptController SUNAdaptController_MRIHTol(SUNAdaptController HControl, SUNAdaptController TolControl, SUNContext sunctx) + + This constructor creates and allocates memory for a SUNAdaptController_MRIHTol + object, and inserts its default parameters. + + :param HControl: the slow time step adaptivity controller object. + :param TolControl: the inner solver tolerance factor adaptivity controller object. + :param sunctx: the current :c:type:`SUNContext` object. + + :returns: if successful, a usable :c:type:`SUNAdaptController` object; + otherwise it will return ``NULL``. + + +.. c:function:: SUNErrCode SUNAdaptController_SetParams_MRIHTol(SUNAdaptController C, sunrealtype inner_max_relch, sunrealtype inner_min_tolfac, sunrealtype inner_max_tolfac) + + This user-callable function provides control over the relevant parameters + above. This should be called *before* the time integrator is called to evolve + the problem. If any argument is outside the allowable range, that parameter + will be reset to its default value. + + :param C: the SUNAdaptController_MRIHTol object. + :param inner_max_relch: the parameter :math:`relch_{\text{max}}` (must be :math:`\ge 1`). + :param inner_min_tolfac: the parameter :math:`\text{tolfac}_{min}` (must be :math:`> 0`). + :param inner_max_tolfac: the parameter :math:`\text{tolfac}_{max}` (must be :math:`> 0` and :math:`\le 1`). + + :returns: :c:type:`SUNErrCode` indicating success or failure. + + +Usage +----- + +Since this adaptivity controller is constructed using multiple single-rate adaptivity +controllers, there are a few steps required when setting this up in an application +(the steps below in *italics* correspond to the surrounding steps described in the +:ref:`MRIStep usage skeleton `. + +#. *Create an inner stepper object to solve the fast (inner) IVP* + +#. Configure the inner stepper to use temporal adaptivity. For example, when using + an ARKODE inner stepper and the :c:func:`ARKodeCreateMRIStepInnerStepper` + function, then either use its default adaptivity approach or supply a + single-rate SUNAdaptController object, e.g. + + .. code:: C + + void* inner_arkode_mem = ERKStepCreate(f_f, T0, y, sunctx); + MRIStepInnerStepper inner_stepper = nullptr; + retval = ARKodeCreateMRIStepInnerStepper(inner_arkode_mem, &inner_stepper); + SUNAdaptController fcontrol = SUNAdaptController_PID(sunctx); + retval = ARKodeSetAdaptController(inner_arkode_mem, fcontrol); + +#. If using an ARKODE inner stepper, then set the desired temporal error accumulation + estimation strategy via a call to :c:func:`ARKodeSetAccumulatedErrorType`, e.g., + + .. code:: C + + retval = ARKodeSetAccumulatedErrorType(inner_arkode_mem, ARK_ACCUMERROR_MAX); + +#. *Create an MRIStep object for the slow (outer) integration* + +#. Create single-rate controllers for both the slow step size and inner solver + tolerance, e.g., + + .. code:: C + + SUNAdaptController scontrol_H = SUNAdaptController_PI(sunctx); + SUNAdaptController scontrol_Tol = SUNAdaptController_I(sunctx); + +#. Create the multirate controller object, e.g., + + .. code:: C + + SUNAdaptController scontrol = SUNAdaptController_MRIHTol(scontrol_H, scontrol_Tol, sunctx); + +#. Attach the multirate controller object to MRIStep, e.g., + + .. code:: C + + retval = ARKodeSetAdaptController(arkode_mem, scontrol); + +An example showing the above steps is provided in +``examples/arkode/CXX_serial/ark_kpr_nestedmri.cpp``, where multirate controller objects +are used for both the slow and intermediate time scales in a 3-time-scale simulation. diff --git a/doc/shared/sundials.bib b/doc/shared/sundials.bib index 8d3ccec6e6..bdd9f72079 100644 --- a/doc/shared/sundials.bib +++ b/doc/shared/sundials.bib @@ -1845,6 +1845,26 @@ @techreport{Fehlberg:69 year = {1969} } +@article{Fish:23, + title = {Adaptive time step control for multirate infinitesimal methods}, + volume = {45}, + doi = {10.1137/22M1479798}, + number = {2}, + journal = {SIAM Journal of Scientific Computing}, + author = {Fish, Alex C. and Reynolds, Daniel R.}, + year = {2023}, + pages = {A958--A984}, +} + +@article{Fish:24, + title = {Implicit–explicit multirate infinitesimal stage-restart methods}, + volume = {438}, + doi = {10.1016/j.cam.2023.115534}, + journal = {Journal of Computational and Applied Mathematics}, + author = {Fish, Alex C. and Reynolds, Daniel R. and Roberts, Steven B.}, + year = {2024}, + pages = {115534}, +} @article{giraldo2013implicit, title = {Implicit-explicit formulations of a three-dimensional nonhydrostatic unified model of the atmosphere (NUMA)}, @@ -1949,6 +1969,17 @@ @article{Kva:04 doi = {10.1023/B:BITN.0000046811.70614.38} } +@article{Luan:20, + title = {A new class of high-order methods for multirate differential equations}, + volume = {42}, + doi = {10.1137/19M125621X}, + number = {2}, + journal = {SIAM Journal of Scientific Computing}, + author = {Luan, Vu Thai and Chinomona, Rujeko and Reynolds, Daniel R.}, + year = {2020}, + pages = {A1245--A1268}, +} + @article{Mclachlan:92, author = {Mclachlan, Robert I AND Atela, Pau}, title = {The accuracy of symplectic integrators}, diff --git a/doc/superbuild/source/sunadaptcontroller/SUNAdaptController_links.rst b/doc/superbuild/source/sunadaptcontroller/SUNAdaptController_links.rst index 716fccb705..a3841b0376 100644 --- a/doc/superbuild/source/sunadaptcontroller/SUNAdaptController_links.rst +++ b/doc/superbuild/source/sunadaptcontroller/SUNAdaptController_links.rst @@ -13,3 +13,4 @@ .. include:: ../../../shared/sunadaptcontroller/SUNAdaptController_Description.rst .. include:: ../../../shared/sunadaptcontroller/SUNAdaptController_Soderlind.rst .. include:: ../../../shared/sunadaptcontroller/SUNAdaptController_ImExGus.rst +.. include:: ../../../shared/sunadaptcontroller/SUNAdaptController_MRIHTol.rst diff --git a/examples/arkode/CXX_parallel/ark_diffusion_reaction_p.cpp b/examples/arkode/CXX_parallel/ark_diffusion_reaction_p.cpp index 5dd2bbd43b..6b46ddd9b4 100644 --- a/examples/arkode/CXX_parallel/ark_diffusion_reaction_p.cpp +++ b/examples/arkode/CXX_parallel/ark_diffusion_reaction_p.cpp @@ -1044,8 +1044,8 @@ static int SetupMRI(SUNContext ctx, UserData* udata, N_Vector y, if (check_flag(&flag, "ARKodeSetMaxNumSteps", 1)) { return 1; } // Wrap ARKODE as an MRIStepInnerStepper - flag = ARKStepCreateMRIStepInnerStepper(inner_arkode_mem, stepper); - if (check_flag(&flag, "ARKStepCreateMRIStepInnerStepper", 1)) { return 1; } + flag = ARKodeCreateMRIStepInnerStepper(inner_arkode_mem, stepper); + if (check_flag(&flag, "ARKodeCreateMRIStepInnerStepper", 1)) { return 1; } // ------------------------- // Setup the slow integrator diff --git a/examples/arkode/CXX_parallel/ark_diffusion_reaction_p_--np_2_2_--mri-arkstep.out b/examples/arkode/CXX_parallel/ark_diffusion_reaction_p_--np_2_2_--mri-arkstep.out index ae206aafd4..2ffc7a6d53 100644 --- a/examples/arkode/CXX_parallel/ark_diffusion_reaction_p_--np_2_2_--mri-arkstep.out +++ b/examples/arkode/CXX_parallel/ark_diffusion_reaction_p_--np_2_2_--mri-arkstep.out @@ -1,23 +1,23 @@ 2D Heat PDE test problem: - --------------------------------- + --------------------------------- nprocs = 4 npx = 2 npy = 2 - --------------------------------- + --------------------------------- Dux = 0.001 Duy = 0.001 Dvx = 0.001 Dvy = 0.001 A = 1 B = 3 - --------------------------------- + --------------------------------- tf = 10 xl = -0.5 xu = 0.5 yl = -0.5 yu = 0.5 - --------------------------------- + --------------------------------- nx = 128 ny = 128 dx = 0.0078125 @@ -28,7 +28,7 @@ ie (proc 0) = 63 je (proc 0) = 0 je (proc 0) = 63 - --------------------------------- + --------------------------------- rtol_slow = 0.0001 atol_slow = 1e-08 rtol_fast = 1e-05 @@ -38,39 +38,39 @@ fixed h fast = 0 controller = 0 linear = 1 - --------------------------------- + --------------------------------- linear solver = PCG lin iters = 10 eps lin = 0 prec = 1 msbp = 0 - --------------------------------- + --------------------------------- output = 1 - --------------------------------- + --------------------------------- - t ||u||_rms + t ||u||_rms ---------------------------------------------- 0.000000000000000e+00 3.172144385112383e+00 - 5.000000000000000e-01 3.136741760652088e+00 - 1.000000000000000e+00 3.125063175301122e+00 - 1.500000000000000e+00 3.152612863029649e+00 - 2.000000000000000e+00 3.252046438757223e+00 - 2.500000000000000e+00 3.404770336275880e+00 - 3.000000000000000e+00 3.570197843463192e+00 - 3.500000000000000e+00 3.699979298705992e+00 - 4.000000000000000e+00 3.694673743577147e+00 - 4.500000000000000e+00 3.628192807357139e+00 - 5.000000000000000e+00 3.475181871691853e+00 - 5.500000000000000e+00 3.343883541753708e+00 - 6.000000000000000e+00 3.234020189727759e+00 - 6.500000000000000e+00 3.082396969215168e+00 - 7.000000000000000e+00 2.890645348225157e+00 - 7.500000000000000e+00 2.837264086636537e+00 - 8.000000000000000e+00 2.898204389104409e+00 - 8.500000000000000e+00 3.140043837970826e+00 - 9.000000000000000e+00 3.442234882231944e+00 - 9.500000000000000e+00 3.740410418605710e+00 - 1.000000000000000e+01 4.014486526389547e+00 + 5.000000000000000e-01 3.136741760652099e+00 + 1.000000000000000e+00 3.125063175301384e+00 + 1.500000000000000e+00 3.152612863412849e+00 + 2.000000000000000e+00 3.252046440476493e+00 + 2.500000000000000e+00 3.404770348632562e+00 + 3.000000000000000e+00 3.570197872739926e+00 + 3.500000000000000e+00 3.699979354348030e+00 + 4.000000000000000e+00 3.694673808835031e+00 + 4.500000000000000e+00 3.628192806293943e+00 + 5.000000000000000e+00 3.475181810897179e+00 + 5.500000000000000e+00 3.343883397076133e+00 + 6.000000000000000e+00 3.234019997282326e+00 + 6.500000000000000e+00 3.082396794749013e+00 + 7.000000000000000e+00 2.890645249288640e+00 + 7.500000000000000e+00 2.837264083079534e+00 + 8.000000000000000e+00 2.898204488519986e+00 + 8.500000000000000e+00 3.140043990739560e+00 + 9.000000000000000e+00 3.442235032838624e+00 + 9.500000000000000e+00 3.740410563929244e+00 + 1.000000000000000e+01 4.014486664210758e+00 ---------------------------------------------- Final integrator statistics: @@ -80,20 +80,20 @@ Slow Integrator: RHS diffusion = 792 NLS iters = 396 NLS fails = 0 - LS iters = 2633 - LS fails = 1 + LS iters = 2648 + LS fails = 0 LS setups = 0 - LS RHS evals = 2633 - Jv products = 2633 + LS RHS evals = 2648 + Jv products = 2648 Avg NLS iters per step attempt = 3.000000 - Avg LS iters per NLS iter = 6.648990 + Avg LS iters per NLS iter = 6.686869 Preconditioner setups = 0 - Preconditioner solves = 2633 + Preconditioner solves = 2648 Fast Integrator: Steps = 470 Step attempts = 470 Error test fails = 0 - RHS reaction = 1827 + RHS reaction = 1940 diff --git a/examples/arkode/CXX_parallel/ark_diffusion_reaction_p_--np_2_2_--mri-cvode-global.out b/examples/arkode/CXX_parallel/ark_diffusion_reaction_p_--np_2_2_--mri-cvode-global.out index 9b913a3b91..841bdda608 100644 --- a/examples/arkode/CXX_parallel/ark_diffusion_reaction_p_--np_2_2_--mri-cvode-global.out +++ b/examples/arkode/CXX_parallel/ark_diffusion_reaction_p_--np_2_2_--mri-cvode-global.out @@ -1,23 +1,23 @@ 2D Heat PDE test problem: - --------------------------------- + --------------------------------- nprocs = 4 npx = 2 npy = 2 - --------------------------------- + --------------------------------- Dux = 0.001 Duy = 0.001 Dvx = 0.001 Dvy = 0.001 A = 1 B = 3 - --------------------------------- + --------------------------------- tf = 10 xl = -0.5 xu = 0.5 yl = -0.5 yu = 0.5 - --------------------------------- + --------------------------------- nx = 128 ny = 128 dx = 0.0078125 @@ -28,7 +28,7 @@ ie (proc 0) = 63 je (proc 0) = 0 je (proc 0) = 63 - --------------------------------- + --------------------------------- rtol_slow = 0.0001 atol_slow = 1e-08 rtol_fast = 1e-05 @@ -38,39 +38,39 @@ fixed h fast = 0 controller = 0 linear = 1 - --------------------------------- + --------------------------------- linear solver = PCG lin iters = 10 eps lin = 0 prec = 1 msbp = 0 - --------------------------------- + --------------------------------- output = 1 - --------------------------------- + --------------------------------- - t ||u||_rms + t ||u||_rms ---------------------------------------------- 0.000000000000000e+00 3.172144385112383e+00 - 5.000000000000000e-01 3.136722629465066e+00 - 1.000000000000000e+00 3.125057552024107e+00 - 1.500000000000000e+00 3.152636979017849e+00 - 2.000000000000000e+00 3.252085784090209e+00 - 2.500000000000000e+00 3.404791619294692e+00 - 3.000000000000000e+00 3.570175845435155e+00 - 3.500000000000000e+00 3.699871659893790e+00 - 4.000000000000000e+00 3.694354186527817e+00 - 4.500000000000000e+00 3.627867393042675e+00 - 5.000000000000000e+00 3.474857085470333e+00 - 5.500000000000000e+00 3.343640002216235e+00 - 6.000000000000000e+00 3.233844046127573e+00 - 6.500000000000000e+00 3.082251062694890e+00 - 7.000000000000000e+00 2.890585369424727e+00 - 7.500000000000000e+00 2.837315452756403e+00 - 8.000000000000000e+00 2.898424893360023e+00 - 8.500000000000000e+00 3.140291028418674e+00 - 9.000000000000000e+00 3.442457327179101e+00 - 9.500000000000000e+00 3.740600281376645e+00 - 1.000000000000000e+01 4.014633156501281e+00 + 5.000000000000000e-01 3.136722629482694e+00 + 1.000000000000000e+00 3.125057552043193e+00 + 1.500000000000000e+00 3.152636979427879e+00 + 2.000000000000000e+00 3.252085798917689e+00 + 2.500000000000000e+00 3.404791659743048e+00 + 3.000000000000000e+00 3.570175896142432e+00 + 3.500000000000000e+00 3.699871775695501e+00 + 4.000000000000000e+00 3.694354328938385e+00 + 4.500000000000000e+00 3.627867445226587e+00 + 5.000000000000000e+00 3.474857036434463e+00 + 5.500000000000000e+00 3.343639835515735e+00 + 6.000000000000000e+00 3.233843797982778e+00 + 6.500000000000000e+00 3.082250805521703e+00 + 7.000000000000000e+00 2.890585190235564e+00 + 7.500000000000000e+00 2.837315402792927e+00 + 8.000000000000000e+00 2.898424997635716e+00 + 8.500000000000000e+00 3.140291193581129e+00 + 9.000000000000000e+00 3.442457501250356e+00 + 9.500000000000000e+00 3.740600449220181e+00 + 1.000000000000000e+01 4.014633315935895e+00 ---------------------------------------------- Final integrator statistics: @@ -80,17 +80,17 @@ Slow Integrator: RHS diffusion = 792 NLS iters = 396 NLS fails = 0 - LS iters = 2641 + LS iters = 2645 LS fails = 0 LS setups = 0 - LS RHS evals = 2641 - Jv products = 2641 + LS RHS evals = 2645 + Jv products = 2645 Avg NLS iters per step attempt = 3.000000 - Avg LS iters per NLS iter = 6.669192 + Avg LS iters per NLS iter = 6.679293 Preconditioner setups = 0 - Preconditioner solves = 2641 + Preconditioner solves = 2645 Fast Integrator: Steps = 2057 @@ -98,4 +98,3 @@ Fast Integrator: RHS reaction = 4991 NLS iters = 3803 NLS fails = 0 - diff --git a/examples/arkode/CXX_parallel/ark_diffusion_reaction_p_--np_2_2_--mri-cvode-local.out b/examples/arkode/CXX_parallel/ark_diffusion_reaction_p_--np_2_2_--mri-cvode-local.out index 0dd0389711..896e702868 100644 --- a/examples/arkode/CXX_parallel/ark_diffusion_reaction_p_--np_2_2_--mri-cvode-local.out +++ b/examples/arkode/CXX_parallel/ark_diffusion_reaction_p_--np_2_2_--mri-cvode-local.out @@ -1,23 +1,23 @@ 2D Heat PDE test problem: - --------------------------------- + --------------------------------- nprocs = 4 npx = 2 npy = 2 - --------------------------------- + --------------------------------- Dux = 0.001 Duy = 0.001 Dvx = 0.001 Dvy = 0.001 A = 1 B = 3 - --------------------------------- + --------------------------------- tf = 10 xl = -0.5 xu = 0.5 yl = -0.5 yu = 0.5 - --------------------------------- + --------------------------------- nx = 128 ny = 128 dx = 0.0078125 @@ -28,7 +28,7 @@ ie (proc 0) = 63 je (proc 0) = 0 je (proc 0) = 63 - --------------------------------- + --------------------------------- rtol_slow = 0.0001 atol_slow = 1e-08 rtol_fast = 1e-05 @@ -38,39 +38,39 @@ fixed h fast = 0 controller = 0 linear = 1 - --------------------------------- + --------------------------------- linear solver = PCG lin iters = 10 eps lin = 0 prec = 1 msbp = 0 - --------------------------------- + --------------------------------- output = 1 - --------------------------------- + --------------------------------- - t ||u||_rms + t ||u||_rms ---------------------------------------------- 0.000000000000000e+00 3.172144385112383e+00 - 5.000000000000000e-01 3.136728141568442e+00 - 1.000000000000000e+00 3.125054078969537e+00 - 1.500000000000000e+00 3.152605475501787e+00 - 2.000000000000000e+00 3.252022913428429e+00 - 2.500000000000000e+00 3.404698680378851e+00 - 3.000000000000000e+00 3.570053730764652e+00 - 3.500000000000000e+00 3.699720763396807e+00 - 4.000000000000000e+00 3.694157931241854e+00 - 4.500000000000000e+00 3.627712125668464e+00 - 5.000000000000000e+00 3.474734466021550e+00 - 5.500000000000000e+00 3.343606933034505e+00 - 6.000000000000000e+00 3.233915506336244e+00 - 6.500000000000000e+00 3.082406527906665e+00 - 7.000000000000000e+00 2.890736516064349e+00 - 7.500000000000000e+00 2.837432528460562e+00 - 8.000000000000000e+00 2.898441248595020e+00 - 8.500000000000000e+00 3.140256919387674e+00 - 9.000000000000000e+00 3.442407086782958e+00 - 9.500000000000000e+00 3.740539247767240e+00 - 1.000000000000000e+01 4.014559182371761e+00 + 5.000000000000000e-01 3.136728141568426e+00 + 1.000000000000000e+00 3.125054078969577e+00 + 1.500000000000000e+00 3.152605475502359e+00 + 2.000000000000000e+00 3.252022912635215e+00 + 2.500000000000000e+00 3.404698691374345e+00 + 3.000000000000000e+00 3.570053772321209e+00 + 3.500000000000000e+00 3.699720878679964e+00 + 4.000000000000000e+00 3.694158055925352e+00 + 4.500000000000000e+00 3.627712121494570e+00 + 5.000000000000000e+00 3.474734332229006e+00 + 5.500000000000000e+00 3.343606665593759e+00 + 6.000000000000000e+00 3.233915182257314e+00 + 6.500000000000000e+00 3.082406235095853e+00 + 7.000000000000000e+00 2.890736346480939e+00 + 7.500000000000000e+00 2.837432523592805e+00 + 8.000000000000000e+00 2.898441382813875e+00 + 8.500000000000000e+00 3.140257099040540e+00 + 9.000000000000000e+00 3.442407273754965e+00 + 9.500000000000000e+00 3.740539414769367e+00 + 1.000000000000000e+01 4.014559307692970e+00 ---------------------------------------------- Final integrator statistics: @@ -80,17 +80,17 @@ Slow Integrator: RHS diffusion = 792 NLS iters = 396 NLS fails = 0 - LS iters = 2630 + LS iters = 2625 LS fails = 0 LS setups = 0 - LS RHS evals = 2630 - Jv products = 2630 + LS RHS evals = 2625 + Jv products = 2625 Avg NLS iters per step attempt = 3.000000 - Avg LS iters per NLS iter = 6.641414 + Avg LS iters per NLS iter = 6.628788 Preconditioner setups = 0 - Preconditioner solves = 2630 + Preconditioner solves = 2625 Fast Integrator: Steps = 2002 @@ -98,4 +98,3 @@ Fast Integrator: RHS reaction = 4898 NLS iters = 3710 NLS fails = 0 - diff --git a/examples/arkode/CXX_parhyp/ark_heat2D_hypre_pfmg_mri.cpp b/examples/arkode/CXX_parhyp/ark_heat2D_hypre_pfmg_mri.cpp index ab2789c7ef..bf090c0020 100644 --- a/examples/arkode/CXX_parhyp/ark_heat2D_hypre_pfmg_mri.cpp +++ b/examples/arkode/CXX_parhyp/ark_heat2D_hypre_pfmg_mri.cpp @@ -466,8 +466,8 @@ int main(int argc, char* argv[]) if (check_flag(&flag, "ARKodeSetMaxNumSteps", 1)) { return 1; } // Create inner stepper - flag = ARKStepCreateMRIStepInnerStepper(inner_arkode_mem, &inner_stepper); - if (check_flag(&flag, "ARKStepCreateMRIStepInnerStepper", 1)) { return 1; } + flag = ARKodeCreateMRIStepInnerStepper(inner_arkode_mem, &inner_stepper); + if (check_flag(&flag, "ARKodeCreateMRIStepInnerStepper", 1)) { return 1; } // ----------------------------------------------- // Set up MRIStep slow integrator and set options diff --git a/examples/arkode/CXX_parhyp/ark_heat2D_hypre_pfmg_mri_--np_2_2.out b/examples/arkode/CXX_parhyp/ark_heat2D_hypre_pfmg_mri_--np_2_2.out index 2a91f4f2ba..6a538dcc0e 100644 --- a/examples/arkode/CXX_parhyp/ark_heat2D_hypre_pfmg_mri_--np_2_2.out +++ b/examples/arkode/CXX_parhyp/ark_heat2D_hypre_pfmg_mri_--np_2_2.out @@ -1,10 +1,10 @@ 2D Heat PDE test problem: - --------------------------------- + --------------------------------- nprocs = 4 npx = 2 npy = 2 - --------------------------------- + --------------------------------- kx = 1 ky = 1 ax = 1 @@ -19,7 +19,7 @@ nyl (proc 0) = 32 dx = 0.015873 dy = 0.015873 - --------------------------------- + --------------------------------- rtol = 1e-05 atol = 1e-10 sorder = 3 @@ -28,30 +28,30 @@ hs = 0.001 controller = 0 linear = 0 - --------------------------------- + --------------------------------- lin iters = 10 eps lins = -1 prectype = 1 msbp = 0 pfmg_relax = 2 pfmg_nrelax = 2 - --------------------------------- + --------------------------------- output = 1 - --------------------------------- + --------------------------------- - t ||u||_rms + t ||u||_rms ---------------------------------------------- 0.000000000000000e+00 3.691406249999997e-01 - 1.000000000000000e-01 5.162014241947240e-02 - 2.000000000000000e-01 7.426100187263422e-03 - 3.000000000000000e-01 1.067221316468460e-03 - 4.000000000000000e-01 1.533638016722887e-04 - 5.000000000000000e-01 2.203889954704845e-05 - 6.000000000000000e-01 3.167064268518253e-06 - 7.000000000000000e-01 4.551178805373316e-07 - 7.999999999999999e-01 6.540199603778498e-08 - 8.999999999999999e-01 9.398525782915539e-09 - 1.000000000000000e+00 1.350608880519736e-09 + 1.000000000000000e-01 5.162014241945451e-02 + 2.000000000000000e-01 7.426100187258647e-03 + 3.000000000000000e-01 1.067221316468833e-03 + 4.000000000000000e-01 1.533638016725418e-04 + 5.000000000000000e-01 2.203889954707766e-05 + 6.000000000000000e-01 3.167064268521805e-06 + 7.000000000000000e-01 4.551178805378924e-07 + 7.999999999999999e-01 6.540199603786467e-08 + 8.999999999999999e-01 9.398525782926989e-09 + 1.000000000000000e+00 1.350608880521382e-09 ---------------------------------------------- Final slow integrator statistics: @@ -75,7 +75,7 @@ Final fast integrator statistics: Steps = 3003 Step attempts = 3003 Error test fails = 0 - RHS evals = 29862 + RHS evals = 30853 NLS iters = 17842 NLS fails = 0 LS iters = 10048 @@ -89,4 +89,3 @@ Final fast integrator statistics: Preconditioner setups = 0 Preconditioner solves = 0 PFMG iters = 10603 - diff --git a/examples/arkode/CXX_serial/CMakeLists.txt b/examples/arkode/CXX_serial/CMakeLists.txt index a8bdf871af..539fd7cc72 100644 --- a/examples/arkode/CXX_serial/CMakeLists.txt +++ b/examples/arkode/CXX_serial/CMakeLists.txt @@ -35,6 +35,7 @@ set(ARKODE_examples "ark_kpr_Mt.cpp\;2 4 0 -10 0\;develop" "ark_kpr_Mt.cpp\;0 4 0 -10 1 10 1\;develop" "ark_kpr_Mt.cpp\;0 4 0 -10 0 10 1\;develop" + "ark_kpr_nestedmri.cpp\;\;exclude-single" "ark_pendulum.cpp\;\;develop") # Header files to install diff --git a/examples/arkode/CXX_serial/ark_advection_diffusion_reaction.cpp b/examples/arkode/CXX_serial/ark_advection_diffusion_reaction.cpp index 4ee2587c82..3423bc5c56 100644 --- a/examples/arkode/CXX_serial/ark_advection_diffusion_reaction.cpp +++ b/examples/arkode/CXX_serial/ark_advection_diffusion_reaction.cpp @@ -783,8 +783,8 @@ int SetupMRIARK(SUNContext ctx, UserData& udata, UserOptions& uopts, N_Vector y, if (check_flag(flag, "ARKodeSetMaxNumSteps")) { return 1; } // Wrap ARKODE as an MRIStepInnerStepper - flag = ARKStepCreateMRIStepInnerStepper(fast_arkode_mem, fast_mem); - if (check_flag(flag, "ARKStepCreateMRIStepInnerStepper")) { return 1; } + flag = ARKodeCreateMRIStepInnerStepper(fast_arkode_mem, fast_mem); + if (check_flag(flag, "ARKodeCreateMRIStepInnerStepper")) { return 1; } // ------------------------- // Setup the slow integrator diff --git a/examples/arkode/CXX_serial/ark_kpr_nestedmri.cpp b/examples/arkode/CXX_serial/ark_kpr_nestedmri.cpp new file mode 100644 index 0000000000..0a486a7a95 --- /dev/null +++ b/examples/arkode/CXX_serial/ark_kpr_nestedmri.cpp @@ -0,0 +1,2011 @@ +/* ---------------------------------------------------------------- + * Programmer(s): Daniel R. Reynolds @ SMU + * ---------------------------------------------------------------- + * SUNDIALS Copyright Start + * Copyright (c) 2002-2024, Lawrence Livermore National Security + * and Southern Methodist University. + * All rights reserved. + * + * See the top-level LICENSE and NOTICE files for details. + * + * SPDX-License-Identifier: BSD-3-Clause + * SUNDIALS Copyright End + * ---------------------------------------------------------------- + * Nested multirate nonlinear Kvaerno-Prothero-Robinson ODE test + * problem: + * + * [u]' = [ G e e ] [(u^2-p-2)/(2u)] + [ p'(t)/(2u) ] + * [v] [ e al be ] [(v^2-q-2)/(2v)] [ q'(t)/(2v) ] + * [w] [ e -be al ] [(w^2-r-2)/(2w)] [ r'(t)/(2w) ] + * + * where p(t) = 0.5*cos(t), q(t) = cos(om*t*(1+exp(-(t-2)^2))), + * and r(t) = cos(om*om*t*(1+exp(-(t-3)^2))). + * + * The first row corresponds to the slowest time scale; when an ImEx method is applied + * to this time scale, we set + * + * fsi = [ G e e ] [(u^2-p-2)/(2u)] + * [ 0 0 0 ] [(v^2-q-2)/(2v)] + * [ 0 0 0 ] [(w^2-r-2)/(2w)] + * + * fse = [ p'(t)/(2u) ] + * [ 0 ] + * [ 0 ] + * + * The second row corresponds to the intermediate time scale; when an ImEx method + * is applied to this time scale, we set + * + * fmi = [ 0 0 0 ] [(u^2-p-2)/(2u)] + * [ e al be ] [(v^2-q-2)/(2v)] + * [ 0 0 0 ] [(w^2-r-2)/(2w)] + * + * fme = [ 0 ] + * [ q'(t)/(2v) ] + * [ 0 ] + * + * The fast RHS is always just the full third row of the IVP. + * + * This problem has analytical solution given by + * u(t) = sqrt(2+p(t)), v(t) = sqrt(2+q(t)), w(t) = sqrt(2+r(t)). + * However, we use a reference solver here to assess performance + * of the local multirate adaptivity controller. + * + * This program allows a number of parameters: + * G: stiffness at slow time scale [default = -10] + * e: fast/slow coupling strength [default = 0.5] + * al,be: oscillatory coupling between v and w [default al = -1, be = 1] + * om: time-scale separation factor [default = 50] + * + * The stiffness of the slow time scale is essentially determined + * by G, for |G| > 50 it is 'stiff' and ideally suited to a + * multirate method that is implicit at the slow time scale. + * + * Coupling between the slow and faster components is determined by e, with + * coupling strength proportional to |e|. Coupling between the intermediate + * and fast components is determined by (al,be). + * + * The "intermediate" variable, v, oscillates at a frequency "om" times + * faster than u, and the "fast" variable, w, oscillates at a frequency + * "om" times faster than v. + * + * Additional input options may be used to select between various + * solver options: + * - slow fixed/initial step size: hs [default = 0.01] + * - intermediate fixed/initial step size: hm [default = 0.001] + * - fast fixed/initial step size: hf [default = 0.0001] + * - set initial adaptive step size as hs/hm/hf above: set_h0 [default 0] + * - relative solution tolerance: rtol [default = 1e-4] + * - absolute solution tolerance: atol [default = 1e-11] + * - relative solution tolerance for each fast integrator (as compared + * to next-slower integrator): fast_rtol [default = 1e-4] + * - use p (0) vs q (1) for slow and intermediate adaptivity: slow_pq [default = 0] + * - use p (0) vs q (1) for fast adaptivity: fast_pq [default = 0] + * - slow stepsize safety factor: safety [default = 0.96] + * - "slow" MRI method: mri_method [default = ARKODE_MRI_GARK_ERK45a] + * - "intermediate" MRI method: mid_method [default = ARKODE_MRI_GARK_ERK45a] + * - "fast" ERKStep method order: fast_order [default 4] + * - "slow" and "intermediate" MRI temporal adaptivity controllers: scontrol [default = 1] + * 0: no controller [fixed time steps] + * 1: I controller (as part of MRI-HTOL) + * 2: PI controller (as part of MRI-HTOL) + * 3: PID controller (as part of MRI-HTOL) + * 4: ExpGus controller (as part of MRI-HTOL) + * 5: ImpGus controller (as part of MRI-HTOL) + * 6: ImExGus controller (as part of MRI-HTOL) + * 7: I controller (alone) + * 8: PI controller (alone) + * 9: PID controller (alone) + * 10: ExpGus controller (alone) + * 11: ImpGus controller (alone) + * 12: ImExGus controller (alone) + * - "fast" ERKStep temporal adaptivity controller: fcontrol [default = 1] + * 0: no controller [fixed time steps] + * 1: I controller + * 2: PI controller + * 3: PID controller + * 4: ExpGus controller + * 5: ImpGus controller + * 6: ImExGus controller + * - "intermediate" and "fast" accumulated error type: faccum [default = 0] + * -1: no accumulation + * 0: maximum accumulation + * 1: additive accumulation + * 2: average accumulation + * - controller parameters: (k1s, k2s, k3s, k1f, k2f, k3f, + * bias, htol_relch, htol_minfac, htol_maxfac) + * slow and intermediate single-rate controllers: use k1s through k3s, + * as appropriate. fast single-rate controllers: use k1f through k3f, + * as appropriate. MRIHTol controllers: use htol_relch, htol_minfac, + * htol_maxfac. all controllers use bias. + * ** if any one of a relevant set are "-1" then the defaults are used + * + * Outputs and solution error values are printed at equal intervals + * of 0.5 and run statistics are printed at the end. + * ----------------------------------------------------------------*/ + +// Header files +#include // prototypes for ERKStep fcts., consts +#include // prototypes for MRIStep fcts., consts +#include +#include +#include // common utility functions +#include +#include +#include +#include // serial N_Vector type, fcts., macros +#include +#include +#include +#include +#include // dense linear solver +#include // dense matrix type, fcts., macros + +#if defined(SUNDIALS_EXTENDED_PRECISION) +#define ESYM "Le" +#define FSYM "Lf" +#else +#define ESYM "e" +#define FSYM "f" +#endif + +#define ZERO SUN_RCONST(0.0) +#define HALF SUN_RCONST(0.5) +#define ONE SUN_RCONST(1.0) +#define TWO SUN_RCONST(2.0) +#define THREE SUN_RCONST(3.0) + +// Problem options +struct Options +{ + // Problem parameters + sunrealtype e = SUN_RCONST(0.5); + sunrealtype G = SUN_RCONST(-10.0); + sunrealtype om = SUN_RCONST(50.0); + sunrealtype al = SUN_RCONST(-1.0); + sunrealtype be = SUN_RCONST(1.0); + + // Step sizes and tolerances + int set_h0 = 0; + sunrealtype hs = SUN_RCONST(1.0e-2); + sunrealtype hm = SUN_RCONST(1.0e-3); + sunrealtype hf = SUN_RCONST(1.0e-4); + sunrealtype rtol = SUN_RCONST(1.0e-4); + sunrealtype atol = SUN_RCONST(1.0e-11); + sunrealtype fast_rtol = SUN_RCONST(1.0e-4); + + // Method selection + std::string mri_method = "ARKODE_MRI_GARK_ERK45a"; + std::string mid_method = "ARKODE_MRI_GARK_ERK45a"; + int fast_order = 4; + int scontrol = 1; + int fcontrol = 1; + int faccum = 0; + int slow_pq = 0; + int fast_pq = 0; + + // controller parameters + sunrealtype k1s = NAN; + sunrealtype k2s = NAN; + sunrealtype k3s = NAN; + sunrealtype k1f = NAN; + sunrealtype k2f = NAN; + sunrealtype k3f = NAN; + sunrealtype bias = NAN; + sunrealtype htol_relch = NAN; + sunrealtype htol_minfac = NAN; + sunrealtype htol_maxfac = NAN; + sunrealtype slow_safety = NAN; +}; + +// User-supplied functions called by the solver +static int fse(sunrealtype t, N_Vector y, N_Vector ydot, void* user_data); +static int fsi(sunrealtype t, N_Vector y, N_Vector ydot, void* user_data); +static int fs(sunrealtype t, N_Vector y, N_Vector ydot, void* user_data); +static int fmi(sunrealtype t, N_Vector y, N_Vector ydot, void* user_data); +static int fme(sunrealtype t, N_Vector y, N_Vector ydot, void* user_data); +static int fm(sunrealtype t, N_Vector y, N_Vector ydot, void* user_data); +static int ff(sunrealtype t, N_Vector y, N_Vector ydot, void* user_data); +static int fn(sunrealtype t, N_Vector y, N_Vector ydot, void* user_data); +static int Js(sunrealtype t, N_Vector y, N_Vector fy, SUNMatrix J, + void* user_data, N_Vector tmp1, N_Vector tmp2, N_Vector tmp3); +static int Jsi(sunrealtype t, N_Vector y, N_Vector fy, SUNMatrix J, + void* user_data, N_Vector tmp1, N_Vector tmp2, N_Vector tmp3); +static int Jm(sunrealtype t, N_Vector y, N_Vector fy, SUNMatrix J, + void* user_data, N_Vector tmp1, N_Vector tmp2, N_Vector tmp3); +static int Jmi(sunrealtype t, N_Vector y, N_Vector fy, SUNMatrix J, + void* user_data, N_Vector tmp1, N_Vector tmp2, N_Vector tmp3); + +// Utility functions +static void InputHelp(); +static int ReadInputs(std::vector& args, Options& opts, + SUNContext ctx); +static void PrintSlowAdaptivity(Options opts); +static void PrintFastAdaptivity(Options opts); +static sunrealtype p(sunrealtype t, const Options& opts); +static sunrealtype q(sunrealtype t, const Options& opts); +static sunrealtype r(sunrealtype t, const Options& opts); +static sunrealtype pdot(sunrealtype t, const Options& opts); +static sunrealtype qdot(sunrealtype t, const Options& opts); +static sunrealtype rdot(sunrealtype t, const Options& opts); +static sunrealtype utrue(sunrealtype t, const Options& opts); +static sunrealtype vtrue(sunrealtype t, const Options& opts); +static sunrealtype wtrue(sunrealtype t, const Options& opts); +static int Ytrue(sunrealtype t, N_Vector y, const Options& opts); + +// Main Program +int main(int argc, char* argv[]) +{ + // SUNDIALS context object for this simulation + sundials::Context sunctx; + + // Read input options + Options opts; + std::vector args(argv + 1, argv + argc); + int flag = ReadInputs(args, opts, sunctx); + if (check_flag(flag, "ReadInputs")) return 1; + + // General problem parameters + sunrealtype T0 = SUN_RCONST(0.0); // initial time + sunrealtype Tf = SUN_RCONST(5.0); // final time + sunindextype NEQ = 3; // number of dependent vars. + int Nt = 20; // number of output times + + // Initial problem output + // While traversing these, set various function pointers, table constants, and method orders. + ARKRhsFn f_f, f_me, f_mi, f_se, f_si; + ARKLsJacFn J_s, J_m; + int retval; + sunbooleantype slowimplicit, slowimex, midimplicit, midimex; + slowimplicit = slowimex = midimplicit = midimex = SUNFALSE; + + f_mi = nullptr; + f_me = fm; + f_si = nullptr; + f_se = fs; + J_m = nullptr; + J_s = nullptr; + f_f = ff; + + if ((opts.mri_method == "ARKODE_MRI_GARK_IRK21a") || + (opts.mri_method == "ARKODE_MRI_GARK_ESDIRK34a") || + (opts.mri_method == "ARKODE_MRI_GARK_ESDIRK46a")) + { + slowimplicit = SUNTRUE; + f_se = nullptr; + f_si = fs; + J_s = Js; + } + if ((opts.mri_method == "ARKODE_IMEX_MRI_SR21") || + (opts.mri_method == "ARKODE_IMEX_MRI_SR32") || + (opts.mri_method == "ARKODE_IMEX_MRI_SR43")) + { + slowimex = SUNTRUE; + slowimplicit = SUNTRUE; + f_se = fse; + f_si = fsi; + J_s = Jsi; + } + if ((opts.mid_method == "ARKODE_MRI_GARK_IRK21a") || + (opts.mid_method == "ARKODE_MRI_GARK_ESDIRK34a") || + (opts.mid_method == "ARKODE_MRI_GARK_ESDIRK46a")) + { + midimplicit = SUNTRUE; + f_me = nullptr; + f_mi = fm; + J_m = Jm; + } + if ((opts.mid_method == "ARKODE_IMEX_MRI_SR21") || + (opts.mid_method == "ARKODE_IMEX_MRI_SR32") || + (opts.mid_method == "ARKODE_IMEX_MRI_SR43")) + { + midimex = SUNTRUE; + midimplicit = SUNTRUE; + f_me = fme; + f_mi = fmi; + J_m = Jmi; + } + std::cout + << "\nAdaptive nested multirate nonlinear Kvaerno-Prothero-Robinson test " + "problem:\n"; + std::cout << " time domain: (" << T0 << "," << Tf << "]\n"; + std::cout << " G = " << opts.G << std::endl; + std::cout << " e = " << opts.e << std::endl; + std::cout << " al = " << opts.al << std::endl; + std::cout << " be = " << opts.be << std::endl; + std::cout << " om = " << opts.om << std::endl; + std::cout << "\n Slow integrator: " << opts.mri_method; + if (slowimex) { std::cout << " (ImEx)" << std::endl; } + else if (slowimplicit) { std::cout << " (implicit)" << std::endl; } + else { std::cout << " (explicit)" << std::endl; } + std::cout << "\n Intermediate integrator: " << opts.mid_method; + if (midimex) { std::cout << " (ImEx)" << std::endl; } + else if (midimplicit) { std::cout << " (implicit)" << std::endl; } + else { std::cout << " (explicit)" << std::endl; } + PrintSlowAdaptivity(opts); + std::cout << "\n Fast order " << opts.fast_order << std::endl; + PrintFastAdaptivity(opts); + + // Create and initialize serial vectors for the solution and reference + N_Vector y = N_VNew_Serial(NEQ, sunctx); + if (check_ptr((void*)y, "N_VNew_Serial")) return 1; + N_Vector yref = N_VClone(y); + if (check_ptr((void*)yref, "N_VClone")) return 1; + + // Set initial conditions + retval = Ytrue(T0, y, opts); + if (check_flag(retval, "Ytrue")) return 1; + N_VScale(ONE, y, yref); + + // Create and configure reference solver object + void* arkode_ref = ERKStepCreate(fn, T0, yref, sunctx); + if (check_ptr((void*)arkode_ref, "ERKStepCreate")) return 1; + retval = ARKodeSetUserData(arkode_ref, (void*)&opts); + if (check_flag(retval, "ARKodeSetUserData")) return 1; + retval = ARKodeSetOrder(arkode_ref, 5); + if (check_flag(retval, "ARKodeSetOrder")) return 1; + retval = ARKodeSStolerances(arkode_ref, SUN_RCONST(1.e-10), SUN_RCONST(1.e-12)); + if (check_flag(retval, "ARKodeSStolerances")) return 1; + retval = ARKodeSetMaxNumSteps(arkode_ref, 10000000); + if (check_flag(retval, "ARKodeSetMaxNumSteps")) return (1); + + // Create and configure fast controller object + SUNAdaptController fcontrol = nullptr; + switch (opts.fcontrol) + { + case (1): + fcontrol = SUNAdaptController_I(sunctx); + if (check_ptr((void*)fcontrol, "SUNAdaptController_I")) return 1; + if (!std::isnan(opts.k1f)) + { + retval = SUNAdaptController_SetParams_I(fcontrol, opts.k1f); + if (check_flag(retval, "SUNAdaptController_SetParams_I")) return 1; + } + break; + case (2): + fcontrol = SUNAdaptController_PI(sunctx); + if (check_ptr((void*)fcontrol, "SUNAdaptController_PI")) return 1; + if (!(std::isnan(opts.k1f) || std::isnan(opts.k2f))) + { + retval = SUNAdaptController_SetParams_PI(fcontrol, opts.k1f, opts.k2f); + if (check_flag(retval, "SUNAdaptController_SetParams_PI")) return 1; + } + break; + case (3): + fcontrol = SUNAdaptController_PID(sunctx); + if (check_ptr((void*)fcontrol, "SUNAdaptController_PID")) return 1; + if (!(std::isnan(opts.k1f) || std::isnan(opts.k2f) || std::isnan(opts.k3f))) + { + retval = SUNAdaptController_SetParams_PID(fcontrol, opts.k1f, opts.k2f, + opts.k3f); + if (check_flag(retval, "SUNAdaptController_SetParams_PID")) return 1; + } + break; + case (4): + fcontrol = SUNAdaptController_ExpGus(sunctx); + if (check_ptr((void*)fcontrol, "SUNAdaptController_ExpGus")) return 1; + if (!(std::isnan(opts.k1f) || std::isnan(opts.k2f))) + { + retval = SUNAdaptController_SetParams_ExpGus(fcontrol, opts.k1f, opts.k2f); + if (check_flag(retval, "SUNAdaptController_SetParams_ExpGus")) return 1; + } + break; + case (5): + fcontrol = SUNAdaptController_ImpGus(sunctx); + if (check_ptr((void*)fcontrol, "SUNAdaptController_ImpGus")) return 1; + if (!(std::isnan(opts.k1f) || std::isnan(opts.k2f))) + { + retval = SUNAdaptController_SetParams_ImpGus(fcontrol, opts.k1f, opts.k2f); + if (check_flag(retval, "SUNAdaptController_SetParams_ImpGus")) return 1; + } + break; + case (6): + fcontrol = SUNAdaptController_ImExGus(sunctx); + if (check_ptr((void*)fcontrol, "SUNAdaptController_ImExGus")) return 1; + break; + } + if (!std::isnan(opts.bias) && (opts.fcontrol > 0)) + { + retval = SUNAdaptController_SetErrorBias(fcontrol, opts.bias); + if (check_flag(retval, "SUNAdaptController_SetErrorBias")) return 1; + } + + // Create ERKStep (fast) integrator + void* inner_arkode_mem = ERKStepCreate(f_f, T0, y, sunctx); + if (check_ptr((void*)inner_arkode_mem, "ERKStepCreate")) return 1; + retval = ARKodeSetOrder(inner_arkode_mem, opts.fast_order); + if (check_flag(retval, "ARKodeSetOrder")) return 1; + retval = ARKodeSStolerances(inner_arkode_mem, opts.fast_rtol, opts.atol); + if (check_flag(retval, "ARKodeSStolerances")) return 1; + if (opts.fcontrol != 0) + { + retval = ARKodeSetAdaptController(inner_arkode_mem, fcontrol); + if (check_flag(retval, "ARKodeSetAdaptController")) return 1; + if (opts.set_h0 != 0) + { + retval = ARKodeSetInitStep(inner_arkode_mem, opts.hf); + if (check_flag(retval, "ARKodeSetInitStep")) return 1; + } + if (opts.fast_pq == 1) + { + retval = ARKodeSetAdaptivityAdjustment(inner_arkode_mem, 0); + if (check_flag(retval, "ARKodeSetAdaptivityAdjustment")) return 1; + } + } + else + { + retval = ARKodeSetFixedStep(inner_arkode_mem, opts.hf); + if (check_flag(retval, "ARKodeSetFixedStep")) return 1; + } + ARKAccumError acc_type = ARK_ACCUMERROR_NONE; + if (opts.faccum == 0) { acc_type = ARK_ACCUMERROR_MAX; } + if (opts.faccum == 1) { acc_type = ARK_ACCUMERROR_SUM; } + if (opts.faccum == 2) { acc_type = ARK_ACCUMERROR_AVG; } + retval = ARKodeSetAccumulatedErrorType(inner_arkode_mem, acc_type); + if (check_flag(retval, "ARKodeSetAccumulatedErrorType")) return 1; + retval = ARKodeSetMaxNumSteps(inner_arkode_mem, 1000000); + if (check_flag(retval, "ARKodeSetMaxNumSteps")) return 1; + retval = ARKodeSetUserData(inner_arkode_mem, (void*)&opts); + if (check_flag(retval, "ARKodeSetUserData")) return 1; + + // Create inner stepper + MRIStepInnerStepper inner_stepper = nullptr; + retval = ARKodeCreateMRIStepInnerStepper(inner_arkode_mem, &inner_stepper); + if (check_flag(retval, "ARKodeCreateMRIStepInnerStepper")) return 1; + + // Create intermediate and slow controller objects, and select orders of accuracy as relevant + SUNAdaptController scontrol = nullptr; + SUNAdaptController scontrol_H = nullptr; + SUNAdaptController scontrol_Tol = nullptr; + SUNAdaptController mcontrol = nullptr; + SUNAdaptController mcontrol_H = nullptr; + SUNAdaptController mcontrol_Tol = nullptr; + switch (opts.scontrol) + { + case (1): + { + scontrol_H = SUNAdaptController_I(sunctx); + if (check_ptr((void*)scontrol_H, "SUNAdaptController_I (slow H)")) return 1; + scontrol_Tol = SUNAdaptController_I(sunctx); + if (check_ptr((void*)scontrol_Tol, "SUNAdaptController_I (slow Tol)")) + return 1; + mcontrol_H = SUNAdaptController_I(sunctx); + if (check_ptr((void*)mcontrol_H, "SUNAdaptController_I (mid H)")) return 1; + mcontrol_Tol = SUNAdaptController_I(sunctx); + if (check_ptr((void*)mcontrol_Tol, "SUNAdaptController_I (mid Tol)")) + return 1; + if (!std::isnan(opts.k1s)) + { + retval = SUNAdaptController_SetParams_I(scontrol_H, opts.k1s); + if (check_flag(retval, "SUNAdaptController_SetParams_I")) return 1; + retval = SUNAdaptController_SetParams_I(scontrol_Tol, opts.k1s); + if (check_flag(retval, "SUNAdaptController_SetParams_I")) return 1; + retval = SUNAdaptController_SetParams_I(mcontrol_H, opts.k1s); + if (check_flag(retval, "SUNAdaptController_SetParams_I")) return 1; + retval = SUNAdaptController_SetParams_I(mcontrol_Tol, opts.k1s); + if (check_flag(retval, "SUNAdaptController_SetParams_I")) return 1; + } + scontrol = SUNAdaptController_MRIHTol(scontrol_H, scontrol_Tol, sunctx); + if (check_ptr((void*)scontrol, "SUNAdaptController_MRIHTol")) return 1; + mcontrol = SUNAdaptController_MRIHTol(mcontrol_H, mcontrol_Tol, sunctx); + if (check_ptr((void*)mcontrol, "SUNAdaptController_MRIHTol")) return 1; + if (!(std::isnan(opts.htol_relch) || std::isnan(opts.htol_minfac) || + std::isnan(opts.htol_maxfac))) + { + retval = SUNAdaptController_SetParams_MRIHTol(scontrol, opts.htol_relch, + opts.htol_minfac, + opts.htol_maxfac); + if (check_flag(retval, "SUNAdaptController_SetParams_MRIHTol")) return 1; + retval = SUNAdaptController_SetParams_MRIHTol(mcontrol, opts.htol_relch, + opts.htol_minfac, + opts.htol_maxfac); + if (check_flag(retval, "SUNAdaptController_SetParams_MRIHTol")) return 1; + } + break; + } + case (2): + { + scontrol_H = SUNAdaptController_PI(sunctx); + if (check_ptr((void*)scontrol_H, "SUNAdaptController_PI (slow H)")) + return 1; + scontrol_Tol = SUNAdaptController_PI(sunctx); + if (check_ptr((void*)scontrol_Tol, "SUNAdaptController_PI (slow Tol)")) + return 1; + mcontrol_H = SUNAdaptController_PI(sunctx); + if (check_ptr((void*)mcontrol_H, "SUNAdaptController_PI (mid H)")) return 1; + mcontrol_Tol = SUNAdaptController_PI(sunctx); + if (check_ptr((void*)mcontrol_Tol, "SUNAdaptController_PI (mid Tol)")) + return 1; + if (!(std::isnan(opts.k1s) || std::isnan(opts.k2s))) + { + retval = SUNAdaptController_SetParams_PI(scontrol_H, opts.k1s, opts.k2s); + if (check_flag(retval, "SUNAdaptController_SetParams_PI")) return 1; + retval = SUNAdaptController_SetParams_PI(scontrol_Tol, opts.k1s, opts.k2s); + if (check_flag(retval, "SUNAdaptController_SetParams_PI")) return 1; + retval = SUNAdaptController_SetParams_PI(mcontrol_H, opts.k1s, opts.k2s); + if (check_flag(retval, "SUNAdaptController_SetParams_PI")) return 1; + retval = SUNAdaptController_SetParams_PI(mcontrol_Tol, opts.k1s, opts.k2s); + if (check_flag(retval, "SUNAdaptController_SetParams_PI")) return 1; + } + scontrol = SUNAdaptController_MRIHTol(scontrol_H, scontrol_Tol, sunctx); + if (check_ptr((void*)scontrol, "SUNAdaptController_MRIHTol")) return 1; + mcontrol = SUNAdaptController_MRIHTol(mcontrol_H, mcontrol_Tol, sunctx); + if (check_ptr((void*)mcontrol, "SUNAdaptController_MRIHTol")) return 1; + if (!(std::isnan(opts.htol_relch) || std::isnan(opts.htol_minfac) || + std::isnan(opts.htol_maxfac))) + { + retval = SUNAdaptController_SetParams_MRIHTol(scontrol, opts.htol_relch, + opts.htol_minfac, + opts.htol_maxfac); + if (check_flag(retval, "SUNAdaptController_SetParams_MRIHTol")) return 1; + retval = SUNAdaptController_SetParams_MRIHTol(mcontrol, opts.htol_relch, + opts.htol_minfac, + opts.htol_maxfac); + if (check_flag(retval, "SUNAdaptController_SetParams_MRIHTol")) return 1; + } + break; + } + case (3): + { + scontrol_H = SUNAdaptController_PID(sunctx); + if (check_ptr((void*)scontrol_H, "SUNAdaptController_PID (slow H)")) + return 1; + scontrol_Tol = SUNAdaptController_PID(sunctx); + if (check_ptr((void*)scontrol_Tol, "SUNAdaptController_PID (slow Tol)")) + return 1; + mcontrol_H = SUNAdaptController_PID(sunctx); + if (check_ptr((void*)mcontrol_H, "SUNAdaptController_PID (mid H)")) + return 1; + mcontrol_Tol = SUNAdaptController_PID(sunctx); + if (check_ptr((void*)mcontrol_Tol, "SUNAdaptController_PID (mid Tol)")) + return 1; + if (!(std::isnan(opts.k1s) || std::isnan(opts.k2s) || std::isnan(opts.k3s))) + { + retval = SUNAdaptController_SetParams_PID(scontrol_H, opts.k1s, opts.k2s, + opts.k3s); + if (check_flag(retval, "SUNAdaptController_SetParams_PID")) return 1; + retval = SUNAdaptController_SetParams_PID(scontrol_Tol, opts.k1s, + opts.k2s, opts.k3s); + if (check_flag(retval, "SUNAdaptController_SetParams_PID")) return 1; + retval = SUNAdaptController_SetParams_PID(mcontrol_H, opts.k1s, opts.k2s, + opts.k3s); + if (check_flag(retval, "SUNAdaptController_SetParams_PID")) return 1; + retval = SUNAdaptController_SetParams_PID(mcontrol_Tol, opts.k1s, + opts.k2s, opts.k3s); + if (check_flag(retval, "SUNAdaptController_SetParams_PID")) return 1; + } + scontrol = SUNAdaptController_MRIHTol(scontrol_H, scontrol_Tol, sunctx); + if (check_ptr((void*)scontrol, "SUNAdaptController_MRIHTol")) return 1; + mcontrol = SUNAdaptController_MRIHTol(mcontrol_H, mcontrol_Tol, sunctx); + if (check_ptr((void*)mcontrol, "SUNAdaptController_MRIHTol")) return 1; + if (!(std::isnan(opts.htol_relch) || std::isnan(opts.htol_minfac) || + std::isnan(opts.htol_maxfac))) + { + retval = SUNAdaptController_SetParams_MRIHTol(scontrol, opts.htol_relch, + opts.htol_minfac, + opts.htol_maxfac); + if (check_flag(retval, "SUNAdaptController_SetParams_MRIHTol")) return 1; + retval = SUNAdaptController_SetParams_MRIHTol(mcontrol, opts.htol_relch, + opts.htol_minfac, + opts.htol_maxfac); + if (check_flag(retval, "SUNAdaptController_SetParams_MRIHTol")) return 1; + } + break; + } + case (4): + { + scontrol_H = SUNAdaptController_ExpGus(sunctx); + if (check_ptr((void*)scontrol_H, "SUNAdaptController_ExpGus (slow H)")) + return 1; + scontrol_Tol = SUNAdaptController_ExpGus(sunctx); + if (check_ptr((void*)scontrol_Tol, "SUNAdaptController_ExpGus (slow Tol)")) + return 1; + mcontrol_H = SUNAdaptController_ExpGus(sunctx); + if (check_ptr((void*)mcontrol_H, "SUNAdaptController_ExpGus (mid H)")) + return 1; + mcontrol_Tol = SUNAdaptController_ExpGus(sunctx); + if (check_ptr((void*)mcontrol_Tol, "SUNAdaptController_ExpGus (mid Tol)")) + return 1; + if (!(std::isnan(opts.k1s) || std::isnan(opts.k2s))) + { + retval = SUNAdaptController_SetParams_ExpGus(scontrol_H, opts.k1s, + opts.k2s); + if (check_flag(retval, "SUNAdaptController_SetParams_ExpGus")) return 1; + retval = SUNAdaptController_SetParams_ExpGus(scontrol_Tol, opts.k1s, + opts.k2s); + if (check_flag(retval, "SUNAdaptController_SetParams_ExpGus")) return 1; + retval = SUNAdaptController_SetParams_ExpGus(mcontrol_H, opts.k1s, + opts.k2s); + if (check_flag(retval, "SUNAdaptController_SetParams_ExpGus")) return 1; + retval = SUNAdaptController_SetParams_ExpGus(mcontrol_Tol, opts.k1s, + opts.k2s); + if (check_flag(retval, "SUNAdaptController_SetParams_ExpGus")) return 1; + } + scontrol = SUNAdaptController_MRIHTol(scontrol_H, scontrol_Tol, sunctx); + if (check_ptr((void*)scontrol, "SUNAdaptController_MRIHTol")) return 1; + mcontrol = SUNAdaptController_MRIHTol(mcontrol_H, mcontrol_Tol, sunctx); + if (check_ptr((void*)mcontrol, "SUNAdaptController_MRIHTol")) return 1; + if (!(std::isnan(opts.htol_relch) || std::isnan(opts.htol_minfac) || + std::isnan(opts.htol_maxfac))) + { + retval = SUNAdaptController_SetParams_MRIHTol(scontrol, opts.htol_relch, + opts.htol_minfac, + opts.htol_maxfac); + if (check_flag(retval, "SUNAdaptController_SetParams_MRIHTol")) return 1; + retval = SUNAdaptController_SetParams_MRIHTol(mcontrol, opts.htol_relch, + opts.htol_minfac, + opts.htol_maxfac); + if (check_flag(retval, "SUNAdaptController_SetParams_MRIHTol")) return 1; + } + break; + } + case (5): + { + scontrol_H = SUNAdaptController_ImpGus(sunctx); + if (check_ptr((void*)scontrol_H, "SUNAdaptController_ImpGus (slow H)")) + return 1; + scontrol_Tol = SUNAdaptController_ImpGus(sunctx); + if (check_ptr((void*)scontrol_Tol, "SUNAdaptController_ImpGus (slow Tol)")) + return 1; + mcontrol_H = SUNAdaptController_ImpGus(sunctx); + if (check_ptr((void*)mcontrol_H, "SUNAdaptController_ImpGus (mid H)")) + return 1; + mcontrol_Tol = SUNAdaptController_ImpGus(sunctx); + if (check_ptr((void*)mcontrol_Tol, "SUNAdaptController_ImpGus (mid Tol)")) + return 1; + if (!(std::isnan(opts.k1s) || std::isnan(opts.k2s))) + { + retval = SUNAdaptController_SetParams_ImpGus(scontrol_H, opts.k1s, + opts.k2s); + if (check_flag(retval, "SUNAdaptController_SetParams_ImpGus")) return 1; + retval = SUNAdaptController_SetParams_ImpGus(scontrol_Tol, opts.k1s, + opts.k2s); + if (check_flag(retval, "SUNAdaptController_SetParams_ImpGus")) return 1; + retval = SUNAdaptController_SetParams_ImpGus(mcontrol_H, opts.k1s, + opts.k2s); + if (check_flag(retval, "SUNAdaptController_SetParams_ImpGus")) return 1; + retval = SUNAdaptController_SetParams_ImpGus(mcontrol_Tol, opts.k1s, + opts.k2s); + if (check_flag(retval, "SUNAdaptController_SetParams_ImpGus")) return 1; + } + scontrol = SUNAdaptController_MRIHTol(scontrol_H, scontrol_Tol, sunctx); + if (check_ptr((void*)scontrol, "SUNAdaptController_MRIHTol")) return 1; + mcontrol = SUNAdaptController_MRIHTol(mcontrol_H, mcontrol_Tol, sunctx); + if (check_ptr((void*)mcontrol, "SUNAdaptController_MRIHTol")) return 1; + if (!(std::isnan(opts.htol_relch) || std::isnan(opts.htol_minfac) || + std::isnan(opts.htol_maxfac))) + { + retval = SUNAdaptController_SetParams_MRIHTol(scontrol, opts.htol_relch, + opts.htol_minfac, + opts.htol_maxfac); + if (check_flag(retval, "SUNAdaptController_SetParams_MRIHTol")) return 1; + retval = SUNAdaptController_SetParams_MRIHTol(mcontrol, opts.htol_relch, + opts.htol_minfac, + opts.htol_maxfac); + if (check_flag(retval, "SUNAdaptController_SetParams_MRIHTol")) return 1; + } + break; + } + case (6): + { + scontrol_H = SUNAdaptController_ImExGus(sunctx); + if (check_ptr((void*)scontrol_H, "SUNAdaptController_ImExGus (slow H)")) + return 1; + scontrol_Tol = SUNAdaptController_ImExGus(sunctx); + if (check_ptr((void*)scontrol_Tol, "SUNAdaptController_ImExGus (slow Tol)")) + return 1; + mcontrol_H = SUNAdaptController_ImExGus(sunctx); + if (check_ptr((void*)mcontrol_H, "SUNAdaptController_ImExGus (mid H)")) + return 1; + mcontrol_Tol = SUNAdaptController_ImExGus(sunctx); + if (check_ptr((void*)mcontrol_Tol, "SUNAdaptController_ImExGus (mid Tol)")) + return 1; + scontrol = SUNAdaptController_MRIHTol(scontrol_H, scontrol_Tol, sunctx); + if (check_ptr((void*)scontrol, "SUNAdaptController_MRIHTol")) return 1; + mcontrol = SUNAdaptController_MRIHTol(scontrol_H, scontrol_Tol, sunctx); + if (check_ptr((void*)mcontrol, "SUNAdaptController_MRIHTol")) return 1; + if (!(std::isnan(opts.htol_relch) || std::isnan(opts.htol_minfac) || + std::isnan(opts.htol_maxfac))) + { + retval = SUNAdaptController_SetParams_MRIHTol(scontrol, opts.htol_relch, + opts.htol_minfac, + opts.htol_maxfac); + if (check_flag(retval, "SUNAdaptController_SetParams_MRIHTol")) return 1; + retval = SUNAdaptController_SetParams_MRIHTol(mcontrol, opts.htol_relch, + opts.htol_minfac, + opts.htol_maxfac); + if (check_flag(retval, "SUNAdaptController_SetParams_MRIHTol")) return 1; + } + break; + } + case (7): + { + scontrol = SUNAdaptController_I(sunctx); + if (check_ptr((void*)scontrol, "SUNAdaptControllerI (slow)")) return 1; + mcontrol = SUNAdaptController_I(sunctx); + if (check_ptr((void*)mcontrol, "SUNAdaptControllerI (mid)")) return 1; + if (!std::isnan(opts.k1s)) + { + retval = SUNAdaptController_SetParams_I(scontrol, opts.k1s); + if (check_flag(retval, "SUNAdaptController_SetParams_I")) return 1; + retval = SUNAdaptController_SetParams_I(mcontrol, opts.k1s); + if (check_flag(retval, "SUNAdaptController_SetParams_I")) return 1; + } + break; + } + case (8): + { + scontrol = SUNAdaptController_PI(sunctx); + if (check_ptr((void*)scontrol, "SUNAdaptController_PI (slow)")) return 1; + mcontrol = SUNAdaptController_PI(sunctx); + if (check_ptr((void*)mcontrol, "SUNAdaptController_PI (mid)")) return 1; + if (!(std::isnan(opts.k1s) || std::isnan(opts.k2s))) + { + retval = SUNAdaptController_SetParams_PI(scontrol, opts.k1s, opts.k2s); + if (check_flag(retval, "SUNAdaptController_SetParams_PI")) return 1; + retval = SUNAdaptController_SetParams_PI(mcontrol, opts.k1s, opts.k2s); + if (check_flag(retval, "SUNAdaptController_SetParams_PI")) return 1; + } + break; + } + case (9): + { + scontrol = SUNAdaptController_PID(sunctx); + if (check_ptr((void*)scontrol, "SUNAdaptController_PID (slow)")) return 1; + mcontrol = SUNAdaptController_PID(sunctx); + if (check_ptr((void*)mcontrol, "SUNAdaptController_PID (mid)")) return 1; + if (!(std::isnan(opts.k1s) || std::isnan(opts.k2s) || std::isnan(opts.k3s))) + { + retval = SUNAdaptController_SetParams_PID(scontrol, opts.k1s, opts.k2s, + opts.k3s); + if (check_flag(retval, "SUNAdaptController_SetParams_PID")) return 1; + retval = SUNAdaptController_SetParams_PID(mcontrol, opts.k1s, opts.k2s, + opts.k3s); + if (check_flag(retval, "SUNAdaptController_SetParams_PID")) return 1; + } + break; + } + case (10): + { + scontrol = SUNAdaptController_ExpGus(sunctx); + if (check_ptr((void*)scontrol, "SUNAdaptController_ExpGus (slow)")) + return 1; + mcontrol = SUNAdaptController_ExpGus(sunctx); + if (check_ptr((void*)mcontrol, "SUNAdaptController_ExpGus (mid)")) return 1; + if (!(std::isnan(opts.k1s) || std::isnan(opts.k2s))) + { + retval = SUNAdaptController_SetParams_ExpGus(scontrol, opts.k1s, opts.k2s); + if (check_flag(retval, "SUNAdaptController_SetParams_ExpGus")) return 1; + retval = SUNAdaptController_SetParams_ExpGus(mcontrol, opts.k1s, opts.k2s); + if (check_flag(retval, "SUNAdaptController_SetParams_ExpGus")) return 1; + } + break; + } + case (11): + { + scontrol = SUNAdaptController_ImpGus(sunctx); + if (check_ptr((void*)scontrol, "SUNAdaptController_ImpGus (slow)")) + return 1; + mcontrol = SUNAdaptController_ImpGus(sunctx); + if (check_ptr((void*)mcontrol, "SUNAdaptController_ImpGus (mid)")) return 1; + if (!(std::isnan(opts.k1s) || std::isnan(opts.k2s))) + { + retval = SUNAdaptController_SetParams_ImpGus(scontrol, opts.k1s, opts.k2s); + if (check_flag(retval, "SUNAdaptController_SetParams_ImpGus")) return 1; + retval = SUNAdaptController_SetParams_ImpGus(mcontrol, opts.k1s, opts.k2s); + if (check_flag(retval, "SUNAdaptController_SetParams_ImpGus")) return 1; + } + break; + } + case (12): + { + scontrol = SUNAdaptController_ImExGus(sunctx); + if (check_ptr((void*)scontrol, "SUNAdaptController_ImExGus (slow)")) + return 1; + mcontrol = SUNAdaptController_ImExGus(sunctx); + if (check_ptr((void*)scontrol, "SUNAdaptController_ImExGus (mid)")) + return 1; + break; + } + } + if (!std::isnan(opts.bias) && (opts.scontrol > 0)) + { + retval = SUNAdaptController_SetErrorBias(scontrol, opts.bias); + if (check_flag(retval, "SUNAdaptController_SetErrorBias")) return 1; + retval = SUNAdaptController_SetErrorBias(mcontrol, opts.bias); + if (check_flag(retval, "SUNAdaptController_SetErrorBias")) return 1; + } + + // Create MRI (intermediate) integrator + void* mid_arkode_mem = MRIStepCreate(f_me, f_mi, T0, y, inner_stepper, sunctx); + if (check_ptr((void*)mid_arkode_mem, "MRIStepCreate")) return 1; + MRIStepCoupling Cm = MRIStepCoupling_LoadTableByName((opts.mid_method).c_str()); + if (check_ptr((void*)Cm, "MRIStepCoupling_LoadTableByName")) return 1; + retval = MRIStepSetCoupling(mid_arkode_mem, Cm); + if (check_flag(retval, "MRIStepSetCoupling")) return 1; + SUNMatrix Am = nullptr; // matrix for intermediate solver + SUNLinearSolver LSm = nullptr; // intermediate linear solver object + if (midimplicit) + { + Am = SUNDenseMatrix(NEQ, NEQ, sunctx); + if (check_ptr((void*)Am, "SUNDenseMatrix")) return 1; + LSm = SUNLinSol_Dense(y, Am, sunctx); + if (check_ptr((void*)LSm, "SUNLinSol_Dense")) return 1; + retval = ARKodeSetLinearSolver(mid_arkode_mem, LSm, Am); + if (check_flag(retval, "ARKodeSetLinearSolver")) return 1; + retval = ARKodeSetJacFn(mid_arkode_mem, J_m); + if (check_flag(retval, "ARKodeSetJacFn")) return 1; + } + retval = ARKodeSStolerances(mid_arkode_mem, opts.rtol, opts.atol); + if (check_flag(retval, "ARKodeSStolerances")) return 1; + retval = ARKodeSetMaxNumSteps(mid_arkode_mem, 100000); + if (check_flag(retval, "ARKodeSetMaxNumSteps")) return 1; + retval = ARKodeSetAccumulatedErrorType(mid_arkode_mem, acc_type); + if (check_flag(retval, "ARKodeSetAccumulatedErrorType")) return 1; + retval = ARKodeSetUserData(mid_arkode_mem, (void*)&opts); + if (check_flag(retval, "ARKodeSetUserData")) return 1; + if (opts.scontrol != 0) + { + retval = ARKodeSetAdaptController(mid_arkode_mem, mcontrol); + if (check_flag(retval, "ARKodeSetAdaptController")) return 1; + if (opts.set_h0 != 0) + { + retval = ARKodeSetInitStep(mid_arkode_mem, opts.hm); + if (check_flag(retval, "ARKodeSetInitStep")) return 1; + } + if (opts.slow_pq == 1) + { + retval = ARKodeSetAdaptivityAdjustment(mid_arkode_mem, 0); + if (check_flag(retval, "ARKodeSetAdaptivityAdjustment")) return 1; + } + if (!std::isnan(opts.slow_safety)) + { + retval = ARKodeSetSafetyFactor(mid_arkode_mem, opts.slow_safety); + if (check_flag(retval, "ARKodeSetSafetyFactor")) return 1; + } + } + else + { + retval = ARKodeSetFixedStep(mid_arkode_mem, opts.hm); + if (check_flag(retval, "ARKodeSetFixedStep")) return 1; + } + + // Create intermediate stepper + MRIStepInnerStepper intermediate_stepper = nullptr; + retval = ARKodeCreateMRIStepInnerStepper(mid_arkode_mem, &intermediate_stepper); + if (check_flag(retval, "ARKodeCreateMRIStepInnerStepper")) return 1; + + // Create MRI (slow) integrator + void* arkode_mem = MRIStepCreate(f_se, f_si, T0, y, intermediate_stepper, + sunctx); + if (check_ptr((void*)arkode_mem, "MRIStepCreate")) return 1; + MRIStepCoupling Cs = MRIStepCoupling_LoadTableByName((opts.mri_method).c_str()); + if (check_ptr((void*)Cs, "MRIStepCoupling_LoadTableByName")) return 1; + retval = MRIStepSetCoupling(arkode_mem, Cs); + if (check_flag(retval, "MRIStepSetCoupling")) return 1; + SUNMatrix As = nullptr; // matrix for slow solver + SUNLinearSolver LSs = nullptr; // slow linear solver object + if (slowimplicit) + { + As = SUNDenseMatrix(NEQ, NEQ, sunctx); + if (check_ptr((void*)As, "SUNDenseMatrix")) return 1; + LSs = SUNLinSol_Dense(y, As, sunctx); + if (check_ptr((void*)LSs, "SUNLinSol_Dense")) return 1; + retval = ARKodeSetLinearSolver(arkode_mem, LSs, As); + if (check_flag(retval, "ARKodeSetLinearSolver")) return 1; + retval = ARKodeSetJacFn(arkode_mem, J_s); + if (check_flag(retval, "ARKodeSetJacFn")) return 1; + } + retval = ARKodeSStolerances(arkode_mem, opts.rtol, opts.atol); + if (check_flag(retval, "ARKodeSStolerances")) return 1; + retval = ARKodeSetMaxNumSteps(arkode_mem, 100000); + if (check_flag(retval, "ARKodeSetMaxNumSteps")) return 1; + retval = ARKodeSetUserData(arkode_mem, (void*)&opts); + if (check_flag(retval, "ARKodeSetUserData")) return 1; + if (opts.scontrol != 0) + { + retval = ARKodeSetAdaptController(arkode_mem, scontrol); + if (check_flag(retval, "ARKodeSetAdaptController")) return 1; + if (opts.set_h0 != 0) + { + retval = ARKodeSetInitStep(arkode_mem, opts.hs); + if (check_flag(retval, "ARKodeSetInitStep")) return 1; + } + if (opts.slow_pq == 1) + { + retval = ARKodeSetAdaptivityAdjustment(arkode_mem, 0); + if (check_flag(retval, "ARKodeSetAdaptivityAdjustment")) return 1; + } + if (!std::isnan(opts.slow_safety)) + { + retval = ARKodeSetSafetyFactor(arkode_mem, opts.slow_safety); + if (check_flag(retval, "ARKodeSetSafetyFactor")) return 1; + } + } + else + { + retval = ARKodeSetFixedStep(arkode_mem, opts.hs); + if (check_flag(retval, "ARKodeSetFixedStep")) return 1; + } + + // + // Integrate ODE + // + + // Main time-stepping loop: calls ARKodeEvolve to perform the + // integration, then prints results. Stops when the final time + // has been reached + sunrealtype t = T0; + sunrealtype t2 = T0; + sunrealtype dTout = (Tf - T0) / Nt; + sunrealtype tout = T0 + dTout; + sunrealtype* ydata = N_VGetArrayPointer(y); + sunrealtype* yrefdata = N_VGetArrayPointer(yref); + sunrealtype u, v, w, uerr, verr, werr, uerrtot, verrtot, werrtot, errtot, + accuracy; + uerr = verr = werr = uerrtot = verrtot = werrtot = errtot = accuracy = ZERO; + printf(" t u v w uerr verr " + " werr\n"); + printf(" " + "---------------------------------------------------------------------" + "-------\n"); + printf(" %10.6" FSYM " %10.6" FSYM " %10.6" FSYM " %10.6" FSYM " %.2" ESYM + " %.2" ESYM " %.2" ESYM "\n", + t, ydata[0], ydata[1], ydata[2], uerr, verr, werr); + while (Tf - t > SUN_RCONST(1.0e-8)) + { + // reset reference solver so that it begins with identical state + retval = ARKodeReset(arkode_ref, t, y); + + // evolve solution in one-step mode + retval = ARKodeSetStopTime(arkode_mem, tout); + if (check_flag(retval, "ARKodeSetStopTime")) return 1; + retval = ARKodeEvolve(arkode_mem, tout, y, &t, ARK_ONE_STEP); + if (retval < 0) + { + printf("ARKodeEvolve error (%i)\n", retval); + return 1; + } + + // evolve reference solver to same time in "normal" mode + retval = ARKodeSetStopTime(arkode_ref, t); + if (check_flag(retval, "ARKodeSetStopTime")) return 1; + retval = ARKodeEvolve(arkode_ref, t, yref, &t2, ARK_NORMAL); + if (retval < 0) + { + printf("ARKodeEvolve reference solution error (%i)\n", retval); + return 1; + } + + // access/print solution and error + u = ydata[0]; + v = ydata[1]; + w = ydata[2]; + uerr = std::abs(yrefdata[0] - u); + verr = std::abs(yrefdata[1] - v); + werr = std::abs(yrefdata[2] - w); + uerrtot += uerr * uerr; + verrtot += verr * verr; + werrtot += werr * werr; + errtot += uerr * uerr + verr * verr + werr * werr; + accuracy = std::max(accuracy, + uerr / std::abs(opts.atol + opts.rtol * yrefdata[0])); + accuracy = std::max(accuracy, + verr / std::abs(opts.atol + opts.rtol * yrefdata[1])); + accuracy = std::max(accuracy, + werr / std::abs(opts.atol + opts.rtol * yrefdata[2])); + + // Periodically output current results to screen + if (t >= tout) + { + tout += dTout; + tout = (tout > Tf) ? Tf : tout; + printf(" %10.6" FSYM " %10.6" FSYM " %10.6" FSYM " %10.6" FSYM + " %.2" ESYM " %.2" ESYM " %.2" ESYM "\n", + t, u, v, w, uerr, verr, werr); + } + } + printf(" " + "---------------------------------------------------------------------" + "-------\n"); + + // + // Finalize + // + + // Get some slow integrator statistics + long int nsts, natts, netfs, nfse, nfsi, nifs; + retval = ARKodeGetNumSteps(arkode_mem, &nsts); + check_flag(retval, "ARKodeGetNumSteps"); + retval = ARKodeGetNumStepAttempts(arkode_mem, &natts); + check_flag(retval, "ARKodeGetNumStepAttempts"); + retval = ARKodeGetNumErrTestFails(arkode_mem, &netfs); + check_flag(retval, "ARKodeGetNumErrTestFails"); + retval = ARKodeGetNumRhsEvals(arkode_mem, 0, &nfse); + check_flag(retval, "ARKodeGetNumRhsEvals"); + retval = ARKodeGetNumRhsEvals(arkode_mem, 1, &nfsi); + check_flag(retval, "ARKodeGetNumRhsEvals"); + retval = MRIStepGetNumInnerStepperFails(arkode_mem, &nifs); + check_flag(retval, "MRIStepGetNumInnerStepperFails"); + + // Get some intermediate integrator statistics + long int nstm, nattm, netfm, nfme, nfmi, nifm; + retval = ARKodeGetNumSteps(mid_arkode_mem, &nstm); + check_flag(retval, "ARKodeGetNumSteps"); + retval = ARKodeGetNumStepAttempts(mid_arkode_mem, &nattm); + check_flag(retval, "ARKodeGetNumStepAttempts"); + retval = ARKodeGetNumErrTestFails(mid_arkode_mem, &netfm); + check_flag(retval, "ARKodeGetNumErrTestFails"); + retval = ARKodeGetNumRhsEvals(mid_arkode_mem, 0, &nfme); + check_flag(retval, "ARKodeGetNumRhsEvals"); + retval = ARKodeGetNumRhsEvals(mid_arkode_mem, 1, &nfmi); + check_flag(retval, "ARKodeGetNumRhsEvals"); + retval = MRIStepGetNumInnerStepperFails(mid_arkode_mem, &nifm); + check_flag(retval, "MRIStepGetNumInnerStepperFails"); + + // Get some fast integrator statistics + long int nstf, nattf, netff, nff; + retval = ARKodeGetNumSteps(inner_arkode_mem, &nstf); + check_flag(retval, "ARKodeGetNumSteps"); + retval = ARKodeGetNumStepAttempts(inner_arkode_mem, &nattf); + check_flag(retval, "ARKodeGetNumStepAttempts"); + retval = ARKodeGetNumErrTestFails(inner_arkode_mem, &netff); + check_flag(retval, "ARKodeGetNumErrTestFails"); + retval = ARKodeGetNumRhsEvals(inner_arkode_mem, 0, &nff); + check_flag(retval, "ARKodeGetNumRhsEvals"); + + // Print some final statistics + uerrtot = std::sqrt(uerrtot / (sunrealtype)nsts); + verrtot = std::sqrt(verrtot / (sunrealtype)nsts); + werrtot = std::sqrt(werrtot / (sunrealtype)nsts); + errtot = std::sqrt(errtot / SUN_RCONST(3.0) / (sunrealtype)nsts); + std::cout << "\nFinal Solver Statistics:\n"; + std::cout << " Slow steps = " << nsts << " (attempts = " << natts + << ", fails = " << netfs << ", innerfails = " << nifs << ")\n"; + std::cout << " Intermediate steps = " << nstm << " (attempts = " << nattm + << ", fails = " << netfm << ", innerfails = " << nifm << ")\n"; + std::cout << " Fast steps = " << nstf << " (attempts = " << nattf + << ", fails = " << netff << ")\n"; + std::cout << " u error = " << uerrtot << ", v error = " << verrtot + << ", total error = " << errtot << std::endl; + std::cout << " Relative accuracy = " << accuracy << std::endl; + std::cout << " Total RHS evals: Fse = " << nfse << ", Fsi = " << nfsi + << ", Fme = " << nfme << ", Fmi = " << nfmi << ", Ff = " << nff + << std::endl; + + // Get/print slow integrator implicit solver statistics + if (slowimplicit) + { + long int nnis, nncs, njes; + retval = ARKodeGetNonlinSolvStats(arkode_mem, &nnis, &nncs); + check_flag(retval, "ARKodeGetNonlinSolvStats"); + retval = ARKodeGetNumJacEvals(arkode_mem, &njes); + check_flag(retval, "ARKodeGetNumJacEvals"); + std::cout << " Slow Newton iters = " << nnis << std::endl; + std::cout << " Slow Newton iters/attempt = " + << (sunrealtype)nnis / (sunrealtype)natts << std::endl; + std::cout << " Slow Newton conv fails = " << nncs << std::endl; + std::cout << " Slow Jacobian evals = " << njes << std::endl; + std::cout << " Slow Jacobian evals/Newton = " + << (sunrealtype)njes / (sunrealtype)nnis << std::endl; + } + + // Get/print intermediate integrator implicit solver statistics + if (midimplicit) + { + long int nnim, nncm, njem; + retval = ARKodeGetNonlinSolvStats(mid_arkode_mem, &nnim, &nncm); + check_flag(retval, "ARKodeGetNonlinSolvStats"); + retval = ARKodeGetNumJacEvals(mid_arkode_mem, &njem); + check_flag(retval, "ARKodeGetNumJacEvals"); + std::cout << " Intermediate Newton iters = " << nnim << std::endl; + std::cout << " Intermediate Newton iters/attempt = " + << (sunrealtype)nnim / (sunrealtype)nattm << std::endl; + std::cout << " Intermediate Newton conv fails = " << nncm << std::endl; + std::cout << " Intermediate Jacobian evals = " << njem << std::endl; + std::cout << " Intermediate Jacobian evals/Newton = " + << (sunrealtype)njem / (sunrealtype)nnim << std::endl; + } + + // Clean up and return + N_VDestroy(y); + N_VDestroy(yref); + MRIStepCoupling_Free(Cs); + MRIStepCoupling_Free(Cm); + SUNMatDestroy(As); + SUNLinSolFree(LSs); + SUNMatDestroy(Am); + SUNLinSolFree(LSm); + SUNAdaptController_Destroy(scontrol); + SUNAdaptController_Destroy(scontrol_H); + SUNAdaptController_Destroy(scontrol_Tol); + SUNAdaptController_Destroy(mcontrol); + SUNAdaptController_Destroy(mcontrol_H); + SUNAdaptController_Destroy(mcontrol_Tol); + SUNAdaptController_Destroy(fcontrol); + ARKodeFree(&inner_arkode_mem); // Free fast integrator memory + ARKodeFree(&mid_arkode_mem); // Free intermediate integrator memory + MRIStepInnerStepper_Free(&inner_stepper); // Free inner stepper structures + MRIStepInnerStepper_Free(&intermediate_stepper); + ARKodeFree(&arkode_mem); // Free slow integrator memory + ARKodeFree(&arkode_ref); // Free reference solver memory + + return 0; +} + +// ------------------------------ +// Functions called by the solver +// ----------------------------- + +// fn routine to compute the full ODE RHS. +static int fn(sunrealtype t, N_Vector y, N_Vector ydot, void* user_data) +{ + Options* opts = static_cast(user_data); + sunrealtype* ydata = N_VGetArrayPointer(y); + sunrealtype* ydotdata = N_VGetArrayPointer(ydot); + const sunrealtype u = ydata[0]; + const sunrealtype v = ydata[1]; + const sunrealtype w = ydata[2]; + const sunrealtype G = opts->G; + const sunrealtype e = opts->e; + const sunrealtype al = opts->al; + const sunrealtype be = opts->be; + sunrealtype tmp1, tmp2, tmp3; + + // fill in the RHS function: + // [ G e e ] [(u^2-p-2)/(2u)] + [ pdot(t)/(2u) ] + // [ e al be ] [(v^2-q-2)/(2v)] [ qdot(t)/(2v) ] + // [ e -be al ] [(w^2-r-2)/(2w)] [ rdot(t)/(2w) ] + tmp1 = (-TWO + u * u - p(t, *opts)) / (TWO * u); + tmp2 = (-TWO + v * v - q(t, *opts)) / (TWO * v); + tmp3 = (-TWO + w * w - r(t, *opts)) / (TWO * w); + ydotdata[0] = G * tmp1 + e * tmp2 + e * tmp3 + pdot(t, *opts) / (TWO * u); + ydotdata[1] = e * tmp1 + al * tmp2 + be * tmp3 + qdot(t, *opts) / (TWO * v); + ydotdata[2] = e * tmp1 - be * tmp2 + al * tmp3 + rdot(t, *opts) / (TWO * w); + + // Return with success + return 0; +} + +// ff routine to compute the fast portion of the ODE RHS. +static int ff(sunrealtype t, N_Vector y, N_Vector ydot, void* user_data) +{ + Options* opts = static_cast(user_data); + sunrealtype* ydata = N_VGetArrayPointer(y); + sunrealtype* ydotdata = N_VGetArrayPointer(ydot); + const sunrealtype u = ydata[0]; + const sunrealtype v = ydata[1]; + const sunrealtype w = ydata[2]; + const sunrealtype e = opts->e; + const sunrealtype al = opts->al; + const sunrealtype be = opts->be; + sunrealtype tmp1, tmp2, tmp3; + + // fill in the RHS function: + // [ 0 0 0 ] [(u^2-p-2)/(2u)] + [ 0 ] + // [ 0 0 0 ] [(v^2-q-2)/(2v)] [ 0 ] + // [ e -be al ] [(w^2-r-2)/(2w)] [ rdot(t)/(2w) ] + tmp1 = (-TWO + u * u - p(t, *opts)) / (TWO * u); + tmp2 = (-TWO + v * v - q(t, *opts)) / (TWO * v); + tmp3 = (-TWO + w * w - r(t, *opts)) / (TWO * w); + ydotdata[0] = ZERO; + ydotdata[1] = ZERO; + ydotdata[2] = e * tmp1 - be * tmp2 + al * tmp3 + rdot(t, *opts) / (TWO * w); + + // Return with success + return 0; +} + +// fm routine to compute the intermediate portion of the ODE RHS. +static int fm(sunrealtype t, N_Vector y, N_Vector ydot, void* user_data) +{ + Options* opts = static_cast(user_data); + sunrealtype* ydata = N_VGetArrayPointer(y); + sunrealtype* ydotdata = N_VGetArrayPointer(ydot); + const sunrealtype u = ydata[0]; + const sunrealtype v = ydata[1]; + const sunrealtype w = ydata[2]; + const sunrealtype e = opts->e; + const sunrealtype al = opts->al; + const sunrealtype be = opts->be; + sunrealtype tmp1, tmp2, tmp3; + + // fill in the RHS function: + // [ 0 0 0 ] [(u^2-p-2)/(2u)] + [ 0 ] + // [ e al be ] [(v^2-q-2)/(2v)] [ qdot(t)/(2v) ] + // [ 0 0 0 ] [(w^2-r-2)/(2w)] [ 0 ] + tmp1 = (-TWO + u * u - p(t, *opts)) / (TWO * u); + tmp2 = (-TWO + v * v - q(t, *opts)) / (TWO * v); + tmp3 = (-TWO + w * w - r(t, *opts)) / (TWO * w); + ydotdata[0] = ZERO; + ydotdata[1] = e * tmp1 + al * tmp2 + be * tmp3 + qdot(t, *opts) / (TWO * v); + ydotdata[2] = ZERO; + + return 0; +} + +// fme routine to compute the explicit intermediate portion of the ODE RHS. +static int fme(sunrealtype t, N_Vector y, N_Vector ydot, void* user_data) +{ + Options* opts = static_cast(user_data); + sunrealtype* ydata = N_VGetArrayPointer(y); + sunrealtype* ydotdata = N_VGetArrayPointer(ydot); + const sunrealtype v = ydata[1]; + + // fill in the RHS function: + // [ 0 ] + // [ qdot(t)/(2v) ] + // [ 0 ] + ydotdata[0] = ZERO; + ydotdata[1] = qdot(t, *opts) / (TWO * v); + ydotdata[2] = ZERO; + + return 0; +} + +// fmi routine to compute the implicit intermediate portion of the ODE RHS. +static int fmi(sunrealtype t, N_Vector y, N_Vector ydot, void* user_data) +{ + Options* opts = static_cast(user_data); + sunrealtype* ydata = N_VGetArrayPointer(y); + sunrealtype* ydotdata = N_VGetArrayPointer(ydot); + const sunrealtype u = ydata[0]; + const sunrealtype v = ydata[1]; + const sunrealtype w = ydata[2]; + const sunrealtype e = opts->e; + const sunrealtype al = opts->al; + const sunrealtype be = opts->be; + sunrealtype tmp1, tmp2, tmp3; + + // fill in the RHS function: + // [ 0 0 0 ] [(u^2-p-2)/(2u)] + // [ e al be ] [(v^2-q-2)/(2v)] + // [ 0 0 0 ] [(w^2-r-2)/(2w)] + tmp1 = (-TWO + u * u - p(t, *opts)) / (TWO * u); + tmp2 = (-TWO + v * v - q(t, *opts)) / (TWO * v); + tmp3 = (-TWO + w * w - r(t, *opts)) / (TWO * w); + ydotdata[0] = ZERO; + ydotdata[1] = e * tmp1 + al * tmp2 + be * tmp3; + ydotdata[2] = ZERO; + + // Return with success + return 0; +} + +// fs routine to compute the slow portion of the ODE RHS. +static int fs(sunrealtype t, N_Vector y, N_Vector ydot, void* user_data) +{ + Options* opts = static_cast(user_data); + sunrealtype* ydata = N_VGetArrayPointer(y); + sunrealtype* ydotdata = N_VGetArrayPointer(ydot); + const sunrealtype u = ydata[0]; + const sunrealtype v = ydata[1]; + const sunrealtype w = ydata[2]; + const sunrealtype G = opts->G; + const sunrealtype e = opts->e; + sunrealtype tmp1, tmp2, tmp3; + + // fill in the RHS function: + // [ G e e ] [(u^2-p-2)/(2u)] + [ pdot(t)/(2u) ] + // [ 0 0 0 ] [(v^2-q-2)/(2v)] [ 0 ] + // [ 0 0 0 ] [(w^2-r-2)/(2w)] [ 0 ] + tmp1 = (-TWO + u * u - p(t, *opts)) / (TWO * u); + tmp2 = (-TWO + v * v - q(t, *opts)) / (TWO * v); + tmp3 = (-TWO + w * w - r(t, *opts)) / (TWO * w); + ydotdata[0] = G * tmp1 + e * tmp2 + e * tmp3 + pdot(t, *opts) / (TWO * u); + ydotdata[1] = ZERO; + ydotdata[2] = ZERO; + + return 0; +} + +// fse routine to compute the explicit slow portion of the ODE RHS. +static int fse(sunrealtype t, N_Vector y, N_Vector ydot, void* user_data) +{ + Options* opts = static_cast(user_data); + sunrealtype* ydata = N_VGetArrayPointer(y); + sunrealtype* ydotdata = N_VGetArrayPointer(ydot); + const sunrealtype u = ydata[0]; + + // fill in the RHS function: + // [ pdot(t)/(2u) ] + // [ 0 ] + // [ 0 ] + ydotdata[0] = pdot(t, *opts) / (TWO * u); + ydotdata[1] = ZERO; + ydotdata[2] = ZERO; + + return 0; +} + +// fsi routine to compute the implicit slow portion of the ODE RHS. +static int fsi(sunrealtype t, N_Vector y, N_Vector ydot, void* user_data) +{ + Options* opts = static_cast(user_data); + sunrealtype* ydata = N_VGetArrayPointer(y); + sunrealtype* ydotdata = N_VGetArrayPointer(ydot); + const sunrealtype u = ydata[0]; + const sunrealtype v = ydata[1]; + const sunrealtype w = ydata[2]; + const sunrealtype G = opts->G; + const sunrealtype e = opts->e; + sunrealtype tmp1, tmp2, tmp3; + + // fill in the RHS function: + // [ G e e ] [(u^2-p-2)/(2u)] + // [ 0 0 0 ] [(v^2-q-2)/(2v)] + // [ 0 0 0 ] [(w^2-r-2)/(2w)] + tmp1 = (-TWO + u * u - p(t, *opts)) / (TWO * u); + tmp2 = (-TWO + v * v - q(t, *opts)) / (TWO * v); + tmp3 = (-TWO + w * w - r(t, *opts)) / (TWO * w); + ydotdata[0] = G * tmp1 + e * tmp2 + e * tmp3; + ydotdata[1] = ZERO; + ydotdata[2] = ZERO; + + // Return with success + return 0; +} + +// Jacobian of fm +static int Jm(sunrealtype t, N_Vector y, N_Vector fy, SUNMatrix J, + void* user_data, N_Vector tmp1, N_Vector tmp2, N_Vector tmp3) +{ + Options* opts = static_cast(user_data); + sunrealtype* ydata = N_VGetArrayPointer(y); + const sunrealtype u = ydata[0]; + const sunrealtype v = ydata[1]; + const sunrealtype w = ydata[2]; + sunrealtype t11, t22, t33; + + // fill in the Jacobian: + // [0 0 0]*[1-(u^2-p(t)-2)/(2*u^2), 0, 0] + [0, 0, 0] + // [e al be] [0, 1-(v^2-q(t)-2)/(2*v^2), 0] [0, -q'(t)/(2*v^2), 0] + // [0 0 0] [0, 0, 1-(w^2-r(t)-2)/(2*w^2)] [0, 0, 0] + t11 = ONE - (u * u - p(t, *opts) - TWO) / (TWO * u * u); + t22 = ONE - (v * v - q(t, *opts) - TWO) / (TWO * v * v); + t33 = ONE - (w * w - r(t, *opts) - TWO) / (TWO * w * w); + SM_ELEMENT_D(J, 0, 0) = ZERO; + SM_ELEMENT_D(J, 0, 1) = ZERO; + SM_ELEMENT_D(J, 0, 2) = ZERO; + SM_ELEMENT_D(J, 1, 0) = opts->e * t11; + SM_ELEMENT_D(J, 1, 1) = opts->al * t22 - qdot(t, *opts) / (TWO * v * v); + SM_ELEMENT_D(J, 1, 2) = opts->be * t33; + SM_ELEMENT_D(J, 2, 0) = ZERO; + SM_ELEMENT_D(J, 2, 1) = ZERO; + SM_ELEMENT_D(J, 2, 2) = ZERO; + + // Return with success + return 0; +} + +// Jacobian of fmi +static int Jmi(sunrealtype t, N_Vector y, N_Vector fy, SUNMatrix J, + void* user_data, N_Vector tmp1, N_Vector tmp2, N_Vector tmp3) +{ + Options* opts = static_cast(user_data); + sunrealtype* ydata = N_VGetArrayPointer(y); + const sunrealtype u = ydata[0]; + const sunrealtype v = ydata[1]; + const sunrealtype w = ydata[2]; + sunrealtype t11, t22, t33; + + // fill in the Jacobian: + // [0 0 0]*[1-(u^2-p(t)-2)/(2*u^2), 0, 0] + // [e al be] [0, 1-(v^2-q(t)-2)/(2*v^2), 0] + // [0 0 0] [0, 0, 1-(w^2-r(t)-2)/(2*w^2)] + t11 = ONE - (u * u - p(t, *opts) - TWO) / (TWO * u * u); + t22 = ONE - (v * v - q(t, *opts) - TWO) / (TWO * v * v); + t33 = ONE - (w * w - r(t, *opts) - TWO) / (TWO * w * w); + SM_ELEMENT_D(J, 0, 0) = ZERO; + SM_ELEMENT_D(J, 0, 1) = ZERO; + SM_ELEMENT_D(J, 0, 2) = ZERO; + SM_ELEMENT_D(J, 1, 0) = opts->e * t11; + SM_ELEMENT_D(J, 1, 1) = opts->al * t22; + SM_ELEMENT_D(J, 1, 2) = opts->be * t33; + SM_ELEMENT_D(J, 2, 0) = ZERO; + SM_ELEMENT_D(J, 2, 1) = ZERO; + SM_ELEMENT_D(J, 2, 2) = ZERO; + + // Return with success + return 0; +} + +// Jacobian of fs +static int Js(sunrealtype t, N_Vector y, N_Vector fy, SUNMatrix J, + void* user_data, N_Vector tmp1, N_Vector tmp2, N_Vector tmp3) +{ + Options* opts = static_cast(user_data); + sunrealtype* ydata = N_VGetArrayPointer(y); + const sunrealtype u = ydata[0]; + const sunrealtype v = ydata[1]; + const sunrealtype w = ydata[2]; + sunrealtype t11, t22, t33; + + // fill in the Jacobian: + // [G e e]*[1-(u^2-p(t)-2)/(2*u^2), 0, 0] + [-p'(t)/(2*u^2), 0, 0] + // [0 0 0] [0, 1-(v^2-q(t)-2)/(2*v^2), 0] [0, 0, 0] + // [0 0 0] [0, 0, 1-(w^2-r(t)-2)/(2*w^2)] [0, 0, 0] + t11 = ONE - (u * u - p(t, *opts) - TWO) / (TWO * u * u); + t22 = ONE - (v * v - q(t, *opts) - TWO) / (TWO * v * v); + t33 = ONE - (w * w - r(t, *opts) - TWO) / (TWO * w * w); + SM_ELEMENT_D(J, 0, 0) = opts->G * t11 - pdot(t, *opts) / (TWO * u * u); + SM_ELEMENT_D(J, 0, 1) = opts->e * t22; + SM_ELEMENT_D(J, 0, 2) = opts->e * t33; + SM_ELEMENT_D(J, 1, 0) = ZERO; + SM_ELEMENT_D(J, 1, 1) = ZERO; + SM_ELEMENT_D(J, 1, 2) = ZERO; + SM_ELEMENT_D(J, 2, 0) = ZERO; + SM_ELEMENT_D(J, 2, 1) = ZERO; + SM_ELEMENT_D(J, 2, 2) = ZERO; + + // Return with success + return 0; +} + +// Jacobian of fsi +static int Jsi(sunrealtype t, N_Vector y, N_Vector fy, SUNMatrix J, + void* user_data, N_Vector tmp1, N_Vector tmp2, N_Vector tmp3) +{ + Options* opts = static_cast(user_data); + sunrealtype* ydata = N_VGetArrayPointer(y); + const sunrealtype u = ydata[0]; + const sunrealtype v = ydata[1]; + const sunrealtype w = ydata[2]; + sunrealtype t11, t22, t33; + + // fill in the Jacobian: + // [G e e]*[1-(u^2-p(t)-2)/(2*u^2), 0, 0] + // [0 0 0] [0, 1-(v^2-q(t)-2)/(2*v^2), 0] + // [0 0 0] [0, 0, 1-(w^2-r(t)-2)/(2*w^2)] + t11 = ONE - (u * u - p(t, *opts) - TWO) / (TWO * u * u); + t22 = ONE - (v * v - q(t, *opts) - TWO) / (TWO * v * v); + t33 = ONE - (w * w - r(t, *opts) - TWO) / (TWO * w * w); + SM_ELEMENT_D(J, 0, 0) = opts->G * t11; + SM_ELEMENT_D(J, 0, 1) = opts->e * t22; + SM_ELEMENT_D(J, 0, 2) = opts->e * t33; + SM_ELEMENT_D(J, 1, 0) = ZERO; + SM_ELEMENT_D(J, 1, 1) = ZERO; + SM_ELEMENT_D(J, 1, 2) = ZERO; + SM_ELEMENT_D(J, 2, 0) = ZERO; + SM_ELEMENT_D(J, 2, 1) = ZERO; + SM_ELEMENT_D(J, 2, 2) = ZERO; + + // Return with success + return 0; +} + +// ------------------------------ +// Private helper functions +// ----------------------------- + +static sunrealtype p(sunrealtype t, const Options& opts) +{ + return HALF * cos(t); +} + +static sunrealtype q(sunrealtype t, const Options& opts) +{ + return (cos(opts.om * t * (ONE + exp(-(t - TWO) * (t - TWO))))); +} + +static sunrealtype r(sunrealtype t, const Options& opts) +{ + return (cos(opts.om * opts.om * t * (ONE + exp(-(t - THREE) * (t - THREE))))); +} + +static sunrealtype pdot(sunrealtype t, const Options& opts) +{ + return -HALF * sin(t); +} + +static sunrealtype qdot(sunrealtype t, const Options& opts) +{ + const sunrealtype tTwo = t - TWO; + const sunrealtype eterm = exp(-tTwo * tTwo); + return (-sin(opts.om * t * (ONE + eterm)) * opts.om * + (ONE + eterm * (ONE - TWO * t * tTwo))); +} + +static sunrealtype rdot(sunrealtype t, const Options& opts) +{ + const sunrealtype tThree = t - THREE; + const sunrealtype eterm = exp(-tThree * tThree); + return (-sin(opts.om * opts.om * t * (ONE + eterm)) * opts.om * opts.om * + (ONE + eterm * (ONE - TWO * t * tThree))); +} + +static sunrealtype utrue(sunrealtype t, const Options& opts) +{ + return (std::sqrt(TWO + p(t, opts))); +} + +static sunrealtype vtrue(sunrealtype t, const Options& opts) +{ + return (std::sqrt(TWO + q(t, opts))); +} + +static sunrealtype wtrue(sunrealtype t, const Options& opts) +{ + return (std::sqrt(TWO + r(t, opts))); +} + +static int Ytrue(sunrealtype t, N_Vector y, const Options& opts) +{ + NV_Ith_S(y, 0) = utrue(t, opts); + NV_Ith_S(y, 1) = vtrue(t, opts); + NV_Ith_S(y, 2) = wtrue(t, opts); + return (0); +} + +// ----------------------------------------------------------------------------- +// Utility functions +// ----------------------------------------------------------------------------- + +// Print command line options +void InputHelp() +{ + std::cout << std::endl; + std::cout << "Command line options:" << std::endl; + std::cout << " --help : print options and exit\n"; + std::cout << " --G : stiffness at slow time scale\n"; + std::cout << " --e : fast/slow coupling strength\n"; + std::cout << " --al : med/fast oscillation term\n"; + std::cout << " --be : med/fast oscillation term\n"; + std::cout << " --om : time-scale separation factor\n"; + std::cout << " --hs : slow (fixed/initial) step size\n"; + std::cout << " --hm : intermediate (fixed/initial) step size\n"; + std::cout << " --hf : fast (fixed/initial) step size\n"; + std::cout + << " --set_h0 : use hs/hf above to set the initial step size\n"; + std::cout << " --rtol : relative solution tolerance\n"; + std::cout << " --atol : absolute solution tolerance\n"; + std::cout + << " --fast_rtol : relative solution tolerance for fast method\n"; + std::cout << " --safety : slow time step safety factor\n"; + std::cout + << " --mri_method : slow MRI method name (valid ARKODE_MRITableID)\n"; + std::cout << " --mid_method : intermediate MRI method name (valid " + "ARKODE_MRITableID)\n"; + std::cout << " --fast_order : fast RK method order\n"; + std::cout << " --scontrol : slow/intermediate time step controllers, " + "int in [0,12] " + "(see source)\n"; + std::cout << " --fcontrol : fast time step controller, int in [0,6] " + "(see source)\n"; + std::cout << " --faccum : fast error accumulation type {-1,0,1,2}\n"; + std::cout << " --slow_pq : use p (0) vs q (1) for slow/intermediate " + "adaptivity\n"; + std::cout << " --fast_pq : use p (0) vs q (1) for fast adaptivity\n"; + std::cout + << " --k1s, --k2s, -k3s : slow/intermediate controller parameters\n"; + std::cout << " --k1f, --k2f, -k3f : fast controller parameters\n"; + std::cout << " --bias : slow and fast controller bias factors\n"; + std::cout + << " --htol_relch : HTol controller maximum relative tolerance change\n"; + std::cout + << " --htol_minfac : HTol controller minimum relative tolerance factor\n"; + std::cout + << " --htol_maxfac : HTol controller maximum relative tolerance factor\n"; +} + +// Read input options +int ReadInputs(std::vector& args, Options& opts, SUNContext ctx) +{ + if (find(args.begin(), args.end(), "--help") != args.end()) + { + InputHelp(); + return 1; + } + + // Problem options + find_arg(args, "--G", opts.G); + find_arg(args, "--e", opts.e); + find_arg(args, "--al", opts.al); + find_arg(args, "--be", opts.be); + find_arg(args, "--om", opts.om); + find_arg(args, "--hs", opts.hs); + find_arg(args, "--hm", opts.hm); + find_arg(args, "--hf", opts.hf); + find_arg(args, "--set_h0", opts.set_h0); + find_arg(args, "--rtol", opts.rtol); + find_arg(args, "--atol", opts.atol); + find_arg(args, "--fast_rtol", opts.fast_rtol); + find_arg(args, "--safety", opts.slow_safety); + find_arg(args, "--mri_method", opts.mri_method); + find_arg(args, "--mid_method", opts.mid_method); + find_arg(args, "--fast_order", opts.fast_order); + find_arg(args, "--scontrol", opts.scontrol); + find_arg(args, "--fcontrol", opts.fcontrol); + find_arg(args, "--faccum", opts.faccum); + find_arg(args, "--slow_pq", opts.slow_pq); + find_arg(args, "--fast_pq", opts.fast_pq); + find_arg(args, "--k1s", opts.k1s); + find_arg(args, "--k2s", opts.k2s); + find_arg(args, "--k3s", opts.k3s); + find_arg(args, "--k1f", opts.k1f); + find_arg(args, "--k2f", opts.k2f); + find_arg(args, "--k3f", opts.k3f); + find_arg(args, "--bias", opts.bias); + find_arg(args, "--htol_relch", opts.htol_relch); + find_arg(args, "--htol_minfac", opts.htol_minfac); + find_arg(args, "--htol_maxfac", opts.htol_maxfac); + + // Check inputs for validity + // 0 < rtol < 1 + if ((opts.rtol <= ZERO) || (opts.rtol >= ONE)) + { + std::cerr << "ERROR: rtol must be in (0,1), (" << opts.rtol << " input)\n"; + return -1; + } + // 0 < atol < 1 + if ((opts.atol <= ZERO) || (opts.atol >= ONE)) + { + std::cerr << "ERROR: atol must be in (0,1), (" << opts.atol << " input)\n"; + return -1; + } + // 0 < fast_rtol < 1 + if ((opts.fast_rtol <= ZERO) || (opts.fast_rtol >= ONE)) + { + std::cerr << "ERROR: fast_rtol must be in (0,1), (" << opts.fast_rtol + << " input)\n"; + return -1; + } + // 0 < fast_order + if (opts.fast_order <= 0) + { + std::cerr << "ERROR: fast_order must be at least 1, (" << opts.fast_order + << " input)\n"; + return -1; + } + // slow_pq in {0,1} + if ((opts.slow_pq < 0) || (opts.slow_pq > 1)) + { + std::cerr << "ERROR: slow_pq must be in {0,1}, (" << opts.slow_pq + << " input)\n"; + return -1; + } + // fast_pq in {0,1} + if ((opts.fast_pq < 0) || (opts.fast_pq > 1)) + { + std::cerr << "ERROR: fast_pq must be in {0,1}, (" << opts.fast_pq + << " input)\n"; + return -1; + } + // scontrol in [0,12] + if ((opts.scontrol < 0) || (opts.scontrol > 12)) + { + std::cerr << "ERROR: scontrol must be in [0,12], (" << opts.scontrol + << " input)\n"; + return -1; + } + // fcontrol in [0,6] + if ((opts.fcontrol < 0) || (opts.fcontrol > 6)) + { + std::cerr << "ERROR: fcontrol must be in [0,6], (" << opts.fcontrol + << " input)\n"; + return -1; + } + // hs > 0 and hm > 0 if scontrol == 0 + if (((opts.hs <= 0) || (opts.hm <= 0)) && (opts.scontrol == 0)) + { + std::cerr << "ERROR: positive hs required with scontrol = 0, (" << opts.hs + << " input)\n"; + return -1; + } + // hf > 0 if fcontrol == 0 + if ((opts.hf <= 0) && (opts.fcontrol == 0)) + { + std::cerr << "ERROR: positive hf required with fcontrol = 0, (" << opts.hf + << " input)\n"; + return -1; + } + // G < 0.0 + if (opts.G >= ZERO) + { + std::cerr << "ERROR: G must be a negative real number, (" << opts.G + << " input)\n"; + return -1; + } + // om >= 1.0 + if (opts.om < ONE) + { + std::cerr << "ERROR: w must be >= 1.0, (" << opts.om << " input)\n"; + return -1; + } + + return 0; +} + +static void PrintSlowAdaptivity(Options opts) +{ + switch (opts.scontrol) + { + case (0): + { + std::cout << " fixed steps, hs = " << opts.hs << ", hm = " << opts.hm + << std::endl; + std::cout << " rtol = " << opts.rtol << ", atol = " << opts.atol << "\n"; + break; + } + case (1): + { + std::cout + << " MRI-HTOL controller (using I for H) based on order of MRI " + << ((opts.slow_pq == 1) ? "method\n" : "embedding\n"); + std::cout << " rtol = " << opts.rtol << ", atol = " << opts.atol << "\n"; + std::cout << " fast error accumulation strategy = " << opts.faccum << "\n"; + if (!std::isnan(opts.k1s)) + { + std::cout << " slow/intermediate controller parameter: " << opts.k1s + << "\n"; + } + if (!(std::isnan(opts.htol_relch) || std::isnan(opts.htol_minfac) || + std::isnan(opts.htol_maxfac))) + { + std::cout << " HTol controller parameters: " << opts.htol_relch << " " + << opts.htol_minfac << " " << opts.htol_maxfac << "\n"; + } + break; + } + case (2): + { + std::cout + << " MRI-HTOL controller (using PI for H) based on order of MRI " + << ((opts.slow_pq == 1) ? "method\n" : "embedding\n"); + std::cout << " rtol = " << opts.rtol << ", atol = " << opts.atol << "\n"; + std::cout << " fast error accumulation strategy = " << opts.faccum << "\n"; + if (!(std::isnan(opts.k1s) || std::isnan(opts.k2s))) + { + std::cout << " slow/intermediate controller parameters: " << opts.k1s + << " " << opts.k2s << "\n"; + } + if (!(std::isnan(opts.htol_relch) || std::isnan(opts.htol_minfac) || + std::isnan(opts.htol_maxfac))) + { + std::cout << " HTol controller parameters: " << opts.htol_relch << " " + << opts.htol_minfac << " " << opts.htol_maxfac << "\n"; + } + break; + } + case (3): + { + std::cout + << " MRI-HTOL controller (using PID for H) based on order of MRI " + << ((opts.slow_pq == 1) ? "method\n" : "embedding\n"); + std::cout << " rtol = " << opts.rtol << ", atol = " << opts.atol << "\n"; + std::cout << " fast error accumulation strategy = " << opts.faccum << "\n"; + if (!(std::isnan(opts.k1s) || std::isnan(opts.k2s) || std::isnan(opts.k3s))) + { + std::cout << " slow/intermediate controller parameters: " << opts.k1s + << " " << opts.k2s << " " << opts.k3s << "\n"; + } + if (!(std::isnan(opts.htol_relch) || std::isnan(opts.htol_minfac) || + std::isnan(opts.htol_maxfac))) + { + std::cout << " HTol controller parameters: " << opts.htol_relch << " " + << opts.htol_minfac << " " << opts.htol_maxfac << "\n"; + } + break; + } + case (4): + { + std::cout + << " MRI-HTOL controller (using ExpGus for H) based on order of MRI " + << ((opts.slow_pq == 1) ? "method\n" : "embedding\n"); + std::cout << " rtol = " << opts.rtol << ", atol = " << opts.atol << "\n"; + std::cout << " fast error accumulation strategy = " << opts.faccum << "\n"; + if (!(std::isnan(opts.k1s) || std::isnan(opts.k2s))) + { + std::cout << " slow/intermediate controller parameters: " << opts.k1s + << " " << opts.k2s << "\n"; + } + if (!(std::isnan(opts.htol_relch) || std::isnan(opts.htol_minfac) || + std::isnan(opts.htol_maxfac))) + { + std::cout << " HTol controller parameters: " << opts.htol_relch << " " + << opts.htol_minfac << " " << opts.htol_maxfac << "\n"; + } + break; + } + case (5): + { + std::cout + << " MRI-HTOL controller (using ImpGus for H) based on order of MRI " + << ((opts.slow_pq == 1) ? "method\n" : "embedding\n"); + std::cout << " rtol = " << opts.rtol << ", atol = " << opts.atol << "\n"; + std::cout << " fast error accumulation strategy = " << opts.faccum << "\n"; + if (!(std::isnan(opts.k1s) || std::isnan(opts.k2s))) + { + std::cout << " slow/intermediate controller parameters: " << opts.k1s + << " " << opts.k2s << "\n"; + } + if (!(std::isnan(opts.htol_relch) || std::isnan(opts.htol_minfac) || + std::isnan(opts.htol_maxfac))) + { + std::cout << " HTol controller parameters: " << opts.htol_relch << " " + << opts.htol_minfac << " " << opts.htol_maxfac << "\n"; + } + break; + } + case (6): + { + std::cout + << " MRI-HTOL controller (using ImExGus for H) based on order of MRI " + << ((opts.slow_pq == 1) ? "method\n" : "embedding\n"); + std::cout << " rtol = " << opts.rtol << ", atol = " << opts.atol << "\n"; + std::cout << " fast error accumulation strategy = " << opts.faccum << "\n"; + break; + } + case (7): + { + std::cout << " Decoupled I controller for slow time scale, based on " + "order of MRI " + << ((opts.slow_pq == 1) ? "method\n" : "embedding\n"); + std::cout << " rtol = " << opts.rtol << ", atol = " << opts.atol << "\n"; + if (!std::isnan(opts.k1s)) + { + std::cout << " slow/intermediate controller parameter: " << opts.k1s + << "\n"; + } + break; + } + case (8): + { + std::cout << " Decoupled PI controller for slow time scale, based on " + "order of MRI " + << ((opts.slow_pq == 1) ? "method\n" : "embedding\n"); + std::cout << " rtol = " << opts.rtol << ", atol = " << opts.atol << "\n"; + if (!(std::isnan(opts.k1s) || std::isnan(opts.k2s))) + { + std::cout << " slow/intermediate controller parameters: " << opts.k1s + << " " << opts.k2s << "\n"; + } + break; + } + case (9): + { + std::cout << " Decoupled PID controller for slow time scale, based on " + "order of MRI " + << ((opts.slow_pq == 1) ? "method\n" : "embedding\n"); + std::cout << " rtol = " << opts.rtol << ", atol = " << opts.atol << "\n"; + if (!(std::isnan(opts.k1s) || std::isnan(opts.k2s) || std::isnan(opts.k3s))) + { + std::cout << " slow/intermediate controller parameters: " << opts.k1s + << " " << opts.k2s << " " << opts.k3s << "\n"; + } + break; + } + case (10): + { + std::cout << " Decoupled ExpGus controller for slow time scale, based " + "on order of MRI " + << ((opts.slow_pq == 1) ? "method\n" : "embedding\n"); + std::cout << " rtol = " << opts.rtol << ", atol = " << opts.atol << "\n"; + if (!(std::isnan(opts.k1s) || std::isnan(opts.k2s))) + { + std::cout << " slow/intermediate controller parameters: " << opts.k1s + << " " << opts.k2s << "\n"; + } + break; + } + case (11): + { + std::cout << " Decoupled ImpGus controller for slow time scale, based " + "on order of MRI " + << ((opts.slow_pq == 1) ? "method\n" : "embedding\n"); + std::cout << " rtol = " << opts.rtol << ", atol = " << opts.atol << "\n"; + if (!(std::isnan(opts.k1s) || std::isnan(opts.k2s))) + { + std::cout << " slow/intermediate controller parameters: " << opts.k1s + << " " << opts.k2s << "\n"; + } + break; + } + case (12): + { + std::cout << " Decoupled ImExGus controller for slow time scale, based " + "on order of MRI " + << ((opts.slow_pq == 1) ? "method\n" : "embedding\n"); + std::cout << " rtol = " << opts.rtol << ", atol = " << opts.atol << "\n"; + break; + } + } + if (!std::isnan(opts.bias)) + { + std::cout << " controller bias factor: " << opts.bias << "\n"; + } + if (!std::isnan(opts.slow_safety)) + { + std::cout << " slow step safety factor: " << opts.slow_safety << "\n"; + } +} + +static void PrintFastAdaptivity(Options opts) +{ + switch (opts.fcontrol) + { + case (0): + { + std::cout << " fixed steps, hf = " << opts.hf << std::endl; + std::cout << " fast_rtol = " << opts.fast_rtol + << ", atol = " << opts.atol << "\n"; + break; + } + case (1): + { + std::cout << " I controller for fast time scale, based on order of RK " + << ((opts.fast_pq == 1) ? "method\n" : "embedding\n"); + std::cout << " fast_rtol = " << opts.fast_rtol + << ", atol = " << opts.atol << "\n"; + if (!std::isnan(opts.k1f)) + { + std::cout << " fast controller parameter: " << opts.k1f << "\n"; + } + break; + } + case (2): + { + std::cout << " PI controller for fast time scale, based on order of RK " + << ((opts.fast_pq == 1) ? "method\n" : "embedding\n"); + std::cout << " fast_rtol = " << opts.fast_rtol + << ", atol = " << opts.atol << "\n"; + if (!(std::isnan(opts.k1f) || std::isnan(opts.k2f))) + { + std::cout << " fast controller parameters: " << opts.k1f << " " + << opts.k2f << "\n"; + } + break; + } + case (3): + { + std::cout << " PID controller for fast time scale, based on order of RK " + << ((opts.fast_pq == 1) ? "method\n" : "embedding\n"); + std::cout << " fast_rtol = " << opts.fast_rtol + << ", atol = " << opts.atol << "\n"; + if (!(std::isnan(opts.k1f) || std::isnan(opts.k2f) || std::isnan(opts.k3f))) + { + std::cout << " fast controller parameters: " << opts.k1f << " " + << opts.k2f << " " << opts.k3f << "\n"; + } + break; + } + case (4): + { + std::cout + << " ExpGus controller for fast time scale, based on order of RK " + << ((opts.fast_pq == 1) ? "method\n" : "embedding\n"); + std::cout << " fast_rtol = " << opts.fast_rtol + << ", atol = " << opts.atol << "\n"; + if (!(std::isnan(opts.k1f) || std::isnan(opts.k2f))) + { + std::cout << " fast controller parameters: " << opts.k1f << " " + << opts.k2f << "\n"; + } + break; + } + case (5): + { + std::cout + << " ImpGus controller for fast time scale, based on order of RK " + << ((opts.fast_pq == 1) ? "method\n" : "embedding\n"); + std::cout << " fast_rtol = " << opts.fast_rtol + << ", atol = " << opts.atol << "\n"; + if (!(std::isnan(opts.k1f) || std::isnan(opts.k2f))) + { + std::cout << " fast controller parameters: " << opts.k1f << " " + << opts.k2f << "\n"; + } + break; + } + case (6): + { + std::cout + << " ImExGus controller for fast time scale, based on order of RK " + << ((opts.fast_pq == 1) ? "method\n" : "embedding\n"); + std::cout << " fast_rtol = " << opts.fast_rtol + << ", atol = " << opts.atol << "\n"; + break; + } + } +} + +//---- end of file ----// diff --git a/examples/arkode/CXX_serial/ark_kpr_nestedmri.out b/examples/arkode/CXX_serial/ark_kpr_nestedmri.out new file mode 100644 index 0000000000..bc66d480bc --- /dev/null +++ b/examples/arkode/CXX_serial/ark_kpr_nestedmri.out @@ -0,0 +1,51 @@ + +Adaptive nested multirate nonlinear Kvaerno-Prothero-Robinson test problem: + time domain: (0,5] + G = -10 + e = 0.5 + al = -1 + be = 1 + om = 50 + + Slow integrator: ARKODE_MRI_GARK_ERK45a (explicit) + + Intermediate integrator: ARKODE_MRI_GARK_ERK45a (explicit) + MRI-HTOL controller (using I for H) based on order of MRI embedding + rtol = 0.0001, atol = 1e-11 + fast error accumulation strategy = 0 + + Fast order 4 + I controller for fast time scale, based on order of RK embedding + fast_rtol = 0.0001, atol = 1e-11 + t u v w uerr verr werr + ---------------------------------------------------------------------------- + 0.000000 1.581139 1.732051 1.732051 0.00e+00 0.00e+00 0.00e+00 + 0.250000 1.576193 1.693804 1.005260 3.23e-06 1.18e-04 7.57e-05 + 0.500000 1.561425 1.094399 1.236935 2.15e-08 1.54e-05 2.85e-05 + 0.750000 1.537204 1.480202 1.289772 8.95e-04 1.47e-04 2.43e-04 + 1.000000 1.506472 1.658437 1.566267 2.26e-07 2.27e-05 1.87e-05 + 1.250000 1.468674 1.117329 1.128753 4.45e-06 8.37e-05 5.27e-06 + 1.500000 1.426602 1.451384 1.383651 1.49e-07 4.03e-06 2.37e-05 + 1.750000 1.382272 1.731275 1.400561 3.01e-05 6.40e-05 1.96e-04 + 2.000000 1.338548 1.576713 1.004568 1.72e-05 4.85e-05 3.52e-04 + 2.250000 1.298433 1.357466 1.203013 3.98e-06 7.57e-06 1.04e-04 + 2.500000 1.264637 1.111610 1.079957 3.74e-07 2.59e-05 3.61e-04 + 2.750000 1.240344 1.181466 1.688515 2.92e-06 3.40e-06 6.04e-05 + 3.000000 1.226753 1.199667 1.243892 3.15e-06 2.39e-06 5.78e-05 + 3.250000 1.225940 1.337036 1.695808 8.05e-05 2.56e-05 5.93e-05 + 3.500000 1.237625 1.494269 1.577837 3.48e-05 1.55e-06 2.09e-05 + 3.750000 1.261615 1.441503 1.440542 1.35e-07 1.70e-08 6.25e-06 + 4.000000 1.293574 1.067975 1.718719 4.77e-05 2.22e-05 1.30e-04 + 4.250000 1.333622 1.725039 1.003950 1.49e-11 6.53e-14 5.93e-10 + 4.500000 1.376484 1.650381 1.499914 2.63e-08 1.70e-06 6.88e-07 + 4.750000 1.420897 1.555399 1.167629 4.82e-08 1.80e-08 5.03e-06 + 5.000000 1.463498 1.506851 1.644668 7.85e-07 1.26e-05 2.66e-05 + ---------------------------------------------------------------------------- + +Final Solver Statistics: + Slow steps = 47 (attempts = 48, fails = 1, innerfails = 0) + Intermediate steps = 714 (attempts = 868, fails = 154, innerfails = 0) + Fast steps = 129455 (attempts = 144940, fails = 15485) + u error = 0.000228112, v error = 8.70956e-05, total error = 0.000169225 + Relative accuracy = 6.75352 + Total RHS evals: Fse = 240, Fsi = 0, Fme = 4234, Fmi = 0, Ff = 709264 diff --git a/examples/arkode/C_serial/CMakeLists.txt b/examples/arkode/C_serial/CMakeLists.txt index de26c61e18..382a9f957c 100644 --- a/examples/arkode/C_serial/CMakeLists.txt +++ b/examples/arkode/C_serial/CMakeLists.txt @@ -62,20 +62,21 @@ set(ARKODE_examples "ark_kepler\;--stepper SPRK --step-mode fixed --method ARKODE_SPRK_RUTH_3_3 --tf 50 --check-order --nout 1\;exclude-single" "ark_kepler\;--stepper SPRK --step-mode fixed --method ARKODE_SPRK_YOSHIDA_6_8 --tf 50 --check-order --nout 1\;exclude-single" "ark_kepler\;\;develop" - "ark_kpr_mri\;\;develop" - "ark_kpr_mri\;0 0.002\;develop" - "ark_kpr_mri\;1 0.002\;develop" - "ark_kpr_mri\;2 0.005\;develop" - "ark_kpr_mri\;3 0.01\;develop" - "ark_kpr_mri\;4 0.002\;develop" - "ark_kpr_mri\;5 0.002\;develop" - "ark_kpr_mri\;6 0.005\;develop" - "ark_kpr_mri\;7 0.001 -100 100 0.5 1\;exclude-single" - "ark_kpr_mri\;7 0.001\;exclude-single" - "ark_kpr_mri\;8 0.001 -100 100 0.5 1\;exclude-single" - "ark_kpr_mri\;8 0.001\;exclude-single" - "ark_kpr_mri\;9 0.001 -100 100 0.5 1\;exclude-single" - "ark_kpr_mri\;9 0.001\;exclude-single" + "ark_kpr_mri\;0 1 0.005\;develop" + "ark_kpr_mri\;1 0 0.01\;develop" + "ark_kpr_mri\;1 1 0.002\;exclude-single" + "ark_kpr_mri\;2 4 0.002\;develop" + "ark_kpr_mri\;3 2 0.001\;develop" + "ark_kpr_mri\;4 3 0.001\;develop" + "ark_kpr_mri\;5 4 0.001\;develop" + "ark_kpr_mri\;6 5 0.001\;develop" + "ark_kpr_mri\;7 2 0.002\;develop" + "ark_kpr_mri\;8 3 0.001 -100 100 0.5 1\;exclude-single" + "ark_kpr_mri\;9 3 0.001 -100 100 0.5 1\;exclude-single" + "ark_kpr_mri\;10 4 0.001 -100 100 0.5 1\;exclude-single" + "ark_kpr_mri\;11 2 0.001\;develop" + "ark_kpr_mri\;12 3 0.005\;develop" + "ark_kpr_mri\;13 4 0.01\;exclude-single" "ark_KrylovDemo_prec\;\;exclude-single" "ark_KrylovDemo_prec\;1\;exclude-single" "ark_KrylovDemo_prec\;2\;exclude-single" diff --git a/examples/arkode/C_serial/ark_brusselator1D_imexmri.c b/examples/arkode/C_serial/ark_brusselator1D_imexmri.c index a779faeb04..03bc844e73 100644 --- a/examples/arkode/C_serial/ark_brusselator1D_imexmri.c +++ b/examples/arkode/C_serial/ark_brusselator1D_imexmri.c @@ -523,11 +523,8 @@ int main(int argc, char* argv[]) if (check_retval(&retval, "ARKodeSetFixedStep", 1)) { return 1; } /* Create inner stepper */ - retval = ARKStepCreateMRIStepInnerStepper(inner_arkode_mem, &inner_stepper); - if (check_retval(&retval, "ARKStepCreateMRIStepInnerStepper", 1)) - { - return 1; - } + retval = ARKodeCreateMRIStepInnerStepper(inner_arkode_mem, &inner_stepper); + if (check_retval(&retval, "ARKodeCreateMRIStepInnerStepper", 1)) { return 1; } /* * Create the slow integrator and set options diff --git a/examples/arkode/C_serial/ark_brusselator1D_imexmri_0_0.001.out b/examples/arkode/C_serial/ark_brusselator1D_imexmri_0_0.001.out index cadd7e5310..e1abd55567 100644 --- a/examples/arkode/C_serial/ark_brusselator1D_imexmri_0_0.001.out +++ b/examples/arkode/C_serial/ark_brusselator1D_imexmri_0_0.001.out @@ -30,7 +30,7 @@ Final Solver Statistics: Slow Steps: nsts = 10001 Fast Steps: nstf = 120012 - Total RHS evals: Fs = 30004, Ff = 864983 + Total RHS evals: Fs = 30004, Ff = 874975 Fast Newton iters = 504937 Fast Newton conv fails = 0 Fast Jacobian evals = 2308 diff --git a/examples/arkode/C_serial/ark_brusselator1D_imexmri_2_0.001.out b/examples/arkode/C_serial/ark_brusselator1D_imexmri_2_0.001.out index d8f1801e46..39c475b902 100644 --- a/examples/arkode/C_serial/ark_brusselator1D_imexmri_2_0.001.out +++ b/examples/arkode/C_serial/ark_brusselator1D_imexmri_2_0.001.out @@ -30,7 +30,7 @@ Final Solver Statistics: Slow Steps: nsts = 10001 Fast Steps: nstf = 120012 - Total RHS evals: Fs = 68887, Ff = 360046 + Total RHS evals: Fs = 68887, Ff = 370038 Slow Newton iters = 38883 Slow Newton conv fails = 0 Slow Jacobian evals = 501 diff --git a/examples/arkode/C_serial/ark_brusselator1D_imexmri_3_0.001.out b/examples/arkode/C_serial/ark_brusselator1D_imexmri_3_0.001.out index 0e3c13961a..89bbf34f58 100644 --- a/examples/arkode/C_serial/ark_brusselator1D_imexmri_3_0.001.out +++ b/examples/arkode/C_serial/ark_brusselator1D_imexmri_3_0.001.out @@ -30,7 +30,7 @@ Final Solver Statistics: Slow Steps: nsts = 10001 Fast Steps: nstf = 120012 - Total RHS evals: Fs = 68887, Ff = 840121 + Total RHS evals: Fs = 68887, Ff = 850113 Slow Newton iters = 38883 Slow Newton conv fails = 0 Slow Jacobian evals = 501 diff --git a/examples/arkode/C_serial/ark_brusselator1D_imexmri_4_0.001.out b/examples/arkode/C_serial/ark_brusselator1D_imexmri_4_0.001.out index 7059273d48..dce0ab719d 100644 --- a/examples/arkode/C_serial/ark_brusselator1D_imexmri_4_0.001.out +++ b/examples/arkode/C_serial/ark_brusselator1D_imexmri_4_0.001.out @@ -30,7 +30,7 @@ Final Solver Statistics: Slow Steps: nsts = 10001 Fast Steps: nstf = 110011 - Total RHS evals: Fse = 40005, Fsi = 78888, Ff = 330043 + Total RHS evals: Fse = 40005, Fsi = 78888, Ff = 340035 Slow Newton iters = 38883 Slow Newton conv fails = 0 Slow Jacobian evals = 501 diff --git a/examples/arkode/C_serial/ark_brusselator1D_imexmri_5_0.001.out b/examples/arkode/C_serial/ark_brusselator1D_imexmri_5_0.001.out index 827c560b02..e8a70f3986 100644 --- a/examples/arkode/C_serial/ark_brusselator1D_imexmri_5_0.001.out +++ b/examples/arkode/C_serial/ark_brusselator1D_imexmri_5_0.001.out @@ -30,7 +30,7 @@ Final Solver Statistics: Slow Steps: nsts = 10001 Fast Steps: nstf = 110011 - Total RHS evals: Fse = 40005, Fsi = 78888, Ff = 1024335 + Total RHS evals: Fse = 40005, Fsi = 78888, Ff = 1034327 Slow Newton iters = 38883 Slow Newton conv fails = 0 Slow Jacobian evals = 501 diff --git a/examples/arkode/C_serial/ark_brusselator1D_imexmri_6_0.001.out b/examples/arkode/C_serial/ark_brusselator1D_imexmri_6_0.001.out index 79287bd749..4dba64aaf9 100644 --- a/examples/arkode/C_serial/ark_brusselator1D_imexmri_6_0.001.out +++ b/examples/arkode/C_serial/ark_brusselator1D_imexmri_6_0.001.out @@ -30,7 +30,7 @@ Final Solver Statistics: Slow Steps: nsts = 10001 Fast Steps: nstf = 130013 - Total RHS evals: Fse = 60007, Fsi = 118894, Ff = 520062 + Total RHS evals: Fse = 60007, Fsi = 118894, Ff = 530054 Slow Newton iters = 58887 Slow Newton conv fails = 0 Slow Jacobian evals = 501 diff --git a/examples/arkode/C_serial/ark_brusselator1D_imexmri_7_0.001.out b/examples/arkode/C_serial/ark_brusselator1D_imexmri_7_0.001.out index c8dd757582..0ebb4a0a14 100644 --- a/examples/arkode/C_serial/ark_brusselator1D_imexmri_7_0.001.out +++ b/examples/arkode/C_serial/ark_brusselator1D_imexmri_7_0.001.out @@ -30,7 +30,7 @@ Final Solver Statistics: Slow Steps: nsts = 10001 Fast Steps: nstf = 130013 - Total RHS evals: Fse = 60007, Fsi = 118894, Ff = 1936011 + Total RHS evals: Fse = 60007, Fsi = 118894, Ff = 1946003 Slow Newton iters = 58887 Slow Newton conv fails = 0 Slow Jacobian evals = 501 diff --git a/examples/arkode/C_serial/ark_brusselator_1D_mri.c b/examples/arkode/C_serial/ark_brusselator_1D_mri.c index 0dc4323bc3..b5379d12f8 100644 --- a/examples/arkode/C_serial/ark_brusselator_1D_mri.c +++ b/examples/arkode/C_serial/ark_brusselator_1D_mri.c @@ -248,11 +248,8 @@ int main(int argc, char* argv[]) if (check_retval(&retval, "ARKodeSetJacFn", 1)) { return 1; } /* Create inner stepper */ - retval = ARKStepCreateMRIStepInnerStepper(inner_arkode_mem, &inner_stepper); - if (check_retval(&retval, "ARKStepCreateMRIStepInnerStepper", 1)) - { - return 1; - } + retval = ARKodeCreateMRIStepInnerStepper(inner_arkode_mem, &inner_stepper); + if (check_retval(&retval, "ARKodeCreateMRIStepInnerStepper", 1)) { return 1; } /* * Create the slow integrator and set options diff --git a/examples/arkode/C_serial/ark_brusselator_1D_mri.out b/examples/arkode/C_serial/ark_brusselator_1D_mri.out index b1968f6e9d..4442e9e3f9 100644 --- a/examples/arkode/C_serial/ark_brusselator_1D_mri.out +++ b/examples/arkode/C_serial/ark_brusselator_1D_mri.out @@ -112,7 +112,7 @@ Final Solver Statistics: Slow Steps: nsts = 1001 Fast Steps: nstf = 3171 (attempted = 3171) - Total RHS evals: Fs = 3004, Ff = 30611 + Total RHS evals: Fs = 3004, Ff = 31513 Total number of fast error test failures = 0 Total linear solver setups = 3118 Total RHS evals for setting up the linear system = 0 diff --git a/examples/arkode/C_serial/ark_brusselator_mri.c b/examples/arkode/C_serial/ark_brusselator_mri.c index 67d2c57b80..2f1cc006c1 100644 --- a/examples/arkode/C_serial/ark_brusselator_mri.c +++ b/examples/arkode/C_serial/ark_brusselator_mri.c @@ -147,11 +147,8 @@ int main(void) if (check_retval(&retval, "ARKodeSetFixedStep", 1)) { return 1; } /* Create inner stepper */ - retval = ARKStepCreateMRIStepInnerStepper(inner_arkode_mem, &inner_stepper); - if (check_retval(&retval, "ARKStepCreateMRIStepInnerStepper", 1)) - { - return 1; - } + retval = ARKodeCreateMRIStepInnerStepper(inner_arkode_mem, &inner_stepper); + if (check_retval(&retval, "ARKodeCreateMRIStepInnerStepper", 1)) { return 1; } /* * Create the slow integrator and set options diff --git a/examples/arkode/C_serial/ark_brusselator_mri.out b/examples/arkode/C_serial/ark_brusselator_mri.out index 602c2e4177..a9115a8c9e 100644 --- a/examples/arkode/C_serial/ark_brusselator_mri.out +++ b/examples/arkode/C_serial/ark_brusselator_mri.out @@ -31,4 +31,4 @@ Brusselator ODE test problem: Final Solver Statistics: Steps: nsts = 81, nstf = 2187 - Total RHS evals: Fs = 244, Ff = 6581 + Total RHS evals: Fs = 244, Ff = 6643 diff --git a/examples/arkode/C_serial/ark_kpr_mri.c b/examples/arkode/C_serial/ark_kpr_mri.c index f119998632..55f3dd3425 100644 --- a/examples/arkode/C_serial/ark_kpr_mri.c +++ b/examples/arkode/C_serial/ark_kpr_mri.c @@ -34,33 +34,42 @@ * by G, for |G| > 50 it is 'stiff' and ideally suited to a * multirate method that is implicit at the slow time scale. * - * We select the MRI method to use based on an additional input, - * solve_type; with options (slow type-order/fast type-order): - * 0. exp-3/exp-3 (standard MIS) [default] - * 1. none/exp-3 (no slow, explicit fast) - * 2. none/dirk-3 (no slow, dirk fast) - * 3. exp-3/none (explicit slow, no fast) - * 4. dirk-2/none (dirk slow, no fast) -- solve-decoupled - * 5. exp-4/exp-4 (MRI-GARK-ERK45a / ERK-4-4) - * 6. exp-4/exp-3 (MRI-GARK-ERK45a / ERK-3-3) - * 7. dirk-3/exp-3 (MRI-GARK-ESDIRK34a / ERK-3-3) -- solve decoupled - * 8. ars343/exp-3 (IMEX-MRI3b / ERK-3-3) -- solve decoupled - * 9. imexark4/exp-4 (IMEX-MRI4/ ERK-4-4) -- solve decoupled + * We select the MRI method to use based on additional inputs: * - * We note that once we have methods that are IMEX at the slow time - * scale, the nonstiff slow term, [ r'(t)/(2u) ], can be treated - * explicitly. + * slow_type: + * 0 - none (full problem at fast scale) + * 1 - ARKODE_MIS_KW3 + * 2 - ARKODE_MRI_GARK_ERK45a + * 3 - ARKODE_MERK21 + * 4 - ARKODE_MERK32 + * 5 - ARKODE_MERK43 + * 6 - ARKODE_MERK54 + * 7 - ARKODE_MRI_GARK_IRK21a + * 8 - ARKODE_MRI_GARK_ESDIRK34a + * 9 - ARKODE_IMEX_MRI_GARK3b + * 10 - ARKODE_IMEX_MRI_GARK4 + * 11 - ARKODE_IMEX_MRI_SR21 + * 12 - ARKODE_IMEX_MRI_SR32 + * 13 - ARKODE_IMEX_MRI_SR43 * + * fast_type: + * 0 - none (full problem at slow scale) + * 1 - esdirk-3-3 (manually entered non-embedded table) + * 2 - ARKODE_HEUN_EULER_2_1_2 + * 3 - erk-3-3 (manually entered non-embedded table) + * 4 - erk-4-4 (manually entered non-embeded table) + * 5 - ARKODE_DORMAND_PRINCE_7_4_5 + * * The program should be run with arguments in the following order: - * $ a.out solve_type h G w e deduce + * $ ark_kpr_mri slow_type fast_type h G w e deduce_rhs * Not all arguments are required, but these must be omitted from * end-to-beginning, i.e. any one of - * $ a.out solve_type h G w e - * $ a.out solve_type h G w - * $ a.out solve_type h G - * $ a.out solve_type h - * $ a.out solve_type - * $ a.out + * $ ark_kpr_mri slow_type fast_type h G w e deduce_rhs + * $ ark_kpr_mri slow_type fast_type h G w e + * $ ark_kpr_mri slow_type fast_type h G w + * $ ark_kpr_mri slow_type fast_type h G + * $ ark_kpr_mri slow_type fast_type h + * $ ark_kpr_mri slow_type fast_type * are acceptable. We require: * * 0 <= solve_type <= 9 * * 0 < h < 1/|G| @@ -109,6 +118,8 @@ static int Jsi(sunrealtype t, N_Vector y, N_Vector fy, SUNMatrix J, void* user_data, N_Vector tmp1, N_Vector tmp2, N_Vector tmp3); static int Jn(sunrealtype t, N_Vector y, N_Vector fy, SUNMatrix J, void* user_data, N_Vector tmp1, N_Vector tmp2, N_Vector tmp3); +static int Jf(sunrealtype t, N_Vector y, N_Vector fy, SUNMatrix J, + void* user_data, N_Vector tmp1, N_Vector tmp2, N_Vector tmp3); /* Private function to check function return values */ static sunrealtype r(sunrealtype t, void* user_data); @@ -131,7 +142,8 @@ int main(int argc, char* argv[]) sunrealtype dTout = SUN_RCONST(0.1); /* time between outputs */ sunindextype NEQ = 2; /* number of dependent vars. */ int Nt = (int)ceil(Tf / dTout); /* number of output times */ - int solve_type = 0; /* problem configuration type */ + int slow_type = 0; /* problem configuration type */ + int fast_type = 0; /* problem configuration type */ sunrealtype hs = SUN_RCONST(0.01); /* slow step size */ sunrealtype e = SUN_RCONST(0.5); /* fast/slow coupling strength */ sunrealtype G = SUN_RCONST(-100.0); /* stiffness at slow time scale */ @@ -151,9 +163,14 @@ int main(int argc, char* argv[]) SUNLinearSolver LSf = NULL; /* fast linear solver object */ SUNMatrix As = NULL; /* matrix for slow solver */ SUNLinearSolver LSs = NULL; /* slow linear solver object */ - sunbooleantype implicit_slow; - sunbooleantype imex_slow = SUNFALSE; - sunbooleantype deduce = SUNFALSE; + sunbooleantype implicit_slow = SUNFALSE; + sunbooleantype imex_slow = SUNFALSE; + sunbooleantype explicit_slow = SUNFALSE; + sunbooleantype no_slow = SUNFALSE; + sunbooleantype implicit_fast = SUNFALSE; + sunbooleantype explicit_fast = SUNFALSE; + sunbooleantype no_fast = SUNFALSE; + sunbooleantype deduce_rhs = SUNFALSE; FILE* UFID; sunrealtype hf, gamma, beta, t, tout, rpar[3]; sunrealtype uerr, verr, uerrtot, verrtot, errtot; @@ -164,36 +181,55 @@ int main(int argc, char* argv[]) * Initialization */ - /* Retrieve the command-line options: solve_type h G w e */ - if (argc > 1) { solve_type = (sunindextype)atol(argv[1]); } - if (argc > 2) { hs = SUNStrToReal(argv[2]); } - if (argc > 3) { G = SUNStrToReal(argv[3]); } - if (argc > 4) { w = SUNStrToReal(argv[4]); } - if (argc > 5) { e = SUNStrToReal(argv[5]); } - if (argc > 6) { deduce = (sunbooleantype)atoi(argv[6]); } + /* Retrieve the command-line options: slow_type fast_type h G w e deduce_rhs */ + if (argc < 3) + { + printf("ERROR: executable requires at least two arguments [slow_type " + "fast_type]\n"); + printf("Usage:\n"); + printf(" ark_kpr_mri slow_type fast_type h G w e deduce_rhs"); + return (-1); + } + slow_type = atoi(argv[1]); + fast_type = atoi(argv[2]); + if (argc > 3) { hs = SUNStrToReal(argv[3]); } + if (argc > 4) { G = SUNStrToReal(argv[4]); } + if (argc > 5) { w = SUNStrToReal(argv[5]); } + if (argc > 6) { e = SUNStrToReal(argv[6]); } + if (argc > 7) { deduce_rhs = (sunbooleantype)atoi(argv[7]); } /* Check arguments for validity */ - /* 0 <= solve_type <= 9 */ + /* 0 <= slow_type <= 13 */ + /* 0 <= fast_type <= 5 */ /* G < 0.0 */ /* h > 0 */ /* h < 1/|G| (explicit slow) */ /* w >= 1.0 */ - if ((solve_type < 0) || (solve_type > 9)) + if ((slow_type < 0) || (slow_type > 13)) { - printf("ERROR: solve_type be an integer in [0,9] \n"); + printf("ERROR: slow_type be an integer in [0,13] \n"); return (-1); } - if (G >= ZERO) + if ((fast_type < 0) || (fast_type > 5)) { - printf("ERROR: G must be a negative real number\n"); + printf("ERROR: fast_type be an integer in [0,5] \n"); return (-1); } - implicit_slow = SUNFALSE; - if ((solve_type == 4) || (solve_type == 7)) { implicit_slow = SUNTRUE; } - if ((solve_type == 8) || (solve_type == 9)) + if ((slow_type == 0) && (fast_type == 0)) { - implicit_slow = SUNTRUE; - imex_slow = SUNTRUE; + printf("ERROR: at least one of slow_type and fast_type must be nonzero\n"); + return (-1); + } + if ((slow_type >= 9) && (fast_type == 0)) + { + printf("ERROR: example not configured for ImEx slow solver with no fast " + "solver\n"); + return (-1); + } + if (G >= ZERO) + { + printf("ERROR: G must be a negative real number\n"); + return (-1); } if (hs <= ZERO) { @@ -223,51 +259,114 @@ int main(int argc, char* argv[]) printf(" G = %" GSYM "\n", G); printf(" w = %" GSYM "\n", w); printf(" e = %" GSYM "\n", e); - switch (solve_type) + switch (slow_type) { - case (0): printf(" solver: exp-3/exp-3 (standard MIS)\n\n"); break; + case (0): + printf(" slow solver: none\n"); + no_slow = SUNTRUE; + break; case (1): - printf(" solver: none/exp-3 (no slow, explicit fast)\n\n"); + printf(" slow solver: ARKODE_MIS_KW3\n"); + explicit_slow = SUNTRUE; break; case (2): - reltol = SUNMAX(hs * hs * hs, 1e-10); - abstol = 1e-11; - printf(" solver: none/dirk-3 (no slow, dirk fast)\n\n"); - printf(" reltol = %.2" ESYM ", abstol = %.2" ESYM "\n", reltol, abstol); + printf(" slow solver: ARKODE_MRI_GARK_ERK45a\n"); + explicit_slow = SUNTRUE; + break; + case (3): + printf(" slow solver: ARKODE_MERK21\n"); + explicit_slow = SUNTRUE; break; - case (3): printf(" solver: exp-3/none (explicit slow, no fast)\n"); break; case (4): - reltol = SUNMAX(hs * hs, 1e-10); - abstol = 1e-11; - printf(" solver: dirk-2/none (dirk slow, no fast)\n"); - printf(" reltol = %.2" ESYM ", abstol = %.2" ESYM "\n", reltol, abstol); + printf(" slow solver: ARKODE_MERK32\n"); + explicit_slow = SUNTRUE; break; case (5): - printf(" solver: exp-4/exp-4 (MRI-GARK-ERK45a / ERK-4-4)\n\n"); + printf(" slow solver: ARKODE_MERK43\n"); + explicit_slow = SUNTRUE; break; case (6): - printf(" solver: exp-4/exp-3 (MRI-GARK-ERK45a / ERK-3-3)\n\n"); + printf(" slow solver: ARKODE_MERK54\n"); + explicit_slow = SUNTRUE; break; case (7): - reltol = SUNMAX(hs * hs * hs, 1e-10); - abstol = 1e-11; - printf(" solver: dirk-3/exp-3 (MRI-GARK-ESDIRK34a / ERK-3-3) -- solve " - "decoupled\n"); - printf(" reltol = %.2" ESYM ", abstol = %.2" ESYM "\n", reltol, abstol); + printf(" slow solver: ARKODE_MRI_GARK_IRK21a\n"); + implicit_slow = SUNTRUE; + reltol = SUNMAX(hs * hs, 1e-10); + abstol = 1e-11; + printf(" reltol = %.2" ESYM ", abstol = %.2" ESYM "\n", reltol, abstol); break; case (8): - reltol = SUNMAX(hs * hs * hs, 1e-10); - abstol = 1e-11; - printf( - " solver: ars343/exp-3 (IMEX-MRI3b / ERK-3-3) -- solve decoupled\n"); - printf(" reltol = %.2" ESYM ", abstol = %.2" ESYM "\n", reltol, abstol); + printf(" slow solver: ARKODE_MRI_GARK_ESDIRK34a\n"); + implicit_slow = SUNTRUE; + reltol = SUNMAX(hs * hs * hs, 1e-10); + abstol = 1e-11; + printf(" reltol = %.2" ESYM ", abstol = %.2" ESYM "\n", reltol, abstol); break; case (9): - reltol = SUNMAX(hs * hs * hs * hs, 1e-14); - abstol = 1e-14; - printf( - " solver: imexark4/exp-4 (IMEX-MRI4 / ERK-4-4) -- solve decoupled\n"); - printf(" reltol = %.2" ESYM ", abstol = %.2" ESYM "\n", reltol, abstol); + printf(" slow solver: ARKODE_IMEX_MRI_GARK3b\n"); + imex_slow = SUNTRUE; + reltol = SUNMAX(hs * hs * hs, 1e-10); + abstol = 1e-11; + printf(" reltol = %.2" ESYM ", abstol = %.2" ESYM "\n", reltol, abstol); + break; + case (10): + printf(" slow solver: ARKODE_IMEX_MRI_GARK4\n"); + imex_slow = SUNTRUE; + reltol = SUNMAX(hs * hs * hs * hs, 1e-14); + abstol = 1e-14; + printf(" reltol = %.2" ESYM ", abstol = %.2" ESYM "\n", reltol, abstol); + break; + case (11): + printf(" slow solver: ARKODE_IMEX_MRI_SR21\n"); + imex_slow = SUNTRUE; + reltol = SUNMAX(hs * hs, 1e-10); + abstol = 1e-11; + printf(" reltol = %.2" ESYM ", abstol = %.2" ESYM "\n", reltol, abstol); + break; + case (12): + printf(" slow solver: ARKODE_IMEX_MRI_SR32\n"); + imex_slow = SUNTRUE; + reltol = SUNMAX(hs * hs * hs, 1e-10); + abstol = 1e-11; + printf(" reltol = %.2" ESYM ", abstol = %.2" ESYM "\n", reltol, abstol); + break; + case (13): + printf(" slow solver: ARKODE_IMEX_MRI_SR43\n"); + imex_slow = SUNTRUE; + reltol = SUNMAX(hs * hs * hs * hs, 1e-14); + abstol = 1e-14; + printf(" reltol = %.2" ESYM ", abstol = %.2" ESYM "\n", reltol, abstol); + break; + } + switch (fast_type) + { + case (0): + printf(" fast solver: none\n"); + no_fast = SUNTRUE; + break; + case (1): + printf(" fast solver: esdirk-3-3\n"); + implicit_fast = SUNTRUE; + reltol = SUNMAX(hs * hs * hs, 1e-10); + abstol = 1e-11; + printf(" reltol = %.2" ESYM ", abstol = %.2" ESYM "\n", reltol, abstol); + break; + case (2): + printf(" fast solver: ARKODE_HEUN_EULER_2_1_2\n"); + explicit_fast = SUNTRUE; + break; + case (3): + printf(" fast solver: erk-3-3\n"); + explicit_fast = SUNTRUE; + break; + case (4): + printf(" fast solver: erk-4-4\n"); + explicit_fast = SUNTRUE; + break; + case (5): + printf(" fast solver: ARKODE_DORMAND_PRINCE_7_4_5\n"); + explicit_fast = SUNTRUE; break; } @@ -287,35 +386,53 @@ int main(int argc, char* argv[]) /* Initialize the fast integrator. Specify the fast right-hand side function in y'=fs(t,y)+ff(t,y) = fse(t,y)+fsi(t,y)+ff(t,y), the initial time T0, - and the initial dependent variable vector y. */ - switch (solve_type) + and the initial dependent variable vector y. If the fast scale is implicit, + set up matrix, linear solver, and Jacobian function */ + if (implicit_fast) + { + Af = SUNDenseMatrix(NEQ, NEQ, ctx); + if (check_retval((void*)Af, "SUNDenseMatrix", 0)) { return 1; } + LSf = SUNLinSol_Dense(y, Af, ctx); + if (check_retval((void*)LSf, "SUNLinSol_Dense", 0)) { return 1; } + } + if (no_fast) + { + inner_arkode_mem = ARKStepCreate(f0, NULL, T0, y, ctx); + if (check_retval((void*)inner_arkode_mem, "ARKStepCreate", 0)) { return 1; } + } + else if (explicit_fast && !no_slow) { - case (0): - case (6): - case (7): - case (8): /* erk-3-3 fast solver */ inner_arkode_mem = ARKStepCreate(ff, NULL, T0, y, ctx); if (check_retval((void*)inner_arkode_mem, "ARKStepCreate", 0)) { return 1; } - B = ARKodeButcherTable_Alloc(3, SUNTRUE); - if (check_retval((void*)B, "ARKodeButcherTable_Alloc", 0)) { return 1; } - B->A[1][0] = SUN_RCONST(0.5); - B->A[2][0] = -ONE; - B->A[2][1] = TWO; - B->b[0] = ONE / SUN_RCONST(6.0); - B->b[1] = TWO / SUN_RCONST(3.0); - B->b[2] = ONE / SUN_RCONST(6.0); - B->d[1] = ONE; - B->c[1] = SUN_RCONST(0.5); - B->c[2] = ONE; - B->q = 3; - B->p = 2; - retval = ARKStepSetTables(inner_arkode_mem, 3, 2, NULL, B); - if (check_retval(&retval, "ARKStepSetTables", 1)) { return 1; } - ARKodeButcherTable_Free(B); - break; - case (1): /* erk-3-3 fast solver (full problem) */ + } + else if (explicit_fast && no_slow) + { inner_arkode_mem = ARKStepCreate(fn, NULL, T0, y, ctx); if (check_retval((void*)inner_arkode_mem, "ARKStepCreate", 0)) { return 1; } + } + else if (implicit_fast && no_slow) + { + inner_arkode_mem = ARKStepCreate(NULL, fn, T0, y, ctx); + if (check_retval((void*)inner_arkode_mem, "ARKStepCreate", 0)) { return 1; } + retval = ARKodeSetLinearSolver(inner_arkode_mem, LSf, Af); + if (check_retval(&retval, "ARKodeSetLinearSolver", 1)) { return 1; } + retval = ARKodeSetJacFn(inner_arkode_mem, Jn); + if (check_retval(&retval, "ARKodeSetJacFn", 1)) { return 1; } + } + else if (implicit_fast && !no_slow) + { + inner_arkode_mem = ARKStepCreate(NULL, ff, T0, y, ctx); + if (check_retval((void*)inner_arkode_mem, "ARKStepCreate", 0)) { return 1; } + retval = ARKodeSetLinearSolver(inner_arkode_mem, LSf, Af); + if (check_retval(&retval, "ARKodeSetLinearSolver", 1)) { return 1; } + retval = ARKodeSetJacFn(inner_arkode_mem, Jf); + if (check_retval(&retval, "ARKodeSetJacFn", 1)) { return 1; } + } + + /* Set Butcher table for fast integrator */ + switch (fast_type) + { + case (0): B = ARKodeButcherTable_Alloc(3, SUNTRUE); if (check_retval((void*)B, "ARKodeButcherTable_Alloc", 0)) { return 1; } B->A[1][0] = SUN_RCONST(0.5); @@ -331,32 +448,8 @@ int main(int argc, char* argv[]) B->p = 2; retval = ARKStepSetTables(inner_arkode_mem, 3, 2, NULL, B); if (check_retval(&retval, "ARKStepSetTables", 1)) { return 1; } - ARKodeButcherTable_Free(B); - break; - case (9): - case (5): /* erk-4-4 fast solver */ - inner_arkode_mem = ARKStepCreate(ff, NULL, T0, y, ctx); - if (check_retval((void*)inner_arkode_mem, "ARKStepCreate", 0)) { return 1; } - B = ARKodeButcherTable_Alloc(4, SUNFALSE); - if (check_retval((void*)B, "ARKodeButcherTable_Alloc", 0)) { return 1; } - B->A[1][0] = SUN_RCONST(0.5); - B->A[2][1] = SUN_RCONST(0.5); - B->A[3][2] = ONE; - B->b[0] = ONE / SUN_RCONST(6.0); - B->b[1] = ONE / SUN_RCONST(3.0); - B->b[2] = ONE / SUN_RCONST(3.0); - B->b[3] = ONE / SUN_RCONST(6.0); - B->c[1] = SUN_RCONST(0.5); - B->c[2] = SUN_RCONST(0.5); - B->c[3] = ONE; - B->q = 4; - retval = ARKStepSetTables(inner_arkode_mem, 4, 0, NULL, B); - if (check_retval(&retval, "ARKStepSetTables", 1)) { return 1; } - ARKodeButcherTable_Free(B); break; - case (2): /* esdirk-3-3 fast solver (full problem) */ - inner_arkode_mem = ARKStepCreate(NULL, fn, T0, y, ctx); - if (check_retval((void*)inner_arkode_mem, "ARKStepCreate", 0)) { return 1; } + case (1): B = ARKodeButcherTable_Alloc(3, SUNFALSE); if (check_retval((void*)B, "ARKodeButcherTable_Alloc", 0)) { return 1; } beta = SUNRsqrt(SUN_RCONST(3.0)) / SUN_RCONST(6.0) + SUN_RCONST(0.5); @@ -374,22 +467,14 @@ int main(int argc, char* argv[]) B->q = 3; retval = ARKStepSetTables(inner_arkode_mem, 3, 0, B, NULL); if (check_retval(&retval, "ARKStepSetTables", 1)) { return 1; } - Af = SUNDenseMatrix(NEQ, NEQ, ctx); - if (check_retval((void*)Af, "SUNDenseMatrix", 0)) { return 1; } - LSf = SUNLinSol_Dense(y, Af, ctx); - if (check_retval((void*)LSf, "SUNLinSol_Dense", 0)) { return 1; } - retval = ARKodeSetLinearSolver(inner_arkode_mem, LSf, Af); - if (check_retval(&retval, "ARKodeSetLinearSolver", 1)) { return 1; } - retval = ARKodeSetJacFn(inner_arkode_mem, Jn); - if (check_retval(&retval, "ARKodeSetJacFn", 1)) { return 1; } - retval = ARKodeSStolerances(inner_arkode_mem, reltol, abstol); - if (check_retval(&retval, "ARKodeSStolerances", 1)) { return 1; } - ARKodeButcherTable_Free(B); break; - case (3): /* no fast dynamics ('evolve' explicitly w/ erk-3-3) */ - case (4): - inner_arkode_mem = ARKStepCreate(f0, NULL, T0, y, ctx); - if (check_retval((void*)inner_arkode_mem, "ARKStepCreate", 0)) { return 1; } + case (2): + B = ARKodeButcherTable_LoadERK(ARKODE_HEUN_EULER_2_1_2); + if (check_retval((void*)B, "ARKodeButcherTable_LoadERK", 0)) { return 1; } + retval = ARKStepSetTables(inner_arkode_mem, 2, 1, NULL, B); + if (check_retval(&retval, "ARKStepSetTables", 1)) { return 1; } + break; + case (3): B = ARKodeButcherTable_Alloc(3, SUNTRUE); if (check_retval((void*)B, "ARKodeButcherTable_Alloc", 0)) { return 1; } B->A[1][0] = SUN_RCONST(0.5); @@ -405,8 +490,36 @@ int main(int argc, char* argv[]) B->p = 2; retval = ARKStepSetTables(inner_arkode_mem, 3, 2, NULL, B); if (check_retval(&retval, "ARKStepSetTables", 1)) { return 1; } - ARKodeButcherTable_Free(B); + break; + case (4): + B = ARKodeButcherTable_Alloc(4, SUNFALSE); + if (check_retval((void*)B, "ARKodeButcherTable_Alloc", 0)) { return 1; } + B->A[1][0] = SUN_RCONST(0.5); + B->A[2][1] = SUN_RCONST(0.5); + B->A[3][2] = ONE; + B->b[0] = ONE / SUN_RCONST(6.0); + B->b[1] = ONE / SUN_RCONST(3.0); + B->b[2] = ONE / SUN_RCONST(3.0); + B->b[3] = ONE / SUN_RCONST(6.0); + B->c[1] = SUN_RCONST(0.5); + B->c[2] = SUN_RCONST(0.5); + B->c[3] = ONE; + B->q = 4; + retval = ARKStepSetTables(inner_arkode_mem, 4, 0, NULL, B); + if (check_retval(&retval, "ARKStepSetTables", 1)) { return 1; } + break; + case (5): + B = ARKodeButcherTable_LoadERK(ARKODE_DORMAND_PRINCE_7_4_5); + if (check_retval((void*)B, "ARKodeButcherTable_LoadERK", 0)) { return 1; } + retval = ARKStepSetTables(inner_arkode_mem, 5, 4, NULL, B); + if (check_retval(&retval, "ARKStepSetTables", 1)) { return 1; } + break; } + ARKodeButcherTable_Free(B); + + /* Set the tolerances */ + retval = ARKodeSStolerances(inner_arkode_mem, reltol, abstol); + if (check_retval(&retval, "ARKodeSStolerances", 1)) { return 1; } /* Set the user data pointer */ retval = ARKodeSetUserData(inner_arkode_mem, (void*)rpar); @@ -417,11 +530,8 @@ int main(int argc, char* argv[]) if (check_retval(&retval, "ARKodeSetFixedStep", 1)) { return 1; } /* Create inner stepper */ - retval = ARKStepCreateMRIStepInnerStepper(inner_arkode_mem, &inner_stepper); - if (check_retval(&retval, "ARKStepCreateMRIStepInnerStepper", 1)) - { - return 1; - } + retval = ARKodeCreateMRIStepInnerStepper(inner_arkode_mem, &inner_stepper); + if (check_retval(&retval, "ARKodeCreateMRIStepInnerStepper", 1)) { return 1; } /* * Create the slow integrator and set options @@ -429,38 +539,63 @@ int main(int argc, char* argv[]) /* Initialize the slow integrator. Specify the slow right-hand side function in y'=fs(t,y)+ff(t,y) = fse(t,y)+fsi(t,y)+ff(t,y), the initial time - T0, the initial dependent variable vector y, and the fast integrator. */ - switch (solve_type) + T0, the initial dependent variable vector y, and the fast integrator. If + the slow scale contains an implicit component, set up matrix, linear solver, + and Jacobian function. */ + if (implicit_slow || imex_slow) + { + As = SUNDenseMatrix(NEQ, NEQ, ctx); + if (check_retval((void*)As, "SUNDenseMatrix", 0)) { return 1; } + LSs = SUNLinSol_Dense(y, As, ctx); + if (check_retval((void*)LSs, "SUNLinSol_Dense", 0)) { return 1; } + } + if (no_slow) + { + arkode_mem = MRIStepCreate(f0, NULL, T0, y, inner_stepper, ctx); + if (check_retval((void*)arkode_mem, "MRIStepCreate", 0)) { return 1; } + } + else if (explicit_slow && !no_fast) { - case (0): /* KW3 slow solver */ arkode_mem = MRIStepCreate(fs, NULL, T0, y, inner_stepper, ctx); if (check_retval((void*)arkode_mem, "MRIStepCreate", 0)) { return 1; } - C = MRIStepCoupling_LoadTable(ARKODE_MIS_KW3); - if (check_retval((void*)C, "MRIStepCoupling_LoadTable", 0)) { return 1; } - retval = MRIStepSetCoupling(arkode_mem, C); - if (check_retval(&retval, "MRIStepSetCoupling", 1)) { return 1; } - break; - case (3): /* KW3 slow solver (full problem) */ + } + else if (explicit_slow && no_fast) + { arkode_mem = MRIStepCreate(fn, NULL, T0, y, inner_stepper, ctx); if (check_retval((void*)arkode_mem, "MRIStepCreate", 0)) { return 1; } - C = MRIStepCoupling_LoadTable(ARKODE_MIS_KW3); - if (check_retval((void*)C, "MRIStepCoupling_LoadTable", 0)) { return 1; } - retval = MRIStepSetCoupling(arkode_mem, C); - if (check_retval(&retval, "MRIStepSetCoupling", 1)) { return 1; } - break; - case (5): /* MRI-GARK-ERK45a slow solver */ - case (6): - arkode_mem = MRIStepCreate(fs, NULL, T0, y, inner_stepper, ctx); + } + else if (implicit_slow && !no_fast) + { + arkode_mem = MRIStepCreate(NULL, fs, T0, y, inner_stepper, ctx); if (check_retval((void*)arkode_mem, "MRIStepCreate", 0)) { return 1; } - C = MRIStepCoupling_LoadTable(ARKODE_MRI_GARK_ERK45a); - if (check_retval((void*)C, "MRIStepCoupling_LoadTable", 1)) { return 1; } - retval = MRIStepSetCoupling(arkode_mem, C); - if (check_retval(&retval, "MRIStepSetCoupling", 1)) { return 1; } - break; - case (1): - case (2): /* no slow dynamics (use ERK-2-2) */ - arkode_mem = MRIStepCreate(f0, NULL, T0, y, inner_stepper, ctx); + retval = ARKodeSetLinearSolver(arkode_mem, LSs, As); + if (check_retval(&retval, "ARKodeSetLinearSolver", 1)) { return 1; } + retval = ARKodeSetJacFn(arkode_mem, Js); + if (check_retval(&retval, "ARKodeSetJacFn", 1)) { return 1; } + } + else if (implicit_slow && no_fast) + { + arkode_mem = MRIStepCreate(NULL, fn, T0, y, inner_stepper, ctx); + if (check_retval((void*)arkode_mem, "MRIStepCreate", 0)) { return 1; } + retval = ARKodeSetLinearSolver(arkode_mem, LSs, As); + if (check_retval(&retval, "ARKodeSetLinearSolver", 1)) { return 1; } + retval = ARKodeSetJacFn(arkode_mem, Jn); + if (check_retval(&retval, "ARKodeSetJacFn", 1)) { return 1; } + } + else if (imex_slow) + { + arkode_mem = MRIStepCreate(fse, fsi, T0, y, inner_stepper, ctx); if (check_retval((void*)arkode_mem, "MRIStepCreate", 0)) { return 1; } + retval = ARKodeSetLinearSolver(arkode_mem, LSs, As); + if (check_retval(&retval, "ARKodeSetLinearSolver", 1)) { return 1; } + retval = ARKodeSetJacFn(arkode_mem, Jsi); + if (check_retval(&retval, "ARKodeSetJacFn", 1)) { return 1; } + } + + /* Set coupling table for slow integrator */ + switch (slow_type) + { + case (0): /* no slow dynamics (use ERK-2-2) */ B = ARKodeButcherTable_Alloc(2, SUNFALSE); if (check_retval((void*)B, "ARKodeButcherTable_Alloc", 0)) { return 1; } B->A[1][0] = TWO / SUN_RCONST(3.0); @@ -470,89 +605,74 @@ int main(int argc, char* argv[]) B->q = 2; C = MRIStepCoupling_MIStoMRI(B, 2, 0); if (check_retval((void*)C, "MRIStepCoupling_MIStoMRI", 0)) { return 1; } - retval = MRIStepSetCoupling(arkode_mem, C); - if (check_retval(&retval, "MRIStepSetCoupling", 1)) { return 1; } ARKodeButcherTable_Free(B); break; - case (4): /* dirk-2 (trapezoidal), solve-decoupled slow solver */ - arkode_mem = MRIStepCreate(NULL, fn, T0, y, inner_stepper, ctx); - if (check_retval((void*)arkode_mem, "MRIStepCreate", 0)) { return 1; } + case (1): + C = MRIStepCoupling_LoadTable(ARKODE_MIS_KW3); + if (check_retval((void*)C, "MRIStepCoupling_LoadTable", 0)) { return 1; } + break; + case (2): + C = MRIStepCoupling_LoadTable(ARKODE_MRI_GARK_ERK45a); + if (check_retval((void*)C, "MRIStepCoupling_LoadTable", 1)) { return 1; } + break; + case (3): + C = MRIStepCoupling_LoadTable(ARKODE_MERK21); + if (check_retval((void*)C, "MRIStepCoupling_LoadTable", 1)) { return 1; } + break; + case (4): + C = MRIStepCoupling_LoadTable(ARKODE_MERK32); + if (check_retval((void*)C, "MRIStepCoupling_LoadTable", 1)) { return 1; } + break; + case (5): + C = MRIStepCoupling_LoadTable(ARKODE_MERK43); + if (check_retval((void*)C, "MRIStepCoupling_LoadTable", 1)) { return 1; } + break; + case (6): + C = MRIStepCoupling_LoadTable(ARKODE_MERK54); + if (check_retval((void*)C, "MRIStepCoupling_LoadTable", 1)) { return 1; } + break; + case (7): C = MRIStepCoupling_LoadTable(ARKODE_MRI_GARK_IRK21a); if (check_retval((void*)C, "MRIStepCoupling_LoadTable", 1)) { return 1; } - retval = MRIStepSetCoupling(arkode_mem, C); - if (check_retval(&retval, "MRIStepSetCoupling", 1)) { return 1; } - As = SUNDenseMatrix(NEQ, NEQ, ctx); - if (check_retval((void*)As, "SUNDenseMatrix", 0)) { return 1; } - LSs = SUNLinSol_Dense(y, As, ctx); - if (check_retval((void*)LSs, "SUNLinSol_Dense", 0)) { return 1; } - retval = ARKodeSetLinearSolver(arkode_mem, LSs, As); - if (check_retval(&retval, "ARKodeSetLinearSolver", 1)) { return 1; } - retval = ARKodeSetJacFn(arkode_mem, Jn); - if (check_retval(&retval, "ARKodeSetJacFn", 1)) { return 1; } - retval = ARKodeSStolerances(arkode_mem, reltol, abstol); - if (check_retval(&retval, "ARKodeSStolerances", 1)) { return 1; } break; - case (7): /* MRI-GARK-ESDIRK34a, solve-decoupled slow solver */ - arkode_mem = MRIStepCreate(NULL, fs, T0, y, inner_stepper, ctx); - if (check_retval((void*)arkode_mem, "MRIStepCreate", 0)) { return 1; } + case (8): C = MRIStepCoupling_LoadTable(ARKODE_MRI_GARK_ESDIRK34a); if (check_retval((void*)C, "MRIStepCoupling_LoadTable", 1)) { return 1; } - retval = MRIStepSetCoupling(arkode_mem, C); - if (check_retval(&retval, "MRIStepSetCoupling", 1)) { return 1; } - As = SUNDenseMatrix(NEQ, NEQ, ctx); - if (check_retval((void*)As, "SUNDenseMatrix", 0)) { return 1; } - LSs = SUNLinSol_Dense(y, As, ctx); - if (check_retval((void*)LSs, "SUNLinSol_Dense", 0)) { return 1; } - retval = ARKodeSetLinearSolver(arkode_mem, LSs, As); - if (check_retval(&retval, "ARKodeSetLinearSolver", 1)) { return 1; } - retval = ARKodeSetJacFn(arkode_mem, Js); - if (check_retval(&retval, "ARKodeSetJacFn", 1)) { return 1; } - retval = ARKodeSStolerances(arkode_mem, reltol, abstol); - if (check_retval(&retval, "ARKodeSStolerances", 1)) { return 1; } break; - case (8): /* IMEX-MRI-GARK3b, solve-decoupled slow solver */ - arkode_mem = MRIStepCreate(fse, fsi, T0, y, inner_stepper, ctx); - if (check_retval((void*)arkode_mem, "MRIStepCreate", 0)) { return 1; } + case (9): C = MRIStepCoupling_LoadTable(ARKODE_IMEX_MRI_GARK3b); if (check_retval((void*)C, "MRIStepCoupling_LoadTable", 0)) { return 1; } - retval = MRIStepSetCoupling(arkode_mem, C); - if (check_retval(&retval, "MRIStepSetCoupling", 1)) { return 1; } - As = SUNDenseMatrix(NEQ, NEQ, ctx); - if (check_retval((void*)As, "SUNDenseMatrix", 0)) { return 1; } - LSs = SUNLinSol_Dense(y, As, ctx); - if (check_retval((void*)LSs, "SUNLinSol_Dense", 0)) { return 1; } - retval = ARKodeSetLinearSolver(arkode_mem, LSs, As); - if (check_retval(&retval, "ARKodeSetLinearSolver", 1)) { return 1; } - retval = ARKodeSetJacFn(arkode_mem, Jsi); - if (check_retval(&retval, "ARKodeSetJacFn", 1)) { return 1; } - retval = ARKodeSStolerances(arkode_mem, reltol, abstol); - if (check_retval(&retval, "ARKodeSStolerances", 1)) { return 1; } break; - case (9): /* IMEX-MRI-GARK4, solve-decoupled slow solver */ - arkode_mem = MRIStepCreate(fse, fsi, T0, y, inner_stepper, ctx); - if (check_retval((void*)arkode_mem, "MRIStepCreate", 0)) { return 1; } + case (10): C = MRIStepCoupling_LoadTable(ARKODE_IMEX_MRI_GARK4); if (check_retval((void*)C, "MRIStepCoupling_LoadTable", 0)) { return 1; } - retval = MRIStepSetCoupling(arkode_mem, C); - if (check_retval(&retval, "MRIStepSetCoupling", 1)) { return 1; } - As = SUNDenseMatrix(NEQ, NEQ, ctx); - if (check_retval((void*)As, "SUNDenseMatrix", 0)) { return 1; } - LSs = SUNLinSol_Dense(y, As, ctx); - if (check_retval((void*)LSs, "SUNLinSol_Dense", 0)) { return 1; } - retval = ARKodeSetLinearSolver(arkode_mem, LSs, As); - if (check_retval(&retval, "ARKodeSetLinearSolver", 1)) { return 1; } - retval = ARKodeSetJacFn(arkode_mem, Jsi); - if (check_retval(&retval, "ARKodeSetJacFn", 1)) { return 1; } - retval = ARKodeSStolerances(arkode_mem, reltol, abstol); - if (check_retval(&retval, "ARKodeSStolerances", 1)) { return 1; } + break; + case (11): + C = MRIStepCoupling_LoadTable(ARKODE_IMEX_MRI_SR21); + if (check_retval((void*)C, "MRIStepCoupling_LoadTable", 0)) { return 1; } + break; + case (12): + C = MRIStepCoupling_LoadTable(ARKODE_IMEX_MRI_SR32); + if (check_retval((void*)C, "MRIStepCoupling_LoadTable", 0)) { return 1; } + break; + case (13): + C = MRIStepCoupling_LoadTable(ARKODE_IMEX_MRI_SR43); + if (check_retval((void*)C, "MRIStepCoupling_LoadTable", 0)) { return 1; } break; } + retval = MRIStepSetCoupling(arkode_mem, C); + if (check_retval(&retval, "MRIStepSetCoupling", 1)) { return 1; } + MRIStepCoupling_Free(C); /* free coupling coefficients */ + + /* Set the tolerances */ + retval = ARKodeSStolerances(arkode_mem, reltol, abstol); + if (check_retval(&retval, "ARKodeSStolerances", 1)) { return 1; } /* Set the user data pointer */ retval = ARKodeSetUserData(arkode_mem, (void*)rpar); if (check_retval(&retval, "ARKodeSetUserData", 1)) { return 1; } - retval = ARKodeSetDeduceImplicitRhs(arkode_mem, deduce); + retval = ARKodeSetDeduceImplicitRhs(arkode_mem, deduce_rhs); if (check_retval(&retval, "ARKodeSetDeduceImplicitRhs", 1)) { return 1; } /* Set the slow step size */ @@ -655,8 +775,7 @@ int main(int argc, char* argv[]) else { printf(" Total RHS evals: Fs = %li, Ff = %li\n", nfse, nff); } /* Get/print slow integrator decoupled implicit solver statistics */ - if ((solve_type == 4) || (solve_type == 7) || (solve_type == 8) || - (solve_type == 9)) + if (implicit_slow || imex_slow) { retval = ARKodeGetNonlinSolvStats(arkode_mem, &nnis, &nncs); check_retval(&retval, "ARKodeGetNonlinSolvStats", 1); @@ -668,7 +787,7 @@ int main(int argc, char* argv[]) } /* Get/print fast integrator implicit solver statistics */ - if (solve_type == 2) + if (implicit_fast) { retval = ARKodeGetNonlinSolvStats(inner_arkode_mem, &nnif, &nncf); check_retval(&retval, "ARKodeGetNonlinSolvStats", 1); @@ -681,7 +800,6 @@ int main(int argc, char* argv[]) /* Clean up and return */ N_VDestroy(y); /* Free y vector */ - MRIStepCoupling_Free(C); /* free coupling coefficients */ SUNMatDestroy(Af); /* free fast matrix */ SUNLinSolFree(LSf); /* free fast linear solver */ SUNMatDestroy(As); /* free fast matrix */ @@ -871,6 +989,26 @@ static int Jn(sunrealtype t, N_Vector y, N_Vector fy, SUNMatrix J, return 0; } +static int Jf(sunrealtype t, N_Vector y, N_Vector fy, SUNMatrix J, + void* user_data, N_Vector tmp1, N_Vector tmp2, N_Vector tmp3) +{ + sunrealtype* rpar = (sunrealtype*)user_data; + const sunrealtype e = rpar[2]; + const sunrealtype u = NV_Ith_S(y, 0); + const sunrealtype v = NV_Ith_S(y, 1); + + /* fill in the Jacobian: + [ 0 0 ] + [e/2+e*(1+r(t))/(2*u^2) -1/2-(2+s(t))/(2*v^2)] */ + SM_ELEMENT_D(J, 0, 0) = ZERO; + SM_ELEMENT_D(J, 0, 1) = ZERO; + SM_ELEMENT_D(J, 1, 0) = e / TWO + e * (ONE + r(t, rpar)) / (TWO * u * u); + SM_ELEMENT_D(J, 1, 1) = -ONE / TWO - (TWO + s(t, rpar)) / (TWO * v * v); + + /* Return with success */ + return 0; +} + /* ------------------------------ * Private helper functions * ------------------------------*/ diff --git a/examples/arkode/C_serial/ark_kpr_mri.out b/examples/arkode/C_serial/ark_kpr_mri.out deleted file mode 100644 index e551c2cee3..0000000000 --- a/examples/arkode/C_serial/ark_kpr_mri.out +++ /dev/null @@ -1,69 +0,0 @@ - -Multirate nonlinear Kvaerno-Prothero-Robinson test problem: - time domain: (0,5] - hs = 0.01 - hf = 0.0001 - G = -100 - w = 100 - e = 0.5 - solver: exp-3/exp-3 (standard MIS) - - t u v uerr verr - ------------------------------------------------------ - 0.000000 1.224745 1.732051 0.00e+00 0.00e+00 - 0.100000 1.223726 1.077464 8.49e-07 8.80e-09 - 0.200000 1.220670 1.551800 8.43e-07 2.05e-08 - 0.300000 1.215595 1.467737 8.33e-07 3.10e-08 - 0.400000 1.208525 1.154583 8.19e-07 4.03e-08 - 0.500000 1.199497 1.721908 8.00e-07 4.85e-08 - 0.600000 1.188558 1.023517 7.77e-07 5.56e-08 - 0.700000 1.175765 1.622751 7.49e-07 6.17e-08 - 0.800000 1.161187 1.374632 7.16e-07 6.68e-08 - 0.900000 1.144905 1.245763 6.78e-07 7.09e-08 - 1.000000 1.127010 1.691839 6.36e-07 7.40e-08 - 1.100000 1.107610 1.000490 5.87e-07 7.62e-08 - 1.200000 1.086821 1.677552 5.33e-07 7.74e-08 - 1.300000 1.064777 1.277775 4.73e-07 7.77e-08 - 1.400000 1.041626 1.342455 4.06e-07 7.71e-08 - 1.500000 1.017531 1.642940 3.32e-07 7.55e-08 - 1.600000 0.992674 1.012112 2.51e-07 7.29e-08 - 1.700000 0.967253 1.714058 1.61e-07 6.93e-08 - 1.800000 0.941488 1.183867 6.33e-08 6.48e-08 - 1.900000 0.915617 1.437465 4.33e-08 5.91e-08 - 2.000000 0.889902 1.577082 1.59e-07 5.24e-08 - 2.100000 0.864625 1.056467 2.83e-07 4.46e-08 - 2.200000 0.840089 1.730920 4.16e-07 3.57e-08 - 2.300000 0.816616 1.101047 5.56e-07 2.56e-08 - 2.400000 0.794545 1.525051 7.01e-07 1.44e-08 - 2.500000 0.774227 1.496993 8.48e-07 2.09e-09 - 2.600000 0.756012 1.126857 9.92e-07 1.12e-08 - 2.700000 0.740245 1.727536 1.13e-06 2.54e-08 - 2.800000 0.727246 1.038393 1.25e-06 4.01e-08 - 2.900000 0.717300 1.600759 1.35e-06 5.53e-08 - 3.000000 0.710635 1.406379 1.43e-06 7.03e-08 - 3.100000 0.707411 1.214353 1.47e-06 8.49e-08 - 3.200000 0.707708 1.704026 1.47e-06 9.86e-08 - 3.300000 0.711518 1.004391 1.44e-06 1.11e-07 - 3.400000 0.718748 1.661225 1.37e-06 1.21e-07 - 3.500000 0.729225 1.310102 1.28e-06 1.30e-07 - 3.600000 0.742711 1.310080 1.16e-06 1.36e-07 - 3.700000 0.758913 1.661237 1.03e-06 1.40e-07 - 3.800000 0.777505 1.004387 8.82e-07 1.41e-07 - 3.900000 0.798143 1.704018 7.35e-07 1.40e-07 - 4.000000 0.820474 1.214374 5.88e-07 1.37e-07 - 4.100000 0.844149 1.406358 4.47e-07 1.32e-07 - 4.200000 0.868832 1.600774 3.11e-07 1.26e-07 - 4.300000 0.894204 1.038382 1.84e-07 1.18e-07 - 4.400000 0.919964 1.727533 6.62e-08 1.09e-07 - 4.500000 0.945834 1.126875 4.29e-08 9.90e-08 - 4.600000 0.971558 1.496973 1.43e-07 8.85e-08 - 4.700000 0.996898 1.525070 2.35e-07 7.76e-08 - 4.800000 1.021641 1.101030 3.18e-07 6.64e-08 - 4.900000 1.045589 1.730922 3.94e-07 5.51e-08 - 5.000000 1.068565 1.056480 4.62e-07 4.38e-08 - ------------------------------------------------------ - -Final Solver Statistics: - Steps: nsts = 501, nstf = 50601 - u error = 7.941e-07, v error = 8.255e-08, total error = 5.646e-07 - Total RHS evals: Fs = 1504, Ff = 151853 diff --git a/examples/arkode/C_serial/ark_kpr_mri_0_0.002.out b/examples/arkode/C_serial/ark_kpr_mri_0_0.002.out deleted file mode 100644 index ef1ab12278..0000000000 --- a/examples/arkode/C_serial/ark_kpr_mri_0_0.002.out +++ /dev/null @@ -1,69 +0,0 @@ - -Multirate nonlinear Kvaerno-Prothero-Robinson test problem: - time domain: (0,5] - hs = 0.002 - hf = 2e-05 - G = -100 - w = 100 - e = 0.5 - solver: exp-3/exp-3 (standard MIS) - - t u v uerr verr - ------------------------------------------------------ - 0.000000 1.224745 1.732051 0.00e+00 0.00e+00 - 0.100000 1.223725 1.077464 4.99e-09 6.32e-11 - 0.200000 1.220669 1.551800 4.96e-09 1.43e-10 - 0.300000 1.215594 1.467737 4.90e-09 2.14e-10 - 0.400000 1.208524 1.154583 4.81e-09 2.78e-10 - 0.500000 1.199496 1.721908 4.70e-09 3.33e-10 - 0.600000 1.188557 1.023517 4.57e-09 3.82e-10 - 0.700000 1.175764 1.622751 4.40e-09 4.23e-10 - 0.800000 1.161186 1.374632 4.21e-09 4.57e-10 - 0.900000 1.144904 1.245763 3.98e-09 4.85e-10 - 1.000000 1.127010 1.691839 3.73e-09 5.06e-10 - 1.100000 1.107609 1.000489 3.45e-09 5.18e-10 - 1.200000 1.086821 1.677552 3.13e-09 5.29e-10 - 1.300000 1.064777 1.277775 2.77e-09 5.29e-10 - 1.400000 1.041625 1.342455 2.38e-09 5.25e-10 - 1.500000 1.017531 1.642940 1.94e-09 5.14e-10 - 1.600000 0.992673 1.012112 1.46e-09 4.94e-10 - 1.700000 0.967253 1.714058 9.32e-10 4.72e-10 - 1.800000 0.941488 1.183867 3.54e-10 4.39e-10 - 1.900000 0.915617 1.437465 2.75e-10 4.01e-10 - 2.000000 0.889903 1.577082 9.56e-10 3.55e-10 - 2.100000 0.864625 1.056467 1.69e-09 3.05e-10 - 2.200000 0.840089 1.730920 2.47e-09 2.38e-10 - 2.300000 0.816616 1.101047 3.30e-09 1.73e-10 - 2.400000 0.794546 1.525051 4.15e-09 9.32e-11 - 2.500000 0.774227 1.496993 5.01e-09 8.75e-12 - 2.600000 0.756013 1.126857 5.86e-09 8.02e-11 - 2.700000 0.740246 1.727536 6.67e-09 1.81e-10 - 2.800000 0.727247 1.038393 7.38e-09 2.78e-10 - 2.900000 0.717301 1.600759 7.97e-09 3.85e-10 - 3.000000 0.710636 1.406380 8.40e-09 4.87e-10 - 3.100000 0.707412 1.214353 8.63e-09 5.85e-10 - 3.200000 0.707709 1.704026 8.65e-09 6.81e-10 - 3.300000 0.711520 1.004391 8.46e-09 7.60e-10 - 3.400000 0.718750 1.661225 8.06e-09 8.35e-10 - 3.500000 0.729227 1.310102 7.50e-09 8.89e-10 - 3.600000 0.742712 1.310080 6.80e-09 9.30e-10 - 3.700000 0.758914 1.661237 6.01e-09 9.57e-10 - 3.800000 0.777506 1.004387 5.16e-09 9.60e-10 - 3.900000 0.798144 1.704019 4.29e-09 9.58e-10 - 4.000000 0.820474 1.214374 3.43e-09 9.33e-10 - 4.100000 0.844149 1.406358 2.60e-09 9.00e-10 - 4.200000 0.868832 1.600774 1.81e-09 8.56e-10 - 4.300000 0.894204 1.038382 1.06e-09 7.99e-10 - 4.400000 0.919964 1.727533 3.69e-10 7.42e-10 - 4.500000 0.945834 1.126875 2.71e-10 6.70e-10 - 4.600000 0.971557 1.496974 8.58e-10 6.01e-10 - 4.700000 0.996898 1.525070 1.40e-09 5.27e-10 - 4.800000 1.021641 1.101030 1.88e-09 4.48e-10 - 4.900000 1.045589 1.730922 2.33e-09 3.74e-10 - 5.000000 1.068565 1.056480 2.73e-09 2.92e-10 - ------------------------------------------------------ - -Final Solver Statistics: - Steps: nsts = 2501, nstf = 252601 - u error = 4.671e-09, v error = 5.638e-10, total error = 3.327e-09 - Total RHS evals: Fs = 7504, Ff = 757853 diff --git a/examples/arkode/C_serial/ark_kpr_mri_2_0.005.out b/examples/arkode/C_serial/ark_kpr_mri_0_1_0.005.out similarity index 97% rename from examples/arkode/C_serial/ark_kpr_mri_2_0.005.out rename to examples/arkode/C_serial/ark_kpr_mri_0_1_0.005.out index abedbafb39..59f23631ed 100644 --- a/examples/arkode/C_serial/ark_kpr_mri_2_0.005.out +++ b/examples/arkode/C_serial/ark_kpr_mri_0_1_0.005.out @@ -6,9 +6,9 @@ Multirate nonlinear Kvaerno-Prothero-Robinson test problem: G = -100 w = 100 e = 0.5 - solver: none/dirk-3 (no slow, dirk fast) - - reltol = 1.25e-07, abstol = 1.00e-11 + slow solver: none + fast solver: esdirk-3-3 + reltol = 1.25e-07, abstol = 1.00e-11 t u v uerr verr ------------------------------------------------------ 0.000000 1.224745 1.732051 0.00e+00 0.00e+00 diff --git a/examples/arkode/C_serial/ark_kpr_mri_10_4_0.001_-100_100_0.5_1.out b/examples/arkode/C_serial/ark_kpr_mri_10_4_0.001_-100_100_0.5_1.out new file mode 100644 index 0000000000..fe552cf2b6 --- /dev/null +++ b/examples/arkode/C_serial/ark_kpr_mri_10_4_0.001_-100_100_0.5_1.out @@ -0,0 +1,73 @@ + +Multirate nonlinear Kvaerno-Prothero-Robinson test problem: + time domain: (0,5] + hs = 0.001 + hf = 1e-05 + G = -100 + w = 100 + e = 0.5 + slow solver: ARKODE_IMEX_MRI_GARK4 + reltol = 1.00e-12, abstol = 1.00e-14 + fast solver: erk-4-4 + t u v uerr verr + ------------------------------------------------------ + 0.000000 1.224745 1.732051 0.00e+00 0.00e+00 + 0.100000 1.223725 1.077464 1.64e-11 6.38e-13 + 0.200000 1.220669 1.551800 1.61e-11 6.85e-13 + 0.300000 1.215594 1.467737 1.58e-11 9.70e-13 + 0.400000 1.208524 1.154583 1.55e-11 9.37e-13 + 0.500000 1.199496 1.721908 1.57e-11 1.74e-12 + 0.600000 1.188557 1.023517 1.50e-11 3.45e-12 + 0.700000 1.175764 1.622751 1.40e-11 2.20e-12 + 0.800000 1.161186 1.374632 1.20e-11 2.83e-12 + 0.900000 1.144904 1.245763 1.23e-11 3.18e-12 + 1.000000 1.127010 1.691839 1.28e-11 2.23e-12 + 1.100000 1.107609 1.000489 1.13e-11 1.92e-12 + 1.200000 1.086821 1.677552 9.92e-12 2.55e-12 + 1.300000 1.064777 1.277775 7.66e-12 1.74e-13 + 1.400000 1.041625 1.342455 6.65e-12 7.06e-13 + 1.500000 1.017531 1.642940 6.43e-12 2.73e-12 + 1.600000 0.992673 1.012112 4.49e-12 1.24e-12 + 1.700000 0.967253 1.714058 3.11e-12 3.19e-12 + 1.800000 0.941488 1.183867 5.76e-14 2.22e-13 + 1.900000 0.915617 1.437465 1.88e-12 1.29e-12 + 2.000000 0.889903 1.577082 4.65e-12 2.09e-12 + 2.100000 0.864625 1.056467 6.53e-12 1.44e-12 + 2.200000 0.840089 1.730920 7.39e-12 2.63e-12 + 2.300000 0.816616 1.101047 1.16e-11 1.62e-12 + 2.400000 0.794546 1.525051 1.48e-11 7.30e-13 + 2.500000 0.774227 1.496993 1.92e-11 2.40e-13 + 2.600000 0.756013 1.126857 2.04e-11 2.57e-12 + 2.700000 0.740246 1.727536 2.11e-11 8.85e-13 + 2.800000 0.727247 1.038393 2.44e-11 3.90e-12 + 2.900000 0.717301 1.600759 2.66e-11 7.89e-13 + 3.000000 0.710636 1.406380 2.78e-11 2.46e-12 + 3.100000 0.707412 1.214353 2.84e-11 4.12e-12 + 3.200000 0.707709 1.704026 2.84e-11 1.38e-12 + 3.300000 0.711520 1.004391 2.77e-11 6.21e-12 + 3.400000 0.718750 1.661225 2.61e-11 2.33e-12 + 3.500000 0.729227 1.310102 2.42e-11 4.77e-12 + 3.600000 0.742712 1.310080 2.16e-11 4.95e-12 + 3.700000 0.758914 1.661237 1.99e-11 2.79e-12 + 3.800000 0.777506 1.004387 1.67e-11 6.97e-12 + 3.900000 0.798144 1.704019 1.39e-11 2.45e-12 + 4.000000 0.820474 1.214374 1.05e-11 5.41e-12 + 4.100000 0.844149 1.406358 7.59e-12 8.30e-12 + 4.200000 0.868832 1.600774 5.04e-12 1.14e-11 + 4.300000 0.894204 1.038382 2.82e-12 3.27e-13 + 4.400000 0.919964 1.727533 1.81e-12 1.24e-11 + 4.500000 0.945834 1.126875 1.89e-12 8.42e-13 + 4.600000 0.971557 1.496974 3.73e-12 6.99e-12 + 4.700000 0.996898 1.525070 5.90e-12 7.03e-12 + 4.800000 1.021641 1.101030 7.16e-12 1.43e-12 + 4.900000 1.045589 1.730922 6.80e-12 9.68e-12 + 5.000000 1.068565 1.056480 9.34e-12 3.23e-12 + ------------------------------------------------------ + +Final Solver Statistics: + Steps: nsts = 5000, nstf = 510000 + u error = 1.533e-11, v error = 4.203e-12, total error = 1.124e-11 + Total RHS evals: Fse = 30001, Fsi = 57555, Ff = 2045001 + Slow Newton iters = 52554 + Slow Newton conv fails = 0 + Slow Jacobian evals = 250 diff --git a/examples/arkode/C_serial/ark_kpr_mri_11_2_0.001.out b/examples/arkode/C_serial/ark_kpr_mri_11_2_0.001.out new file mode 100644 index 0000000000..f34f31abb5 --- /dev/null +++ b/examples/arkode/C_serial/ark_kpr_mri_11_2_0.001.out @@ -0,0 +1,73 @@ + +Multirate nonlinear Kvaerno-Prothero-Robinson test problem: + time domain: (0,5] + hs = 0.001 + hf = 1e-05 + G = -100 + w = 100 + e = 0.5 + slow solver: ARKODE_IMEX_MRI_SR21 + reltol = 1.00e-06, abstol = 1.00e-11 + fast solver: ARKODE_HEUN_EULER_2_1_2 + t u v uerr verr + ------------------------------------------------------ + 0.000000 1.224745 1.732051 0.00e+00 0.00e+00 + 0.100000 1.223724 1.077464 3.33e-07 4.20e-08 + 0.200000 1.220669 1.551800 4.24e-07 8.85e-09 + 0.300000 1.215593 1.467737 1.15e-06 1.86e-08 + 0.400000 1.208524 1.154583 5.07e-07 2.20e-09 + 0.500000 1.199497 1.721908 2.65e-07 4.68e-08 + 0.600000 1.188557 1.023517 7.96e-08 1.14e-08 + 0.700000 1.175764 1.622750 3.38e-07 5.33e-08 + 0.800000 1.161186 1.374632 2.38e-07 5.06e-08 + 0.900000 1.144903 1.245763 5.34e-07 3.98e-08 + 1.000000 1.127010 1.691839 2.21e-07 7.09e-08 + 1.100000 1.107609 1.000489 4.62e-08 9.12e-09 + 1.200000 1.086820 1.677552 2.34e-07 8.42e-08 + 1.300000 1.064776 1.277775 2.44e-07 6.08e-08 + 1.400000 1.041625 1.342455 5.10e-07 6.67e-08 + 1.500000 1.017531 1.642940 6.50e-08 8.39e-08 + 1.600000 0.992673 1.012112 1.90e-07 3.00e-08 + 1.700000 0.967253 1.714058 6.43e-08 9.87e-08 + 1.800000 0.941487 1.183866 9.42e-07 6.18e-08 + 1.900000 0.915617 1.437465 5.51e-07 8.36e-08 + 2.000000 0.889902 1.577082 5.63e-07 9.28e-08 + 2.100000 0.864625 1.056467 3.79e-07 4.72e-08 + 2.200000 0.840089 1.730920 1.91e-07 1.01e-07 + 2.300000 0.816616 1.101047 4.88e-07 5.28e-08 + 2.400000 0.794545 1.525051 4.88e-07 9.00e-08 + 2.500000 0.774227 1.496993 1.22e-07 9.18e-08 + 2.600000 0.756012 1.126857 5.41e-07 5.83e-08 + 2.700000 0.740246 1.727536 1.69e-07 1.03e-07 + 2.800000 0.727247 1.038393 2.16e-07 4.30e-08 + 2.900000 0.717301 1.600759 4.45e-07 9.81e-08 + 3.000000 0.710636 1.406379 1.65e-07 8.71e-08 + 3.100000 0.707412 1.214353 5.06e-07 6.86e-08 + 3.200000 0.707710 1.704026 1.90e-07 1.02e-07 + 3.300000 0.711519 1.004391 1.00e-07 3.73e-08 + 3.400000 0.718749 1.661225 2.14e-07 1.01e-07 + 3.500000 0.729226 1.310102 2.53e-07 7.93e-08 + 3.600000 0.742711 1.310080 3.52e-07 8.04e-08 + 3.700000 0.758914 1.661237 1.20e-08 9.89e-08 + 3.800000 0.777506 1.004387 1.70e-07 4.01e-08 + 3.900000 0.798144 1.704018 1.75e-08 1.03e-07 + 4.000000 0.820473 1.214374 1.10e-06 7.09e-08 + 4.100000 0.844149 1.406358 4.60e-07 8.77e-08 + 4.200000 0.868832 1.600774 3.92e-07 9.80e-08 + 4.300000 0.894203 1.038382 3.30e-07 5.31e-08 + 4.400000 0.919964 1.727533 1.58e-07 1.09e-07 + 4.500000 0.945833 1.126875 6.42e-07 6.63e-08 + 4.600000 0.971557 1.496973 4.87e-07 9.63e-08 + 4.700000 0.996897 1.525070 8.90e-07 1.01e-07 + 4.800000 1.021640 1.101030 4.60e-07 6.49e-08 + 4.900000 1.045589 1.730922 3.00e-07 1.08e-07 + 5.000000 1.068565 1.056480 2.32e-07 5.06e-08 + ------------------------------------------------------ + +Final Solver Statistics: + Steps: nsts = 5000, nstf = 935000 + u error = 4.409e-07, v error = 7.409e-08, total error = 3.161e-07 + Total RHS evals: Fse = 15001, Fsi = 32981, Ff = 1875001 + Slow Newton iters = 17980 + Slow Newton conv fails = 0 + Slow Jacobian evals = 250 diff --git a/examples/arkode/C_serial/ark_kpr_mri_12_3_0.005.out b/examples/arkode/C_serial/ark_kpr_mri_12_3_0.005.out new file mode 100644 index 0000000000..248f0c3b32 --- /dev/null +++ b/examples/arkode/C_serial/ark_kpr_mri_12_3_0.005.out @@ -0,0 +1,73 @@ + +Multirate nonlinear Kvaerno-Prothero-Robinson test problem: + time domain: (0,5] + hs = 0.005 + hf = 5e-05 + G = -100 + w = 100 + e = 0.5 + slow solver: ARKODE_IMEX_MRI_SR32 + reltol = 1.25e-07, abstol = 1.00e-11 + fast solver: erk-3-3 + t u v uerr verr + ------------------------------------------------------ + 0.000000 1.224745 1.732051 0.00e+00 0.00e+00 + 0.100000 1.223725 1.077464 1.04e-07 1.78e-10 + 0.200000 1.220669 1.551800 1.03e-07 3.02e-10 + 0.300000 1.215594 1.467737 1.04e-07 7.49e-10 + 0.400000 1.208524 1.154583 1.03e-07 1.17e-09 + 0.500000 1.199496 1.721908 1.01e-07 1.58e-09 + 0.600000 1.188557 1.023517 9.63e-08 1.93e-09 + 0.700000 1.175764 1.622751 9.18e-08 2.23e-09 + 0.800000 1.161186 1.374632 9.21e-08 2.49e-09 + 0.900000 1.144904 1.245763 8.98e-08 2.75e-09 + 1.000000 1.127010 1.691839 8.66e-08 3.02e-09 + 1.100000 1.107609 1.000489 7.61e-08 3.25e-09 + 1.200000 1.086821 1.677552 6.53e-08 3.39e-09 + 1.300000 1.064777 1.277775 6.27e-08 3.48e-09 + 1.400000 1.041626 1.342455 5.85e-08 3.54e-09 + 1.500000 1.017531 1.642940 5.47e-08 3.65e-09 + 1.600000 0.992673 1.012112 3.94e-08 3.74e-09 + 1.700000 0.967253 1.714058 2.18e-08 3.76e-09 + 1.800000 0.941488 1.183867 1.09e-08 3.66e-09 + 1.900000 0.915617 1.437465 2.03e-09 3.48e-09 + 2.000000 0.889903 1.577082 3.28e-09 3.36e-09 + 2.100000 0.864625 1.056467 2.22e-08 3.24e-09 + 2.200000 0.840089 1.730920 4.49e-08 3.09e-09 + 2.300000 0.816616 1.101047 6.69e-08 2.78e-09 + 2.400000 0.794546 1.525051 8.32e-08 2.32e-09 + 2.500000 0.774227 1.496993 9.13e-08 1.89e-09 + 2.600000 0.756013 1.126857 1.10e-07 1.47e-09 + 2.700000 0.740246 1.727536 1.30e-07 1.05e-09 + 2.800000 0.727247 1.038393 1.52e-07 4.97e-10 + 2.900000 0.717301 1.600759 1.66e-07 1.62e-10 + 3.000000 0.710636 1.406380 1.70e-07 7.36e-10 + 3.100000 0.707412 1.214353 1.76e-07 1.36e-09 + 3.200000 0.707709 1.704026 1.78e-07 1.97e-09 + 3.300000 0.711519 1.004391 1.75e-07 2.57e-09 + 3.400000 0.718749 1.661225 1.66e-07 3.12e-09 + 3.500000 0.729227 1.310102 2.06e-07 4.23e-09 + 3.600000 0.742712 1.310080 1.46e-07 4.79e-09 + 3.700000 0.758914 1.661237 1.35e-07 5.10e-09 + 3.800000 0.777506 1.004387 1.13e-07 5.35e-09 + 3.900000 0.798144 1.704019 8.93e-08 5.73e-09 + 4.000000 0.820474 1.214374 7.47e-08 5.72e-09 + 4.100000 0.844149 1.406358 6.22e-08 5.61e-09 + 4.200000 0.868832 1.600774 5.40e-08 5.54e-09 + 4.300000 0.894204 1.038382 3.41e-08 5.46e-09 + 4.400000 0.919964 1.727533 1.30e-08 5.34e-09 + 4.500000 0.945834 1.126875 2.93e-09 5.06e-09 + 4.600000 0.971557 1.496974 1.25e-08 4.68e-09 + 4.700000 0.996898 1.525070 1.46e-08 4.35e-09 + 4.800000 1.021641 1.101030 2.63e-08 4.06e-09 + 4.900000 1.045589 1.730922 3.94e-08 3.79e-09 + 5.000000 1.068565 1.056480 5.40e-08 3.42e-09 + ------------------------------------------------------ + +Final Solver Statistics: + Steps: nsts = 1001, nstf = 362362 + u error = 9.913e-08, v error = 3.506e-09, total error = 7.014e-08 + Total RHS evals: Fse = 4005, Fsi = 12096, Ff = 1088088 + Slow Newton iters = 8091 + Slow Newton conv fails = 0 + Slow Jacobian evals = 51 diff --git a/examples/arkode/C_serial/ark_kpr_mri_13_4_0.01.out b/examples/arkode/C_serial/ark_kpr_mri_13_4_0.01.out new file mode 100644 index 0000000000..868d51e963 --- /dev/null +++ b/examples/arkode/C_serial/ark_kpr_mri_13_4_0.01.out @@ -0,0 +1,73 @@ + +Multirate nonlinear Kvaerno-Prothero-Robinson test problem: + time domain: (0,5] + hs = 0.01 + hf = 0.0001 + G = -100 + w = 100 + e = 0.5 + slow solver: ARKODE_IMEX_MRI_SR43 + reltol = 1.00e-08, abstol = 1.00e-14 + fast solver: erk-4-4 + t u v uerr verr + ------------------------------------------------------ + 0.000000 1.224745 1.732051 0.00e+00 0.00e+00 + 0.100000 1.223725 1.077464 7.51e-08 2.97e-08 + 0.200000 1.220669 1.551800 7.47e-08 5.67e-08 + 0.300000 1.215594 1.467737 7.40e-08 8.09e-08 + 0.400000 1.208524 1.154583 7.27e-08 1.02e-07 + 0.500000 1.199496 1.721908 7.14e-08 1.21e-07 + 0.600000 1.188557 1.023517 6.91e-08 1.37e-07 + 0.700000 1.175764 1.622750 6.68e-08 1.51e-07 + 0.800000 1.161186 1.374632 6.39e-08 1.63e-07 + 0.900000 1.144904 1.245763 6.08e-08 1.72e-07 + 1.000000 1.127010 1.691839 5.67e-08 1.79e-07 + 1.100000 1.107609 1.000489 5.49e-08 1.83e-07 + 1.200000 1.086820 1.677552 4.79e-08 1.85e-07 + 1.300000 1.064777 1.277775 4.43e-08 1.85e-07 + 1.400000 1.041625 1.342455 3.64e-08 1.83e-07 + 1.500000 1.017531 1.642940 3.04e-08 1.79e-07 + 1.600000 0.992673 1.012112 2.26e-08 1.72e-07 + 1.700000 0.967253 1.714058 1.02e-08 1.62e-07 + 1.800000 0.941488 1.183866 6.48e-09 1.51e-07 + 1.900000 0.915617 1.437465 3.83e-09 1.36e-07 + 2.000000 0.889903 1.577082 1.47e-08 1.20e-07 + 2.100000 0.864625 1.056467 2.48e-08 1.00e-07 + 2.200000 0.840089 1.730920 3.69e-08 7.78e-08 + 2.300000 0.816616 1.101047 5.28e-08 5.29e-08 + 2.400000 0.794546 1.525051 6.32e-08 2.51e-08 + 2.500000 0.774228 1.496993 7.57e-08 5.16e-09 + 2.600000 0.756013 1.126857 8.92e-08 3.76e-08 + 2.700000 0.740246 1.727536 1.01e-07 7.20e-08 + 2.800000 0.727248 1.038393 1.12e-07 1.08e-07 + 2.900000 0.717301 1.600759 1.21e-07 1.44e-07 + 3.000000 0.710636 1.406380 1.27e-07 1.79e-07 + 3.100000 0.707413 1.214353 1.31e-07 2.14e-07 + 3.200000 0.707710 1.704026 1.31e-07 2.45e-07 + 3.300000 0.711520 1.004391 1.28e-07 2.73e-07 + 3.400000 0.718750 1.661225 1.22e-07 2.97e-07 + 3.500000 0.729227 1.310102 1.14e-07 3.15e-07 + 3.600000 0.742712 1.310080 1.03e-07 3.28e-07 + 3.700000 0.758914 1.661237 9.11e-08 3.35e-07 + 3.800000 0.777506 1.004387 7.85e-08 3.36e-07 + 3.900000 0.798144 1.704019 6.30e-08 3.32e-07 + 4.000000 0.820474 1.214374 5.22e-08 3.24e-07 + 4.100000 0.844149 1.406358 4.01e-08 3.11e-07 + 4.200000 0.868832 1.600775 2.78e-08 2.94e-07 + 4.300000 0.894204 1.038382 1.74e-08 2.75e-07 + 4.400000 0.919964 1.727534 6.17e-09 2.53e-07 + 4.500000 0.945834 1.126875 2.12e-09 2.29e-07 + 4.600000 0.971557 1.496974 1.37e-08 2.03e-07 + 4.700000 0.996898 1.525070 1.98e-08 1.77e-07 + 4.800000 1.021641 1.101030 2.80e-08 1.50e-07 + 4.900000 1.045589 1.730922 4.06e-08 1.23e-07 + 5.000000 1.068565 1.056480 4.09e-08 9.61e-08 + ------------------------------------------------------ + +Final Solver Statistics: + Steps: nsts = 501, nstf = 202905 + u error = 7.089e-08, v error = 1.972e-07, total error = 1.482e-07 + Total RHS evals: Fse = 3007, Fsi = 8869, Ff = 812122 + Slow Newton iters = 5862 + Slow Newton conv fails = 0 + Slow Jacobian evals = 26 diff --git a/examples/arkode/C_serial/ark_kpr_mri_1_0.002.out b/examples/arkode/C_serial/ark_kpr_mri_1_0.002.out deleted file mode 100644 index 2cb8b8d4ff..0000000000 --- a/examples/arkode/C_serial/ark_kpr_mri_1_0.002.out +++ /dev/null @@ -1,69 +0,0 @@ - -Multirate nonlinear Kvaerno-Prothero-Robinson test problem: - time domain: (0,5] - hs = 0.002 - hf = 2e-05 - G = -100 - w = 100 - e = 0.5 - solver: none/exp-3 (no slow, explicit fast) - - t u v uerr verr - ------------------------------------------------------ - 0.000000 1.224745 1.732051 0.00e+00 0.00e+00 - 0.100000 1.223725 1.077464 5.15e-13 1.86e-13 - 0.200000 1.220669 1.551800 3.61e-13 4.93e-14 - 0.300000 1.215594 1.467737 2.05e-13 2.51e-13 - 0.400000 1.208524 1.154583 9.50e-14 5.58e-13 - 0.500000 1.199496 1.721908 2.07e-13 4.33e-14 - 0.600000 1.188557 1.023517 4.75e-13 6.09e-13 - 0.700000 1.175764 1.622751 3.64e-13 3.18e-14 - 0.800000 1.161186 1.374632 3.10e-13 2.24e-13 - 0.900000 1.144904 1.245763 1.97e-13 3.70e-13 - 1.000000 1.127010 1.691839 1.30e-13 1.26e-13 - 1.100000 1.107609 1.000489 3.46e-13 3.11e-12 - 1.200000 1.086821 1.677552 3.71e-13 7.33e-14 - 1.300000 1.064777 1.277775 3.83e-13 1.61e-12 - 1.400000 1.041625 1.342455 2.93e-13 1.22e-12 - 1.500000 1.017531 1.642940 5.93e-14 2.38e-13 - 1.600000 0.992673 1.012112 2.03e-13 2.53e-12 - 1.700000 0.967253 1.714058 3.44e-13 7.20e-13 - 1.800000 0.941488 1.183867 4.52e-13 1.59e-12 - 1.900000 0.915617 1.437465 3.44e-13 3.82e-13 - 2.000000 0.889903 1.577082 3.50e-14 3.23e-13 - 2.100000 0.864625 1.056467 9.49e-14 3.63e-12 - 2.200000 0.840089 1.730920 2.82e-13 9.77e-13 - 2.300000 0.816616 1.101047 5.31e-13 3.10e-12 - 2.400000 0.794546 1.525051 3.55e-13 1.45e-13 - 2.500000 0.774227 1.496993 1.73e-13 1.47e-13 - 2.600000 0.756013 1.126857 5.61e-14 2.76e-12 - 2.700000 0.740246 1.727536 2.34e-13 1.63e-12 - 2.800000 0.727247 1.038393 4.93e-13 3.33e-12 - 2.900000 0.717301 1.600759 3.84e-13 8.97e-13 - 3.000000 0.710636 1.406380 2.69e-13 3.69e-13 - 3.100000 0.707412 1.214353 1.84e-13 1.89e-12 - 3.200000 0.707709 1.704026 1.75e-13 1.92e-12 - 3.300000 0.711520 1.004391 3.96e-13 3.62e-12 - 3.400000 0.718750 1.661225 3.90e-13 1.72e-12 - 3.500000 0.729227 1.310102 3.60e-13 8.16e-13 - 3.600000 0.742712 1.310080 2.78e-13 9.20e-13 - 3.700000 0.758914 1.661237 9.77e-14 1.96e-12 - 3.800000 0.777506 1.004387 2.59e-13 3.77e-12 - 3.900000 0.798144 1.704019 3.72e-13 2.32e-12 - 4.000000 0.820474 1.214374 4.43e-13 1.53e-12 - 4.100000 0.844149 1.406358 3.40e-13 1.78e-14 - 4.200000 0.868832 1.600774 6.66e-16 1.74e-12 - 4.300000 0.894204 1.038382 1.07e-13 3.58e-12 - 4.400000 0.919964 1.727533 3.31e-13 2.75e-12 - 4.500000 0.945834 1.126875 4.96e-13 2.41e-12 - 4.600000 0.971557 1.496974 3.76e-13 9.10e-13 - 4.700000 0.996898 1.525070 1.11e-13 1.32e-12 - 4.800000 1.021641 1.101030 3.06e-14 2.99e-12 - 4.900000 1.045589 1.730922 2.75e-13 3.00e-12 - 5.000000 1.068565 1.056480 5.02e-13 3.36e-12 - ------------------------------------------------------ - -Final Solver Statistics: - Steps: nsts = 2501, nstf = 252601 - u error = 3.156e-13, v error = 1.909e-12, total error = 1.368e-12 - Total RHS evals: Fs = 5003, Ff = 757853 diff --git a/examples/arkode/C_serial/ark_kpr_mri_3_0.01.out b/examples/arkode/C_serial/ark_kpr_mri_1_0_0.01.out similarity index 97% rename from examples/arkode/C_serial/ark_kpr_mri_3_0.01.out rename to examples/arkode/C_serial/ark_kpr_mri_1_0_0.01.out index 9504b4c524..ef66f4a445 100644 --- a/examples/arkode/C_serial/ark_kpr_mri_3_0.01.out +++ b/examples/arkode/C_serial/ark_kpr_mri_1_0_0.01.out @@ -6,7 +6,8 @@ Multirate nonlinear Kvaerno-Prothero-Robinson test problem: G = -100 w = 100 e = 0.5 - solver: exp-3/none (explicit slow, no fast) + slow solver: ARKODE_MIS_KW3 + fast solver: none t u v uerr verr ------------------------------------------------------ 0.000000 1.224745 1.732051 0.00e+00 0.00e+00 @@ -65,4 +66,4 @@ Multirate nonlinear Kvaerno-Prothero-Robinson test problem: Final Solver Statistics: Steps: nsts = 501, nstf = 50601 u error = 5.052e-05, v error = 7.684e-04, total error = 5.445e-04 - Total RHS evals: Fs = 1504, Ff = 151853 + Total RHS evals: Fs = 1504, Ff = 152305 diff --git a/examples/arkode/C_serial/ark_kpr_mri_1_1_0.002.out b/examples/arkode/C_serial/ark_kpr_mri_1_1_0.002.out new file mode 100644 index 0000000000..ce045454c5 --- /dev/null +++ b/examples/arkode/C_serial/ark_kpr_mri_1_1_0.002.out @@ -0,0 +1,73 @@ + +Multirate nonlinear Kvaerno-Prothero-Robinson test problem: + time domain: (0,5] + hs = 0.002 + hf = 2e-05 + G = -100 + w = 100 + e = 0.5 + slow solver: ARKODE_MIS_KW3 + fast solver: esdirk-3-3 + reltol = 8.00e-09, abstol = 1.00e-11 + t u v uerr verr + ------------------------------------------------------ + 0.000000 1.224745 1.732051 0.00e+00 0.00e+00 + 0.100000 1.223725 1.077464 4.99e-09 6.44e-11 + 0.200000 1.220669 1.551800 4.96e-09 1.43e-10 + 0.300000 1.215594 1.467737 4.90e-09 2.14e-10 + 0.400000 1.208524 1.154583 4.81e-09 2.79e-10 + 0.500000 1.199496 1.721908 4.70e-09 3.33e-10 + 0.600000 1.188557 1.023517 4.57e-09 3.84e-10 + 0.700000 1.175764 1.622751 4.40e-09 4.23e-10 + 0.800000 1.161186 1.374632 4.21e-09 4.58e-10 + 0.900000 1.144904 1.245763 3.98e-09 4.86e-10 + 1.000000 1.127010 1.691839 3.73e-09 5.06e-10 + 1.100000 1.107609 1.000489 3.45e-09 5.20e-10 + 1.200000 1.086821 1.677552 3.13e-09 5.29e-10 + 1.300000 1.064777 1.277775 2.77e-09 5.30e-10 + 1.400000 1.041625 1.342455 2.38e-09 5.25e-10 + 1.500000 1.017531 1.642940 1.94e-09 5.15e-10 + 1.600000 0.992673 1.012112 1.46e-09 4.96e-10 + 1.700000 0.967253 1.714058 9.32e-10 4.72e-10 + 1.800000 0.941488 1.183867 3.54e-10 4.40e-10 + 1.900000 0.915617 1.437465 2.75e-10 4.01e-10 + 2.000000 0.889903 1.577082 9.56e-10 3.55e-10 + 2.100000 0.864625 1.056467 1.69e-09 3.06e-10 + 2.200000 0.840089 1.730920 2.47e-09 2.39e-10 + 2.300000 0.816616 1.101047 3.30e-09 1.74e-10 + 2.400000 0.794546 1.525051 4.15e-09 9.35e-11 + 2.500000 0.774227 1.496993 5.01e-09 9.06e-12 + 2.600000 0.756013 1.126857 5.86e-09 7.92e-11 + 2.700000 0.740246 1.727536 6.67e-09 1.81e-10 + 2.800000 0.727247 1.038393 7.38e-09 2.77e-10 + 2.900000 0.717301 1.600759 7.97e-09 3.85e-10 + 3.000000 0.710636 1.406380 8.40e-09 4.86e-10 + 3.100000 0.707412 1.214353 8.63e-09 5.84e-10 + 3.200000 0.707709 1.704026 8.65e-09 6.81e-10 + 3.300000 0.711520 1.004391 8.46e-09 7.58e-10 + 3.400000 0.718750 1.661225 8.06e-09 8.35e-10 + 3.500000 0.729227 1.310102 7.50e-09 8.89e-10 + 3.600000 0.742712 1.310080 6.80e-09 9.29e-10 + 3.700000 0.758914 1.661237 6.01e-09 9.56e-10 + 3.800000 0.777506 1.004387 5.16e-09 9.59e-10 + 3.900000 0.798144 1.704019 4.29e-09 9.58e-10 + 4.000000 0.820474 1.214374 3.43e-09 9.32e-10 + 4.100000 0.844149 1.406358 2.60e-09 9.00e-10 + 4.200000 0.868832 1.600774 1.81e-09 8.56e-10 + 4.300000 0.894204 1.038382 1.06e-09 7.97e-10 + 4.400000 0.919964 1.727533 3.69e-10 7.42e-10 + 4.500000 0.945834 1.126875 2.71e-10 6.69e-10 + 4.600000 0.971557 1.496974 8.58e-10 6.01e-10 + 4.700000 0.996898 1.525070 1.40e-09 5.27e-10 + 4.800000 1.021641 1.101030 1.88e-09 4.46e-10 + 4.900000 1.045589 1.730922 2.33e-09 3.74e-10 + 5.000000 1.068565 1.056480 2.73e-09 2.91e-10 + ------------------------------------------------------ + +Final Solver Statistics: + Steps: nsts = 2501, nstf = 252601 + u error = 4.671e-09, v error = 5.637e-10, total error = 3.327e-09 + Total RHS evals: Fs = 7504, Ff = 0 + Fast Newton iters = 653849 + Fast Newton conv fails = 0 + Fast Jacobian evals = 4169 diff --git a/examples/arkode/C_serial/ark_kpr_mri_2_4_0.002.out b/examples/arkode/C_serial/ark_kpr_mri_2_4_0.002.out new file mode 100644 index 0000000000..6a22e6fbc0 --- /dev/null +++ b/examples/arkode/C_serial/ark_kpr_mri_2_4_0.002.out @@ -0,0 +1,69 @@ + +Multirate nonlinear Kvaerno-Prothero-Robinson test problem: + time domain: (0,5] + hs = 0.002 + hf = 2e-05 + G = -100 + w = 100 + e = 0.5 + slow solver: ARKODE_MRI_GARK_ERK45a + fast solver: erk-4-4 + t u v uerr verr + ------------------------------------------------------ + 0.000000 1.224745 1.732051 0.00e+00 0.00e+00 + 0.100000 1.223725 1.077464 1.78e-10 1.07e-11 + 0.200000 1.220669 1.551800 1.77e-10 2.15e-11 + 0.300000 1.215594 1.467737 1.75e-10 3.07e-11 + 0.400000 1.208524 1.154583 1.72e-10 3.88e-11 + 0.500000 1.199496 1.721908 1.68e-10 4.68e-11 + 0.600000 1.188557 1.023517 1.63e-10 5.25e-11 + 0.700000 1.175764 1.622751 1.57e-10 5.85e-11 + 0.800000 1.161186 1.374632 1.50e-10 6.28e-11 + 0.900000 1.144904 1.245763 1.42e-10 6.63e-11 + 1.000000 1.127010 1.691839 1.33e-10 6.94e-11 + 1.100000 1.107609 1.000489 1.23e-10 7.12e-11 + 1.200000 1.086821 1.677552 1.12e-10 7.21e-11 + 1.300000 1.064777 1.277775 9.89e-11 7.21e-11 + 1.400000 1.041625 1.342455 8.49e-11 7.13e-11 + 1.500000 1.017531 1.642940 6.94e-11 6.96e-11 + 1.600000 0.992673 1.012112 5.24e-11 6.69e-11 + 1.700000 0.967253 1.714058 3.37e-11 6.34e-11 + 1.800000 0.941488 1.183867 1.32e-11 5.89e-11 + 1.900000 0.915617 1.437465 9.11e-12 5.33e-11 + 2.000000 0.889903 1.577082 3.33e-11 4.69e-11 + 2.100000 0.864625 1.056467 5.94e-11 3.62e-11 + 2.200000 0.840089 1.730920 8.72e-11 3.20e-11 + 2.300000 0.816616 1.101047 1.16e-10 1.85e-11 + 2.400000 0.794546 1.525051 1.47e-10 1.05e-11 + 2.500000 0.774227 1.496993 1.78e-10 1.19e-12 + 2.600000 0.756013 1.126857 2.08e-10 1.60e-11 + 2.700000 0.740246 1.727536 2.36e-10 2.55e-11 + 2.800000 0.727247 1.038393 2.62e-10 4.36e-11 + 2.900000 0.717301 1.600759 2.83e-10 5.41e-11 + 3.000000 0.710636 1.406380 2.99e-10 6.92e-11 + 3.100000 0.707412 1.214353 3.07e-10 8.37e-11 + 3.200000 0.707709 1.704026 3.08e-10 9.30e-11 + 3.300000 0.711520 1.004391 3.02e-10 1.08e-10 + 3.400000 0.718750 1.661225 2.88e-10 1.14e-10 + 3.500000 0.729227 1.310102 2.68e-10 1.23e-10 + 3.600000 0.742712 1.310080 2.43e-10 1.28e-10 + 3.700000 0.758914 1.661237 2.15e-10 1.29e-10 + 3.800000 0.777506 1.004387 1.85e-10 1.34e-10 + 3.900000 0.798144 1.704019 1.54e-10 1.28e-10 + 4.000000 0.820474 1.214374 1.24e-10 1.28e-10 + 4.100000 0.844149 1.406358 9.39e-11 1.22e-10 + 4.200000 0.868832 1.600774 6.55e-11 1.14e-10 + 4.300000 0.894204 1.038382 3.88e-11 1.10e-10 + 4.400000 0.919964 1.727533 1.40e-11 9.70e-11 + 4.500000 0.945834 1.126875 8.93e-12 9.14e-11 + 4.600000 0.971557 1.496974 3.00e-11 7.93e-11 + 4.700000 0.996898 1.525070 4.92e-11 6.88e-11 + 4.800000 1.021641 1.101030 6.67e-11 6.10e-11 + 4.900000 1.045589 1.730922 8.26e-11 4.65e-11 + 5.000000 1.068565 1.056480 9.70e-11 4.02e-11 + ------------------------------------------------------ + +Final Solver Statistics: + Steps: nsts = 2501, nstf = 250100 + u error = 1.665e-10, v error = 7.685e-11, total error = 1.296e-10 + Total RHS evals: Fs = 12506, Ff = 1002902 diff --git a/examples/arkode/C_serial/ark_kpr_mri_3_2_0.001.out b/examples/arkode/C_serial/ark_kpr_mri_3_2_0.001.out new file mode 100644 index 0000000000..00f9fbb881 --- /dev/null +++ b/examples/arkode/C_serial/ark_kpr_mri_3_2_0.001.out @@ -0,0 +1,69 @@ + +Multirate nonlinear Kvaerno-Prothero-Robinson test problem: + time domain: (0,5] + hs = 0.001 + hf = 1e-05 + G = -100 + w = 100 + e = 0.5 + slow solver: ARKODE_MERK21 + fast solver: ARKODE_HEUN_EULER_2_1_2 + t u v uerr verr + ------------------------------------------------------ + 0.000000 1.224745 1.732051 0.00e+00 0.00e+00 + 0.100000 1.223725 1.077464 2.66e-08 4.86e-08 + 0.200000 1.220669 1.551800 2.66e-08 1.34e-09 + 0.300000 1.215594 1.467737 2.62e-08 4.29e-09 + 0.400000 1.208524 1.154583 2.58e-08 2.80e-08 + 0.500000 1.199496 1.721908 2.53e-08 1.39e-08 + 0.600000 1.188557 1.023517 2.44e-08 4.48e-08 + 0.700000 1.175764 1.622750 2.37e-08 1.39e-08 + 0.800000 1.161186 1.374632 2.25e-08 9.64e-11 + 0.900000 1.144904 1.245763 2.14e-08 8.43e-09 + 1.000000 1.127010 1.691839 2.01e-08 2.07e-08 + 1.100000 1.107609 1.000490 1.84e-08 4.20e-08 + 1.200000 1.086821 1.677552 1.69e-08 2.25e-08 + 1.300000 1.064777 1.277775 1.48e-08 2.79e-09 + 1.400000 1.041625 1.342455 1.28e-08 4.44e-09 + 1.500000 1.017531 1.642940 1.04e-08 2.19e-08 + 1.600000 0.992673 1.012112 7.76e-09 3.67e-08 + 1.700000 0.967253 1.714058 5.06e-09 2.59e-08 + 1.800000 0.941488 1.183867 1.75e-09 1.13e-08 + 1.900000 0.915617 1.437465 1.44e-09 1.16e-08 + 2.000000 0.889903 1.577082 5.21e-09 1.82e-08 + 2.100000 0.864625 1.056467 9.17e-09 2.94e-08 + 2.200000 0.840089 1.730920 1.33e-08 2.47e-08 + 2.300000 0.816616 1.101047 1.79e-08 2.45e-08 + 2.400000 0.794546 1.525051 2.23e-08 1.36e-08 + 2.500000 0.774228 1.496993 2.71e-08 9.85e-09 + 2.600000 0.756013 1.126857 3.16e-08 2.30e-08 + 2.700000 0.740246 1.727536 3.59e-08 1.92e-08 + 2.800000 0.727247 1.038393 3.99e-08 4.04e-08 + 2.900000 0.717301 1.600759 4.28e-08 1.12e-08 + 3.000000 0.710636 1.406380 4.52e-08 2.44e-09 + 3.100000 0.707413 1.214353 4.63e-08 1.90e-08 + 3.200000 0.707709 1.704026 4.64e-08 1.14e-08 + 3.300000 0.711520 1.004391 4.55e-08 5.32e-08 + 3.400000 0.718750 1.661225 4.31e-08 8.10e-09 + 3.500000 0.729227 1.310102 4.03e-08 1.50e-08 + 3.600000 0.742712 1.310080 3.64e-08 1.43e-08 + 3.700000 0.758914 1.661237 3.21e-08 6.04e-09 + 3.800000 0.777506 1.004387 2.77e-08 5.53e-08 + 3.900000 0.798144 1.704019 2.29e-08 8.68e-09 + 4.000000 0.820474 1.214374 1.85e-08 2.42e-08 + 4.100000 0.844149 1.406358 1.38e-08 6.00e-09 + 4.200000 0.868832 1.600774 9.67e-09 4.99e-09 + 4.300000 0.894204 1.038382 5.70e-09 4.57e-08 + 4.400000 0.919964 1.727533 1.89e-09 1.31e-08 + 4.500000 0.945834 1.126875 1.34e-09 3.06e-08 + 4.600000 0.971557 1.496974 4.69e-09 4.31e-09 + 4.700000 0.996898 1.525070 7.45e-09 5.97e-09 + 4.800000 1.021641 1.101030 1.01e-08 2.99e-08 + 4.900000 1.045589 1.730922 1.25e-08 1.86e-08 + 5.000000 1.068565 1.056480 1.45e-08 3.56e-08 + ------------------------------------------------------ + +Final Solver Statistics: + Steps: nsts = 5000, nstf = 750000 + u error = 2.508e-08, v error = 2.443e-08, total error = 2.476e-08 + Total RHS evals: Fs = 10001, Ff = 1505001 diff --git a/examples/arkode/C_serial/ark_kpr_mri_4_0.002.out b/examples/arkode/C_serial/ark_kpr_mri_4_0.002.out deleted file mode 100644 index 9f53b0e3b4..0000000000 --- a/examples/arkode/C_serial/ark_kpr_mri_4_0.002.out +++ /dev/null @@ -1,72 +0,0 @@ - -Multirate nonlinear Kvaerno-Prothero-Robinson test problem: - time domain: (0,5] - hs = 0.002 - hf = 2e-05 - G = -100 - w = 100 - e = 0.5 - solver: dirk-2/none (dirk slow, no fast) - reltol = 4.00e-06, abstol = 1.00e-11 - t u v uerr verr - ------------------------------------------------------ - 0.000000 1.224745 1.732051 0.00e+00 0.00e+00 - 0.100000 1.223734 1.079428 9.43e-06 1.96e-03 - 0.200000 1.220669 1.551975 3.21e-07 1.75e-04 - 0.300000 1.215599 1.468008 5.52e-06 2.71e-04 - 0.400000 1.208526 1.155919 2.23e-06 1.34e-03 - 0.500000 1.199497 1.721561 8.79e-07 3.47e-04 - 0.600000 1.188564 1.025537 7.38e-06 2.02e-03 - 0.700000 1.175763 1.622485 1.23e-06 2.66e-04 - 0.800000 1.161186 1.374900 2.52e-07 2.68e-04 - 0.900000 1.144904 1.246450 1.12e-07 6.87e-04 - 1.000000 1.127010 1.691322 5.38e-07 5.17e-04 - 1.100000 1.107615 1.002500 5.42e-06 2.01e-03 - 1.200000 1.086818 1.677003 2.06e-06 5.49e-04 - 1.300000 1.064782 1.278198 5.48e-06 4.23e-04 - 1.400000 1.041624 1.342655 1.37e-06 2.00e-04 - 1.500000 1.017531 1.642375 7.35e-07 5.65e-04 - 1.600000 0.992677 1.013911 3.39e-06 1.80e-03 - 1.700000 0.967249 1.713353 3.48e-06 7.05e-04 - 1.800000 0.941493 1.184579 5.35e-06 7.12e-04 - 1.900000 0.915615 1.437305 2.35e-06 1.61e-04 - 2.000000 0.889904 1.576564 1.28e-06 5.18e-04 - 2.100000 0.864627 1.057868 1.53e-06 1.40e-03 - 2.200000 0.840087 1.730117 2.43e-06 8.03e-04 - 2.300000 0.816622 1.102136 5.78e-06 1.09e-03 - 2.400000 0.794543 1.524625 3.12e-06 4.26e-04 - 2.500000 0.774230 1.496597 2.15e-06 3.96e-04 - 2.600000 0.756013 1.127800 7.68e-08 9.44e-04 - 2.700000 0.740244 1.726696 1.85e-06 8.41e-04 - 2.800000 0.727253 1.039861 5.33e-06 1.47e-03 - 2.900000 0.717298 1.600138 3.24e-06 6.21e-04 - 3.000000 0.710633 1.406200 3.03e-06 1.79e-04 - 3.100000 0.707411 1.214845 1.22e-06 4.92e-04 - 3.200000 0.707708 1.703196 1.21e-06 8.30e-04 - 3.300000 0.711524 1.006102 4.35e-06 1.71e-03 - 3.400000 0.718746 1.660466 3.40e-06 7.59e-04 - 3.500000 0.729231 1.310194 4.07e-06 9.26e-05 - 3.600000 0.742710 1.310190 2.18e-06 1.11e-04 - 3.700000 0.758913 1.660462 4.65e-07 7.74e-04 - 3.800000 0.777509 1.006087 3.06e-06 1.70e-03 - 3.900000 0.798140 1.703188 3.88e-06 8.31e-04 - 4.000000 0.820479 1.214819 4.63e-06 4.45e-04 - 4.100000 0.844147 1.406163 2.79e-06 1.95e-04 - 4.200000 0.868833 1.600102 4.16e-07 6.73e-04 - 4.300000 0.894205 1.039813 1.50e-06 1.43e-03 - 4.400000 0.919961 1.726651 2.81e-06 8.83e-04 - 4.500000 0.945839 1.127737 5.31e-06 8.63e-04 - 4.600000 0.971554 1.496541 3.29e-06 4.33e-04 - 4.700000 0.996899 1.524547 1.45e-06 5.23e-04 - 4.800000 1.021641 1.102066 8.60e-08 1.04e-03 - 4.900000 1.045587 1.730025 2.02e-06 8.96e-04 - 5.000000 1.068570 1.057773 5.26e-06 1.29e-03 - ------------------------------------------------------ - -Final Solver Statistics: - Steps: nsts = 2501, nstf = 250100 - u error = 3.482e-06, v error = 9.535e-04, total error = 6.742e-04 - Total RHS evals: Fs = 7143, Ff = 750350 - Slow Newton iters = 4641 - Slow Newton conv fails = 0 - Slow Jacobian evals = 126 diff --git a/examples/arkode/C_serial/ark_kpr_mri_4_3_0.001.out b/examples/arkode/C_serial/ark_kpr_mri_4_3_0.001.out new file mode 100644 index 0000000000..65f7d03033 --- /dev/null +++ b/examples/arkode/C_serial/ark_kpr_mri_4_3_0.001.out @@ -0,0 +1,69 @@ + +Multirate nonlinear Kvaerno-Prothero-Robinson test problem: + time domain: (0,5] + hs = 0.001 + hf = 1e-05 + G = -100 + w = 100 + e = 0.5 + slow solver: ARKODE_MERK32 + fast solver: erk-3-3 + t u v uerr verr + ------------------------------------------------------ + 0.000000 1.224745 1.732051 0.00e+00 0.00e+00 + 0.100000 1.223725 1.077464 8.92e-10 3.75e-11 + 0.200000 1.220669 1.551800 8.86e-10 7.57e-11 + 0.300000 1.215594 1.467737 8.75e-10 1.10e-10 + 0.400000 1.208524 1.154583 8.59e-10 1.40e-10 + 0.500000 1.199496 1.721908 8.39e-10 1.66e-10 + 0.600000 1.188557 1.023517 8.15e-10 1.89e-10 + 0.700000 1.175764 1.622751 7.85e-10 2.09e-10 + 0.800000 1.161186 1.374632 7.50e-10 2.25e-10 + 0.900000 1.144904 1.245763 7.10e-10 2.38e-10 + 1.000000 1.127010 1.691839 6.65e-10 2.47e-10 + 1.100000 1.107609 1.000489 6.13e-10 2.58e-10 + 1.200000 1.086821 1.677552 5.56e-10 2.57e-10 + 1.300000 1.064777 1.277775 4.92e-10 2.59e-10 + 1.400000 1.041625 1.342455 4.21e-10 2.56e-10 + 1.500000 1.017531 1.642940 3.43e-10 2.47e-10 + 1.600000 0.992673 1.012112 2.56e-10 2.42e-10 + 1.700000 0.967253 1.714058 1.61e-10 2.25e-10 + 1.800000 0.941488 1.183867 5.78e-11 2.12e-10 + 1.900000 0.915617 1.437465 5.52e-11 1.90e-10 + 2.000000 0.889903 1.577082 1.78e-10 1.66e-10 + 2.100000 0.864625 1.056467 3.09e-10 1.42e-10 + 2.200000 0.840089 1.730920 4.50e-10 1.07e-10 + 2.300000 0.816616 1.101047 5.97e-10 7.65e-11 + 2.400000 0.794546 1.525051 7.50e-10 3.53e-11 + 2.500000 0.774227 1.496993 9.05e-10 6.53e-12 + 2.600000 0.756013 1.126857 1.06e-09 4.93e-11 + 2.700000 0.740246 1.727536 1.20e-09 1.01e-10 + 2.800000 0.727247 1.038393 1.33e-09 1.46e-10 + 2.900000 0.717301 1.600759 1.43e-09 2.00e-10 + 3.000000 0.710636 1.406380 1.50e-09 2.49e-10 + 3.100000 0.707412 1.214353 1.54e-09 2.95e-10 + 3.200000 0.707709 1.704026 1.55e-09 3.43e-10 + 3.300000 0.711520 1.004391 1.51e-09 3.77e-10 + 3.400000 0.718750 1.661225 1.44e-09 4.14e-10 + 3.500000 0.729227 1.310102 1.33e-09 4.38e-10 + 3.600000 0.742712 1.310080 1.21e-09 4.56e-10 + 3.700000 0.758914 1.661237 1.07e-09 4.68e-10 + 3.800000 0.777506 1.004387 9.14e-10 4.66e-10 + 3.900000 0.798144 1.704019 7.60e-10 4.65e-10 + 4.000000 0.820474 1.214374 6.06e-10 4.50e-10 + 4.100000 0.844149 1.406358 4.58e-10 4.31e-10 + 4.200000 0.868832 1.600774 3.16e-10 4.10e-10 + 4.300000 0.894204 1.038382 1.84e-10 3.81e-10 + 4.400000 0.919964 1.727533 6.02e-11 3.51e-10 + 4.500000 0.945834 1.126875 5.36e-11 3.19e-10 + 4.600000 0.971557 1.496974 1.58e-10 2.82e-10 + 4.700000 0.996898 1.525070 2.54e-10 2.47e-10 + 4.800000 1.021641 1.101030 3.41e-10 2.09e-10 + 4.900000 1.045589 1.730922 4.20e-10 1.72e-10 + 5.000000 1.068565 1.056480 4.91e-10 1.34e-10 + ------------------------------------------------------ + +Final Solver Statistics: + Steps: nsts = 5000, nstf = 1085000 + u error = 8.345e-10, v error = 2.743e-10, total error = 6.212e-10 + Total RHS evals: Fs = 15001, Ff = 3260001 diff --git a/examples/arkode/C_serial/ark_kpr_mri_5_0.002.out b/examples/arkode/C_serial/ark_kpr_mri_5_0.002.out deleted file mode 100644 index 1a38aa16e6..0000000000 --- a/examples/arkode/C_serial/ark_kpr_mri_5_0.002.out +++ /dev/null @@ -1,69 +0,0 @@ - -Multirate nonlinear Kvaerno-Prothero-Robinson test problem: - time domain: (0,5] - hs = 0.002 - hf = 2e-05 - G = -100 - w = 100 - e = 0.5 - solver: exp-4/exp-4 (MRI-GARK-ERK45a / ERK-4-4) - - t u v uerr verr - ------------------------------------------------------ - 0.000000 1.224745 1.732051 0.00e+00 0.00e+00 - 0.100000 1.223725 1.077464 1.78e-10 1.07e-11 - 0.200000 1.220669 1.551800 1.77e-10 2.15e-11 - 0.300000 1.215594 1.467737 1.75e-10 3.07e-11 - 0.400000 1.208524 1.154583 1.72e-10 3.88e-11 - 0.500000 1.199496 1.721908 1.68e-10 4.68e-11 - 0.600000 1.188557 1.023517 1.63e-10 5.25e-11 - 0.700000 1.175764 1.622751 1.57e-10 5.85e-11 - 0.800000 1.161186 1.374632 1.50e-10 6.28e-11 - 0.900000 1.144904 1.245763 1.42e-10 6.63e-11 - 1.000000 1.127010 1.691839 1.33e-10 6.94e-11 - 1.100000 1.107609 1.000489 1.23e-10 7.12e-11 - 1.200000 1.086821 1.677552 1.12e-10 7.21e-11 - 1.300000 1.064777 1.277775 9.89e-11 7.21e-11 - 1.400000 1.041625 1.342455 8.49e-11 7.13e-11 - 1.500000 1.017531 1.642940 6.94e-11 6.96e-11 - 1.600000 0.992673 1.012112 5.24e-11 6.69e-11 - 1.700000 0.967253 1.714058 3.37e-11 6.34e-11 - 1.800000 0.941488 1.183867 1.32e-11 5.89e-11 - 1.900000 0.915617 1.437465 9.11e-12 5.33e-11 - 2.000000 0.889903 1.577082 3.33e-11 4.69e-11 - 2.100000 0.864625 1.056467 5.94e-11 3.57e-11 - 2.200000 0.840089 1.730920 8.72e-11 3.22e-11 - 2.300000 0.816616 1.101047 1.16e-10 1.97e-11 - 2.400000 0.794546 1.525051 1.47e-10 7.75e-12 - 2.500000 0.774227 1.496993 1.78e-10 2.45e-12 - 2.600000 0.756013 1.126857 2.08e-10 1.99e-11 - 2.700000 0.740246 1.727536 2.36e-10 2.32e-11 - 2.800000 0.727247 1.038393 2.62e-10 4.19e-11 - 2.900000 0.717301 1.600759 2.83e-10 5.92e-11 - 3.000000 0.710636 1.406380 2.99e-10 6.19e-11 - 3.100000 0.707412 1.214353 3.07e-10 9.20e-11 - 3.200000 0.707709 1.704026 3.08e-10 8.71e-11 - 3.300000 0.711520 1.004391 3.02e-10 1.08e-10 - 3.400000 0.718750 1.661225 2.88e-10 1.19e-10 - 3.500000 0.729227 1.310102 2.68e-10 1.13e-10 - 3.600000 0.742712 1.310080 2.43e-10 1.41e-10 - 3.700000 0.758914 1.661237 2.15e-10 1.18e-10 - 3.800000 0.777506 1.004387 1.85e-10 1.38e-10 - 3.900000 0.798144 1.704019 1.54e-10 1.31e-10 - 4.000000 0.820474 1.214374 1.24e-10 1.16e-10 - 4.100000 0.844149 1.406358 9.39e-11 1.38e-10 - 4.200000 0.868832 1.600774 6.55e-11 9.88e-11 - 4.300000 0.894204 1.038382 3.88e-11 1.20e-10 - 4.400000 0.919964 1.727533 1.40e-11 9.58e-11 - 4.500000 0.945834 1.126875 8.93e-12 8.01e-11 - 4.600000 0.971557 1.496974 3.00e-11 9.82e-11 - 4.700000 0.996898 1.525070 4.92e-11 4.94e-11 - 4.800000 1.021641 1.101030 6.67e-11 7.79e-11 - 4.900000 1.045589 1.730922 8.26e-11 3.90e-11 - 5.000000 1.068565 1.056480 9.70e-11 3.19e-11 - ------------------------------------------------------ - -Final Solver Statistics: - Steps: nsts = 2501, nstf = 250100 - u error = 1.665e-10, v error = 7.714e-11, total error = 1.297e-10 - Total RHS evals: Fs = 12506, Ff = 1000450 diff --git a/examples/arkode/C_serial/ark_kpr_mri_5_4_0.001.out b/examples/arkode/C_serial/ark_kpr_mri_5_4_0.001.out new file mode 100644 index 0000000000..817fa1eff9 --- /dev/null +++ b/examples/arkode/C_serial/ark_kpr_mri_5_4_0.001.out @@ -0,0 +1,69 @@ + +Multirate nonlinear Kvaerno-Prothero-Robinson test problem: + time domain: (0,5] + hs = 0.001 + hf = 1e-05 + G = -100 + w = 100 + e = 0.5 + slow solver: ARKODE_MERK43 + fast solver: erk-4-4 + t u v uerr verr + ------------------------------------------------------ + 0.000000 1.224745 1.732051 0.00e+00 0.00e+00 + 0.100000 1.223725 1.077464 2.23e-11 1.15e-12 + 0.200000 1.220669 1.551800 2.21e-11 1.92e-12 + 0.300000 1.215594 1.467737 2.19e-11 2.71e-12 + 0.400000 1.208524 1.154583 2.15e-11 3.14e-12 + 0.500000 1.199496 1.721908 2.10e-11 4.37e-12 + 0.600000 1.188557 1.023517 2.03e-11 4.94e-12 + 0.700000 1.175764 1.622751 1.96e-11 5.31e-12 + 0.800000 1.161186 1.374632 1.87e-11 5.82e-12 + 0.900000 1.144904 1.245763 1.77e-11 5.97e-12 + 1.000000 1.127010 1.691839 1.66e-11 6.30e-12 + 1.100000 1.107609 1.000489 1.52e-11 2.13e-12 + 1.200000 1.086821 1.677552 1.38e-11 6.72e-12 + 1.300000 1.064777 1.277775 1.22e-11 4.31e-12 + 1.400000 1.041625 1.342455 1.04e-11 4.75e-12 + 1.500000 1.017531 1.642940 8.47e-12 6.69e-12 + 1.600000 0.992673 1.012112 6.30e-12 2.43e-12 + 1.700000 0.967253 1.714058 3.95e-12 6.77e-12 + 1.800000 0.941488 1.183867 1.35e-12 3.05e-12 + 1.900000 0.915617 1.437465 1.47e-12 4.22e-12 + 2.000000 0.889903 1.577082 4.53e-12 4.66e-12 + 2.100000 0.864625 1.056467 7.81e-12 6.12e-13 + 2.200000 0.840089 1.730920 1.13e-11 4.29e-12 + 2.300000 0.816616 1.101047 1.50e-11 6.09e-13 + 2.400000 0.794546 1.525051 1.88e-11 1.21e-12 + 2.500000 0.774227 1.496993 2.27e-11 7.39e-14 + 2.600000 0.756013 1.126857 2.64e-11 3.44e-12 + 2.700000 0.740246 1.727536 3.00e-11 6.68e-13 + 2.800000 0.727247 1.038393 3.32e-11 6.30e-12 + 2.900000 0.717301 1.600759 3.58e-11 3.89e-12 + 3.000000 0.710636 1.406380 3.76e-11 6.33e-12 + 3.100000 0.707412 1.214353 3.86e-11 8.76e-12 + 3.200000 0.707709 1.704026 3.86e-11 6.62e-12 + 3.300000 0.711520 1.004391 3.77e-11 1.21e-11 + 3.400000 0.718750 1.661225 3.59e-11 8.63e-12 + 3.500000 0.729227 1.310102 3.33e-11 1.15e-11 + 3.600000 0.742712 1.310080 3.02e-11 1.19e-11 + 3.700000 0.758914 1.661237 2.66e-11 9.88e-12 + 3.800000 0.777506 1.004387 2.28e-11 1.42e-11 + 3.900000 0.798144 1.704019 1.89e-11 9.52e-12 + 4.000000 0.820474 1.214374 1.51e-11 1.23e-11 + 4.100000 0.844149 1.406358 1.14e-11 1.30e-11 + 4.200000 0.868832 1.600774 7.85e-12 1.11e-11 + 4.300000 0.894204 1.038382 4.53e-12 1.12e-11 + 4.400000 0.919964 1.727533 1.45e-12 9.88e-12 + 4.500000 0.945834 1.126875 1.40e-12 8.44e-12 + 4.600000 0.971557 1.496974 4.01e-12 8.57e-12 + 4.700000 0.996898 1.525070 6.40e-12 6.35e-12 + 4.800000 1.021641 1.101030 8.58e-12 6.61e-12 + 4.900000 1.045589 1.730922 1.06e-11 4.80e-12 + 5.000000 1.068565 1.056480 1.23e-11 3.61e-12 + ------------------------------------------------------ + +Final Solver Statistics: + Steps: nsts = 5000, nstf = 1425000 + u error = 2.086e-11, v error = 7.078e-12, total error = 1.557e-11 + Total RHS evals: Fs = 30001, Ff = 5705001 diff --git a/examples/arkode/C_serial/ark_kpr_mri_6_0.005.out b/examples/arkode/C_serial/ark_kpr_mri_6_0.005.out deleted file mode 100644 index 7929d73e39..0000000000 --- a/examples/arkode/C_serial/ark_kpr_mri_6_0.005.out +++ /dev/null @@ -1,69 +0,0 @@ - -Multirate nonlinear Kvaerno-Prothero-Robinson test problem: - time domain: (0,5] - hs = 0.005 - hf = 5e-05 - G = -100 - w = 100 - e = 0.5 - solver: exp-4/exp-3 (MRI-GARK-ERK45a / ERK-3-3) - - t u v uerr verr - ------------------------------------------------------ - 0.000000 1.224745 1.732051 0.00e+00 0.00e+00 - 0.100000 1.223725 1.077464 8.08e-09 4.56e-10 - 0.200000 1.220669 1.551800 8.03e-09 9.03e-10 - 0.300000 1.215594 1.467737 7.94e-09 1.30e-09 - 0.400000 1.208524 1.154583 7.80e-09 1.66e-09 - 0.500000 1.199496 1.721908 7.62e-09 1.97e-09 - 0.600000 1.188557 1.023517 7.40e-09 2.24e-09 - 0.700000 1.175764 1.622751 7.13e-09 2.47e-09 - 0.800000 1.161186 1.374632 6.82e-09 2.66e-09 - 0.900000 1.144904 1.245763 6.46e-09 2.81e-09 - 1.000000 1.127010 1.691839 6.05e-09 2.92e-09 - 1.100000 1.107609 1.000489 5.59e-09 3.00e-09 - 1.200000 1.086821 1.677552 5.08e-09 3.04e-09 - 1.300000 1.064777 1.277775 4.50e-09 3.04e-09 - 1.400000 1.041625 1.342455 3.87e-09 3.00e-09 - 1.500000 1.017531 1.642940 3.17e-09 2.93e-09 - 1.600000 0.992673 1.012112 2.39e-09 2.82e-09 - 1.700000 0.967253 1.714058 1.54e-09 2.67e-09 - 1.800000 0.941488 1.183867 6.13e-10 2.48e-09 - 1.900000 0.915617 1.437465 4.00e-10 2.25e-09 - 2.000000 0.889903 1.577082 1.50e-09 1.98e-09 - 2.100000 0.864625 1.056467 2.68e-09 1.66e-09 - 2.200000 0.840089 1.730920 3.94e-09 1.30e-09 - 2.300000 0.816616 1.101047 5.27e-09 9.00e-10 - 2.400000 0.794546 1.525051 6.65e-09 4.47e-10 - 2.500000 0.774227 1.496993 8.05e-09 3.94e-11 - 2.600000 0.756013 1.126857 9.42e-09 5.73e-10 - 2.700000 0.740246 1.727536 1.07e-08 1.13e-09 - 2.800000 0.727247 1.038393 1.19e-08 1.71e-09 - 2.900000 0.717301 1.600759 1.29e-08 2.31e-09 - 3.000000 0.710636 1.406380 1.36e-08 2.89e-09 - 3.100000 0.707412 1.214353 1.40e-08 3.46e-09 - 3.200000 0.707709 1.704026 1.40e-08 3.98e-09 - 3.300000 0.711520 1.004391 1.37e-08 4.45e-09 - 3.400000 0.718750 1.661225 1.31e-08 4.85e-09 - 3.500000 0.729227 1.310102 1.22e-08 5.15e-09 - 3.600000 0.742712 1.310080 1.11e-08 5.38e-09 - 3.700000 0.758914 1.661237 9.81e-09 5.49e-09 - 3.800000 0.777506 1.004387 8.45e-09 5.53e-09 - 3.900000 0.798144 1.704019 7.04e-09 5.47e-09 - 4.000000 0.820474 1.214374 5.64e-09 5.33e-09 - 4.100000 0.844149 1.406358 4.29e-09 5.13e-09 - 4.200000 0.868832 1.600774 3.00e-09 4.86e-09 - 4.300000 0.894204 1.038382 1.78e-09 4.54e-09 - 4.400000 0.919964 1.727533 6.51e-10 4.18e-09 - 4.500000 0.945834 1.126875 3.93e-10 3.79e-09 - 4.600000 0.971557 1.496974 1.35e-09 3.38e-09 - 4.700000 0.996898 1.525070 2.23e-09 2.94e-09 - 4.800000 1.021641 1.101030 3.02e-09 2.51e-09 - 4.900000 1.045589 1.730922 3.75e-09 2.06e-09 - 5.000000 1.068565 1.056480 4.40e-09 1.61e-09 - ------------------------------------------------------ - -Final Solver Statistics: - Steps: nsts = 1001, nstf = 100100 - u error = 7.569e-09, v error = 3.238e-09, total error = 5.821e-09 - Total RHS evals: Fs = 5006, Ff = 300350 diff --git a/examples/arkode/C_serial/ark_kpr_mri_6_5_0.001.out b/examples/arkode/C_serial/ark_kpr_mri_6_5_0.001.out new file mode 100644 index 0000000000..8f12b1e794 --- /dev/null +++ b/examples/arkode/C_serial/ark_kpr_mri_6_5_0.001.out @@ -0,0 +1,69 @@ + +Multirate nonlinear Kvaerno-Prothero-Robinson test problem: + time domain: (0,5] + hs = 0.001 + hf = 1e-05 + G = -100 + w = 100 + e = 0.5 + slow solver: ARKODE_MERK54 + fast solver: ARKODE_DORMAND_PRINCE_7_4_5 + t u v uerr verr + ------------------------------------------------------ + 0.000000 1.224745 1.732051 0.00e+00 0.00e+00 + 0.100000 1.223725 1.077464 4.46e-13 2.08e-13 + 0.200000 1.220669 1.551800 4.42e-13 6.88e-15 + 0.300000 1.215594 1.467737 4.37e-13 7.22e-14 + 0.400000 1.208524 1.154583 4.28e-13 3.99e-13 + 0.500000 1.199496 1.721908 4.18e-13 1.65e-13 + 0.600000 1.188557 1.023517 4.07e-13 1.50e-13 + 0.700000 1.175764 1.622751 3.88e-13 2.86e-14 + 0.800000 1.161186 1.374632 3.73e-13 1.48e-13 + 0.900000 1.144904 1.245763 3.52e-13 3.93e-14 + 1.000000 1.127010 1.691839 3.32e-13 4.77e-14 + 1.100000 1.107609 1.000489 3.33e-13 4.28e-12 + 1.200000 1.086821 1.677552 2.90e-13 2.44e-13 + 1.300000 1.064777 1.277775 2.73e-13 2.18e-12 + 1.400000 1.041625 1.342455 2.24e-13 1.65e-12 + 1.500000 1.017531 1.642940 1.91e-13 4.45e-13 + 1.600000 0.992673 1.012112 1.51e-13 3.56e-12 + 1.700000 0.967253 1.714058 9.28e-14 1.09e-12 + 1.800000 0.941488 1.183867 5.50e-14 2.24e-12 + 1.900000 0.915617 1.437465 1.53e-14 5.52e-13 + 2.000000 0.889903 1.577082 6.75e-14 4.87e-13 + 2.100000 0.864625 1.056467 1.36e-13 2.86e-12 + 2.200000 0.840089 1.730920 2.15e-13 1.59e-12 + 2.300000 0.816616 1.101047 2.74e-13 2.40e-12 + 2.400000 0.794546 1.525051 3.67e-13 3.79e-13 + 2.500000 0.774227 1.496993 4.35e-13 3.14e-13 + 2.600000 0.756013 1.126857 5.16e-13 2.06e-12 + 2.700000 0.740246 1.727536 5.92e-13 1.91e-12 + 2.800000 0.727247 1.038393 6.45e-13 2.49e-12 + 2.900000 0.717301 1.600759 7.16e-13 1.19e-12 + 3.000000 0.710636 1.406380 7.43e-13 6.88e-15 + 3.100000 0.707412 1.214353 7.73e-13 1.22e-12 + 3.200000 0.707709 1.704026 7.76e-13 2.02e-12 + 3.300000 0.711520 1.004391 7.50e-13 2.48e-12 + 3.400000 0.718750 1.661225 7.31e-13 1.78e-12 + 3.500000 0.729227 1.310102 6.67e-13 4.31e-13 + 3.600000 0.742712 1.310080 6.17e-13 4.42e-13 + 3.700000 0.758914 1.661237 5.44e-13 1.88e-12 + 3.800000 0.777506 1.004387 4.64e-13 2.38e-12 + 3.900000 0.798144 1.704019 4.01e-13 2.16e-12 + 4.000000 0.820474 1.214374 3.08e-13 9.57e-13 + 4.100000 0.844149 1.406358 2.21e-13 2.06e-12 + 4.200000 0.868832 1.600774 1.53e-13 7.17e-13 + 4.300000 0.894204 1.038382 8.45e-14 1.60e-12 + 4.400000 0.919964 1.727533 2.65e-14 1.04e-12 + 4.500000 0.945834 1.126875 3.23e-14 4.35e-13 + 4.600000 0.971557 1.496974 8.37e-14 1.42e-12 + 4.700000 0.996898 1.525070 1.30e-13 1.38e-13 + 4.800000 1.021641 1.101030 1.79e-13 1.33e-12 + 4.900000 1.045589 1.730922 2.13e-13 5.01e-13 + 5.000000 1.068565 1.056480 2.51e-13 2.92e-13 + ------------------------------------------------------ + +Final Solver Statistics: + Steps: nsts = 5000, nstf = 1615000 + u error = 4.177e-13, v error = 1.555e-12, total error = 1.139e-12 + Total RHS evals: Fs = 50051, Ff = 9715052 diff --git a/examples/arkode/C_serial/ark_kpr_mri_7_0.001.out b/examples/arkode/C_serial/ark_kpr_mri_7_0.001.out deleted file mode 100644 index 460bf53318..0000000000 --- a/examples/arkode/C_serial/ark_kpr_mri_7_0.001.out +++ /dev/null @@ -1,72 +0,0 @@ - -Multirate nonlinear Kvaerno-Prothero-Robinson test problem: - time domain: (0,5] - hs = 0.001 - hf = 1e-05 - G = -100 - w = 100 - e = 0.5 - solver: dirk-3/exp-3 (MRI-GARK-ESDIRK34a / ERK-3-3) -- solve decoupled - reltol = 1.00e-09, abstol = 1.00e-11 - t u v uerr verr - ------------------------------------------------------ - 0.000000 1.224745 1.732051 0.00e+00 0.00e+00 - 0.100000 1.223725 1.077464 4.01e-10 5.72e-11 - 0.200000 1.220669 1.551800 4.06e-10 1.12e-10 - 0.300000 1.215594 1.467737 3.95e-10 1.60e-10 - 0.400000 1.208524 1.154583 3.88e-10 2.03e-10 - 0.500000 1.199496 1.721908 3.80e-10 2.39e-10 - 0.600000 1.188557 1.023517 3.85e-10 2.71e-10 - 0.700000 1.175764 1.622751 3.48e-10 3.02e-10 - 0.800000 1.161186 1.374632 3.42e-10 3.23e-10 - 0.900000 1.144904 1.245763 3.24e-10 3.40e-10 - 1.000000 1.127010 1.691839 3.03e-10 3.56e-10 - 1.100000 1.107609 1.000489 2.77e-10 3.66e-10 - 1.200000 1.086821 1.677552 2.55e-10 3.66e-10 - 1.300000 1.064777 1.277775 2.29e-10 3.68e-10 - 1.400000 1.041625 1.342455 1.96e-10 3.63e-10 - 1.500000 1.017531 1.642940 1.59e-10 3.51e-10 - 1.600000 0.992673 1.012112 1.22e-10 3.42e-10 - 1.700000 0.967253 1.714058 7.84e-11 3.18e-10 - 1.800000 0.941488 1.183867 3.53e-11 2.98e-10 - 1.900000 0.915617 1.437465 1.65e-11 2.68e-10 - 2.000000 0.889903 1.577082 7.04e-11 2.33e-10 - 2.100000 0.864625 1.056467 1.30e-10 1.98e-10 - 2.200000 0.840089 1.730920 1.96e-10 1.49e-10 - 2.300000 0.816616 1.101047 2.60e-10 1.03e-10 - 2.400000 0.794546 1.525051 3.29e-10 4.53e-11 - 2.500000 0.774227 1.496993 4.02e-10 1.97e-11 - 2.600000 0.756013 1.126857 4.66e-10 8.15e-11 - 2.700000 0.740246 1.727536 5.35e-10 1.53e-10 - 2.800000 0.727247 1.038393 5.92e-10 2.19e-10 - 2.900000 0.717301 1.600759 7.54e-10 2.96e-10 - 3.000000 0.710636 1.406380 6.69e-10 3.66e-10 - 3.100000 0.707412 1.214353 6.92e-10 4.31e-10 - 3.200000 0.707709 1.704026 6.98e-10 4.97e-10 - 3.300000 0.711520 1.004391 6.80e-10 5.46e-10 - 3.400000 0.718750 1.661225 6.52e-10 5.96e-10 - 3.500000 0.729227 1.310102 6.05e-10 6.29e-10 - 3.600000 0.742712 1.310080 5.52e-10 6.53e-10 - 3.700000 0.758914 1.661237 4.96e-10 6.77e-10 - 3.800000 0.777506 1.004387 4.21e-10 6.74e-10 - 3.900000 0.798144 1.704019 3.55e-10 6.70e-10 - 4.000000 0.820474 1.214374 2.86e-10 6.48e-10 - 4.100000 0.844149 1.406358 2.57e-10 6.16e-10 - 4.200000 0.868832 1.600774 1.53e-10 5.75e-10 - 4.300000 0.894204 1.038382 9.25e-11 5.57e-10 - 4.400000 0.919964 1.727533 3.64e-11 4.94e-10 - 4.500000 0.945834 1.126875 1.44e-11 4.68e-10 - 4.600000 0.971557 1.496974 6.29e-11 4.03e-10 - 4.700000 0.996898 1.525070 1.03e-10 3.50e-10 - 4.800000 1.021641 1.101030 1.45e-10 3.12e-10 - 4.900000 1.045589 1.730922 1.85e-10 2.34e-10 - 5.000000 1.068565 1.056480 3.89e-11 2.06e-10 - ------------------------------------------------------ - -Final Solver Statistics: - Steps: nsts = 5000, nstf = 510000 - u error = 3.803e-10, v error = 3.943e-10, total error = 3.874e-10 - Total RHS evals: Fs = 45313, Ff = 1530050 - Slow Newton iters = 30312 - Slow Newton conv fails = 0 - Slow Jacobian evals = 250 diff --git a/examples/arkode/C_serial/ark_kpr_mri_7_2_0.002.out b/examples/arkode/C_serial/ark_kpr_mri_7_2_0.002.out new file mode 100644 index 0000000000..899ff3f7a8 --- /dev/null +++ b/examples/arkode/C_serial/ark_kpr_mri_7_2_0.002.out @@ -0,0 +1,73 @@ + +Multirate nonlinear Kvaerno-Prothero-Robinson test problem: + time domain: (0,5] + hs = 0.002 + hf = 2e-05 + G = -100 + w = 100 + e = 0.5 + slow solver: ARKODE_MRI_GARK_IRK21a + reltol = 4.00e-06, abstol = 1.00e-11 + fast solver: ARKODE_HEUN_EULER_2_1_2 + t u v uerr verr + ------------------------------------------------------ + 0.000000 1.224745 1.732051 0.00e+00 0.00e+00 + 0.100000 1.223725 1.077464 2.77e-08 1.95e-07 + 0.200000 1.220666 1.551800 2.88e-06 1.72e-08 + 0.300000 1.215594 1.467737 5.07e-10 2.58e-08 + 0.400000 1.208524 1.154583 1.40e-07 8.86e-08 + 0.500000 1.199497 1.721908 3.78e-07 7.73e-08 + 0.600000 1.188557 1.023517 3.84e-07 1.66e-07 + 0.700000 1.175764 1.622750 1.13e-08 7.38e-08 + 0.800000 1.161181 1.374632 5.67e-06 2.19e-08 + 0.900000 1.144904 1.245763 5.40e-08 6.40e-09 + 1.000000 1.127010 1.691839 4.83e-09 1.22e-07 + 1.100000 1.107609 1.000490 3.50e-07 1.24e-07 + 1.200000 1.086820 1.677552 1.80e-07 1.28e-07 + 1.300000 1.064777 1.277775 2.08e-08 5.87e-08 + 1.400000 1.041625 1.342455 6.57e-08 8.60e-08 + 1.500000 1.017531 1.642940 1.02e-08 1.45e-07 + 1.600000 0.992673 1.012112 7.42e-10 8.75e-08 + 1.700000 0.967251 1.714058 1.26e-06 1.96e-07 + 1.800000 0.941487 1.183866 5.89e-07 4.82e-08 + 1.900000 0.915617 1.437465 8.48e-11 1.34e-07 + 2.000000 0.889902 1.577082 8.30e-08 1.60e-07 + 2.100000 0.864625 1.056467 2.81e-08 3.18e-08 + 2.200000 0.840089 1.730920 2.75e-07 2.23e-07 + 2.300000 0.816616 1.101047 1.41e-08 3.14e-08 + 2.400000 0.794545 1.525051 5.03e-07 1.81e-07 + 2.500000 0.774227 1.496993 7.88e-10 1.70e-07 + 2.600000 0.756013 1.126857 1.27e-07 8.49e-08 + 2.700000 0.740246 1.727536 2.32e-07 2.61e-07 + 2.800000 0.727247 1.038393 6.92e-08 2.11e-08 + 2.900000 0.717301 1.600759 1.26e-08 2.31e-07 + 3.000000 0.710630 1.406379 6.27e-06 1.95e-07 + 3.100000 0.707412 1.214352 2.29e-08 1.59e-07 + 3.200000 0.707709 1.704026 1.45e-09 2.91e-07 + 3.300000 0.711519 1.004391 8.68e-08 2.89e-08 + 3.400000 0.718749 1.661225 2.14e-07 2.74e-07 + 3.500000 0.729227 1.310102 1.60e-08 2.21e-07 + 3.600000 0.742712 1.310080 1.03e-08 2.20e-07 + 3.700000 0.758914 1.661236 2.40e-08 2.91e-07 + 3.800000 0.777506 1.004387 4.29e-09 3.73e-08 + 3.900000 0.798143 1.704018 8.32e-07 3.27e-07 + 4.000000 0.820474 1.214374 7.44e-07 1.84e-07 + 4.100000 0.844149 1.406358 2.75e-09 2.40e-07 + 4.200000 0.868832 1.600774 1.39e-07 2.70e-07 + 4.300000 0.894204 1.038382 6.99e-08 5.45e-08 + 4.400000 0.919964 1.727533 3.58e-07 3.16e-07 + 4.500000 0.945834 1.126875 7.57e-09 1.27e-07 + 4.600000 0.971557 1.496973 7.25e-07 2.44e-07 + 4.700000 0.996898 1.525070 4.95e-08 2.35e-07 + 4.800000 1.021640 1.101030 1.22e-07 1.22e-07 + 4.900000 1.045589 1.730922 1.36e-07 3.02e-07 + 5.000000 1.068565 1.056480 2.82e-07 6.29e-08 + ------------------------------------------------------ + +Final Solver Statistics: + Steps: nsts = 2501, nstf = 250100 + u error = 1.301e-06, v error = 1.744e-07, total error = 9.284e-07 + Total RHS evals: Fs = 7002, Ff = 502702 + Slow Newton iters = 4500 + Slow Newton conv fails = 0 + Slow Jacobian evals = 126 diff --git a/examples/arkode/C_serial/ark_kpr_mri_8_0.001.out b/examples/arkode/C_serial/ark_kpr_mri_8_0.001.out deleted file mode 100644 index f96e203514..0000000000 --- a/examples/arkode/C_serial/ark_kpr_mri_8_0.001.out +++ /dev/null @@ -1,72 +0,0 @@ - -Multirate nonlinear Kvaerno-Prothero-Robinson test problem: - time domain: (0,5] - hs = 0.001 - hf = 1e-05 - G = -100 - w = 100 - e = 0.5 - solver: ars343/exp-3 (IMEX-MRI3b / ERK-3-3) -- solve decoupled - reltol = 1.00e-09, abstol = 1.00e-11 - t u v uerr verr - ------------------------------------------------------ - 0.000000 1.224745 1.732051 0.00e+00 0.00e+00 - 0.100000 1.223725 1.077464 2.79e-10 2.64e-11 - 0.200000 1.220669 1.551800 1.84e-10 4.85e-11 - 0.300000 1.215594 1.467737 1.86e-10 6.94e-11 - 0.400000 1.208524 1.154583 1.83e-10 8.79e-11 - 0.500000 1.199496 1.721908 1.82e-10 1.04e-10 - 0.600000 1.188557 1.023517 1.72e-10 1.20e-10 - 0.700000 1.175764 1.622751 1.67e-10 1.28e-10 - 0.800000 1.161186 1.374632 1.63e-10 1.39e-10 - 0.900000 1.144904 1.245763 1.52e-10 1.47e-10 - 1.000000 1.127010 1.691839 1.39e-10 1.50e-10 - 1.100000 1.107609 1.000489 1.29e-10 1.51e-10 - 1.200000 1.086821 1.677552 1.17e-10 1.57e-10 - 1.300000 1.064777 1.277775 1.10e-10 1.55e-10 - 1.400000 1.041625 1.342455 9.08e-11 1.53e-10 - 1.500000 1.017531 1.642940 6.96e-11 1.52e-10 - 1.600000 0.992673 1.012112 5.33e-11 1.42e-10 - 1.700000 0.967253 1.714058 3.20e-11 1.38e-10 - 1.800000 0.941488 1.183867 1.63e-11 1.24e-10 - 1.900000 0.915617 1.437465 1.06e-11 1.13e-10 - 2.000000 0.889903 1.577082 3.61e-11 9.93e-11 - 2.100000 0.864625 1.056467 6.56e-11 7.88e-11 - 2.200000 0.840089 1.730920 9.97e-11 6.38e-11 - 2.300000 0.816616 1.101047 1.27e-10 3.80e-11 - 2.400000 0.794546 1.525051 1.59e-10 1.69e-11 - 2.500000 0.774227 1.496993 1.88e-10 9.36e-12 - 2.600000 0.756013 1.126857 2.24e-10 3.98e-11 - 2.700000 0.740246 1.727536 2.59e-10 6.53e-11 - 2.800000 0.727247 1.038393 2.83e-10 1.00e-10 - 2.900000 0.717301 1.600759 3.04e-10 1.27e-10 - 3.000000 0.710636 1.406380 3.17e-10 1.58e-10 - 3.100000 0.707412 1.214353 3.28e-10 1.88e-10 - 3.200000 0.707709 1.704026 3.27e-10 2.11e-10 - 3.300000 0.711520 1.004391 3.17e-10 2.40e-10 - 3.400000 0.718750 1.661225 3.04e-10 2.54e-10 - 3.500000 0.729227 1.310102 2.87e-10 2.71e-10 - 3.600000 0.742712 1.310080 2.57e-10 2.81e-10 - 3.700000 0.758914 1.661237 2.23e-10 2.83e-10 - 3.800000 0.777506 1.004387 1.91e-10 2.87e-10 - 3.900000 0.798144 1.704019 1.58e-10 2.78e-10 - 4.000000 0.820474 1.214374 1.33e-10 2.73e-10 - 4.100000 0.844149 1.406358 9.74e-11 2.68e-10 - 4.200000 0.868832 1.600774 6.64e-11 2.60e-10 - 4.300000 0.894204 1.038382 3.79e-11 2.21e-10 - 4.400000 0.919964 1.727533 9.36e-12 2.25e-10 - 4.500000 0.945834 1.126875 1.03e-11 1.82e-10 - 4.600000 0.971557 1.496974 3.35e-11 1.74e-10 - 4.700000 0.996898 1.525070 5.03e-11 1.52e-10 - 4.800000 1.021641 1.101030 7.16e-11 1.11e-10 - 4.900000 1.045589 1.730922 9.30e-11 1.12e-10 - 5.000000 1.068565 1.056480 1.05e-10 6.39e-11 - ------------------------------------------------------ - -Final Solver Statistics: - Steps: nsts = 5000, nstf = 510000 - u error = 1.795e-10, v error = 1.678e-10, total error = 1.737e-10 - Total RHS evals: Fse = 20001, Fsi = 50342, Ff = 1530050 - Slow Newton iters = 30341 - Slow Newton conv fails = 0 - Slow Jacobian evals = 250 diff --git a/examples/arkode/C_serial/ark_kpr_mri_7_0.001_-100_100_0.5_1.out b/examples/arkode/C_serial/ark_kpr_mri_8_3_0.001_-100_100_0.5_1.out similarity index 93% rename from examples/arkode/C_serial/ark_kpr_mri_7_0.001_-100_100_0.5_1.out rename to examples/arkode/C_serial/ark_kpr_mri_8_3_0.001_-100_100_0.5_1.out index 38dc23acf1..fe05e8f5db 100644 --- a/examples/arkode/C_serial/ark_kpr_mri_7_0.001_-100_100_0.5_1.out +++ b/examples/arkode/C_serial/ark_kpr_mri_8_3_0.001_-100_100_0.5_1.out @@ -6,8 +6,9 @@ Multirate nonlinear Kvaerno-Prothero-Robinson test problem: G = -100 w = 100 e = 0.5 - solver: dirk-3/exp-3 (MRI-GARK-ESDIRK34a / ERK-3-3) -- solve decoupled - reltol = 1.00e-09, abstol = 1.00e-11 + slow solver: ARKODE_MRI_GARK_ESDIRK34a + reltol = 1.00e-09, abstol = 1.00e-11 + fast solver: erk-3-3 t u v uerr verr ------------------------------------------------------ 0.000000 1.224745 1.732051 0.00e+00 0.00e+00 @@ -51,7 +52,7 @@ Multirate nonlinear Kvaerno-Prothero-Robinson test problem: 3.800000 0.777506 1.004387 4.21e-10 6.69e-10 3.900000 0.798144 1.704019 3.62e-10 6.66e-10 4.000000 0.820474 1.214374 2.84e-10 6.45e-10 - 4.100000 0.844149 1.406358 3.43e-10 6.14e-10 + 4.100000 0.844149 1.406358 3.44e-10 6.14e-10 4.200000 0.868832 1.600774 1.51e-10 5.74e-10 4.300000 0.894204 1.038382 9.08e-11 5.56e-10 4.400000 0.919964 1.727533 4.15e-11 5.08e-10 @@ -66,7 +67,7 @@ Multirate nonlinear Kvaerno-Prothero-Robinson test problem: Final Solver Statistics: Steps: nsts = 5000, nstf = 510000 u error = 3.764e-10, v error = 3.952e-10, total error = 3.859e-10 - Total RHS evals: Fs = 35313, Ff = 1530050 + Total RHS evals: Fs = 35313, Ff = 1535001 Slow Newton iters = 30312 Slow Newton conv fails = 0 Slow Jacobian evals = 250 diff --git a/examples/arkode/C_serial/ark_kpr_mri_9_0.001.out b/examples/arkode/C_serial/ark_kpr_mri_9_0.001.out deleted file mode 100644 index 665cd0a588..0000000000 --- a/examples/arkode/C_serial/ark_kpr_mri_9_0.001.out +++ /dev/null @@ -1,72 +0,0 @@ - -Multirate nonlinear Kvaerno-Prothero-Robinson test problem: - time domain: (0,5] - hs = 0.001 - hf = 1e-05 - G = -100 - w = 100 - e = 0.5 - solver: imexark4/exp-4 (IMEX-MRI4 / ERK-4-4) -- solve decoupled - reltol = 1.00e-12, abstol = 1.00e-14 - t u v uerr verr - ------------------------------------------------------ - 0.000000 1.224745 1.732051 0.00e+00 0.00e+00 - 0.100000 1.223725 1.077464 1.63e-11 6.38e-13 - 0.200000 1.220669 1.551800 1.60e-11 6.83e-13 - 0.300000 1.215594 1.467737 1.52e-11 9.61e-13 - 0.400000 1.208524 1.154583 1.51e-11 9.21e-13 - 0.500000 1.199496 1.721908 1.60e-11 1.73e-12 - 0.600000 1.188557 1.023517 1.48e-11 3.43e-12 - 0.700000 1.175764 1.622751 1.36e-11 2.17e-12 - 0.800000 1.161186 1.374632 1.23e-11 2.77e-12 - 0.900000 1.144904 1.245763 1.12e-11 3.13e-12 - 1.000000 1.127010 1.691839 1.31e-11 2.17e-12 - 1.100000 1.107609 1.000489 1.11e-11 2.12e-12 - 1.200000 1.086821 1.677552 9.50e-12 1.93e-12 - 1.300000 1.064777 1.277775 7.58e-12 1.91e-12 - 1.400000 1.041625 1.342455 5.18e-12 2.57e-12 - 1.500000 1.017531 1.642940 6.04e-12 5.82e-12 - 1.600000 0.992673 1.012112 3.77e-12 3.35e-12 - 1.700000 0.967253 1.714058 3.32e-12 2.74e-12 - 1.800000 0.941488 1.183867 2.38e-13 3.75e-12 - 1.900000 0.915617 1.437465 3.30e-12 5.77e-12 - 2.000000 0.889903 1.577082 6.57e-12 8.88e-12 - 2.100000 0.864625 1.056467 7.88e-12 7.37e-12 - 2.200000 0.840089 1.730920 6.75e-12 4.53e-12 - 2.300000 0.816616 1.101047 1.18e-11 3.00e-12 - 2.400000 0.794546 1.525051 1.53e-11 8.93e-12 - 2.500000 0.774227 1.496993 1.85e-11 1.08e-11 - 2.600000 0.756013 1.126857 2.18e-11 1.35e-11 - 2.700000 0.740246 1.727536 2.05e-11 6.87e-12 - 2.800000 0.727247 1.038393 2.46e-11 7.76e-13 - 2.900000 0.717301 1.600759 2.68e-11 1.11e-11 - 3.000000 0.710636 1.406380 2.78e-11 1.14e-11 - 3.100000 0.707412 1.214353 2.85e-11 2.04e-11 - 3.200000 0.707709 1.704026 2.85e-11 9.74e-12 - 3.300000 0.711520 1.004391 2.77e-11 7.12e-12 - 3.400000 0.718750 1.661225 2.60e-11 1.06e-11 - 3.500000 0.729227 1.310102 2.41e-11 1.14e-11 - 3.600000 0.742712 1.310080 2.08e-11 2.60e-11 - 3.700000 0.758914 1.661237 1.99e-11 1.39e-11 - 3.800000 0.777506 1.004387 1.62e-11 1.43e-11 - 3.900000 0.798144 1.704019 1.39e-11 5.96e-12 - 4.000000 0.820474 1.214374 1.04e-11 1.12e-11 - 4.100000 0.844149 1.406358 6.45e-12 2.95e-11 - 4.200000 0.868832 1.600774 3.65e-12 5.01e-12 - 4.300000 0.894204 1.038382 1.63e-12 9.96e-12 - 4.400000 0.919964 1.727533 2.33e-12 1.06e-11 - 4.500000 0.945834 1.126875 2.28e-12 5.45e-12 - 4.600000 0.971557 1.496974 5.15e-12 1.52e-11 - 4.700000 0.996898 1.525070 8.52e-12 7.66e-13 - 4.800000 1.021641 1.101030 8.55e-12 1.92e-12 - 4.900000 1.045589 1.730922 6.11e-12 8.80e-12 - 5.000000 1.068565 1.056480 9.97e-12 3.37e-12 - ------------------------------------------------------ - -Final Solver Statistics: - Steps: nsts = 5000, nstf = 510000 - u error = 1.532e-11, v error = 9.496e-12, total error = 1.274e-11 - Total RHS evals: Fse = 30001, Fsi = 82555, Ff = 2040050 - Slow Newton iters = 52554 - Slow Newton conv fails = 0 - Slow Jacobian evals = 250 diff --git a/examples/arkode/C_serial/ark_kpr_mri_9_0.001_-100_100_0.5_1.out b/examples/arkode/C_serial/ark_kpr_mri_9_0.001_-100_100_0.5_1.out deleted file mode 100644 index a227a0db6a..0000000000 --- a/examples/arkode/C_serial/ark_kpr_mri_9_0.001_-100_100_0.5_1.out +++ /dev/null @@ -1,72 +0,0 @@ - -Multirate nonlinear Kvaerno-Prothero-Robinson test problem: - time domain: (0,5] - hs = 0.001 - hf = 1e-05 - G = -100 - w = 100 - e = 0.5 - solver: imexark4/exp-4 (IMEX-MRI4 / ERK-4-4) -- solve decoupled - reltol = 1.00e-12, abstol = 1.00e-14 - t u v uerr verr - ------------------------------------------------------ - 0.000000 1.224745 1.732051 0.00e+00 0.00e+00 - 0.100000 1.223725 1.077464 1.64e-11 6.38e-13 - 0.200000 1.220669 1.551800 1.61e-11 6.85e-13 - 0.300000 1.215594 1.467737 1.58e-11 9.70e-13 - 0.400000 1.208524 1.154583 1.55e-11 9.37e-13 - 0.500000 1.199496 1.721908 1.57e-11 1.74e-12 - 0.600000 1.188557 1.023517 1.50e-11 3.45e-12 - 0.700000 1.175764 1.622751 1.40e-11 2.20e-12 - 0.800000 1.161186 1.374632 1.20e-11 2.83e-12 - 0.900000 1.144904 1.245763 1.23e-11 3.18e-12 - 1.000000 1.127010 1.691839 1.28e-11 2.23e-12 - 1.100000 1.107609 1.000489 1.13e-11 2.05e-12 - 1.200000 1.086821 1.677552 9.92e-12 2.03e-12 - 1.300000 1.064777 1.277775 7.66e-12 2.00e-12 - 1.400000 1.041625 1.342455 6.65e-12 2.48e-12 - 1.500000 1.017531 1.642940 6.42e-12 5.92e-12 - 1.600000 0.992673 1.012112 4.49e-12 3.23e-12 - 1.700000 0.967253 1.714058 3.11e-12 2.87e-12 - 1.800000 0.941488 1.183867 5.85e-14 3.89e-12 - 1.900000 0.915617 1.437465 1.88e-12 5.63e-12 - 2.000000 0.889903 1.577082 4.65e-12 9.04e-12 - 2.100000 0.864625 1.056467 6.53e-12 7.20e-12 - 2.200000 0.840089 1.730920 7.39e-12 4.70e-12 - 2.300000 0.816616 1.101047 1.16e-11 3.16e-12 - 2.400000 0.794546 1.525051 1.48e-11 8.77e-12 - 2.500000 0.774227 1.496993 1.92e-11 1.10e-11 - 2.600000 0.756013 1.126857 2.04e-11 1.34e-11 - 2.700000 0.740246 1.727536 2.11e-11 7.02e-12 - 2.800000 0.727247 1.038393 2.44e-11 6.36e-13 - 2.900000 0.717301 1.600759 2.66e-11 1.09e-11 - 3.000000 0.710636 1.406380 2.78e-11 1.16e-11 - 3.100000 0.707412 1.214353 2.84e-11 2.03e-11 - 3.200000 0.707709 1.704026 2.84e-11 9.85e-12 - 3.300000 0.711520 1.004391 2.77e-11 7.02e-12 - 3.400000 0.718750 1.661225 2.61e-11 1.05e-11 - 3.500000 0.729227 1.310102 2.42e-11 1.14e-11 - 3.600000 0.742712 1.310080 2.16e-11 2.60e-11 - 3.700000 0.758914 1.661237 1.99e-11 1.39e-11 - 3.800000 0.777506 1.004387 1.67e-11 1.43e-11 - 3.900000 0.798144 1.704019 1.39e-11 5.96e-12 - 4.000000 0.820474 1.214374 1.05e-11 1.12e-11 - 4.100000 0.844149 1.406358 7.58e-12 2.96e-11 - 4.200000 0.868832 1.600774 5.04e-12 4.97e-12 - 4.300000 0.894204 1.038382 2.82e-12 1.00e-11 - 4.400000 0.919964 1.727533 1.81e-12 1.06e-11 - 4.500000 0.945834 1.126875 1.89e-12 5.36e-12 - 4.600000 0.971557 1.496974 3.73e-12 1.53e-11 - 4.700000 0.996898 1.525070 5.90e-12 8.98e-13 - 4.800000 1.021641 1.101030 7.16e-12 2.06e-12 - 4.900000 1.045589 1.730922 6.81e-12 8.94e-12 - 5.000000 1.068565 1.056480 9.34e-12 3.23e-12 - ------------------------------------------------------ - -Final Solver Statistics: - Steps: nsts = 5000, nstf = 510000 - u error = 1.533e-11, v error = 9.500e-12, total error = 1.275e-11 - Total RHS evals: Fse = 30001, Fsi = 57555, Ff = 2040050 - Slow Newton iters = 52554 - Slow Newton conv fails = 0 - Slow Jacobian evals = 250 diff --git a/examples/arkode/C_serial/ark_kpr_mri_8_0.001_-100_100_0.5_1.out b/examples/arkode/C_serial/ark_kpr_mri_9_3_0.001_-100_100_0.5_1.out similarity index 95% rename from examples/arkode/C_serial/ark_kpr_mri_8_0.001_-100_100_0.5_1.out rename to examples/arkode/C_serial/ark_kpr_mri_9_3_0.001_-100_100_0.5_1.out index f9d68539de..6eaf5ec418 100644 --- a/examples/arkode/C_serial/ark_kpr_mri_8_0.001_-100_100_0.5_1.out +++ b/examples/arkode/C_serial/ark_kpr_mri_9_3_0.001_-100_100_0.5_1.out @@ -6,8 +6,9 @@ Multirate nonlinear Kvaerno-Prothero-Robinson test problem: G = -100 w = 100 e = 0.5 - solver: ars343/exp-3 (IMEX-MRI3b / ERK-3-3) -- solve decoupled - reltol = 1.00e-09, abstol = 1.00e-11 + slow solver: ARKODE_IMEX_MRI_GARK3b + reltol = 1.00e-09, abstol = 1.00e-11 + fast solver: erk-3-3 t u v uerr verr ------------------------------------------------------ 0.000000 1.224745 1.732051 0.00e+00 0.00e+00 @@ -66,7 +67,7 @@ Multirate nonlinear Kvaerno-Prothero-Robinson test problem: Final Solver Statistics: Steps: nsts = 5000, nstf = 510000 u error = 1.860e-10, v error = 1.672e-10, total error = 1.769e-10 - Total RHS evals: Fse = 20001, Fsi = 35342, Ff = 1530050 + Total RHS evals: Fse = 20001, Fsi = 35342, Ff = 1535001 Slow Newton iters = 30341 Slow Newton conv fails = 0 Slow Jacobian evals = 250 diff --git a/examples/arkode/C_serial/ark_onewaycouple_mri.c b/examples/arkode/C_serial/ark_onewaycouple_mri.c index 78e1ede79c..623177acfc 100644 --- a/examples/arkode/C_serial/ark_onewaycouple_mri.c +++ b/examples/arkode/C_serial/ark_onewaycouple_mri.c @@ -148,11 +148,8 @@ int main(void) if (check_retval(&retval, "ARKodeSetFixedStep", 1)) { return 1; } /* Create inner stepper */ - retval = ARKStepCreateMRIStepInnerStepper(inner_arkode_mem, &inner_stepper); - if (check_retval(&retval, "ARKStepCreateMRIStepInnerStepper", 1)) - { - return 1; - } + retval = ARKodeCreateMRIStepInnerStepper(inner_arkode_mem, &inner_stepper); + if (check_retval(&retval, "ARKodeCreateMRIStepInnerStepper", 1)) { return 1; } /* * Create the slow integrator and set options diff --git a/examples/arkode/C_serial/ark_onewaycouple_mri.out b/examples/arkode/C_serial/ark_onewaycouple_mri.out index 3769f0e775..6b5ad2f798 100644 --- a/examples/arkode/C_serial/ark_onewaycouple_mri.out +++ b/examples/arkode/C_serial/ark_onewaycouple_mri.out @@ -20,4 +20,4 @@ One way coupling ODE test problem: Final Solver Statistics: Steps: nsts = 1000, nstf = 12000 - Total RHS evals: Fs = 3001, Ff = 36010 + Total RHS evals: Fs = 3001, Ff = 37001 diff --git a/examples/arkode/C_serial/ark_reaction_diffusion_mri.c b/examples/arkode/C_serial/ark_reaction_diffusion_mri.c index e6a5b6d138..2bb420efc2 100644 --- a/examples/arkode/C_serial/ark_reaction_diffusion_mri.c +++ b/examples/arkode/C_serial/ark_reaction_diffusion_mri.c @@ -157,11 +157,8 @@ int main(void) if (check_retval(&retval, "ARKodeSetFixedStep", 1)) { return 1; } /* Create inner stepper */ - retval = ARKStepCreateMRIStepInnerStepper(inner_arkode_mem, &inner_stepper); - if (check_retval(&retval, "ARKStepCreateMRIStepInnerStepper", 1)) - { - return 1; - } + retval = ARKodeCreateMRIStepInnerStepper(inner_arkode_mem, &inner_stepper); + if (check_retval(&retval, "ARKodeCreateMRIStepInnerStepper", 1)) { return 1; } /* * Create the slow integrator and set options diff --git a/examples/arkode/C_serial/ark_reaction_diffusion_mri.out b/examples/arkode/C_serial/ark_reaction_diffusion_mri.out index f8cd47dfdc..34af3937e9 100644 --- a/examples/arkode/C_serial/ark_reaction_diffusion_mri.out +++ b/examples/arkode/C_serial/ark_reaction_diffusion_mri.out @@ -51,6 +51,7 @@ Last step size = 0.001 Current step size = 0.001 Explicit slow RHS fn evals = 9004 Implicit slow RHS fn evals = 0 +Inner stepper failures = 0 NLS iters = 0 NLS fails = 0 NLS iters per step = 0 @@ -68,7 +69,7 @@ Inequality constraint fails = 0 Initial step size = 2e-05 Last step size = 9.999999998289147e-06 Current step size = 2e-05 -Explicit RHS fn evals = 459183 +Explicit RHS fn evals = 462155 Implicit RHS fn evals = 0 NLS iters = 0 NLS fails = 0 diff --git a/examples/arkode/C_serial/ark_twowaycouple_mri.c b/examples/arkode/C_serial/ark_twowaycouple_mri.c index 67b5415850..de7263c9c2 100644 --- a/examples/arkode/C_serial/ark_twowaycouple_mri.c +++ b/examples/arkode/C_serial/ark_twowaycouple_mri.c @@ -127,11 +127,8 @@ int main(void) if (check_retval(&retval, "ARKodeSetFixedStep", 1)) { return 1; } /* Create inner stepper */ - retval = ARKStepCreateMRIStepInnerStepper(inner_arkode_mem, &inner_stepper); - if (check_retval(&retval, "ARKStepCreateMRIStepInnerStepper", 1)) - { - return 1; - } + retval = ARKodeCreateMRIStepInnerStepper(inner_arkode_mem, &inner_stepper); + if (check_retval(&retval, "ARKodeCreateMRIStepInnerStepper", 1)) { return 1; } /* * Create the slow integrator and set options diff --git a/examples/arkode/C_serial/ark_twowaycouple_mri.out b/examples/arkode/C_serial/ark_twowaycouple_mri.out index 8aee3f02b7..96603859bf 100644 --- a/examples/arkode/C_serial/ark_twowaycouple_mri.out +++ b/examples/arkode/C_serial/ark_twowaycouple_mri.out @@ -30,4 +30,4 @@ Two way coupling ODE test problem: Final Solver Statistics: Steps: nsts = 2001, nstf = 102051 - Total RHS evals: Fs = 6004, Ff = 306173 + Total RHS evals: Fs = 6004, Ff = 308155 diff --git a/examples/arkode/F2003_serial/ark_kpr_mri_f2003.f90 b/examples/arkode/F2003_serial/ark_kpr_mri_f2003.f90 index 7556117b4d..a4f520a28c 100644 --- a/examples/arkode/F2003_serial/ark_kpr_mri_f2003.f90 +++ b/examples/arkode/F2003_serial/ark_kpr_mri_f2003.f90 @@ -886,9 +886,9 @@ program main end if ! Create inner stepper */ - retval = FARKStepCreateMRIStepInnerStepper(inner_arkode_mem, inner_stepper) + retval = FARKodeCreateMRIStepInnerStepper(inner_arkode_mem, inner_stepper) if (retval /= 0) then - print *, 'ERROR: FARKStepCreateMRIStepInnerStepper failed' + print *, 'ERROR: FARKodeCreateMRIStepInnerStepper failed' stop 1 end if diff --git a/examples/arkode/F2003_serial/ark_kpr_mri_f2003.out b/examples/arkode/F2003_serial/ark_kpr_mri_f2003.out index 9bdbea5dcb..036ba341ee 100644 --- a/examples/arkode/F2003_serial/ark_kpr_mri_f2003.out +++ b/examples/arkode/F2003_serial/ark_kpr_mri_f2003.out @@ -63,4 +63,4 @@ Final Solver Statistics: Steps: nsts = 501, nstf = 50601 u error = 0.794E-06, v error = 0.825E-07, total error = 0.565E-06 - Total RHS evals: Fs = 1504, Ff = 151853 + Total RHS evals: Fs = 1504, Ff = 152305 diff --git a/examples/arkode/F2003_serial/ark_kpr_mri_f2003_0_0.002.out b/examples/arkode/F2003_serial/ark_kpr_mri_f2003_0_0.002.out index c5001c9ed2..30dd3330cd 100644 --- a/examples/arkode/F2003_serial/ark_kpr_mri_f2003_0_0.002.out +++ b/examples/arkode/F2003_serial/ark_kpr_mri_f2003_0_0.002.out @@ -63,4 +63,4 @@ Final Solver Statistics: Steps: nsts = 2501, nstf = 252601 u error = 0.467E-08, v error = 0.564E-09, total error = 0.333E-08 - Total RHS evals: Fs = 7504, Ff = 757853 + Total RHS evals: Fs = 7504, Ff = 760305 diff --git a/examples/arkode/F2003_serial/ark_kpr_mri_f2003_1_0.002.out b/examples/arkode/F2003_serial/ark_kpr_mri_f2003_1_0.002.out index c84e3cde4b..d49bb3b964 100644 --- a/examples/arkode/F2003_serial/ark_kpr_mri_f2003_1_0.002.out +++ b/examples/arkode/F2003_serial/ark_kpr_mri_f2003_1_0.002.out @@ -63,4 +63,4 @@ Final Solver Statistics: Steps: nsts = 2501, nstf = 252601 u error = 0.316E-12, v error = 0.191E-11, total error = 0.137E-11 - Total RHS evals: Fs = 5003, Ff = 757853 + Total RHS evals: Fs = 5003, Ff = 760305 diff --git a/examples/arkode/F2003_serial/ark_kpr_mri_f2003_3_0.01.out b/examples/arkode/F2003_serial/ark_kpr_mri_f2003_3_0.01.out index fb98664760..b3260e55ab 100644 --- a/examples/arkode/F2003_serial/ark_kpr_mri_f2003_3_0.01.out +++ b/examples/arkode/F2003_serial/ark_kpr_mri_f2003_3_0.01.out @@ -63,4 +63,4 @@ Final Solver Statistics: Steps: nsts = 501, nstf = 50601 u error = 0.505E-04, v error = 0.768E-03, total error = 0.545E-03 - Total RHS evals: Fs = 1504, Ff = 151853 + Total RHS evals: Fs = 1504, Ff = 152305 diff --git a/examples/arkode/F2003_serial/ark_kpr_mri_f2003_4_0.002.out b/examples/arkode/F2003_serial/ark_kpr_mri_f2003_4_0.002.out index 22fca6299a..3814478dc7 100644 --- a/examples/arkode/F2003_serial/ark_kpr_mri_f2003_4_0.002.out +++ b/examples/arkode/F2003_serial/ark_kpr_mri_f2003_4_0.002.out @@ -64,7 +64,7 @@ Final Solver Statistics: Steps: nsts = 2501, nstf = 250100 u error = 0.348E-05, v error = 0.953E-03, total error = 0.674E-03 - Total RHS evals: Fs = 7143, Ff = 750350 + Total RHS evals: Fs = 7143, Ff = 752802 Slow Newton iters = 4641 Slow Newton conv fails = 0 Slow Jacobian evals = 126 diff --git a/examples/arkode/F2003_serial/ark_kpr_mri_f2003_5_0.002.out b/examples/arkode/F2003_serial/ark_kpr_mri_f2003_5_0.002.out index 48dd3ab5e5..848386387e 100644 --- a/examples/arkode/F2003_serial/ark_kpr_mri_f2003_5_0.002.out +++ b/examples/arkode/F2003_serial/ark_kpr_mri_f2003_5_0.002.out @@ -31,36 +31,36 @@ 2.000000 0.889903 1.577082 0.33E-10 0.47E-10 2.100000 0.864625 1.056467 0.59E-10 0.36E-10 2.200000 0.840089 1.730920 0.87E-10 0.32E-10 - 2.300000 0.816616 1.101047 0.12E-09 0.20E-10 - 2.400000 0.794546 1.525051 0.15E-09 0.78E-11 - 2.500000 0.774227 1.496993 0.18E-09 0.25E-11 - 2.600000 0.756013 1.126857 0.21E-09 0.20E-10 - 2.700000 0.740246 1.727536 0.24E-09 0.23E-10 - 2.800000 0.727247 1.038393 0.26E-09 0.42E-10 - 2.900000 0.717301 1.600759 0.28E-09 0.59E-10 - 3.000000 0.710636 1.406380 0.30E-09 0.62E-10 - 3.100000 0.707412 1.214353 0.31E-09 0.92E-10 - 3.200000 0.707709 1.704026 0.31E-09 0.87E-10 + 2.300000 0.816616 1.101047 0.12E-09 0.19E-10 + 2.400000 0.794546 1.525051 0.15E-09 0.11E-10 + 2.500000 0.774227 1.496993 0.18E-09 0.12E-11 + 2.600000 0.756013 1.126857 0.21E-09 0.16E-10 + 2.700000 0.740246 1.727536 0.24E-09 0.25E-10 + 2.800000 0.727247 1.038393 0.26E-09 0.44E-10 + 2.900000 0.717301 1.600759 0.28E-09 0.54E-10 + 3.000000 0.710636 1.406380 0.30E-09 0.69E-10 + 3.100000 0.707412 1.214353 0.31E-09 0.84E-10 + 3.200000 0.707709 1.704026 0.31E-09 0.93E-10 3.300000 0.711520 1.004391 0.30E-09 0.11E-09 - 3.400000 0.718750 1.661225 0.29E-09 0.12E-09 - 3.500000 0.729227 1.310102 0.27E-09 0.11E-09 - 3.600000 0.742712 1.310080 0.24E-09 0.14E-09 - 3.700000 0.758914 1.661237 0.22E-09 0.12E-09 - 3.800000 0.777506 1.004387 0.19E-09 0.14E-09 + 3.400000 0.718750 1.661225 0.29E-09 0.11E-09 + 3.500000 0.729227 1.310102 0.27E-09 0.12E-09 + 3.600000 0.742712 1.310080 0.24E-09 0.13E-09 + 3.700000 0.758914 1.661237 0.22E-09 0.13E-09 + 3.800000 0.777506 1.004387 0.19E-09 0.13E-09 3.900000 0.798144 1.704019 0.15E-09 0.13E-09 - 4.000000 0.820474 1.214374 0.12E-09 0.12E-09 - 4.100000 0.844149 1.406358 0.94E-10 0.14E-09 - 4.200000 0.868832 1.600774 0.65E-10 0.99E-10 - 4.300000 0.894204 1.038382 0.39E-10 0.12E-09 - 4.400000 0.919964 1.727533 0.14E-10 0.96E-10 - 4.500000 0.945834 1.126875 0.89E-11 0.80E-10 - 4.600000 0.971557 1.496974 0.30E-10 0.98E-10 - 4.700000 0.996898 1.525070 0.49E-10 0.49E-10 - 4.800000 1.021641 1.101030 0.67E-10 0.78E-10 - 4.900000 1.045589 1.730922 0.83E-10 0.39E-10 - 5.000000 1.068565 1.056480 0.97E-10 0.32E-10 + 4.000000 0.820474 1.214374 0.12E-09 0.13E-09 + 4.100000 0.844149 1.406358 0.94E-10 0.12E-09 + 4.200000 0.868832 1.600774 0.65E-10 0.11E-09 + 4.300000 0.894204 1.038382 0.39E-10 0.11E-09 + 4.400000 0.919964 1.727533 0.14E-10 0.97E-10 + 4.500000 0.945834 1.126875 0.89E-11 0.91E-10 + 4.600000 0.971557 1.496974 0.30E-10 0.79E-10 + 4.700000 0.996898 1.525070 0.49E-10 0.69E-10 + 4.800000 1.021641 1.101030 0.67E-10 0.61E-10 + 4.900000 1.045589 1.730922 0.83E-10 0.47E-10 + 5.000000 1.068565 1.056480 0.97E-10 0.40E-10 ------------------------------------------------------ Final Solver Statistics: Steps: nsts = 2501, nstf = 250100 - u error = 0.166E-09, v error = 0.771E-10, total error = 0.130E-09 - Total RHS evals: Fs = 12506, Ff = 1000450 + u error = 0.166E-09, v error = 0.768E-10, total error = 0.130E-09 + Total RHS evals: Fs = 12506, Ff = 1002902 diff --git a/examples/arkode/F2003_serial/ark_kpr_mri_f2003_6_0.005.out b/examples/arkode/F2003_serial/ark_kpr_mri_f2003_6_0.005.out index fa764c5633..20d2cb720a 100644 --- a/examples/arkode/F2003_serial/ark_kpr_mri_f2003_6_0.005.out +++ b/examples/arkode/F2003_serial/ark_kpr_mri_f2003_6_0.005.out @@ -33,7 +33,7 @@ 2.200000 0.840089 1.730920 0.39E-08 0.13E-08 2.300000 0.816616 1.101047 0.53E-08 0.90E-09 2.400000 0.794546 1.525051 0.67E-08 0.45E-09 - 2.500000 0.774227 1.496993 0.80E-08 0.39E-10 + 2.500000 0.774227 1.496993 0.80E-08 0.42E-10 2.600000 0.756013 1.126857 0.94E-08 0.57E-09 2.700000 0.740246 1.727536 0.11E-07 0.11E-08 2.800000 0.727247 1.038393 0.12E-07 0.17E-08 @@ -63,4 +63,4 @@ Final Solver Statistics: Steps: nsts = 1001, nstf = 100100 u error = 0.757E-08, v error = 0.324E-08, total error = 0.582E-08 - Total RHS evals: Fs = 5006, Ff = 300350 + Total RHS evals: Fs = 5006, Ff = 301302 diff --git a/examples/arkode/F2003_serial/ark_kpr_mri_f2003_7_0.001.out b/examples/arkode/F2003_serial/ark_kpr_mri_f2003_7_0.001.out index 925d9c3474..980984a104 100644 --- a/examples/arkode/F2003_serial/ark_kpr_mri_f2003_7_0.001.out +++ b/examples/arkode/F2003_serial/ark_kpr_mri_f2003_7_0.001.out @@ -64,7 +64,7 @@ Final Solver Statistics: Steps: nsts = 5000, nstf = 510000 u error = 0.380E-09, v error = 0.394E-09, total error = 0.387E-09 - Total RHS evals: Fs = 45313, Ff = 1530050 + Total RHS evals: Fs = 45313, Ff = 1535001 Slow Newton iters = 30312 Slow Newton conv fails = 0 Slow Jacobian evals = 250 diff --git a/examples/arkode/F2003_serial/ark_kpr_mri_f2003_8_0.001.out b/examples/arkode/F2003_serial/ark_kpr_mri_f2003_8_0.001.out index bd101638aa..5e9fd70305 100644 --- a/examples/arkode/F2003_serial/ark_kpr_mri_f2003_8_0.001.out +++ b/examples/arkode/F2003_serial/ark_kpr_mri_f2003_8_0.001.out @@ -64,7 +64,7 @@ Final Solver Statistics: Steps: nsts = 5000, nstf = 510000 u error = 0.179E-09, v error = 0.168E-09, total error = 0.174E-09 - Total RHS evals: Fse = 20001, Fsi = 50342, Ff = 1530050 + Total RHS evals: Fse = 20001, Fsi = 50342, Ff = 1535001 Slow Newton iters = 30341 Slow Newton conv fails = 0 Slow Jacobian evals = 250 diff --git a/examples/arkode/F2003_serial/ark_kpr_mri_f2003_9_0.001.out b/examples/arkode/F2003_serial/ark_kpr_mri_f2003_9_0.001.out index 6e504b619b..d4a07bc167 100644 --- a/examples/arkode/F2003_serial/ark_kpr_mri_f2003_9_0.001.out +++ b/examples/arkode/F2003_serial/ark_kpr_mri_f2003_9_0.001.out @@ -20,51 +20,51 @@ 0.800000 1.161186 1.374632 0.12E-10 0.28E-11 0.900000 1.144904 1.245763 0.11E-10 0.31E-11 1.000000 1.127010 1.691839 0.13E-10 0.22E-11 - 1.100000 1.107609 1.000489 0.11E-10 0.21E-11 - 1.200000 1.086821 1.677552 0.95E-11 0.19E-11 - 1.300000 1.064777 1.277775 0.76E-11 0.19E-11 - 1.400000 1.041625 1.342455 0.52E-11 0.26E-11 - 1.500000 1.017531 1.642940 0.60E-11 0.58E-11 - 1.600000 0.992673 1.012112 0.38E-11 0.34E-11 - 1.700000 0.967253 1.714058 0.33E-11 0.27E-11 - 1.800000 0.941488 1.183867 0.24E-12 0.38E-11 - 1.900000 0.915617 1.437465 0.33E-11 0.58E-11 - 2.000000 0.889903 1.577082 0.66E-11 0.89E-11 - 2.100000 0.864625 1.056467 0.79E-11 0.74E-11 - 2.200000 0.840089 1.730920 0.67E-11 0.45E-11 - 2.300000 0.816616 1.101047 0.12E-10 0.30E-11 - 2.400000 0.794546 1.525051 0.15E-10 0.89E-11 - 2.500000 0.774227 1.496993 0.18E-10 0.11E-10 - 2.600000 0.756013 1.126857 0.22E-10 0.14E-10 - 2.700000 0.740246 1.727536 0.20E-10 0.69E-11 - 2.800000 0.727247 1.038393 0.25E-10 0.78E-12 - 2.900000 0.717301 1.600759 0.27E-10 0.11E-10 - 3.000000 0.710636 1.406380 0.28E-10 0.11E-10 - 3.100000 0.707412 1.214353 0.29E-10 0.20E-10 - 3.200000 0.707709 1.704026 0.28E-10 0.97E-11 - 3.300000 0.711520 1.004391 0.28E-10 0.71E-11 - 3.400000 0.718750 1.661225 0.26E-10 0.11E-10 - 3.500000 0.729227 1.310102 0.24E-10 0.11E-10 - 3.600000 0.742712 1.310080 0.21E-10 0.26E-10 - 3.700000 0.758914 1.661237 0.20E-10 0.14E-10 - 3.800000 0.777506 1.004387 0.16E-10 0.14E-10 - 3.900000 0.798144 1.704019 0.14E-10 0.60E-11 - 4.000000 0.820474 1.214374 0.10E-10 0.11E-10 - 4.100000 0.844149 1.406358 0.65E-11 0.30E-10 - 4.200000 0.868832 1.600774 0.36E-11 0.50E-11 - 4.300000 0.894204 1.038382 0.16E-11 0.10E-10 - 4.400000 0.919964 1.727533 0.23E-11 0.11E-10 - 4.500000 0.945834 1.126875 0.23E-11 0.55E-11 - 4.600000 0.971557 1.496974 0.52E-11 0.15E-10 - 4.700000 0.996898 1.525070 0.85E-11 0.77E-12 - 4.800000 1.021641 1.101030 0.85E-11 0.19E-11 - 4.900000 1.045589 1.730922 0.61E-11 0.88E-11 + 1.100000 1.107609 1.000489 0.11E-10 0.20E-11 + 1.200000 1.086821 1.677552 0.95E-11 0.25E-11 + 1.300000 1.064777 1.277775 0.76E-11 0.83E-13 + 1.400000 1.041625 1.342455 0.52E-11 0.62E-12 + 1.500000 1.017531 1.642940 0.60E-11 0.26E-11 + 1.600000 0.992673 1.012112 0.38E-11 0.14E-11 + 1.700000 0.967253 1.714058 0.33E-11 0.31E-11 + 1.800000 0.941488 1.183867 0.24E-12 0.36E-12 + 1.900000 0.915617 1.437465 0.33E-11 0.12E-11 + 2.000000 0.889903 1.577082 0.66E-11 0.19E-11 + 2.100000 0.864625 1.056467 0.79E-11 0.16E-11 + 2.200000 0.840089 1.730920 0.67E-11 0.25E-11 + 2.300000 0.816616 1.101047 0.12E-10 0.18E-11 + 2.400000 0.794546 1.525051 0.15E-10 0.57E-12 + 2.500000 0.774227 1.496993 0.18E-10 0.68E-13 + 2.600000 0.756013 1.126857 0.22E-10 0.27E-11 + 2.700000 0.740246 1.727536 0.20E-10 0.73E-12 + 2.800000 0.727247 1.038393 0.25E-10 0.40E-11 + 2.900000 0.717301 1.600759 0.27E-10 0.93E-12 + 3.000000 0.710636 1.406380 0.28E-10 0.26E-11 + 3.100000 0.707412 1.214353 0.29E-10 0.42E-11 + 3.200000 0.707709 1.704026 0.28E-10 0.15E-11 + 3.300000 0.711520 1.004391 0.28E-10 0.63E-11 + 3.400000 0.718750 1.661225 0.26E-10 0.24E-11 + 3.500000 0.729227 1.310102 0.24E-10 0.48E-11 + 3.600000 0.742712 1.310080 0.21E-10 0.50E-11 + 3.700000 0.758914 1.661237 0.20E-10 0.28E-11 + 3.800000 0.777506 1.004387 0.16E-10 0.70E-11 + 3.900000 0.798144 1.704019 0.14E-10 0.25E-11 + 4.000000 0.820474 1.214374 0.10E-10 0.54E-11 + 4.100000 0.844149 1.406358 0.65E-11 0.83E-11 + 4.200000 0.868832 1.600774 0.37E-11 0.11E-10 + 4.300000 0.894204 1.038382 0.16E-11 0.25E-12 + 4.400000 0.919964 1.727533 0.23E-11 0.12E-10 + 4.500000 0.945834 1.126875 0.23E-11 0.75E-12 + 4.600000 0.971557 1.496974 0.52E-11 0.69E-11 + 4.700000 0.996898 1.525070 0.85E-11 0.69E-11 + 4.800000 1.021641 1.101030 0.85E-11 0.16E-11 + 4.900000 1.045589 1.730922 0.61E-11 0.95E-11 5.000000 1.068565 1.056480 0.10E-10 0.34E-11 ------------------------------------------------------ Final Solver Statistics: Steps: nsts = 5000, nstf = 510000 - u error = 0.153E-10, v error = 0.950E-11, total error = 0.127E-10 - Total RHS evals: Fse = 30001, Fsi = 82555, Ff = 2040050 + u error = 0.153E-10, v error = 0.419E-11, total error = 0.112E-10 + Total RHS evals: Fse = 30001, Fsi = 82555, Ff = 2045001 Slow Newton iters = 52554 Slow Newton conv fails = 0 Slow Jacobian evals = 250 diff --git a/examples/utilities/example_utilities.hpp b/examples/utilities/example_utilities.hpp index 00b4d843fc..448ac8e268 100644 --- a/examples/utilities/example_utilities.hpp +++ b/examples/utilities/example_utilities.hpp @@ -43,7 +43,7 @@ static int check_ptr(const void* ptr, const std::string funcname) inline void find_arg(std::vector& args, const std::string key, float& dest) { - auto it = std::find(args.begin(), args.end(), key); + auto it = std::find(args.cbegin(), args.cend(), key); if (it != args.end()) { dest = stof(*(it + 1)); @@ -54,7 +54,7 @@ inline void find_arg(std::vector& args, const std::string key, inline void find_arg(std::vector& args, const std::string key, double& dest) { - auto it = std::find(args.begin(), args.end(), key); + auto it = std::find(args.cbegin(), args.cend(), key); if (it != args.end()) { dest = stod(*(it + 1)); @@ -65,7 +65,7 @@ inline void find_arg(std::vector& args, const std::string key, inline void find_arg(std::vector& args, const std::string key, long double& dest) { - auto it = std::find(args.begin(), args.end(), key); + auto it = std::find(args.cbegin(), args.cend(), key); if (it != args.end()) { dest = stold(*(it + 1)); @@ -76,7 +76,7 @@ inline void find_arg(std::vector& args, const std::string key, inline void find_arg(std::vector& args, const std::string key, long long& dest) { - auto it = std::find(args.begin(), args.end(), key); + auto it = std::find(args.cbegin(), args.cend(), key); if (it != args.end()) { dest = stoll(*(it + 1)); @@ -87,7 +87,7 @@ inline void find_arg(std::vector& args, const std::string key, inline void find_arg(std::vector& args, const std::string key, long int& dest) { - auto it = std::find(args.begin(), args.end(), key); + auto it = std::find(args.cbegin(), args.cend(), key); if (it != args.end()) { dest = stol(*(it + 1)); @@ -98,7 +98,7 @@ inline void find_arg(std::vector& args, const std::string key, inline void find_arg(std::vector& args, const std::string key, int& dest) { - auto it = std::find(args.begin(), args.end(), key); + auto it = std::find(args.cbegin(), args.cend(), key); if (it != args.end()) { dest = stoi(*(it + 1)); @@ -109,10 +109,21 @@ inline void find_arg(std::vector& args, const std::string key, inline void find_arg(std::vector& args, const std::string key, bool& dest, bool store = true) { - auto it = std::find(args.begin(), args.end(), key); + auto it = std::find(args.cbegin(), args.cend(), key); if (it != args.end()) { dest = store; args.erase(it); } } + +inline void find_arg(std::vector& args, const std::string key, + std::string& dest) +{ + auto it = std::find(args.cbegin(), args.cend(), key); + if (it != args.end()) + { + dest = std::move(*(it + 1)); + args.erase(it, it + 2); + } +} diff --git a/include/arkode/arkode.h b/include/arkode/arkode.h index 684e4fadab..516dffd60c 100644 --- a/include/arkode/arkode.h +++ b/include/arkode/arkode.h @@ -196,6 +196,18 @@ typedef enum ARK_RELAX_NEWTON } ARKRelaxSolver; +/* -------------------------- + * Error Accumulation Options + * -------------------------- */ + +typedef enum +{ + ARK_ACCUMERROR_NONE, + ARK_ACCUMERROR_MAX, + ARK_ACCUMERROR_SUM, + ARK_ACCUMERROR_AVG +} ARKAccumError; + /* -------------------------- * Shared API routines * -------------------------- */ @@ -206,6 +218,10 @@ SUNDIALS_EXPORT int ARKodeResize(void* arkode_mem, N_Vector ynew, ARKVecResizeFn resize, void* resize_data); SUNDIALS_EXPORT int ARKodeReset(void* arkode_mem, sunrealtype tR, N_Vector yR); +/* Utility to wrap ARKODE as an MRIStepInnerStepper */ +SUNDIALS_EXPORT int ARKodeCreateMRIStepInnerStepper(void* arkode_mem, + MRIStepInnerStepper* stepper); + /* Tolerance input functions */ SUNDIALS_EXPORT int ARKodeSStolerances(void* arkode_mem, sunrealtype reltol, sunrealtype abstol); @@ -286,6 +302,9 @@ SUNDIALS_EXPORT int ARKodeSetInitStep(void* arkode_mem, sunrealtype hin); SUNDIALS_EXPORT int ARKodeSetMinStep(void* arkode_mem, sunrealtype hmin); SUNDIALS_EXPORT int ARKodeSetMaxStep(void* arkode_mem, sunrealtype hmax); SUNDIALS_EXPORT int ARKodeSetMaxNumConstrFails(void* arkode_mem, int maxfails); +SUNDIALS_EXPORT int ARKodeSetAccumulatedErrorType(void* arkode_mem, + ARKAccumError accum_type); +SUNDIALS_EXPORT int ARKodeResetAccumulatedError(void* arkode_mem); /* Integrate the ODE over an interval in t */ SUNDIALS_EXPORT int ARKodeEvolve(void* arkode_mem, sunrealtype tout, @@ -333,6 +352,8 @@ SUNDIALS_EXPORT int ARKodeGetNumConstrFails(void* arkode_mem, SUNDIALS_EXPORT int ARKodeGetStepStats(void* arkode_mem, long int* nsteps, sunrealtype* hinused, sunrealtype* hlast, sunrealtype* hcur, sunrealtype* tcur); +SUNDIALS_EXPORT int ARKodeGetAccumulatedError(void* arkode_mem, + sunrealtype* accum_error); /* Optional output functions (implicit solver) */ SUNDIALS_EXPORT int ARKodeGetNumLinSolvSetups(void* arkode_mem, diff --git a/include/arkode/arkode_arkstep.h b/include/arkode/arkode_arkstep.h index 9a0cfbb5a1..777663da61 100644 --- a/include/arkode/arkode_arkstep.h +++ b/include/arkode/arkode_arkstep.h @@ -94,14 +94,13 @@ SUNDIALS_EXPORT int ARKStepGetTimestepperStats( long int* step_attempts, long int* nfe_evals, long int* nfi_evals, long int* nlinsetups, long int* netfails); -/* MRIStep interface functions */ -SUNDIALS_EXPORT int ARKStepCreateMRIStepInnerStepper(void* arkode_mem, - MRIStepInnerStepper* stepper); - /* -------------------------------------------------------------------------- * Deprecated Functions -- all are superseded by shared ARKODE-level routines * -------------------------------------------------------------------------- */ +SUNDIALS_DEPRECATED_EXPORT_MSG("use ARKodeCreateMRIStepInnerStepper instead") +int ARKStepCreateMRIStepInnerStepper(void* arkode_mem, + MRIStepInnerStepper* stepper); SUNDIALS_DEPRECATED_EXPORT_MSG("use ARKodeResize instead") int ARKStepResize(void* arkode_mem, N_Vector ynew, sunrealtype hscale, sunrealtype t0, ARKVecResizeFn resize, void* resize_data); diff --git a/include/arkode/arkode_mristep.h b/include/arkode/arkode_mristep.h index 506534b9db..6b8fcda102 100644 --- a/include/arkode/arkode_mristep.h +++ b/include/arkode/arkode_mristep.h @@ -22,6 +22,7 @@ #include #include #include +#include #include #ifdef __cplusplus /* wrapper to enable C++ usage */ @@ -37,9 +38,12 @@ typedef enum { MRISTEP_EXPLICIT, MRISTEP_IMPLICIT, - MRISTEP_IMEX + MRISTEP_IMEX, + MRISTEP_MERK, + MRISTEP_SR } MRISTEP_METHOD_TYPE; +/* MRI coupling table IDs */ typedef enum { ARKODE_MRI_NONE = -1, /* ensure enum is signed int */ @@ -63,15 +67,27 @@ typedef enum ARKODE_IMEX_MRI_GARK_EULER, ARKODE_IMEX_MRI_GARK_TRAPEZOIDAL, ARKODE_IMEX_MRI_GARK_MIDPOINT, - ARKODE_MAX_MRI_NUM = ARKODE_IMEX_MRI_GARK_MIDPOINT, + ARKODE_MERK21, + ARKODE_MERK32, + ARKODE_MERK43, + ARKODE_MERK54, + ARKODE_IMEX_MRI_SR21, + ARKODE_IMEX_MRI_SR32, + ARKODE_IMEX_MRI_SR43, + ARKODE_MAX_MRI_NUM = ARKODE_IMEX_MRI_SR43 } ARKODE_MRITableID; -/* Default MRI coupling tables for each order */ +/* Default MRI coupling tables for each order and type */ static const int MRISTEP_DEFAULT_EXPL_1 = ARKODE_MRI_GARK_FORWARD_EULER; static const int MRISTEP_DEFAULT_EXPL_2 = ARKODE_MRI_GARK_ERK22b; static const int MRISTEP_DEFAULT_EXPL_3 = ARKODE_MIS_KW3; static const int MRISTEP_DEFAULT_EXPL_4 = ARKODE_MRI_GARK_ERK45a; +static const int MRISTEP_DEFAULT_EXPL_2_AD = ARKODE_MRI_GARK_ERK22b; +static const int MRISTEP_DEFAULT_EXPL_3_AD = ARKODE_MRI_GARK_ERK33a; +static const int MRISTEP_DEFAULT_EXPL_4_AD = ARKODE_MRI_GARK_ERK45a; +static const int MRISTEP_DEFAULT_EXPL_5_AD = ARKODE_MERK54; + static const int MRISTEP_DEFAULT_IMPL_SD_1 = ARKODE_MRI_GARK_BACKWARD_EULER; static const int MRISTEP_DEFAULT_IMPL_SD_2 = ARKODE_MRI_GARK_IRK21a; static const int MRISTEP_DEFAULT_IMPL_SD_3 = ARKODE_MRI_GARK_ESDIRK34a; @@ -82,6 +98,10 @@ static const int MRISTEP_DEFAULT_IMEX_SD_2 = ARKODE_IMEX_MRI_GARK_TRAPEZOIDAL; static const int MRISTEP_DEFAULT_IMEX_SD_3 = ARKODE_IMEX_MRI_GARK3b; static const int MRISTEP_DEFAULT_IMEX_SD_4 = ARKODE_IMEX_MRI_GARK4; +static const int MRISTEP_DEFAULT_IMEX_SD_2_AD = ARKODE_IMEX_MRI_SR21; +static const int MRISTEP_DEFAULT_IMEX_SD_3_AD = ARKODE_IMEX_MRI_SR32; +static const int MRISTEP_DEFAULT_IMEX_SD_4_AD = ARKODE_IMEX_MRI_SR43; + /* ------------------------------------ * MRIStep Inner Stepper Function Types * ------------------------------------ */ @@ -95,18 +115,29 @@ typedef int (*MRIStepInnerFullRhsFn)(MRIStepInnerStepper stepper, sunrealtype t, typedef int (*MRIStepInnerResetFn)(MRIStepInnerStepper stepper, sunrealtype tR, N_Vector yR); +typedef int (*MRIStepInnerGetAccumulatedError)(MRIStepInnerStepper stepper, + sunrealtype* accum_error); + +typedef int (*MRIStepInnerResetAccumulatedError)(MRIStepInnerStepper stepper); + +typedef int (*MRIStepInnerSetRTol)(MRIStepInnerStepper stepper, sunrealtype rtol); + /*--------------------------------------------------------------- MRI coupling data structure and associated utility routines ---------------------------------------------------------------*/ struct MRIStepCouplingMem { - int nmat; /* number of MRI coupling matrices */ - int stages; /* size of coupling matrices (stages * stages) */ - int q; /* method order of accuracy */ - int p; /* embedding order of accuracy */ - sunrealtype* c; /* stage abscissae */ - sunrealtype*** W; /* explicit coupling matrices [nmat][stages][stages] */ - sunrealtype*** G; /* implicit coupling matrices [nmat][stages][stages] */ + MRISTEP_METHOD_TYPE type; /* flag to encode the MRI method type */ + int nmat; /* number of MRI coupling matrices */ + int stages; /* size of coupling matrices ((stages+1) * stages) */ + int q; /* method order of accuracy */ + int p; /* embedding order of accuracy */ + sunrealtype* c; /* stage abscissae */ + sunrealtype*** W; /* explicit coupling matrices [nmat][stages+1][stages] */ + sunrealtype*** G; /* implicit coupling matrices [nmat][stages+1][stages] */ + + int ngroup; /* number of stage groups (MERK-specific) */ + int** group; /* stages to integrate together (MERK-specific) */ }; typedef _SUNDIALS_STRUCT_ MRIStepCouplingMem* MRIStepCoupling; @@ -164,6 +195,8 @@ SUNDIALS_EXPORT int MRIStepSetPostInnerFn(void* arkode_mem, SUNDIALS_EXPORT int MRIStepGetCurrentCoupling(void* arkode_mem, MRIStepCoupling* MRIC); SUNDIALS_EXPORT int MRIStepGetLastInnerStepFlag(void* arkode_mem, int* flag); +SUNDIALS_EXPORT int MRIStepGetNumInnerStepperFails(void* arkode_mem, + long int* inner_fails); /* Custom inner stepper functions */ SUNDIALS_EXPORT int MRIStepInnerStepper_Create(SUNContext sunctx, @@ -183,6 +216,12 @@ SUNDIALS_EXPORT int MRIStepInnerStepper_SetFullRhsFn(MRIStepInnerStepper stepper MRIStepInnerFullRhsFn fn); SUNDIALS_EXPORT int MRIStepInnerStepper_SetResetFn(MRIStepInnerStepper stepper, MRIStepInnerResetFn fn); +SUNDIALS_EXPORT int MRIStepInnerStepper_SetAccumulatedErrorGetFn( + MRIStepInnerStepper stepper, MRIStepInnerGetAccumulatedError fn); +SUNDIALS_EXPORT int MRIStepInnerStepper_SetAccumulatedErrorResetFn( + MRIStepInnerStepper stepper, MRIStepInnerResetAccumulatedError fn); +SUNDIALS_EXPORT int MRIStepInnerStepper_SetRTolFn(MRIStepInnerStepper stepper, + MRIStepInnerSetRTol fn); SUNDIALS_EXPORT int MRIStepInnerStepper_AddForcing(MRIStepInnerStepper stepper, sunrealtype t, N_Vector f); SUNDIALS_EXPORT int MRIStepInnerStepper_GetForcingData( diff --git a/include/sunadaptcontroller/sunadaptcontroller_mrihtol.h b/include/sunadaptcontroller/sunadaptcontroller_mrihtol.h new file mode 100644 index 0000000000..baeffe7f73 --- /dev/null +++ b/include/sunadaptcontroller/sunadaptcontroller_mrihtol.h @@ -0,0 +1,88 @@ +/* ----------------------------------------------------------------- + * Programmer(s): Daniel R. Reynolds @ SMU + * ----------------------------------------------------------------- + * SUNDIALS Copyright Start + * Copyright (c) 2002-2024, Lawrence Livermore National Security + * and Southern Methodist University. + * All rights reserved. + * + * See the top-level LICENSE and NOTICE files for details. + * + * SPDX-License-Identifier: BSD-3-Clause + * SUNDIALS Copyright End + * ----------------------------------------------------------------- + * This is the header file for the SUNAdaptController_MRIHTol module. + * -----------------------------------------------------------------*/ + +#ifndef _SUNADAPTCONTROLLER_MRIHTOL_H +#define _SUNADAPTCONTROLLER_MRIHTOL_H + +#include +#include + +#ifdef __cplusplus /* wrapper to enable C++ usage */ +extern "C" { +#endif + +/* ---------------------------------------------------- + * MRI H+tolerance implementation of SUNAdaptController + * ---------------------------------------------------- */ + +struct SUNAdaptControllerContent_MRIHTol_ +{ + SUNAdaptController HControl; + SUNAdaptController TolControl; + sunrealtype inner_max_relch; + sunrealtype inner_min_tolfac; + sunrealtype inner_max_tolfac; +}; + +typedef struct SUNAdaptControllerContent_MRIHTol_* SUNAdaptControllerContent_MRIHTol; + +/* ------------------ + * Exported Functions + * ------------------ */ + +SUNDIALS_EXPORT +SUNAdaptController SUNAdaptController_MRIHTol(SUNAdaptController HControl, + SUNAdaptController TolControl, + SUNContext sunctx); +SUNDIALS_EXPORT +SUNErrCode SUNAdaptController_SetParams_MRIHTol(SUNAdaptController C, + sunrealtype inner_max_relch, + sunrealtype inner_min_tolfac, + sunrealtype inner_max_tolfac); +SUNDIALS_EXPORT +SUNErrCode SUNAdaptController_GetSlowController_MRIHTol(SUNAdaptController C, + SUNAdaptController* Cslow); +SUNDIALS_EXPORT +SUNErrCode SUNAdaptController_GetFastController_MRIHTol(SUNAdaptController C, + SUNAdaptController* Cfast); +SUNDIALS_EXPORT +SUNAdaptController_Type SUNAdaptController_GetType_MRIHTol(SUNAdaptController C); +SUNDIALS_EXPORT +int SUNAdaptController_EstimateStepTol_MRIHTol( + SUNAdaptController C, sunrealtype H, sunrealtype tolfac, int P, + sunrealtype DSM, sunrealtype dsm, sunrealtype* Hnew, sunrealtype* tolfacnew); +SUNDIALS_EXPORT +int SUNAdaptController_Reset_MRIHTol(SUNAdaptController C); +SUNDIALS_EXPORT +int SUNAdaptController_SetDefaults_MRIHTol(SUNAdaptController C); +SUNDIALS_EXPORT +int SUNAdaptController_Write_MRIHTol(SUNAdaptController C, FILE* fptr); +SUNDIALS_EXPORT +int SUNAdaptController_SetErrorBias_MRIHTol(SUNAdaptController C, + sunrealtype bias); +SUNDIALS_EXPORT +int SUNAdaptController_UpdateMRIHTol_MRIHTol(SUNAdaptController C, + sunrealtype H, sunrealtype tolfac, + sunrealtype DSM, sunrealtype dsm); +SUNDIALS_EXPORT +int SUNAdaptController_Space_MRIHTol(SUNAdaptController C, long int* lenrw, + long int* leniw); + +#ifdef __cplusplus +} +#endif + +#endif /* _SUNADAPTCONTROLLER_MRIHTOL_H */ diff --git a/include/sundials/sundials_adaptcontroller.h b/include/sundials/sundials_adaptcontroller.h index b27d7c73c8..4d5c9bf9ca 100644 --- a/include/sundials/sundials_adaptcontroller.h +++ b/include/sundials/sundials_adaptcontroller.h @@ -31,16 +31,17 @@ extern "C" { #endif /* ----------------------------------------------------------------- - * SUNAdaptController types (currently, only "H" is implemented; - * others are planned): + * SUNAdaptController types: * NONE - empty controller (does nothing) * H - controls a single-rate step size + * MRI_H_TOL - controls slow step and fast relative tolerances * ----------------------------------------------------------------- */ typedef enum { SUN_ADAPTCONTROLLER_NONE, - SUN_ADAPTCONTROLLER_H + SUN_ADAPTCONTROLLER_H, + SUN_ADAPTCONTROLLER_MRI_H_TOL } SUNAdaptController_Type; /* ----------------------------------------------------------------- @@ -63,6 +64,12 @@ struct _generic_SUNAdaptController_Ops SUNErrCode (*estimatestep)(SUNAdaptController C, sunrealtype h, int p, sunrealtype dsm, sunrealtype* hnew); + /* REQUIRED for controllers of SUN_ADAPTCONTROLLER_MRI_H_TOL type. */ + SUNErrCode (*estimatesteptol)(SUNAdaptController C, sunrealtype H, + sunrealtype tolfac, int P, sunrealtype DSM, + sunrealtype dsm, sunrealtype* Hnew, + sunrealtype* tolfacnew); + /* OPTIONAL for all SUNAdaptController implementations. */ SUNErrCode (*destroy)(SUNAdaptController C); SUNErrCode (*reset)(SUNAdaptController C); @@ -70,6 +77,9 @@ struct _generic_SUNAdaptController_Ops SUNErrCode (*write)(SUNAdaptController C, FILE* fptr); SUNErrCode (*seterrorbias)(SUNAdaptController C, sunrealtype bias); SUNErrCode (*updateh)(SUNAdaptController C, sunrealtype h, sunrealtype dsm); + SUNErrCode (*updatemrihtol)(SUNAdaptController C, sunrealtype H, + sunrealtype tolfac, sunrealtype DSM, + sunrealtype dsm); SUNErrCode (*space)(SUNAdaptController C, long int* lenrw, long int* leniw); }; @@ -118,6 +128,20 @@ SUNErrCode SUNAdaptController_EstimateStep(SUNAdaptController C, sunrealtype h, int p, sunrealtype dsm, sunrealtype* hnew); +/* Combined slow step/fast tolerance multirate controller function. + This is called following a slow multirate time step with size 'H' + and fast/slow relative tolerance ratio 'tolfac', and error factors + 'DSM' and 'dsm' (slow and fast, resp.). The controller should + estimate slow stepsize 'Hnew' and updated relative tolerance ratio + 'tolfacnew', so that the ensuing step will have 'DSM' and 'dsm' + values JUST BELOW 1 with minimal computational effort. */ +SUNDIALS_EXPORT +SUNErrCode SUNAdaptController_EstimateStepTol(SUNAdaptController C, + sunrealtype H, sunrealtype tolfac, + int P, sunrealtype DSM, + sunrealtype dsm, sunrealtype* Hnew, + sunrealtype* tolfacnew); + /* Function to reset the controller to its initial state, e.g., if it stores a small number of previous dsm or step size values. */ SUNDIALS_EXPORT @@ -145,6 +169,15 @@ SUNDIALS_EXPORT SUNErrCode SUNAdaptController_UpdateH(SUNAdaptController C, sunrealtype h, sunrealtype dsm); +/* Function to notify the controller of a successful multirate time step + with size H and fast tolerance factor tolfac, and local error factors + DSM and dsm, indicating that the step size, tolerance factor, or local + error factors can be saved for subsequent controller functions. */ +SUNDIALS_EXPORT +SUNErrCode SUNAdaptController_UpdateMRIHTol(SUNAdaptController C, sunrealtype H, + sunrealtype tolfac, sunrealtype DSM, + sunrealtype dsm); + /* Function to return the memory requirements of the controller object. */ SUNDIALS_EXPORT SUNErrCode SUNAdaptController_Space(SUNAdaptController C, long int* lenrw, diff --git a/scripts/shared b/scripts/shared index fb6a1e0079..c6e5ae255c 100755 --- a/scripts/shared +++ b/scripts/shared @@ -101,6 +101,7 @@ $tar $tarfile $distrobase/test/unit_tests/CMakeLists.txt $tar $tarfile $distrobase/test/unit_tests/profiling $tar $tarfile $distrobase/test/unit_tests/sunmemory $tar $tarfile $distrobase/test/unit_tests/sundials +$tar $tarfile $distrobase/test/unit_tests/utilities echo " --- Add external files to $tarfile" $tar $tarfile $distrobase/external diff --git a/src/arkode/CMakeLists.txt b/src/arkode/CMakeLists.txt index f5019337f9..edcc90e1a2 100644 --- a/src/arkode/CMakeLists.txt +++ b/src/arkode/CMakeLists.txt @@ -35,6 +35,7 @@ set(arkode_SOURCES arkode_lsrkstep_io.c arkode_lsrkstep.c arkode_mri_tables.c + arkode_mristep_controller.c arkode_mristep_io.c arkode_mristep_nls.c arkode_mristep.c @@ -76,8 +77,9 @@ sundials_add_library( OBJECT_LIBRARIES sundials_sunmemsys_obj sundials_nvecserial_obj - sundials_sunadaptcontrollerimexgus_obj sundials_sunadaptcontrollersoderlind_obj + sundials_sunadaptcontrollerimexgus_obj + sundials_sunadaptcontrollermrihtol_obj sundials_sunmatrixband_obj sundials_sunmatrixdense_obj sundials_sunmatrixsparse_obj diff --git a/src/arkode/arkode.c b/src/arkode/arkode.c index 2234cc653b..c64713a320 100644 --- a/src/arkode/arkode.c +++ b/src/arkode/arkode.c @@ -135,7 +135,7 @@ int ARKodeResize(void* arkode_mem, N_Vector y0, sunrealtype hscale, } } - /* Determining change in vector sizes */ + /* Determine change in vector sizes */ lrw1 = liw1 = 0; if (y0->ops->nvspace != NULL) { N_VSpace(y0, &lrw1, &liw1); } lrw_diff = lrw1 - ark_mem->lrw1; @@ -816,7 +816,7 @@ int ARKodeEvolve(void* arkode_mem, sunrealtype tout, N_Vector yout, /* Check for too much accuracy requested */ nrm = N_VWrmsNorm(ark_mem->yn, ark_mem->ewt); ark_mem->tolsf = ark_mem->uround * nrm; - if (ark_mem->tolsf > ONE) + if (ark_mem->tolsf > ONE && !ark_mem->fixedstep) { arkProcessError(ark_mem, ARK_TOO_MUCH_ACC, __LINE__, __func__, __FILE__, MSG_ARK_TOO_MUCH_ACC, ark_mem->tcur); @@ -1339,7 +1339,7 @@ void ARKodePrintMem(void* arkode_mem, FILE* outfile) fprintf(outfile, "yn:\n"); N_VPrintFile(ark_mem->yn, outfile); fprintf(outfile, "fn:\n"); - N_VPrintFile(ark_mem->fn, outfile); + if (ark_mem->fn) { N_VPrintFile(ark_mem->fn, outfile); } fprintf(outfile, "tempv1:\n"); N_VPrintFile(ark_mem->tempv1, outfile); fprintf(outfile, "tempv2:\n"); @@ -1358,6 +1358,66 @@ void ARKodePrintMem(void* arkode_mem, FILE* outfile) if (ark_mem->step_printmem) { ark_mem->step_printmem(ark_mem, outfile); } } +/*------------------------------------------------------------------------------ + ARKodeCreateMRIStepInnerStepper + + Wraps an ARKODE integrator as an MRIStep inner stepper. + ----------------------------------------------------------------------------*/ + +int ARKodeCreateMRIStepInnerStepper(void* inner_arkode_mem, + MRIStepInnerStepper* stepper) +{ + ARKodeMem ark_mem; + int retval; + + /* Check if ark_mem exists */ + if (inner_arkode_mem == NULL) + { + arkProcessError(NULL, ARK_MEM_NULL, __LINE__, __func__, __FILE__, + MSG_ARK_NO_MEM); + return (ARK_MEM_NULL); + } + ark_mem = (ARKodeMem)inner_arkode_mem; + + /* return with an error if the ARKODE solver does not support forcing */ + if (ark_mem->step_setforcing == NULL) + { + arkProcessError(ark_mem, ARK_STEPPER_UNSUPPORTED, __LINE__, __func__, + __FILE__, "time-stepping module does not support forcing"); + return (ARK_STEPPER_UNSUPPORTED); + } + + retval = MRIStepInnerStepper_Create(ark_mem->sunctx, stepper); + if (retval != ARK_SUCCESS) { return (retval); } + + retval = MRIStepInnerStepper_SetContent(*stepper, inner_arkode_mem); + if (retval != ARK_SUCCESS) { return (retval); } + + retval = MRIStepInnerStepper_SetEvolveFn(*stepper, ark_MRIStepInnerEvolve); + if (retval != ARK_SUCCESS) { return (retval); } + + retval = MRIStepInnerStepper_SetFullRhsFn(*stepper, ark_MRIStepInnerFullRhs); + if (retval != ARK_SUCCESS) { return (retval); } + + retval = MRIStepInnerStepper_SetResetFn(*stepper, ark_MRIStepInnerReset); + if (retval != ARK_SUCCESS) { return (retval); } + + retval = + MRIStepInnerStepper_SetAccumulatedErrorGetFn(*stepper, + ark_MRIStepInnerGetAccumulatedError); + if (retval != ARK_SUCCESS) { return (retval); } + + retval = + MRIStepInnerStepper_SetAccumulatedErrorResetFn(*stepper, + ark_MRIStepInnerResetAccumulatedError); + if (retval != ARK_SUCCESS) { return (retval); } + + retval = MRIStepInnerStepper_SetRTolFn(*stepper, ark_MRIStepInnerSetRTol); + if (retval != ARK_SUCCESS) { return (retval); } + + return (ARK_SUCCESS); +} + /*=============================================================== Private internal functions ===============================================================*/ @@ -1441,6 +1501,7 @@ ARKodeMem arkCreate(SUNContext sunctx) ark_mem->step_setstagepredictfn = NULL; ark_mem->step_getnumrhsevals = NULL; ark_mem->step_getnumlinsolvsetups = NULL; + ark_mem->step_setadaptcontroller = NULL; ark_mem->step_getestlocalerrors = NULL; ark_mem->step_getcurrentgamma = NULL; ark_mem->step_getnonlinearsystemdata = NULL; @@ -1519,6 +1580,10 @@ ARKodeMem arkCreate(SUNContext sunctx) ark_mem->h = ZERO; ark_mem->h0u = ZERO; + /* Accumulated error estimation strategy */ + ark_mem->AccumErrorType = ARK_ACCUMERROR_NONE; + ark_mem->AccumError = ZERO; + /* Set default values for integrator and stepper optional inputs */ iret = ARKodeSetDefaults(ark_mem); if (iret != ARK_SUCCESS) @@ -1717,6 +1782,9 @@ int arkInit(ARKodeMem ark_mem, sunrealtype t0, N_Vector y0, int init_type) ark_mem->hadapt_mem->nst_acc = 0; ark_mem->hadapt_mem->nst_exp = 0; + /* Accumulated error estimate */ + ark_mem->AccumError = ZERO; + /* Indicate that calling the full RHS function is not required, this flag is updated to SUNTRUE by the interpolation module initialization function and/or the stepper initialization function in arkInitialSetup */ @@ -1791,21 +1859,6 @@ int arkInitialSetup(ARKodeMem ark_mem, sunrealtype tout) sunrealtype tout_hin, rh, htmp; sunbooleantype conOK; - /* Set up the time stepper module */ - if (ark_mem->step_init == NULL) - { - arkProcessError(ark_mem, ARK_ILL_INPUT, __LINE__, __func__, __FILE__, - "Time stepper module is missing"); - return (ARK_ILL_INPUT); - } - retval = ark_mem->step_init(ark_mem, ark_mem->init_type); - if (retval != ARK_SUCCESS) - { - arkProcessError(ark_mem, retval, __LINE__, __func__, __FILE__, - "Error in initialization of time stepper module"); - return (retval); - } - /* Check that user has supplied an initial step size if fixedstep mode is on */ if ((ark_mem->fixedstep) && (ark_mem->hin == ZERO)) { @@ -1871,6 +1924,21 @@ int arkInitialSetup(ARKodeMem ark_mem, sunrealtype tout) return (ARK_ILL_INPUT); } + /* Set up the time stepper module */ + if (ark_mem->step_init == NULL) + { + arkProcessError(ark_mem, ARK_ILL_INPUT, __LINE__, __func__, __FILE__, + "Time stepper module is missing"); + return (ARK_ILL_INPUT); + } + retval = ark_mem->step_init(ark_mem, tout, ark_mem->init_type); + if (retval != ARK_SUCCESS) + { + arkProcessError(ark_mem, retval, __LINE__, __func__, __FILE__, + "Error in initialization of time stepper module"); + return (retval); + } + /* Load initial residual weights */ if (ark_mem->rwt_is_ewt) { /* update pointer to ewt */ @@ -1950,7 +2018,8 @@ int arkInitialSetup(ARKodeMem ark_mem, sunrealtype tout) /* If fullrhs will be called (to estimate initial step, explicit steppers, Hermite interpolation module, and possibly (but not always) arkRootCheck1), then - ensure that it is provided, and space is allocated for fn. */ + ensure that it is provided, and space is allocated for fn. Otherwise, + we should free ark_mem->fn if it is allocated. */ if (ark_mem->call_fullrhs || (ark_mem->h0u == ZERO && ark_mem->hin == ZERO) || ark_mem->root_mem) { @@ -1968,6 +2037,10 @@ int arkInitialSetup(ARKodeMem ark_mem, sunrealtype tout) return (ARK_MEM_FAIL); } } + else + { + if (ark_mem->fn != NULL) { arkFreeVec(ark_mem, &ark_mem->fn); } + } /* initialization complete */ ark_mem->initialized = SUNTRUE; @@ -1987,9 +2060,11 @@ int arkInitialSetup(ARKodeMem ark_mem, sunrealtype tout) /* Estimate initial h if not set */ if (ark_mem->h == ZERO) { - /* Again, temporarily set h for estimating an optimal value */ + /* If necessary, temporarily set h as it is used to compute the tolerance + in a potential mass matrix solve when computing the full rhs */ ark_mem->h = SUNRabs(tout - ark_mem->tcur); if (ark_mem->h == ZERO) { ark_mem->h = ONE; } + /* Estimate the first step size */ tout_hin = tout; if (ark_mem->tstopset && @@ -2003,6 +2078,7 @@ int arkInitialSetup(ARKodeMem ark_mem, sunrealtype tout) istate = arkHandleFailure(ark_mem, hflag); return (istate); } + /* Use first step growth factor for estimated h */ ark_mem->hadapt_mem->etamax = ark_mem->hadapt_mem->etamx1; } @@ -2526,6 +2602,20 @@ int arkCompleteStep(ARKodeMem ark_mem, sunrealtype dsm) ark_mem->nst, ark_mem->h, ark_mem->tcur); #endif + /* store this step's contribution to accumulated temporal error */ + if (ark_mem->AccumErrorType != ARK_ACCUMERROR_NONE) + { + if (ark_mem->AccumErrorType == ARK_ACCUMERROR_MAX) + { + ark_mem->AccumError = SUNMAX(dsm, ark_mem->AccumError); + } + else if (ark_mem->AccumErrorType == ARK_ACCUMERROR_SUM) + { + ark_mem->AccumError += dsm; + } + else /* ARK_ACCUMERROR_AVG */ { ark_mem->AccumError += (dsm * ark_mem->h); } + } + /* apply user-supplied step postprocessing function (if supplied) */ if (ark_mem->ProcessStep != NULL) { @@ -3014,6 +3104,7 @@ int arkCheckConvergence(ARKodeMem ark_mem, int* nflagPtr, int* ncfPtr) { ARKodeHAdaptMem hadapt_mem; + /* If nonlinear solver succeeded, return with ARK_SUCCESS */ if (*nflagPtr == ARK_SUCCESS) { return (ARK_SUCCESS); } /* Returns with an ARK_RETRY_STEP flag occur at a stage well before any algebraic solvers are involved. On the other hand, @@ -3604,6 +3695,188 @@ void arkProcessError(ARKodeMem ark_mem, int error_code, int line, return; } +/*--------------------------------------------------------------- + Utility routines for ARKODE to serve as an MRIStepInnerStepper + ---------------------------------------------------------------*/ + +/*------------------------------------------------------------------------------ + ark_MRIStepInnerEvolve + + Implementation of MRIStepInnerStepperEvolveFn to advance the inner (fast) + ODE IVP. Since the raw return value from an MRIStepInnerStepper is + meaningless, aside from whether it is 0 (success), >0 (recoverable failure), + and <0 (unrecoverable failure), we map various ARKODE return values + accordingly. + ----------------------------------------------------------------------------*/ + +int ark_MRIStepInnerEvolve(MRIStepInnerStepper stepper, + SUNDIALS_MAYBE_UNUSED sunrealtype t0, + sunrealtype tout, N_Vector y) +{ + void* arkode_mem; /* arkode memory */ + ARKodeMem ark_mem; + sunrealtype tret; /* return time */ + sunrealtype tshift, tscale; /* time normalization values */ + N_Vector* forcing; /* forcing vectors */ + int nforcing; /* number of forcing vectors */ + int retval; /* return value */ + + /* extract the ARKODE memory struct */ + retval = MRIStepInnerStepper_GetContent(stepper, &arkode_mem); + if (retval != ARK_SUCCESS) { return -1; } + if (arkode_mem == NULL) + { + arkProcessError(NULL, ARK_MEM_NULL, __LINE__, __func__, __FILE__, + MSG_ARK_NO_MEM); + return -1; + } + ark_mem = (ARKodeMem)arkode_mem; + + /* get the forcing data */ + retval = MRIStepInnerStepper_GetForcingData(stepper, &tshift, &tscale, + &forcing, &nforcing); + if (retval != ARK_SUCCESS) { return -1; } + + /* set the inner forcing data */ + retval = ark_mem->step_setforcing(ark_mem, tshift, tscale, forcing, nforcing); + if (retval != ARK_SUCCESS) { return -1; } + + /* set the stop time */ + retval = ARKodeSetStopTime(arkode_mem, tout); + if (retval != ARK_SUCCESS) { return -1; } + + /* evolve inner ODE, consider all positive return values as 'success' */ + retval = ARKodeEvolve(arkode_mem, tout, y, &tret, ARK_NORMAL); + if (retval > 0) { retval = 0; } + + /* set a recoverable failure for a few ARKODE failure modes; + on other ARKODE errors return with an unrecoverable failure */ + if (retval < 0) + { + if ((retval == ARK_TOO_MUCH_WORK) || (retval == ARK_CONV_FAILURE) || + (retval == ARK_ERR_FAILURE)) + { + retval = 1; + } + else { return -1; } + } + + /* disable inner forcing */ + if (ark_mem->step_setforcing(ark_mem, ZERO, ONE, NULL, 0) != ARK_SUCCESS) + { + return -1; + } + + return retval; +} + +/*------------------------------------------------------------------------------ + ark_MRIStepInnerFullRhs + + Implementation of MRIStepInnerStepperFullRhsFn to compute the full inner + (fast) ODE IVP RHS. + ----------------------------------------------------------------------------*/ + +int ark_MRIStepInnerFullRhs(MRIStepInnerStepper stepper, sunrealtype t, + N_Vector y, N_Vector f, int mode) +{ + void* arkode_mem; /* arkode memory */ + ARKodeMem ark_mem; + int retval = MRIStepInnerStepper_GetContent(stepper, &arkode_mem); + if (retval != ARK_SUCCESS) { return -1; } + if (arkode_mem == NULL) + { + arkProcessError(NULL, ARK_MEM_NULL, __LINE__, __func__, __FILE__, + MSG_ARK_NO_MEM); + return -1; + } + ark_mem = (ARKodeMem)arkode_mem; + retval = ark_mem->step_fullrhs(arkode_mem, t, y, f, mode); + if (retval == ARK_SUCCESS) { return 0; } + return -1; +} + +/*------------------------------------------------------------------------------ + ark_MRIStepInnerReset + + Implementation of MRIStepInnerStepperResetFn to reset the inner (fast) stepper + state. + ----------------------------------------------------------------------------*/ + +int ark_MRIStepInnerReset(MRIStepInnerStepper stepper, sunrealtype tR, N_Vector yR) +{ + void* arkode_mem; + int retval = MRIStepInnerStepper_GetContent(stepper, &arkode_mem); + if (retval != ARK_SUCCESS) { return -1; } + retval = ARKodeReset(arkode_mem, tR, yR); + if (retval == ARK_SUCCESS) { return 0; } + return -1; +} + +/*------------------------------------------------------------------------------ + ark_MRIStepInnerGetAccumulatedError + + Implementation of MRIStepInnerGetAccumulatedError to retrieve the accumulated + temporal error estimate from the inner (fast) stepper. + ----------------------------------------------------------------------------*/ + +int ark_MRIStepInnerGetAccumulatedError(MRIStepInnerStepper stepper, + sunrealtype* accum_error) +{ + void* arkode_mem; + int retval = MRIStepInnerStepper_GetContent(stepper, &arkode_mem); + if (retval != ARK_SUCCESS) { return -1; } + retval = ARKodeGetAccumulatedError(arkode_mem, accum_error); + if (retval == ARK_SUCCESS) { return 0; } + if (retval > 0) { return 1; } + return -1; +} + +/*------------------------------------------------------------------------------ + ark_MRIStepInnerResetAccumulatedError + + Implementation of MRIStepInnerResetAccumulatedError to reset the accumulated + temporal error estimator in the inner (fast) stepper. + ----------------------------------------------------------------------------*/ + +int ark_MRIStepInnerResetAccumulatedError(MRIStepInnerStepper stepper) +{ + void* arkode_mem; + int retval = MRIStepInnerStepper_GetContent(stepper, &arkode_mem); + if (retval != ARK_SUCCESS) { return -1; } + retval = ARKodeResetAccumulatedError(arkode_mem); + if (retval == ARK_SUCCESS) { return 0; } + return -1; +} + +/*------------------------------------------------------------------------------ + ark_MRIStepInnerSetRTol + + Implementation of MRIStepInnerSetRTol to set a relative tolerance for the + upcoming evolution using the inner (fast) stepper. + ----------------------------------------------------------------------------*/ + +int ark_MRIStepInnerSetRTol(MRIStepInnerStepper stepper, sunrealtype rtol) +{ + void* arkode_mem; + ARKodeMem ark_mem; + int retval = MRIStepInnerStepper_GetContent(stepper, &arkode_mem); + if (retval != ARK_SUCCESS) { return -1; } + if (arkode_mem == NULL) + { + arkProcessError(NULL, ARK_MEM_NULL, __LINE__, __func__, __FILE__, + MSG_ARK_NO_MEM); + return -1; + } + ark_mem = (ARKodeMem)arkode_mem; + if (rtol > ZERO) + { + ark_mem->reltol = rtol; + return 0; + } + else { return -1; } +} + /*=============================================================== EOF ===============================================================*/ diff --git a/src/arkode/arkode_arkstep.c b/src/arkode/arkode_arkstep.c index 93ac87e227..eb7ccedc68 100644 --- a/src/arkode/arkode_arkstep.c +++ b/src/arkode/arkode_arkstep.c @@ -345,47 +345,6 @@ int ARKStepReInit(void* arkode_mem, ARKRhsFn fe, ARKRhsFn fi, sunrealtype t0, return (ARK_SUCCESS); } -/*------------------------------------------------------------------------------ - ARKStepCreateMRIStepInnerStepper - - Wraps an ARKStep memory structure as an MRIStep inner stepper. - ----------------------------------------------------------------------------*/ -int ARKStepCreateMRIStepInnerStepper(void* inner_arkode_mem, - MRIStepInnerStepper* stepper) -{ - int retval; - ARKodeMem ark_mem; - ARKodeARKStepMem step_mem; - - retval = arkStep_AccessARKODEStepMem(inner_arkode_mem, - "ARKStepCreateMRIStepInnerStepper", - &ark_mem, &step_mem); - if (retval) - { - arkProcessError(NULL, ARK_ILL_INPUT, __LINE__, __func__, __FILE__, - "The ARKStep memory pointer is NULL"); - return ARK_ILL_INPUT; - } - - retval = MRIStepInnerStepper_Create(ark_mem->sunctx, stepper); - if (retval != ARK_SUCCESS) { return (retval); } - - retval = MRIStepInnerStepper_SetContent(*stepper, inner_arkode_mem); - if (retval != ARK_SUCCESS) { return (retval); } - - retval = MRIStepInnerStepper_SetEvolveFn(*stepper, arkStep_MRIStepInnerEvolve); - if (retval != ARK_SUCCESS) { return (retval); } - - retval = MRIStepInnerStepper_SetFullRhsFn(*stepper, - arkStep_MRIStepInnerFullRhs); - if (retval != ARK_SUCCESS) { return (retval); } - - retval = MRIStepInnerStepper_SetResetFn(*stepper, arkStep_MRIStepInnerReset); - if (retval != ARK_SUCCESS) { return (retval); } - - return (ARK_SUCCESS); -} - /*=============================================================== Interface routines supplied to ARKODE ===============================================================*/ @@ -982,7 +941,8 @@ int arkStep_GetGammas(ARKodeMem ark_mem, sunrealtype* gamma, sunrealtype* gamrat With initialization type RESET_INIT, this routine does nothing. ---------------------------------------------------------------*/ -int arkStep_Init(ARKodeMem ark_mem, int init_type) +int arkStep_Init(ARKodeMem ark_mem, SUNDIALS_MAYBE_UNUSED sunrealtype tout, + int init_type) { ARKodeARKStepMem step_mem; int j, retval; @@ -999,12 +959,17 @@ int arkStep_Init(ARKodeMem ark_mem, int init_type) if (init_type == FIRST_INIT) { /* enforce use of arkEwtSmallReal if using a fixed step size for - an explicit method, an internal error weight function, and not - using an iterative mass matrix solver with rwt=ewt */ + an explicit method, an internal error weight function, not + using an iterative mass matrix solver with rwt=ewt, and not + performing accumulated temporal error estimation */ reset_efun = SUNTRUE; if (step_mem->implicit) { reset_efun = SUNFALSE; } if (!ark_mem->fixedstep) { reset_efun = SUNFALSE; } if (ark_mem->user_efun) { reset_efun = SUNFALSE; } + if (ark_mem->AccumErrorType != ARK_ACCUMERROR_NONE) + { + reset_efun = SUNFALSE; + } if (ark_mem->rwt_is_ewt && (step_mem->msolve_type == SUNLINEARSOLVER_ITERATIVE)) { @@ -1052,11 +1017,13 @@ int arkStep_Init(ARKodeMem ark_mem, int init_type) step_mem->p = ark_mem->hadapt_mem->p = step_mem->Be->p; } - /* Ensure that if adaptivity is enabled, then method includes embedding coefficients */ - if (!ark_mem->fixedstep && (step_mem->p == 0)) + /* Ensure that if adaptivity or error accumulation is enabled, then + method includes embedding coefficients */ + if ((!ark_mem->fixedstep || (ark_mem->AccumErrorType != ARK_ACCUMERROR_NONE)) && + (step_mem->p <= 0)) { arkProcessError(ark_mem, ARK_ILL_INPUT, __LINE__, __func__, - __FILE__, "Adaptive timestepping cannot be performed without embedding coefficients"); + __FILE__, "Temporal error estimation cannot be performed without embedding coefficients"); return (ARK_ILL_INPUT); } @@ -1269,28 +1236,62 @@ int arkStep_Init(ARKodeMem ark_mem, int init_type) This will be called in one of three 'modes': - ARK_FULLRHS_START -> called at the beginning of a simulation i.e., at - (tn, yn) = (t0, y0) or (tR, yR) - - ARK_FULLRHS_END -> called at the end of a successful step i.e, at - (tcur, ycur) or the start of the subsequent step i.e., - at (tn, yn) = (tcur, ycur) from the end of the last - step - - ARK_FULLRHS_OTHER -> called elsewhere (e.g. for dense output) - - If this function is called in ARK_FULLRHS_START or ARK_FULLRHS_END mode and - evaluating the RHS functions is necessary, we store the vectors fe(t,y) and - fi(t,y) in Fe[0] and Fi[0] for possible reuse in the first stage of the - subsequent time step. - - In ARK_FULLRHS_END mode we check if the method is stiffly accurate and, if - appropriate, copy the vectors Fe[stages - 1] and Fi[stages - 1] to Fe[0] and - Fi[0] for possible reuse in the first stage of the subsequent time step. - - ARK_FULLRHS_OTHER mode is only called for dense output in-between steps, or - when estimating the initial time step size, so we strive to store the - intermediate parts so that they do not interfere with the other two modes. + ARK_FULLRHS_START -> called in the following circumstances: + (a) at the beginning of a simulation i.e., at + (tn, yn) = (t0, y0) or (tR, yR), + (b) when transitioning between time steps t_{n-1} + \to t_{n} to fill f_{n-1} within the Hermite + interpolation module, or + (c) potentially by ARKStep at the start of the first + internal step. + + In each case, we may check the fn_is_current flag to + know whether the values stored in Fe[0] and Fi[0] are + up-to-date, allowing us to copy those values instead of + recomputing. If these values are not current, then the RHS + should be stored in Fe[0] and Fi[0] for reuse later, + before copying the values into the output vector. + + ARK_FULLRHS_END -> called in the following circumstances: + (a) when temporal root-finding is enabled, this will be + called in-between steps t_{n-1} \to t_{n} to fill f_{n}, + (b) when high-order dense output is requested from the + Hermite interpolation module in-between steps t_{n-1} + \to t_{n} to fill f_{n}, + (c) when an implicit predictor is requested from the Hermite + interpolation module within the time step t_{n} \to + t_{n+1}, in which case f_{n} needs to be filled, or + (d) potentially by ARKStep when starting a time step t_{n} + \to t_{n+1}. + + Again, we may check the fn_is_current flag to know whether + ARKODE believes that the values stored in Fe[0] and Fi[0] + are up-to-date, and may just be copied. If those values + are not current, then the only instance where recomputation + is not needed is (d), since the values in Fe[stages - 1] + and Fi[stages - 1] may be copied into Fe[0] and Fi[0], + respectively. In all other cases, the RHS should be + recomputed and stored in Fe[0] and Fi[0] for reuse + later, before copying the values into the output vector. + + ARK_FULLRHS_OTHER -> called in the following circumstances: + (a) when estimating the initial time step size, + (b) for high-order dense output with the Hermite + interpolation module, + (c) by an "outer" stepper when ARKStep is used as an + inner solver), or + (d) when a high-order implicit predictor is requested from + the Hermite interpolation module within the time step + t_{n} \to t_{n+1}. + + While instances (a)-(c) will occur in-between ARKStep time + steps, instance (d) can occur at the start of each internal + ARKStep stage. Since the (t,y) input does not correspond + to an "official" time step, thus the RHS functions should + always be evaluated, and the values should *not* be stored + anywhere that will interfere with other reused ARKStep data + from one stage to the next (but it may use nonlinear solver + scratch space). ----------------------------------------------------------------------------*/ int arkStep_FullRHS(ARKodeMem ark_mem, sunrealtype t, N_Vector y, N_Vector f, int mode) @@ -2961,8 +2962,8 @@ int arkStep_ComputeSolutions(ARKodeMem ark_mem, sunrealtype* dsmPtr) if (retval != 0) { return (ARK_VECTOROP_ERR); } } - /* Compute yerr (if step adaptivity enabled) */ - if (!ark_mem->fixedstep) + /* Compute yerr (if temporal error estimation is enabled). */ + if (!ark_mem->fixedstep || (ark_mem->AccumErrorType != ARK_ACCUMERROR_NONE)) { /* set arrays for fused vector operation */ nvec = 0; @@ -3166,92 +3167,6 @@ int arkStep_ComputeSolutions_MassFixed(ARKodeMem ark_mem, sunrealtype* dsmPtr) Internal utility routines for interacting with MRIStep ===============================================================*/ -/*------------------------------------------------------------------------------ - arkStep_MRIStepInnerEvolve - - Implementation of MRIStepInnerStepperEvolveFn to advance the inner (fast) - ODE IVP. - ----------------------------------------------------------------------------*/ - -int arkStep_MRIStepInnerEvolve(MRIStepInnerStepper stepper, - SUNDIALS_MAYBE_UNUSED sunrealtype t0, - sunrealtype tout, N_Vector y) -{ - void* arkode_mem; /* arkode memory */ - sunrealtype tret; /* return time */ - sunrealtype tshift, tscale; /* time normalization values */ - N_Vector* forcing; /* forcing vectors */ - int nforcing; /* number of forcing vectors */ - int retval; /* return value */ - - /* extract the ARKODE memory struct */ - retval = MRIStepInnerStepper_GetContent(stepper, &arkode_mem); - if (retval != ARK_SUCCESS) { return (retval); } - - /* get the forcing data */ - retval = MRIStepInnerStepper_GetForcingData(stepper, &tshift, &tscale, - &forcing, &nforcing); - if (retval != ARK_SUCCESS) { return (retval); } - - /* set the inner forcing data */ - retval = arkStep_SetInnerForcing(arkode_mem, tshift, tscale, forcing, nforcing); - if (retval != ARK_SUCCESS) { return (retval); } - - /* set the stop time */ - retval = ARKodeSetStopTime(arkode_mem, tout); - if (retval != ARK_SUCCESS) { return (retval); } - - /* evolve inner ODE */ - retval = ARKodeEvolve(arkode_mem, tout, y, &tret, ARK_NORMAL); - if (retval < 0) { return (retval); } - - /* disable inner forcing */ - retval = arkStep_SetInnerForcing(arkode_mem, ZERO, ONE, NULL, 0); - if (retval != ARK_SUCCESS) { return (retval); } - - return (ARK_SUCCESS); -} - -/*------------------------------------------------------------------------------ - arkStep_MRIStepInnerFullRhs - - Implementation of MRIStepInnerStepperFullRhsFn to compute the full inner - (fast) ODE IVP RHS. - ----------------------------------------------------------------------------*/ - -int arkStep_MRIStepInnerFullRhs(MRIStepInnerStepper stepper, sunrealtype t, - N_Vector y, N_Vector f, int mode) -{ - void* arkode_mem; - int retval; - - /* extract the ARKODE memory struct */ - retval = MRIStepInnerStepper_GetContent(stepper, &arkode_mem); - if (retval != ARK_SUCCESS) { return (retval); } - - return (arkStep_FullRHS(arkode_mem, t, y, f, mode)); -} - -/*------------------------------------------------------------------------------ - arkStep_MRIStepInnerReset - - Implementation of MRIStepInnerStepperResetFn to reset the inner (fast) stepper - state. - ----------------------------------------------------------------------------*/ - -int arkStep_MRIStepInnerReset(MRIStepInnerStepper stepper, sunrealtype tR, - N_Vector yR) -{ - void* arkode_mem; - int retval; - - /* extract the ARKODE memory struct */ - retval = MRIStepInnerStepper_GetContent(stepper, &arkode_mem); - if (retval != ARK_SUCCESS) { return (retval); } - - return (ARKodeReset(arkode_mem, tR, yR)); -} - /*------------------------------------------------------------------------------ arkStep_ApplyForcing @@ -3332,15 +3247,11 @@ int arkStep_SetInnerForcing(ARKodeMem ark_mem, sunrealtype tshift, sunrealtype tscale, N_Vector* forcing, int nvecs) { ARKodeARKStepMem step_mem; + int retval; /* access ARKodeARKStepMem structure */ - if (ark_mem->step_mem == NULL) - { - arkProcessError(ark_mem, ARK_MEM_NULL, __LINE__, __func__, __FILE__, - MSG_ARKSTEP_NO_MEM); - return ARK_MEM_NULL; - } - step_mem = (ARKodeARKStepMem)ark_mem->step_mem; + retval = arkStep_AccessStepMem(ark_mem, __func__, &step_mem); + if (retval != ARK_SUCCESS) { return (retval); } if (nvecs > 0) { diff --git a/src/arkode/arkode_arkstep_impl.h b/src/arkode/arkode_arkstep_impl.h index 21e0231a89..ce4d1b4e63 100644 --- a/src/arkode/arkode_arkstep_impl.h +++ b/src/arkode/arkode_arkstep_impl.h @@ -181,7 +181,7 @@ int arkStep_AttachMasssol(ARKodeMem ark_mem, ARKMassInitFn minit, SUNLinearSolver_Type msolve_type, void* mass_mem); void arkStep_DisableLSetup(ARKodeMem ark_mem); void arkStep_DisableMSetup(ARKodeMem ark_mem); -int arkStep_Init(ARKodeMem ark_mem, int init_type); +int arkStep_Init(ARKodeMem ark_mem, sunrealtype tout, int init_type); void* arkStep_GetLmem(ARKodeMem ark_mem); void* arkStep_GetMassMem(ARKodeMem ark_mem); ARKRhsFn arkStep_GetImplicitRHS(ARKodeMem ark_mem); @@ -228,6 +228,8 @@ int arkStep_Resize(ARKodeMem ark_mem, N_Vector y0, sunrealtype hscale, int arkStep_ComputeState(ARKodeMem ark_mem, N_Vector zcor, N_Vector z); void arkStep_Free(ARKodeMem ark_mem); void arkStep_PrintMem(ARKodeMem ark_mem, FILE* outfile); +int arkStep_SetInnerForcing(ARKodeMem ark_mem, sunrealtype tshift, + sunrealtype tscale, N_Vector* f, int nvecs); /* Internal utility routines */ int arkStep_AccessARKODEStepMem(void* arkode_mem, const char* fname, diff --git a/src/arkode/arkode_arkstep_io.c b/src/arkode/arkode_arkstep_io.c index 8a0ee66761..665f2e4e45 100644 --- a/src/arkode/arkode_arkstep_io.c +++ b/src/arkode/arkode_arkstep_io.c @@ -757,7 +757,7 @@ int arkStep_SetDefaults(ARKodeMem ark_mem) if (ark_mem->hadapt_mem->hcontroller == NULL) { arkProcessError(ark_mem, ARK_MEM_FAIL, __LINE__, __func__, __FILE__, - "SUNAdaptControllerPID allocation failure"); + "SUNAdaptController_PID allocation failure"); return (ARK_MEM_FAIL); } ark_mem->hadapt_mem->owncontroller = SUNTRUE; @@ -1183,7 +1183,11 @@ int arkStep_GetEstLocalErrors(ARKodeMem ark_mem, N_Vector ele) if (retval != ARK_SUCCESS) { return (retval); } /* return an error if local truncation error is not computed */ - if (ark_mem->fixedstep) { return (ARK_STEPPER_UNSUPPORTED); } + if ((ark_mem->fixedstep && (ark_mem->AccumErrorType == ARK_ACCUMERROR_NONE)) || + (step_mem->p <= 0)) + { + return (ARK_STEPPER_UNSUPPORTED); + } /* otherwise, copy local truncation error vector to output */ N_VScale(ONE, ark_mem->tempv1, ele); @@ -1472,6 +1476,12 @@ int arkStep_WriteParameters(ARKodeMem ark_mem, FILE* fp) Exported-but-deprecated user-callable functions. ===============================================================*/ +int ARKStepCreateMRIStepInnerStepper(void* inner_arkode_mem, + MRIStepInnerStepper* stepper) +{ + return (ARKodeCreateMRIStepInnerStepper(inner_arkode_mem, stepper)); +} + int ARKStepResize(void* arkode_mem, N_Vector y0, sunrealtype hscale, sunrealtype t0, ARKVecResizeFn resize, void* resize_data) { diff --git a/src/arkode/arkode_erkstep.c b/src/arkode/arkode_erkstep.c index 3eaa11ca9d..a62b732afc 100644 --- a/src/arkode/arkode_erkstep.c +++ b/src/arkode/arkode_erkstep.c @@ -104,6 +104,7 @@ void* ERKStepCreate(ARKRhsFn f, sunrealtype t0, N_Vector y0, SUNContext sunctx) ark_mem->step_setorder = erkStep_SetOrder; ark_mem->step_getnumrhsevals = erkStep_GetNumRhsEvals; ark_mem->step_getestlocalerrors = erkStep_GetEstLocalErrors; + ark_mem->step_setforcing = erkStep_SetInnerForcing; ark_mem->step_supports_adaptive = SUNTRUE; ark_mem->step_supports_relaxation = SUNTRUE; ark_mem->step_mem = (void*)step_mem; @@ -132,6 +133,15 @@ void* ERKStepCreate(ARKRhsFn f, sunrealtype t0, N_Vector y0, SUNContext sunctx) /* Initialize all the counters */ step_mem->nfe = 0; + /* Initialize fused op work space */ + step_mem->cvals = NULL; + step_mem->Xvecs = NULL; + step_mem->nfusedopvecs = 0; + + /* Initialize external polynomial forcing data */ + step_mem->forcing = NULL; + step_mem->nforcing = 0; + /* Initialize main ARKODE infrastructure */ retval = arkInit(ark_mem, t0, y0, FIRST_INIT); if (retval != ARK_SUCCESS) @@ -297,13 +307,29 @@ void erkStep_Free(ARKodeMem ark_mem) { free(step_mem->cvals); step_mem->cvals = NULL; - ark_mem->lrw -= (step_mem->stages + 1); + ark_mem->lrw -= step_mem->nfusedopvecs; } if (step_mem->Xvecs != NULL) { free(step_mem->Xvecs); step_mem->Xvecs = NULL; - ark_mem->liw -= (step_mem->stages + 1); + ark_mem->liw -= step_mem->nfusedopvecs; + } + step_mem->nfusedopvecs = 0; + + /* free work arrays for MRI forcing */ + if (step_mem->stage_times) + { + free(step_mem->stage_times); + step_mem->stage_times = NULL; + ark_mem->lrw -= step_mem->stages; + } + + if (step_mem->stage_coefs) + { + free(step_mem->stage_coefs); + step_mem->stage_coefs = NULL; + ark_mem->lrw -= step_mem->stages; } /* free the time stepper module itself */ @@ -368,9 +394,11 @@ void erkStep_PrintMem(ARKodeMem ark_mem, FILE* outfile) With other initialization types, this routine does nothing. ---------------------------------------------------------------*/ -int erkStep_Init(ARKodeMem ark_mem, int init_type) +int erkStep_Init(ARKodeMem ark_mem, SUNDIALS_MAYBE_UNUSED sunrealtype tout, + int init_type) { ARKodeERKStepMem step_mem; + sunbooleantype reset_efun; int retval, j; /* access ARKodeERKStepMem structure */ @@ -383,9 +411,14 @@ int erkStep_Init(ARKodeMem ark_mem, int init_type) return (ARK_SUCCESS); } - /* enforce use of arkEwtSmallReal if using a fixed step size - and an internal error weight function */ - if (ark_mem->fixedstep && !ark_mem->user_efun) + /* enforce use of arkEwtSmallReal if using a fixed step size, + an internal error weight function, and not performing accumulated + temporal error estimation */ + reset_efun = SUNTRUE; + if (!ark_mem->fixedstep) { reset_efun = SUNFALSE; } + if (ark_mem->user_efun) { reset_efun = SUNFALSE; } + if (ark_mem->AccumErrorType != ARK_ACCUMERROR_NONE) { reset_efun = SUNFALSE; } + if (reset_efun) { ark_mem->user_efun = SUNFALSE; ark_mem->efun = arkEwtSetSmallReal; @@ -414,11 +447,13 @@ int erkStep_Init(ARKodeMem ark_mem, int init_type) step_mem->q = ark_mem->hadapt_mem->q = step_mem->B->q; step_mem->p = ark_mem->hadapt_mem->p = step_mem->B->p; - /* Ensure that if adaptivity is enabled, then method includes embedding coefficients */ - if (!ark_mem->fixedstep && (step_mem->p == 0)) + /* Ensure that if adaptivity or error accumulation is enabled, then + method includes embedding coefficients */ + if ((!ark_mem->fixedstep || (ark_mem->AccumErrorType != ARK_ACCUMERROR_NONE)) && + (step_mem->p == 0)) { arkProcessError(ark_mem, ARK_ILL_INPUT, __LINE__, __func__, - __FILE__, "Adaptive timestepping cannot be performed without embedding coefficients"); + __FILE__, "Temporal error estimation cannot be performed without embedding coefficients"); return (ARK_ILL_INPUT); } @@ -438,18 +473,40 @@ int erkStep_Init(ARKodeMem ark_mem, int init_type) ark_mem->liw += step_mem->stages; /* pointers */ /* Allocate reusable arrays for fused vector interface */ + step_mem->nfusedopvecs = 2 * step_mem->stages + 2 + step_mem->nforcing; if (step_mem->cvals == NULL) { - step_mem->cvals = (sunrealtype*)calloc(step_mem->stages + 1, + step_mem->cvals = (sunrealtype*)calloc(step_mem->nfusedopvecs, sizeof(sunrealtype)); if (step_mem->cvals == NULL) { return (ARK_MEM_FAIL); } - ark_mem->lrw += (step_mem->stages + 1); + ark_mem->lrw += step_mem->nfusedopvecs; } if (step_mem->Xvecs == NULL) { - step_mem->Xvecs = (N_Vector*)calloc(step_mem->stages + 1, sizeof(N_Vector)); + step_mem->Xvecs = (N_Vector*)calloc(step_mem->nfusedopvecs, sizeof(N_Vector)); if (step_mem->Xvecs == NULL) { return (ARK_MEM_FAIL); } - ark_mem->liw += (step_mem->stages + 1); /* pointers */ + ark_mem->liw += step_mem->nfusedopvecs; /* pointers */ + } + + /* Allocate workspace for MRI forcing -- need to allocate here as the + number of stages may not bet set before this point and we assume + SetInnerForcing has been called before the first step i.e., methods + start with a fast integration */ + if (step_mem->nforcing > 0) + { + if (!(step_mem->stage_times)) + { + step_mem->stage_times = (sunrealtype*)calloc(step_mem->stages, + sizeof(sunrealtype)); + ark_mem->lrw += step_mem->stages; + } + + if (!(step_mem->stage_coefs)) + { + step_mem->stage_coefs = (sunrealtype*)calloc(step_mem->stages, + sizeof(sunrealtype)); + ark_mem->lrw += step_mem->stages; + } } /* Override the interpolant degree (if needed), used in arkInitialSetup */ @@ -478,45 +535,75 @@ int erkStep_Init(ARKodeMem ark_mem, int init_type) This will be called in one of three 'modes': - ARK_FULLRHS_START -> called at the beginning of a simulation i.e., at - (tn, yn) = (t0, y0) or (tR, yR) - - ARK_FULLRHS_END -> called at the end of a successful step i.e, at - (tcur, ycur) or the start of the subsequent step i.e., - at (tn, yn) = (tcur, ycur) from the end of the last - step - - ARK_FULLRHS_OTHER -> called elsewhere (e.g. for dense output) - - If this function is called in ARK_FULLRHS_START or ARK_FULLRHS_END mode and - evaluating the RHS functions is necessary, we store the vector f(t,y) in Fe[0] - for reuse in the first stage of the subsequent time step. - - In ARK_FULLRHS_END mode we check if the method is "stiffly accurate" and, if - appropriate, copy the vector F[stages - 1] to F[0] for reuse in the first - stage of the subsequent time step. - - ARK_FULLRHS_OTHER mode is only called for dense output in-between steps, or - when estimating the initial time step size, so we strive to store the - intermediate parts so that they do not interfere with the other two modes. + ARK_FULLRHS_START -> called in the following circumstances: + (a) at the beginning of a simulation i.e., at + (tn, yn) = (t0, y0) or (tR, yR), + (b) when transitioning between time steps t_{n-1} + \to t_{n} to fill f_{n-1} within the Hermite + interpolation module, or + (c) by ERKStep at the start of the first internal step. + + In each case, we may check the fn_is_current flag to + know whether the values stored in F[0] are up-to-date, + allowing us to copy those values instead of recomputing. + If these values are not current, then the RHS should be + stored in F[0] for reuse later, before copying the values + into the output vector. + + ARK_FULLRHS_END -> called in the following circumstances: + (a) when temporal root-finding is enabled, this will be + called in-between steps t_{n-1} \to t_{n} to fill f_{n}, + (b) when high-order dense output is requested from the + Hermite interpolation module in-between steps t_{n-1} + \to t_{n} to fill f_{n}, or + (c) by ERKStep when starting a time step t_{n} \to t_{n+1} + and when using an FSAL method. + + Again, we may check the fn_is_current flag to know whether + ARKODE believes that the values stored in F[0] are + up-to-date, and may just be copied. If the values stored + in F[0] are not current, then the only instance where + recomputation is not needed is (c), since the values in + F[stages - 1] may be copied into F[0]. In all other cases, + the RHS should be recomputed and stored in F[0] for reuse + later, before copying the values into the output vector. + + ARK_FULLRHS_OTHER -> called in the following circumstances: + (a) when estimating the initial time step size, + (b) for high-order dense output with the Hermite + interpolation module, or + (c) by an "outer" stepper when ERKStep is used as an + inner solver). + + All of these instances will occur in-between ERKStep time + steps, but the (t,y) input does not correspond to an + "official" time step, thus the RHS should always be + evaluated, with the values *not* stored in F[0]. ----------------------------------------------------------------------------*/ int erkStep_FullRHS(ARKodeMem ark_mem, sunrealtype t, N_Vector y, N_Vector f, int mode) { - int retval; + int nvec, retval; ARKodeERKStepMem step_mem; sunbooleantype recomputeRHS; + sunrealtype* cvals; + N_Vector* Xvecs; + sunrealtype stage_coefs = ONE; /* access ARKodeERKStepMem structure */ retval = erkStep_AccessStepMem(ark_mem, __func__, &step_mem); if (retval != ARK_SUCCESS) { return (retval); } + /* local shortcuts for use with fused vector operations */ + cvals = step_mem->cvals; + Xvecs = step_mem->Xvecs; + /* perform RHS functions contingent on 'mode' argument */ switch (mode) { case ARK_FULLRHS_START: - /* compute the RHS */ + /* compute the RHS if needed */ if (!(ark_mem->fn_is_current)) { retval = step_mem->f(t, y, step_mem->F[0], ark_mem->user_data); @@ -529,9 +616,19 @@ int erkStep_FullRHS(ARKodeMem ark_mem, sunrealtype t, N_Vector y, N_Vector f, } } - /* copy RHS vector into output */ + /* copy RHS into output */ N_VScale(ONE, step_mem->F[0], f); + /* apply external polynomial forcing */ + if (step_mem->nforcing > 0) + { + cvals[0] = ONE; + Xvecs[0] = f; + nvec = 1; + erkStep_ApplyForcing(step_mem, &t, &stage_coefs, 1, &nvec); + N_VLinearCombination(nvec, cvals, Xvecs, f); + } + break; case ARK_FULLRHS_END: @@ -544,7 +641,7 @@ int erkStep_FullRHS(ARKodeMem ark_mem, sunrealtype t, N_Vector y, N_Vector f, /* First Same As Last methods are not FSAL when relaxation is enabled */ if (ark_mem->relax_enabled) { recomputeRHS = SUNTRUE; } - /* base RHS calls on recomputeRHS argument */ + /* base RHS call on recomputeRHS argument */ if (recomputeRHS) { /* call f */ @@ -558,10 +655,20 @@ int erkStep_FullRHS(ARKodeMem ark_mem, sunrealtype t, N_Vector y, N_Vector f, } } else { N_VScale(ONE, step_mem->F[step_mem->stages - 1], step_mem->F[0]); } - } - /* copy RHS vector into output */ - N_VScale(ONE, step_mem->F[0], f); + /* copy RHS vector into output */ + N_VScale(ONE, step_mem->F[0], f); + + /* apply external polynomial forcing */ + if (step_mem->nforcing > 0) + { + cvals[0] = ONE; + Xvecs[0] = f; + nvec = 1; + erkStep_ApplyForcing(step_mem, &t, &stage_coefs, 1, &nvec); + N_VLinearCombination(nvec, cvals, Xvecs, f); + } + } break; @@ -576,6 +683,15 @@ int erkStep_FullRHS(ARKodeMem ark_mem, sunrealtype t, N_Vector y, N_Vector f, MSG_ARK_RHSFUNC_FAILED, t); return (ARK_RHSFUNC_FAIL); } + /* apply external polynomial forcing */ + if (step_mem->nforcing > 0) + { + cvals[0] = ONE; + Xvecs[0] = f; + nvec = 1; + erkStep_ApplyForcing(step_mem, &t, &stage_coefs, 1, &nvec); + N_VLinearCombination(nvec, cvals, Xvecs, f); + } break; @@ -684,6 +800,18 @@ int erkStep_TakeStep(ARKodeMem ark_mem, sunrealtype* dsmPtr, int* nflagPtr) Xvecs[nvec] = ark_mem->yn; nvec += 1; + /* apply external polynomial forcing */ + if (step_mem->nforcing > 0) + { + for (js = 0; js < is; js++) + { + step_mem->stage_times[js] = ark_mem->tn + step_mem->B->c[js] * ark_mem->h; + step_mem->stage_coefs[js] = ark_mem->h * step_mem->B->A[is][js]; + } + erkStep_ApplyForcing(step_mem, step_mem->stage_times, + step_mem->stage_coefs, is, &nvec); + } + /* call fused vector operation to do the work */ retval = N_VLinearCombination(nvec, cvals, Xvecs, ark_mem->ycur); if (retval != 0) { return (ARK_VECTOROP_ERR); } @@ -1023,12 +1151,24 @@ int erkStep_ComputeSolutions(ARKodeMem ark_mem, sunrealtype* dsmPtr) Xvecs[nvec] = ark_mem->yn; nvec += 1; + /* apply external polynomial forcing */ + if (step_mem->nforcing > 0) + { + for (j = 0; j < step_mem->stages; j++) + { + step_mem->stage_times[j] = ark_mem->tn + step_mem->B->c[j] * ark_mem->h; + step_mem->stage_coefs[j] = ark_mem->h * step_mem->B->b[j]; + } + erkStep_ApplyForcing(step_mem, step_mem->stage_times, step_mem->stage_coefs, + step_mem->stages, &nvec); + } + /* call fused vector operation to do the work */ retval = N_VLinearCombination(nvec, cvals, Xvecs, y); if (retval != 0) { return (ARK_VECTOROP_ERR); } - /* Compute yerr (if step adaptivity enabled) */ - if (!ark_mem->fixedstep) + /* Compute yerr (if step adaptivity or error accumulation enabled) */ + if (!ark_mem->fixedstep || (ark_mem->AccumErrorType != ARK_ACCUMERROR_NONE)) { /* set arrays for fused vector operation */ nvec = 0; @@ -1039,6 +1179,19 @@ int erkStep_ComputeSolutions(ARKodeMem ark_mem, sunrealtype* dsmPtr) nvec += 1; } + /* apply external polynomial forcing */ + if (step_mem->nforcing > 0) + { + for (j = 0; j < step_mem->stages; j++) + { + step_mem->stage_times[j] = ark_mem->tn + step_mem->B->c[j] * ark_mem->h; + step_mem->stage_coefs[j] = ark_mem->h * + (step_mem->B->b[j] - step_mem->B->d[j]); + } + erkStep_ApplyForcing(step_mem, step_mem->stage_times, + step_mem->stage_coefs, step_mem->stages, &nvec); + } + /* call fused vector operation to do the work */ retval = N_VLinearCombination(nvec, cvals, Xvecs, yerr); if (retval != 0) { return (ARK_VECTOROP_ERR); } @@ -1145,6 +1298,145 @@ int erkStep_GetOrder(ARKodeMem ark_mem) return step_mem->q; } +/*--------------------------------------------------------------- + Utility routines for ERKStep to serve as an MRIStepInnerStepper + ---------------------------------------------------------------*/ + +/*------------------------------------------------------------------------------ + erkStep_ApplyForcing + + Determines the linear combination coefficients and vectors to apply forcing + at a given value of the independent variable (t). This occurs through + appending coefficients and N_Vector pointers to the underlying cvals and Xvecs + arrays in the step_mem structure. The dereferenced input *nvec should indicate + the next available entry in the cvals/Xvecs arrays. The input 's' is a + scaling factor that should be applied to each of these coefficients. + ----------------------------------------------------------------------------*/ + +void erkStep_ApplyForcing(ARKodeERKStepMem step_mem, sunrealtype* stage_times, + sunrealtype* stage_coefs, int jmax, int* nvec) +{ + sunrealtype tau, taui; + int j, k; + + /* Shortcuts to step_mem data */ + sunrealtype* vals = step_mem->cvals; + N_Vector* vecs = step_mem->Xvecs; + sunrealtype tshift = step_mem->tshift; + sunrealtype tscale = step_mem->tscale; + int nforcing = step_mem->nforcing; + N_Vector* forcing = step_mem->forcing; + + /* Offset into vals and vecs arrays */ + int offset = *nvec; + + /* Initialize scaling values, set vectors */ + for (k = 0; k < nforcing; k++) + { + vals[offset + k] = ZERO; + vecs[offset + k] = forcing[k]; + } + + for (j = 0; j < jmax; j++) + { + tau = (stage_times[j] - tshift) / tscale; + taui = ONE; + + for (k = 0; k < nforcing; k++) + { + vals[offset + k] += stage_coefs[j] * taui; + taui *= tau; + } + } + + /* Update vector count for linear combination */ + *nvec += nforcing; +} + +/*------------------------------------------------------------------------------ + erkStep_SetInnerForcing + + Sets an array of coefficient vectors for a time-dependent external polynomial + forcing term in the ODE RHS i.e., y' = f(t,y) + p(t). This function is + primarily intended for use with multirate integration methods (e.g., MRIStep) + where ERKStep is used to solve a modified ODE at a fast time scale. The + polynomial is of the form + + p(t) = sum_{i = 0}^{nvecs - 1} forcing[i] * ((t - tshift) / (tscale))^i + + where tshift and tscale are used to normalize the time t (e.g., with MRIGARK + methods). + ----------------------------------------------------------------------------*/ + +int erkStep_SetInnerForcing(ARKodeMem ark_mem, sunrealtype tshift, + sunrealtype tscale, N_Vector* forcing, int nvecs) +{ + ARKodeERKStepMem step_mem; + int retval; + + /* access ARKodeERKStepMem structure */ + retval = erkStep_AccessStepMem(ark_mem, __func__, &step_mem); + if (retval != ARK_SUCCESS) { return (retval); } + + if (nvecs > 0) + { + /* store forcing inputs */ + step_mem->tshift = tshift; + step_mem->tscale = tscale; + step_mem->forcing = forcing; + step_mem->nforcing = nvecs; + + /* If cvals and Xvecs are not allocated then erkStep_Init has not been + called and the number of stages has not been set yet. These arrays will + be allocated in erkStep_Init and take into account the value of nforcing. + On subsequent calls will check if enough space has allocated in case + nforcing has increased since the original allocation. */ + if (step_mem->cvals != NULL && step_mem->Xvecs != NULL) + { + /* check if there are enough reusable arrays for fused operations */ + if ((step_mem->nfusedopvecs - nvecs) < (step_mem->stages + 1)) + { + /* free current work space */ + if (step_mem->cvals != NULL) + { + free(step_mem->cvals); + ark_mem->lrw -= step_mem->nfusedopvecs; + } + if (step_mem->Xvecs != NULL) + { + free(step_mem->Xvecs); + ark_mem->liw -= step_mem->nfusedopvecs; + } + + /* allocate reusable arrays for fused vector operations */ + step_mem->nfusedopvecs = step_mem->stages + 1 + nvecs; + + step_mem->cvals = NULL; + step_mem->cvals = (sunrealtype*)calloc(step_mem->nfusedopvecs, + sizeof(sunrealtype)); + if (step_mem->cvals == NULL) { return (ARK_MEM_FAIL); } + ark_mem->lrw += step_mem->nfusedopvecs; + + step_mem->Xvecs = NULL; + step_mem->Xvecs = (N_Vector*)calloc(step_mem->nfusedopvecs, + sizeof(N_Vector)); + if (step_mem->Xvecs == NULL) { return (ARK_MEM_FAIL); } + ark_mem->liw += step_mem->nfusedopvecs; + } + } + } + else + { + /* disable forcing */ + step_mem->tshift = ZERO; + step_mem->tscale = ONE; + step_mem->forcing = NULL; + step_mem->nforcing = 0; + } + + return (ARK_SUCCESS); +} + /*=============================================================== EOF ===============================================================*/ diff --git a/src/arkode/arkode_erkstep_impl.h b/src/arkode/arkode_erkstep_impl.h index 8b99460ca7..11f5158f0b 100644 --- a/src/arkode/arkode_erkstep_impl.h +++ b/src/arkode/arkode_erkstep_impl.h @@ -60,6 +60,15 @@ typedef struct ARKodeERKStepMemRec /* Reusable arrays for fused vector operations */ sunrealtype* cvals; N_Vector* Xvecs; + int nfusedopvecs; /* length of cvals and Xvecs arrays */ + + /* Data for using ERKStep with external polynomial forcing */ + sunrealtype tshift; /* time normalization shift */ + sunrealtype tscale; /* time normalization scaling */ + N_Vector* forcing; /* array of forcing vectors */ + int nforcing; /* number of forcing vectors */ + sunrealtype* stage_times; /* workspace for applying forcing */ + sunrealtype* stage_coefs; /* workspace for applying forcing */ }* ARKodeERKStepMem; @@ -68,7 +77,7 @@ typedef struct ARKodeERKStepMemRec ===============================================================*/ /* Interface routines supplied to ARKODE */ -int erkStep_Init(ARKodeMem ark_mem, int init_type); +int erkStep_Init(ARKodeMem ark_mem, sunrealtype tout, int init_type); int erkStep_FullRHS(ARKodeMem ark_mem, sunrealtype t, N_Vector y, N_Vector f, int mode); int erkStep_TakeStep(ARKodeMem ark_mem, sunrealtype* dsmPtr, int* nflagPtr); @@ -84,6 +93,8 @@ void erkStep_PrintMem(ARKodeMem ark_mem, FILE* outfile); int erkStep_GetNumRhsEvals(ARKodeMem ark_mem, int partition_index, long int* rhs_evals); int erkStep_GetEstLocalErrors(ARKodeMem ark_mem, N_Vector ele); +int erkStep_SetInnerForcing(ARKodeMem ark_mem, sunrealtype tshift, + sunrealtype tscale, N_Vector* f, int nvecs); /* Internal utility routines */ int erkStep_AccessARKODEStepMem(void* arkode_mem, const char* fname, @@ -94,6 +105,8 @@ sunbooleantype erkStep_CheckNVector(N_Vector tmpl); int erkStep_SetButcherTable(ARKodeMem ark_mem); int erkStep_CheckButcherTable(ARKodeMem ark_mem); int erkStep_ComputeSolutions(ARKodeMem ark_mem, sunrealtype* dsm); +void erkStep_ApplyForcing(ARKodeERKStepMem step_mem, sunrealtype* stage_times, + sunrealtype* stage_coefs, int jmax, int* nvec); /* private functions for relaxation */ int erkStep_SetRelaxFn(ARKodeMem ark_mem, ARKRelaxFn rfn, ARKRelaxJacFn rjac); diff --git a/src/arkode/arkode_erkstep_io.c b/src/arkode/arkode_erkstep_io.c index 748736098e..9708b535f6 100644 --- a/src/arkode/arkode_erkstep_io.c +++ b/src/arkode/arkode_erkstep_io.c @@ -325,7 +325,7 @@ int erkStep_SetDefaults(ARKodeMem ark_mem) if (ark_mem->hadapt_mem->hcontroller == NULL) { arkProcessError(ark_mem, ARK_MEM_FAIL, __LINE__, __func__, __FILE__, - "SUNAdaptControllerPI allocation failure"); + "SUNAdaptController_PI allocation failure"); return (ARK_MEM_FAIL); } ark_mem->hadapt_mem->owncontroller = SUNTRUE; @@ -390,7 +390,11 @@ int erkStep_GetEstLocalErrors(ARKodeMem ark_mem, N_Vector ele) if (retval != ARK_SUCCESS) { return (retval); } /* return an error if local truncation error is not computed */ - if (ark_mem->fixedstep) { return (ARK_STEPPER_UNSUPPORTED); } + if ((ark_mem->fixedstep && (ark_mem->AccumErrorType == ARK_ACCUMERROR_NONE)) || + (step_mem->p <= 0)) + { + return (ARK_STEPPER_UNSUPPORTED); + } /* otherwise, copy local truncation error vector to output */ N_VScale(ONE, ark_mem->tempv1, ele); diff --git a/src/arkode/arkode_impl.h b/src/arkode/arkode_impl.h index a79f3e0d91..020fc6f6aa 100644 --- a/src/arkode/arkode_impl.h +++ b/src/arkode/arkode_impl.h @@ -23,6 +23,7 @@ #include #include #include +#include #include #include #include @@ -210,7 +211,8 @@ typedef int (*ARKMassSolveFn)(ARKodeMem ark_mem, N_Vector b, typedef int (*ARKMassFreeFn)(ARKodeMem ark_mem); /* time stepper interface functions -- general */ -typedef int (*ARKTimestepInitFn)(ARKodeMem ark_mem, int init_type); +typedef int (*ARKTimestepInitFn)(ARKodeMem ark_mem, sunrealtype tout, + int init_type); typedef int (*ARKTimestepFullRHSFn)(ARKodeMem ark_mem, sunrealtype t, N_Vector y, N_Vector f, int mode); typedef int (*ARKTimestepStepFn)(ARKodeMem ark_mem, sunrealtype* dsm, int* nflag); @@ -231,6 +233,7 @@ typedef int (*ARKTimestepGetNumRhsEvals)(ARKodeMem ark_mem, int partition_index, /* time stepper interface functions -- temporal adaptivity */ typedef int (*ARKTimestepGetEstLocalErrors)(ARKodeMem ark_mem, N_Vector ele); +typedef int (*ARKSetAdaptControllerFn)(ARKodeMem ark_mem, SUNAdaptController C); /* time stepper interface functions -- relaxation */ typedef int (*ARKTimestepSetRelaxFn)(ARKodeMem ark_mem, ARKRelaxFn rfn, @@ -419,6 +422,7 @@ struct ARKodeMemRec /* Time stepper module -- temporal adaptivity */ sunbooleantype step_supports_adaptive; + ARKSetAdaptControllerFn step_setadaptcontroller; ARKTimestepGetEstLocalErrors step_getestlocalerrors; /* Time stepper module -- relaxation */ @@ -503,7 +507,7 @@ struct ARKodeMemRec overtake tstop */ sunrealtype eta; /* eta = hprime / h */ sunrealtype tcur; /* current internal value of t - (changes with each stage) */ + (changes with each stage) */ sunrealtype tretlast; /* value of tret last returned by ARKODE */ sunbooleantype fixedstep; /* flag to disable temporal adaptivity */ ARKodeHAdaptMem hadapt_mem; /* time step adaptivity structure */ @@ -537,6 +541,9 @@ struct ARKodeMemRec sunrealtype terr; /* error in tn for compensated sums */ sunrealtype hold; /* last successful h value used */ sunrealtype tolsf; /* tolerance scale factor (suggestion to user) */ + ARKAccumError AccumErrorType; /* accumulated error estimation type */ + sunrealtype AccumErrorStart; /* time of last accumulated error reset */ + sunrealtype AccumError; /* accumulated error estimate */ sunbooleantype VabstolMallocDone; sunbooleantype VRabstolMallocDone; sunbooleantype MallocDone; @@ -649,6 +656,7 @@ int arkCheckTemporalError(ARKodeMem ark_mem, int* nflagPtr, int* nefPtr, int arkAccessHAdaptMem(void* arkode_mem, const char* fname, ARKodeMem* ark_mem, ARKodeHAdaptMem* hadapt_mem); +int arkReplaceAdaptController(ARKodeMem ark_mem, SUNAdaptController C); int arkSetAdaptivityMethod(void* arkode_mem, int imethod, int idefault, int pq, sunrealtype adapt_params[3]); int arkSetAdaptivityFn(void* arkode_mem, ARKAdaptFn hfun, void* h_data); @@ -656,6 +664,18 @@ int arkSetAdaptivityFn(void* arkode_mem, ARKAdaptFn hfun, void* h_data); ARKODE_DIRKTableID arkButcherTableDIRKNameToID(const char* imethod); ARKODE_ERKTableID arkButcherTableERKNameToID(const char* emethod); +/* utility functions for wrapping ARKODE as an MRIStep inner stepper */ +int ark_MRIStepInnerEvolve(MRIStepInnerStepper stepper, sunrealtype t0, + sunrealtype tout, N_Vector y); +int ark_MRIStepInnerFullRhs(MRIStepInnerStepper stepper, sunrealtype t, + N_Vector y, N_Vector f, int mode); +int ark_MRIStepInnerReset(MRIStepInnerStepper stepper, sunrealtype tR, + N_Vector yR); +int ark_MRIStepInnerGetAccumulatedError(MRIStepInnerStepper stepper, + sunrealtype* accum_error); +int ark_MRIStepInnerResetAccumulatedError(MRIStepInnerStepper stepper); +int ark_MRIStepInnerSetRTol(MRIStepInnerStepper stepper, sunrealtype rtol); + /* XBraid interface functions */ int arkSetForcePass(void* arkode_mem, sunbooleantype force_pass); int arkGetLastKFlag(void* arkode_mem, int* last_kflag); @@ -1004,31 +1024,95 @@ int arkGetLastKFlag(void* arkode_mem, int* last_kflag); This routine must compute the full ODE right-hand side function at the inputs (t,y), and store the result in the N_Vector f. Depending on the type of stepper, this may be just the single - ODE RHS function supplied (e.g. ERK, DIRK, IRK), or it may be + ODE RHS function supplied (e.g. ERK, DIRK), or it may be the sum of many ODE RHS functions (e.g. ARK, MRI). The 'mode' indicates where this routine is called: - ARK_FULLRHS_START -> called at the beginning of a simulation - i.e., at (tn, yn) = (t0, y0) or (tR, yR) - - ARK_FULLRHS_END -> called at the end of a successful step i.e, - at (tcur, ycur) or the start of the subsequent - step i.e., at (tn, yn) = (tcur, ycur) from - the end of the last step - - ARK_FULLRHS_OTHER -> called elsewhere (e.g. for dense output) - - It is recommended that the stepper use the mode information to - maximize reuse between calls to this function and RHS - evaluations inside the stepper itself. - - This routine is only required to be supplied to ARKODE if: - * ARKODE's initial time step selection algorithm is used, + ARK_FULLRHS_START -> called in the following circumstances: + (a) at the beginning of a simulation + i.e., at (tn, yn) = (t0, y0) or + (tR, yR), or + (b) when transitioning between time + steps t_{n-1} \to t_{n} to fill + f_{n-1} within the Hermite + interpolation module. + + In each case, the stepper may check the + fn_is_current flag to know whether + ARKODE believes that the RHS may have + already been computed at this (t,y) + value, in which case the stepper can + copy the RHS data from its own internal + storage instead of recomputing. If + these values are not current, then the + RHS should be recomputed, and the + stepper should consider storing the + values internally, for potential reuse + later. + + ARK_FULLRHS_END -> called in the following circumstances: + (a) when temporal root-finding is + enabled, this will be called + in-between steps t_{n-1} \to t_{n} + to fill f_{n}, + (b) when high-order dense output is + requested from the Hermite + interpolation module in-between + steps t_{n-1} \to t_{n} to fill + f_{n}, or + (c) when an implicit predictor is + requested from the Hermite + interpolation module within the + time step t_{n} \to t_{n+1}, in + which case f_{n} needs to be + filled. + + Again, the stepper may check the + fn_is_current flag to know whether + ARKODE believes that the RHS may have + already been computed at this (t,y) + value, in which case the stepper can + copy the RHS data from its own + internal storage instead of + recomputing. If these values are not + current, then the RHS should be + recomputed, and the stepper should + consider storing the values internally, + for potential reuse later. + + ARK_FULLRHS_OTHER -> called in the following circumstances: + (a) when estimating the initial time + step size, + (b) for high-order dense output with the + Hermite interpolation module, + (c) by an "outer" stepper when ARKODE is + used as an inner solver), or + (d) when a high-order implicit predictor + is requested from the Hermite + interpolation module within the time + step t_{n} \to t_{n+1}. + + While instances (a)-(c) will occur + in-between calls to the stepper's + ARKTimestepStepFn, instance (d) would + occur from within the ARKTimestepStepFn + (only if it calls an arkPredict_* function + that internally calls arkInterpEvaluate). + Since the (t,y) input does not correspond + to an "official" time step, the RHS + functions should always be evaluated, and + the values should *not* be stored anywhere + that will interfere with other reused + stepper data. + + This routine is only *required* to be supplied to ARKODE if: + * ARKODE's initial time step selection algorithm (arkHin) is used, * the user requests temporal root-finding, * the Hermite interpolation module is used, or - * the user requests the "bootstrap" implicit predictor. + * the time-stepping module requests the "bootstrap" implicit predictor. Note that any stepper can itself require that this routine - exist for its own internal business (e.g., ERKStep). + exist for its own internal business (as in both ERKStep and ARKStep), + and/or call this routine for its own internal purposes. This routine should return 0 if successful, and a negative value otherwise. If an error does occur, an appropriate message diff --git a/src/arkode/arkode_io.c b/src/arkode/arkode_io.c index 2ae790ed86..f8e1087b43 100644 --- a/src/arkode/arkode_io.c +++ b/src/arkode/arkode_io.c @@ -148,6 +148,7 @@ int ARKodeSetOrder(void* arkode_mem, int ord) interpolation module. itype == ARK_INTERP_LAGRANGE specifies the Lagrange (stiff) interpolation module. + itype == ARK_INTERP_NONE disables interpolation. Return values: ARK_SUCCESS on success. @@ -890,8 +891,6 @@ int ARKodeSetUserData(void* arkode_mem, void* user_data) ---------------------------------------------------------------*/ int ARKodeSetAdaptController(void* arkode_mem, SUNAdaptController C) { - int retval; - long int lenrw, leniw; ARKodeMem ark_mem; if (arkode_mem == NULL) { @@ -909,54 +908,14 @@ int ARKodeSetAdaptController(void* arkode_mem, SUNAdaptController C) return (ARK_STEPPER_UNSUPPORTED); } - /* Remove current SUNAdaptController object - (delete if owned, and then nullify pointer) */ - if (ark_mem->hadapt_mem->owncontroller && - (ark_mem->hadapt_mem->hcontroller != NULL)) - { - retval = SUNAdaptController_Space(ark_mem->hadapt_mem->hcontroller, &lenrw, - &leniw); - if (retval == SUN_SUCCESS) - { - ark_mem->liw -= leniw; - ark_mem->lrw -= lenrw; - } - - retval = SUNAdaptController_Destroy(ark_mem->hadapt_mem->hcontroller); - ark_mem->hadapt_mem->owncontroller = SUNFALSE; - if (retval != SUN_SUCCESS) - { - arkProcessError(ark_mem, ARK_MEM_FAIL, __LINE__, __func__, __FILE__, - "SUNAdaptController_Destroy failure"); - return (ARK_MEM_FAIL); - } - } - ark_mem->hadapt_mem->hcontroller = NULL; - - /* On NULL-valued input, create default SUNAdaptController object */ - if (C == NULL) + /* If the stepper has provided a custom function, then call it and return */ + if (ark_mem->step_setadaptcontroller) { - C = SUNAdaptController_PID(ark_mem->sunctx); - if (C == NULL) - { - arkProcessError(ark_mem, ARK_MEM_FAIL, __LINE__, __func__, __FILE__, - "SUNAdaptControllerPID allocation failure"); - return (ARK_MEM_FAIL); - } - ark_mem->hadapt_mem->owncontroller = SUNTRUE; + return (ark_mem->step_setadaptcontroller(ark_mem, C)); } - else { ark_mem->hadapt_mem->owncontroller = SUNFALSE; } - /* Attach new SUNAdaptController object */ - retval = SUNAdaptController_Space(C, &lenrw, &leniw); - if (retval == SUN_SUCCESS) - { - ark_mem->liw += leniw; - ark_mem->lrw += lenrw; - } - ark_mem->hadapt_mem->hcontroller = C; - - return (ARK_SUCCESS); + /* Otherwise, call a utility routine to replace the current controller object */ + return (arkReplaceAdaptController(ark_mem, C)); } /*--------------------------------------------------------------- @@ -1995,6 +1954,50 @@ int ARKodeSetMaxConvFails(void* arkode_mem, int maxncf) return (ARK_SUCCESS); } +/*--------------------------------------------------------------- + ARKodeSetAccumulatedErrorType: + + This routine sets the accumulated temporal error estimation + strategy. + ---------------------------------------------------------------*/ +int ARKodeSetAccumulatedErrorType(void* arkode_mem, ARKAccumError accum_type) +{ + int retval = ARKodeResetAccumulatedError(arkode_mem); + if (retval != ARK_SUCCESS) { return retval; } + ((ARKodeMem)arkode_mem)->AccumErrorType = accum_type; + return (ARK_SUCCESS); +} + +/*--------------------------------------------------------------- + ARKodeResetAccumulatedError: + + This routine resets the accumulated temporal error estimate. + ---------------------------------------------------------------*/ +int ARKodeResetAccumulatedError(void* arkode_mem) +{ + ARKodeMem ark_mem; + if (arkode_mem == NULL) + { + arkProcessError(NULL, ARK_MEM_NULL, __LINE__, __func__, __FILE__, + MSG_ARK_NO_MEM); + return (ARK_MEM_NULL); + } + ark_mem = (ARKodeMem)arkode_mem; + + /* Guard against use for non-adaptive time stepper modules */ + if (!ark_mem->step_supports_adaptive) + { + arkProcessError(ark_mem, ARK_STEPPER_UNSUPPORTED, __LINE__, __func__, + __FILE__, "time-stepping module does not support temporal adaptivity"); + return (ARK_STEPPER_UNSUPPORTED); + } + + /* Reset value and counter, and return */ + ark_mem->AccumErrorStart = ark_mem->tn; + ark_mem->AccumError = ZERO; + return (ARK_SUCCESS); +} + /*=============================================================== ARKODE optional output utility functions ===============================================================*/ @@ -2427,6 +2430,56 @@ int ARKodeGetStepStats(void* arkode_mem, long int* nsteps, sunrealtype* hinused, return (ARK_SUCCESS); } +/*--------------------------------------------------------------- + ARKodeGetAccumulatedError: + + This routine returns the accumulated temporal error estimate. + ---------------------------------------------------------------*/ +int ARKodeGetAccumulatedError(void* arkode_mem, sunrealtype* accum_error) +{ + ARKodeMem ark_mem; + if (arkode_mem == NULL) + { + arkProcessError(NULL, ARK_MEM_NULL, __LINE__, __func__, __FILE__, + MSG_ARK_NO_MEM); + return (ARK_MEM_NULL); + } + ark_mem = (ARKodeMem)arkode_mem; + + /* Return an error if the stepper cannot accumulate temporal error */ + if (!ark_mem->step_supports_adaptive) + { + arkProcessError(ark_mem, ARK_STEPPER_UNSUPPORTED, __LINE__, __func__, + __FILE__, "time-stepping module does not support accumulated error estimation"); + return (ARK_STEPPER_UNSUPPORTED); + } + + /* Get time since last accumulated error reset */ + sunrealtype time_interval = ark_mem->tcur - ark_mem->AccumErrorStart; + + /* Fill output based on error accumulation type */ + if (ark_mem->AccumErrorType == ARK_ACCUMERROR_MAX) + { + *accum_error = ark_mem->AccumError * ark_mem->reltol; + } + else if (ark_mem->AccumErrorType == ARK_ACCUMERROR_SUM) + { + *accum_error = ark_mem->AccumError * ark_mem->reltol; + } + else if (ark_mem->AccumErrorType == ARK_ACCUMERROR_AVG) + { + *accum_error = ark_mem->AccumError * ark_mem->reltol / time_interval; + } + else + { + arkProcessError(ark_mem, ARK_WARNING, __LINE__, __func__, __FILE__, + "temporal error accumulation is currently disabled"); + return (ARK_WARNING); + } + + return (ARK_SUCCESS); +} + /*--------------------------------------------------------------- ARKodeGetNumConstrFails: @@ -3016,6 +3069,72 @@ int ARKodeWriteParameters(void* arkode_mem, FILE* fp) return (ARK_SUCCESS); } +/*=============================================================== + ARKODE-IO internal utility functions + ===============================================================*/ + +/*--------------------------------------------------------------- + arkReplaceAdaptController + + Replaces the current SUNAdaptController time step controller + object. If a NULL-valued SUNAdaptController is input, the + default will be re-enabled. + ---------------------------------------------------------------*/ +int arkReplaceAdaptController(ARKodeMem ark_mem, SUNAdaptController C) +{ + int retval; + long int lenrw, leniw; + + /* Remove current SUNAdaptController object + (delete if owned, and then nullify pointer) */ + if (ark_mem->hadapt_mem->owncontroller && + (ark_mem->hadapt_mem->hcontroller != NULL)) + { + retval = SUNAdaptController_Space(ark_mem->hadapt_mem->hcontroller, &lenrw, + &leniw); + if (retval == SUN_SUCCESS) + { + ark_mem->liw -= leniw; + ark_mem->lrw -= lenrw; + } + + retval = SUNAdaptController_Destroy(ark_mem->hadapt_mem->hcontroller); + ark_mem->hadapt_mem->owncontroller = SUNFALSE; + if (retval != SUN_SUCCESS) + { + arkProcessError(ark_mem, ARK_MEM_FAIL, __LINE__, __func__, __FILE__, + "SUNAdaptController_Destroy failure"); + return (ARK_MEM_FAIL); + } + } + ark_mem->hadapt_mem->hcontroller = NULL; + + /* On NULL-valued input, create default SUNAdaptController object */ + if (C == NULL) + { + C = SUNAdaptController_PID(ark_mem->sunctx); + if (C == NULL) + { + arkProcessError(ark_mem, ARK_MEM_FAIL, __LINE__, __func__, __FILE__, + "SUNAdaptControllerPID allocation failure"); + return (ARK_MEM_FAIL); + } + ark_mem->hadapt_mem->owncontroller = SUNTRUE; + } + else { ark_mem->hadapt_mem->owncontroller = SUNFALSE; } + + /* Attach new SUNAdaptController object */ + retval = SUNAdaptController_Space(C, &lenrw, &leniw); + if (retval == SUN_SUCCESS) + { + ark_mem->liw += leniw; + ark_mem->lrw += lenrw; + } + ark_mem->hadapt_mem->hcontroller = C; + + return (ARK_SUCCESS); +} + /*=============================================================== ARKODE + XBraid interface utility functions ===============================================================*/ diff --git a/src/arkode/arkode_lsrkstep.c b/src/arkode/arkode_lsrkstep.c index 9cae2f4300..ce6d56fc6b 100644 --- a/src/arkode/arkode_lsrkstep.c +++ b/src/arkode/arkode_lsrkstep.c @@ -309,7 +309,8 @@ int lsrkStep_ReInit_Commons(void* arkode_mem, ARKRhsFn rhs, sunrealtype t0, With other initialization types, this routine does nothing. ---------------------------------------------------------------*/ -int lsrkStep_Init(ARKodeMem ark_mem, int init_type) +int lsrkStep_Init(ARKodeMem ark_mem, SUNDIALS_MAYBE_UNUSED sunrealtype tout, + int init_type) { ARKodeLSRKStepMem step_mem; int retval; diff --git a/src/arkode/arkode_lsrkstep_impl.h b/src/arkode/arkode_lsrkstep_impl.h index d6cec7f545..9b51b92963 100644 --- a/src/arkode/arkode_lsrkstep_impl.h +++ b/src/arkode/arkode_lsrkstep_impl.h @@ -34,7 +34,7 @@ extern "C" { LSRK time step module private math function macros =============================================================== * SUNRlog calls the appropriate version of log - * + * * SUNRsinh calls the appropriate version of sinh * * SUNRcosh calls the appropriate version of cosh @@ -176,7 +176,7 @@ void* lsrkStep_Create_Commons(ARKRhsFn rhs, sunrealtype t0, N_Vector y0, SUNContext sunctx); int lsrkStep_ReInit_Commons(void* arkode_mem, ARKRhsFn rhs, sunrealtype t0, N_Vector y0); -int lsrkStep_Init(ARKodeMem ark_mem, int init_type); +int lsrkStep_Init(ARKodeMem ark_mem, sunrealtype tout, int init_type); int lsrkStep_FullRHS(ARKodeMem ark_mem, sunrealtype t, N_Vector y, N_Vector f, int mode); int lsrkStep_TakeStepRKC(ARKodeMem ark_mem, sunrealtype* dsmPtr, int* nflagPtr); diff --git a/src/arkode/arkode_mri_tables.c b/src/arkode/arkode_mri_tables.c index 7d68143884..75db52c6de 100644 --- a/src/arkode/arkode_mri_tables.c +++ b/src/arkode/arkode_mri_tables.c @@ -73,6 +73,7 @@ MRIStepCoupling MRIStepCoupling_Alloc(int nmat, int stages, MRISTEP_METHOD_TYPE type) { int i, j; + sunbooleantype hasOmegas, hasGammas; MRIStepCoupling MRIC = NULL; /* Check for legal input values */ @@ -85,6 +86,7 @@ MRIStepCoupling MRIStepCoupling_Alloc(int nmat, int stages, MRIC = (MRIStepCoupling)malloc(sizeof(struct MRIStepCouplingMem)); if (!MRIC) { return (NULL); } + MRIC->type = type; MRIC->nmat = nmat; MRIC->stages = stages; MRIC->q = 0; @@ -92,6 +94,24 @@ MRIStepCoupling MRIStepCoupling_Alloc(int nmat, int stages, MRIC->c = NULL; MRIC->W = NULL; MRIC->G = NULL; + MRIC->ngroup = 0; + MRIC->group = NULL; + + /* -------------------------------------------- + * Determine general storage format + * -------------------------------------------- */ + + hasOmegas = hasGammas = SUNFALSE; + if ((type == MRISTEP_EXPLICIT) || (type == MRISTEP_IMEX) || + (type == MRISTEP_MERK) || (type == MRISTEP_SR)) + { + hasOmegas = SUNTRUE; + } + if ((type == MRISTEP_IMPLICIT) || (type == MRISTEP_IMEX) || + (type == MRISTEP_SR)) + { + hasGammas = SUNTRUE; + } /* -------------------------------------------- * Allocate abscissae and coupling coefficients @@ -104,7 +124,7 @@ MRIStepCoupling MRIStepCoupling_Alloc(int nmat, int stages, return (NULL); } - if (type == MRISTEP_EXPLICIT || type == MRISTEP_IMEX) + if (hasOmegas) { /* allocate W matrices */ MRIC->W = (sunrealtype***)calloc(nmat, sizeof(sunrealtype**)); @@ -118,7 +138,7 @@ MRIStepCoupling MRIStepCoupling_Alloc(int nmat, int stages, for (i = 0; i < nmat; i++) { MRIC->W[i] = NULL; - MRIC->W[i] = (sunrealtype**)calloc(stages, sizeof(sunrealtype*)); + MRIC->W[i] = (sunrealtype**)calloc(stages + 1, sizeof(sunrealtype*)); if (!(MRIC->W[i])) { MRIStepCoupling_Free(MRIC); @@ -129,7 +149,7 @@ MRIStepCoupling MRIStepCoupling_Alloc(int nmat, int stages, /* allocate columns of each matrix in W */ for (i = 0; i < nmat; i++) { - for (j = 0; j < stages; j++) + for (j = 0; j <= stages; j++) { MRIC->W[i][j] = NULL; MRIC->W[i][j] = (sunrealtype*)calloc(stages, sizeof(sunrealtype)); @@ -142,7 +162,7 @@ MRIStepCoupling MRIStepCoupling_Alloc(int nmat, int stages, } } - if (type == MRISTEP_IMPLICIT || type == MRISTEP_IMEX) + if (hasGammas) { /* allocate G matrices */ MRIC->G = (sunrealtype***)calloc(nmat, sizeof(sunrealtype**)); @@ -156,7 +176,7 @@ MRIStepCoupling MRIStepCoupling_Alloc(int nmat, int stages, for (i = 0; i < nmat; i++) { MRIC->G[i] = NULL; - MRIC->G[i] = (sunrealtype**)calloc(stages, sizeof(sunrealtype*)); + MRIC->G[i] = (sunrealtype**)calloc(stages + 1, sizeof(sunrealtype*)); if (!(MRIC->G[i])) { MRIStepCoupling_Free(MRIC); @@ -167,7 +187,7 @@ MRIStepCoupling MRIStepCoupling_Alloc(int nmat, int stages, /* allocate columns of each matrix in G */ for (i = 0; i < nmat; i++) { - for (j = 0; j < stages; j++) + for (j = 0; j <= stages; j++) { MRIC->G[i][j] = NULL; MRIC->G[i][j] = (sunrealtype*)calloc(stages, sizeof(sunrealtype)); @@ -180,11 +200,35 @@ MRIStepCoupling MRIStepCoupling_Alloc(int nmat, int stages, } } + /* for MERK methods, allocate maximum possible number/sizes of stage groups */ + if (type == MRISTEP_MERK) + { + MRIC->ngroup = stages; + MRIC->group = (int**)malloc(stages * sizeof(int*)); + if (!(MRIC->group)) + { + MRIStepCoupling_Free(MRIC); + return (NULL); + } + for (i = 0; i < stages; i++) + { + MRIC->group[i] = NULL; + MRIC->group[i] = (int*)malloc(stages * sizeof(int)); + if (!(MRIC->group[i])) + { + MRIStepCoupling_Free(MRIC); + return (NULL); + } + for (j = 0; j < stages; j++) { MRIC->group[i][j] = -1; } + } + } + return (MRIC); } /*--------------------------------------------------------------- - Routine to allocate and fill a MRIStepCoupling structure + Routine to allocate and fill an explicit, implicit, or ImEx + MRIGARK MRIStepCoupling structure. ---------------------------------------------------------------*/ MRIStepCoupling MRIStepCoupling_Create(int nmat, int stages, int q, int p, sunrealtype* W, sunrealtype* G, @@ -218,41 +262,60 @@ MRIStepCoupling MRIStepCoupling_Create(int nmat, int stages, int q, int p, /* Abscissae */ for (i = 0; i < stages; i++) { MRIC->c[i] = c[i]; } - /* Coupling coefficients stored as 1D arrays of length nmat * stages * stages, - with each stages * stages matrix stored in C (row-major) order */ - if (type == MRISTEP_EXPLICIT || type == MRISTEP_IMEX) + /* Coupling coefficients stored as 1D arrays, based on whether they + include embedding coefficients */ + if (p == 0) { + /* non-embedded method: coupling coefficient 1D arrays have + length nmat * stages * stages, with each stages * stages + matrix stored in C (row-major) order */ for (k = 0; k < nmat; k++) { for (i = 0; i < stages; i++) { for (j = 0; j < stages; j++) { - MRIC->W[k][i][j] = W[stages * (stages * k + i) + j]; + if (type == MRISTEP_EXPLICIT || type == MRISTEP_IMEX) + { + MRIC->W[k][i][j] = W[stages * (stages * k + i) + j]; + } + if (type == MRISTEP_IMPLICIT || type == MRISTEP_IMEX) + { + MRIC->G[k][i][j] = G[stages * (stages * k + i) + j]; + } } } } } - if (type == MRISTEP_IMPLICIT || type == MRISTEP_IMEX) + else { + /* embedded method: coupling coefficient 1D arrays have + length nmat * (stages+1) * stages, with each (stages+1) * stages + matrix stored in C (row-major) order */ for (k = 0; k < nmat; k++) { - for (i = 0; i < stages; i++) + for (i = 0; i <= stages; i++) { for (j = 0; j < stages; j++) { - MRIC->G[k][i][j] = G[stages * (stages * k + i) + j]; + if (type == MRISTEP_EXPLICIT || type == MRISTEP_IMEX) + { + MRIC->W[k][i][j] = W[(stages + 1) * (stages * k + i) + j]; + } + if (type == MRISTEP_IMPLICIT || type == MRISTEP_IMEX) + { + MRIC->G[k][i][j] = G[(stages + 1) * (stages * k + i) + j]; + } } } } } - return (MRIC); } /*--------------------------------------------------------------- - Construct the MRI coupling matrix for an MIS method based on - a given 'slow' Butcher table. + Construct the MRIGARK coupling matrix for an MIS method based + on a given "slow" Butcher table. ---------------------------------------------------------------*/ MRIStepCoupling MRIStepCoupling_MIStoMRI(ARKodeButcherTable B, int q, int p) { @@ -268,6 +331,9 @@ MRIStepCoupling MRIStepCoupling_MIStoMRI(ARKodeButcherTable B, int q, int p) /* Check that input table is non-NULL */ if (!B) { return (NULL); } + /* If p>0, check that input table includes embedding coefficients */ + if ((p > 0) && (B->d == NULL)) { return (NULL); } + /* ----------------------------------- * Check that the input table is valid * ----------------------------------- */ @@ -300,14 +366,21 @@ MRIStepCoupling MRIStepCoupling_MIStoMRI(ARKodeButcherTable B, int q, int p) padding = SUNFALSE; - /* Last stage time should equal 1 */ + /* Pad if last stage does not equal 1 */ if (SUNRabs(B->c[B->stages - 1] - ONE) > tol) { padding = SUNTRUE; } - /* Last row of A should equal b */ + /* Pad if last row of A does not equal b */ for (j = 0; j < B->stages; j++) { if (SUNRabs(B->A[B->stages - 1][j] - B->b[j]) > tol) { padding = SUNTRUE; } } + + /* If final stage is implicit and the method contains an embedding, + we require padding since d != b */ + if ((p > 0) && (SUNRabs(B->A[B->stages - 1][B->stages - 1]) > tol)) + { + padding = SUNTRUE; + } stages = (padding) ? B->stages + 1 : B->stages; /* ------------------------- @@ -369,6 +442,15 @@ MRIStepCoupling MRIStepCoupling_MIStoMRI(ARKodeButcherTable B, int q, int p) } } + /* Embedded row = d(:) - A(end,:) */ + if (p > 0) + { + for (j = 0; j < B->stages; j++) + { + C[0][stages][j] = B->d[j] - B->A[B->stages - 1][j]; + } + } + return (MRIC); } @@ -384,11 +466,8 @@ MRIStepCoupling MRIStepCoupling_Copy(MRIStepCoupling MRIC) /* Check for legal input */ if (!MRIC) { return (NULL); } - /* Check for method coefficients and set method type */ - if (MRIC->W && MRIC->G) { type = MRISTEP_IMEX; } - else if (MRIC->W && !(MRIC->G)) { type = MRISTEP_EXPLICIT; } - else if (!(MRIC->W) && MRIC->G) { type = MRISTEP_IMPLICIT; } - else { return (NULL); } + /* Copy method type */ + type = MRIC->type; /* Check for stage times */ if (!(MRIC->c)) { return (NULL); } @@ -413,7 +492,7 @@ MRIStepCoupling MRIStepCoupling_Copy(MRIStepCoupling MRIC) { for (k = 0; k < nmat; k++) { - for (i = 0; i < stages; i++) + for (i = 0; i <= stages; i++) { for (j = 0; j < stages; j++) { @@ -428,7 +507,7 @@ MRIStepCoupling MRIStepCoupling_Copy(MRIStepCoupling MRIC) { for (k = 0; k < nmat; k++) { - for (i = 0; i < stages; i++) + for (i = 0; i <= stages; i++) { for (j = 0; j < stages; j++) { @@ -438,6 +517,19 @@ MRIStepCoupling MRIStepCoupling_Copy(MRIStepCoupling MRIC) } } + /* Copy MERK stage groups */ + if (MRIC->group) + { + MRICcopy->ngroup = MRIC->ngroup; + for (i = 0; i < stages; i++) + { + for (j = 0; j < stages; j++) + { + MRICcopy->group[i][j] = MRIC->group[i][j]; + } + } + } + return (MRICcopy); } @@ -453,10 +545,11 @@ void MRIStepCoupling_Space(MRIStepCoupling MRIC, sunindextype* liw, if (!MRIC) { return; } /* fill outputs based on MRIC */ - *liw = 4; + *liw = 5; if (MRIC->c) { *lrw += MRIC->stages; } - if (MRIC->W) { *lrw += MRIC->nmat * MRIC->stages * MRIC->stages; } - if (MRIC->G) { *lrw += MRIC->nmat * MRIC->stages * MRIC->stages; } + if (MRIC->W) { *lrw += MRIC->nmat * (MRIC->stages + 1) * MRIC->stages; } + if (MRIC->G) { *lrw += MRIC->nmat * (MRIC->stages + 1) * MRIC->stages; } + if (MRIC->group) { *liw += MRIC->stages * MRIC->stages; } } /*--------------------------------------------------------------- @@ -478,7 +571,7 @@ void MRIStepCoupling_Free(MRIStepCoupling MRIC) { if (MRIC->W[k]) { - for (i = 0; i < MRIC->stages; i++) + for (i = 0; i <= MRIC->stages; i++) { if (MRIC->W[k][i]) { @@ -499,7 +592,7 @@ void MRIStepCoupling_Free(MRIStepCoupling MRIC) { if (MRIC->G[k]) { - for (i = 0; i < MRIC->stages; i++) + for (i = 0; i <= MRIC->stages; i++) { if (MRIC->G[k][i]) { @@ -514,6 +607,19 @@ void MRIStepCoupling_Free(MRIStepCoupling MRIC) free(MRIC->G); } + if (MRIC->group) + { + for (i = 0; i < MRIC->stages; i++) + { + if (MRIC->group[i]) + { + free(MRIC->group[i]); + MRIC->group[i] = NULL; + } + } + free(MRIC->group); + } + free(MRIC); } } @@ -535,7 +641,7 @@ void MRIStepCoupling_Write(MRIStepCoupling MRIC, FILE* outfile) for (i = 0; i < MRIC->nmat; i++) { if (!(MRIC->W[i])) { return; } - for (j = 0; j < MRIC->stages; j++) + for (j = 0; j <= MRIC->stages; j++) { if (!(MRIC->W[i][j])) { return; } } @@ -547,13 +653,30 @@ void MRIStepCoupling_Write(MRIStepCoupling MRIC, FILE* outfile) for (i = 0; i < MRIC->nmat; i++) { if (!(MRIC->G[i])) { return; } - for (j = 0; j < MRIC->stages; j++) + for (j = 0; j <= MRIC->stages; j++) { if (!(MRIC->G[i][j])) { return; } } } } + if (MRIC->group) + { + for (i = 0; i < MRIC->stages; i++) + { + if (!(MRIC->group[i])) { return; } + } + } + + switch (MRIC->type) + { + case MRISTEP_EXPLICIT: fprintf(outfile, " type = explicit MRI\n"); break; + case MRISTEP_IMPLICIT: fprintf(outfile, " type = implicit MRI\n"); break; + case MRISTEP_IMEX: fprintf(outfile, " type = ImEx MRI\n"); break; + case MRISTEP_MERK: fprintf(outfile, " type = MERK\n"); break; + case MRISTEP_SR: fprintf(outfile, " type = MRISR\n"); break; + default: fprintf(outfile, " type = unknown\n"); + } fprintf(outfile, " nmat = %i\n", MRIC->nmat); fprintf(outfile, " stages = %i\n", MRIC->stages); fprintf(outfile, " method order (q) = %i\n", MRIC->q); @@ -570,7 +693,7 @@ void MRIStepCoupling_Write(MRIStepCoupling MRIC, FILE* outfile) for (k = 0; k < MRIC->nmat; k++) { fprintf(outfile, " W[%i] = \n", k); - for (i = 0; i < MRIC->stages; i++) + for (i = 0; i <= MRIC->stages; i++) { fprintf(outfile, " "); for (j = 0; j < MRIC->stages; j++) @@ -588,7 +711,7 @@ void MRIStepCoupling_Write(MRIStepCoupling MRIC, FILE* outfile) for (k = 0; k < MRIC->nmat; k++) { fprintf(outfile, " G[%i] = \n", k); - for (i = 0; i < MRIC->stages; i++) + for (i = 0; i <= MRIC->stages; i++) { fprintf(outfile, " "); for (j = 0; j < MRIC->stages; j++) @@ -600,6 +723,23 @@ void MRIStepCoupling_Write(MRIStepCoupling MRIC, FILE* outfile) fprintf(outfile, "\n"); } } + + if (MRIC->group) + { + fprintf(outfile, " ngroup = %i\n", MRIC->ngroup); + for (i = 0; i < MRIC->ngroup; i++) + { + fprintf(outfile, " group[%i] = ", i); + for (j = 0; j < MRIC->stages; j++) + { + if (MRIC->group[i][j] >= 0) + { + fprintf(outfile, "%i ", MRIC->group[i][j]); + } + } + fprintf(outfile, "\n"); + } + } } /* =========================================================================== @@ -613,36 +753,99 @@ void MRIStepCoupling_Write(MRIStepCoupling MRIC, FILE* outfile) * MRISTAGE_ERK_NOFAST -- standard ERK stage * MRISTAGE_DIRK_NOFAST -- standard DIRK stage * MRISTAGE_DIRK_FAST -- coupled DIRK + MIS-like stage + * MRISTAGE_STIFF_ACC -- "extra" stiffly-accurate stage * - * for each nontrivial stage in an MRI-like method. Otherwise (i.e., stage is - * not in [1,MRIC->stages-1]), returns ARK_INVALID_TABLE (<0). + * for each nontrivial stage, or embedding stage, in an MRI-like method. + * Otherwise (i.e., stage is not in [1,MRIC->stages]), returns + * ARK_INVALID_TABLE (<0). * - * The stage type is determined by 2 factors: + * The stage type is determined by 2 factors (for normal stages): * (a) Sum |MRIC->G[:][is][is]| (nonzero => DIRK) * (b) MRIC->c[is] - MRIC->c[is-1] (nonzero => fast) + * Similar tests are used for embedding stages. + * + * Note that MERK and MRI-SR methods do not use the stage-type identifiers, + * so if those tables are input we just return MRISTAGE_ERK_FAST. * ---------------------------------------------------------------------------*/ int mriStepCoupling_GetStageType(MRIStepCoupling MRIC, int is) { - int i; - sunrealtype Gabs, cdiff; + int i, j; + sunbooleantype Gdiag, Grow, Wrow, cdiff; const sunrealtype tol = SUN_RCONST(100.0) * SUN_UNIT_ROUNDOFF; - if ((is < 1) || (is >= MRIC->stages)) { return ARK_INVALID_TABLE; } + if ((is < 0) || (is > MRIC->stages)) { return ARK_INVALID_TABLE; } - /* sum of stage diagonal entries across implicit tables */ - Gabs = ZERO; - if (MRIC->G) + /* report MRISTAGE_ERK_FAST for MERK and MRI-SR methods */ + if ((MRIC->type == MRISTEP_SR) || (MRIC->type == MRISTEP_MERK)) { - for (i = 0; i < MRIC->nmat; i++) { Gabs += SUNRabs(MRIC->G[i][is][is]); } + return (MRISTAGE_ERK_FAST); } - /* abscissae difference */ - cdiff = MRIC->c[is] - MRIC->c[is - 1]; + /* separately handle an embedding "stage" from normal stages */ + if (is < MRIC->stages) + { /* normal */ + Gdiag = Grow = Wrow = cdiff = SUNFALSE; + if (MRIC->G) + { + for (i = 0; i < MRIC->nmat; i++) + { + Gdiag = Gdiag || (SUNRabs(MRIC->G[i][is][is]) > tol); + for (j = 0; j < MRIC->stages; j++) + { + Grow = Grow || (SUNRabs(MRIC->G[i][is][j]) > tol); + } + } + } + if (MRIC->W) + { + for (i = 0; i < MRIC->nmat; i++) + { + for (j = 0; j < MRIC->stages; j++) + { + Wrow = Wrow || (SUNRabs(MRIC->W[i][is][j]) > tol); + } + } + } + + /* abscissae difference */ + cdiff = (SUNRabs(MRIC->c[is] - MRIC->c[is - 1]) > tol); + } + else + { /* embedding */ + Gdiag = Grow = Wrow = cdiff = SUNFALSE; + if (MRIC->G) + { + for (i = 0; i < MRIC->nmat; i++) + { + Gdiag = Gdiag || (SUNRabs(MRIC->G[i][is][is - 1]) > tol); + for (j = 0; j < MRIC->stages; j++) + { + Grow = Grow || (SUNRabs(MRIC->G[i][is][j]) > tol); + } + } + } + if (MRIC->W) + { + for (i = 0; i < MRIC->nmat; i++) + { + for (j = 0; j < MRIC->stages; j++) + { + Wrow = Wrow || (SUNRabs(MRIC->W[i][is][j]) > tol); + } + } + } + cdiff = (SUNRabs(MRIC->c[is - 1] - MRIC->c[is - 2]) > tol); + } - if (Gabs > tol) + /* make determination */ + if (!(Gdiag || Grow || Wrow || cdiff) && (is > 0)) + { /* stiffly-accurate stage */ + return (MRISTAGE_STIFF_ACC); + } + if (Gdiag) { /* DIRK */ - if (cdiff > tol) + if (cdiff) { /* Fast */ return (MRISTAGE_DIRK_FAST); } @@ -650,7 +853,7 @@ int mriStepCoupling_GetStageType(MRIStepCoupling MRIC, int is) } else { /* ERK */ - if (cdiff > tol) + if (cdiff) { /* Fast */ return (MRISTAGE_ERK_FAST); } @@ -663,6 +866,9 @@ int mriStepCoupling_GetStageType(MRIStepCoupling MRIC, int is) * first stage of the pair generally corresponds to a column of zeros and so * does not need to be computed and stored. The stage_map indicates if the RHS * needs to be computed and where to store it i.e., stage_map[i] > -1. + * + * Note: for MERK and MRI-SR methods, this should be an "identity" map, and all + * stage vectors should be allocated. * ---------------------------------------------------------------------------*/ int mriStepCoupling_GetStageMap(MRIStepCoupling MRIC, int* stage_map, @@ -680,9 +886,23 @@ int mriStepCoupling_GetStageMap(MRIStepCoupling MRIC, int* stage_map, if (!(MRIC->W) && !(MRIC->G)) { return (ARK_ILL_INPUT); } if (!stage_map || !nstages_active) { return (ARK_ILL_INPUT); } - /* ------------------- - * Compute storage map - * ------------------- */ + /* ------------------------------------------- + * MERK and MRI-SR have "identity" storage map + * ------------------------------------------- */ + + if ((MRIC->type == MRISTEP_MERK) || (MRIC->type == MRISTEP_SR)) + { + /* Number of stage RHS vectors active */ + *nstages_active = MRIC->stages; + + /* Create an identity map (all columns are non-zero) */ + for (j = 0; j < MRIC->stages; j++) { stage_map[j] = j; } + return (ARK_SUCCESS); + } + + /* ---------------------------------------- + * Compute storage map for MRI-GARK methods + * ---------------------------------------- */ /* Number of stage RHS vectors active */ *nstages_active = 0; @@ -701,7 +921,7 @@ int mriStepCoupling_GetStageMap(MRIStepCoupling MRIC, int* stage_map, { for (k = 0; k < MRIC->nmat; k++) { - for (i = 0; i < MRIC->stages; i++) + for (i = 0; i <= MRIC->stages; i++) { Wsum += SUNRabs(MRIC->W[k][i][j]); } @@ -712,7 +932,7 @@ int mriStepCoupling_GetStageMap(MRIStepCoupling MRIC, int* stage_map, { for (k = 0; k < MRIC->nmat; k++) { - for (i = 0; i < MRIC->stages; i++) + for (i = 0; i <= MRIC->stages; i++) { Gsum += SUNRabs(MRIC->G[k][i][j]); } diff --git a/src/arkode/arkode_mri_tables.def b/src/arkode/arkode_mri_tables.def index 999ef71f95..9e6bb316a8 100644 --- a/src/arkode/arkode_mri_tables.def +++ b/src/arkode/arkode_mri_tables.def @@ -25,34 +25,43 @@ below. The 'type' column denotes whether the method is explicit (E), - or solve-decoupled implicit (ID). + solve-decoupled implicit (ID), solve-decoupled ImEx (IED), + and/or has stage-restart structure (S). The 'QP' column denotes whether the coefficients of the method are known precisely enough for use in quad precision (128-bit) calculations. - imeth order type QP - ----------------------------------------------------- - ARKODE_MRI_GARK_FORWARD_EULER 1 E Y - ARKODE_MRI_GARK_RALSTON2 2 E Y - ARKODE_MIS_KW3 3 E Y - ARKODE_MRI_GARK_ERK22a 2 E Y - ARKODE_MRI_GARK_ERK22b 2 E Y - ARKODE_MRI_GARK_ERK33a 3 E Y - ARKODE_MRI_GARK_RALSTON3 3 E Y - ARKODE_MRI_GARK_ERK45a 4 E Y - ARKODE_MRI_GARK_BACKWARD_EULER 1 ID Y - ARKODE_MRI_GARK_IRK21a 2 ID Y - ARKODE_MRI_GARK_IMPLICIT_MIDPOINT 2 ID Y - ARKODE_MRI_GARK_ESDIRK34a 3 ID Y - ARKODE_MRI_GARK_ESDIRK46a 4 ID Y - ARKODE_IMEX_MRI_GARK_EULER 1 ID Y - ARKODE_IMEX_MRI_GARK_TRAPEZOIDAL 2 ID Y - ARKODE_IMEX_MRI_GARK_MIDPOINT 2 ID Y - ARKODE_IMEX_MRI_GARK3a 3 ID Y - ARKODE_IMEX_MRI_GARK3b 3 ID Y - ARKODE_IMEX_MRI_GARK4 4 ID Y - ----------------------------------------------------- + method embedding + imeth order order type QP + ---------------------------------------------------------------- + ARKODE_MRI_GARK_FORWARD_EULER 1 0 E Y + ARKODE_MRI_GARK_ERK22a 2 1 E Y + ARKODE_MRI_GARK_ERK22b 2 1 E Y + ARKODE_MRI_GARK_RALSTON2 2 1 E Y + ARKODE_MIS_KW3 3 0 E Y + ARKODE_MRI_GARK_ERK33a 3 2 E Y + ARKODE_MRI_GARK_RALSTON3 3 2 E Y + ARKODE_MRI_GARK_ERK45a 4 3 E Y + ARKODE_MERK21 2 1 ES Y + ARKODE_MERK32 3 2 ES Y + ARKODE_MERK43 4 3 ES Y + ARKODE_MERK54 5 4 ES Y + ARKODE_MRI_GARK_BACKWARD_EULER 1 0 ID Y + ARKODE_MRI_GARK_IRK21a 2 1 ID Y + ARKODE_MRI_GARK_IMPLICIT_MIDPOINT 2 0 ID Y + ARKODE_MRI_GARK_ESDIRK34a 3 2 ID Y + ARKODE_MRI_GARK_ESDIRK46a 4 3 ID Y + ARKODE_IMEX_MRI_GARK_EULER 1 0 ID Y + ARKODE_IMEX_MRI_GARK_TRAPEZOIDAL 2 0 ID Y + ARKODE_IMEX_MRI_GARK_MIDPOINT 2 0 ID Y + ARKODE_IMEX_MRI_GARK3a 3 0 IED Y + ARKODE_IMEX_MRI_GARK3b 3 0 IED Y + ARKODE_IMEX_MRI_GARK4 4 0 IED Y + ARKODE_IMEX_MRI_SR21 2 1 IEDS Y + ARKODE_IMEX_MRI_SR32 3 2 IEDS Y + ARKODE_IMEX_MRI_SR43 4 3 IEDS Y + ---------------------------------------------------------------- */ @@ -62,35 +71,35 @@ ARK_MRI_TABLE(ARKODE_MRI_NONE, { ARK_MRI_TABLE(ARKODE_MRI_GARK_FORWARD_EULER, { ARKodeButcherTable B = ARKodeButcherTable_LoadERK(ARKODE_FORWARD_EULER_1_1); - MRIStepCoupling C = MRIStepCoupling_MIStoMRI(B, 1, 0); + MRIStepCoupling C = MRIStepCoupling_MIStoMRI(B, B->q, B->p); ARKodeButcherTable_Free(B); return C; }) ARK_MRI_TABLE(ARKODE_MRI_GARK_RALSTON2, { /* Roberts et al., SISC 44:A1405 - A1427, 2022 */ ARKodeButcherTable B = ARKodeButcherTable_LoadERK(ARKODE_RALSTON_EULER_2_1_2); - MRIStepCoupling C = MRIStepCoupling_MIStoMRI(B, 2, 0); + MRIStepCoupling C = MRIStepCoupling_MIStoMRI(B, B->q, B->p); ARKodeButcherTable_Free(B); return C; }) ARK_MRI_TABLE(ARKODE_MIS_KW3, { /* Schlegel et al., JCAM 226:345-357, 2009 */ ARKodeButcherTable B = ARKodeButcherTable_LoadERK(ARKODE_KNOTH_WOLKE_3_3); - MRIStepCoupling C = MRIStepCoupling_MIStoMRI(B, 3, 0); + MRIStepCoupling C = MRIStepCoupling_MIStoMRI(B, B->q, B->p); ARKodeButcherTable_Free(B); return C; }) ARK_MRI_TABLE(ARKODE_MRI_GARK_ERK22a, { /* A. Sandu, SINUM 57:2300-2327, 2019 */ ARKodeButcherTable B = ARKodeButcherTable_LoadERK(ARKODE_EXPLICIT_MIDPOINT_EULER_2_1_2); - MRIStepCoupling C = MRIStepCoupling_MIStoMRI(B, 2, 0); + MRIStepCoupling C = MRIStepCoupling_MIStoMRI(B, B->q, B->p); ARKodeButcherTable_Free(B); return C; }) ARK_MRI_TABLE(ARKODE_MRI_GARK_ERK22b, { /* A. Sandu, SINUM 57:2300-2327, 2019 */ ARKodeButcherTable B = ARKodeButcherTable_LoadERK(ARKODE_HEUN_EULER_2_1_2); - MRIStepCoupling C = MRIStepCoupling_MIStoMRI(B, 2, 0); + MRIStepCoupling C = MRIStepCoupling_MIStoMRI(B, B->q, B->p); ARKodeButcherTable_Free(B); return C; }) @@ -99,7 +108,7 @@ ARK_MRI_TABLE(ARKODE_MRI_GARK_ERK33a, { /* A. Sandu, SINUM 57:2300-2327, 2019 */ MRIStepCoupling C = MRIStepCoupling_Alloc(2, 4, MRISTEP_EXPLICIT); C->q = 3; - C->p = 0; + C->p = 2; C->c[1] = ONE/SUN_RCONST(3.0); C->c[2] = TWO/SUN_RCONST(3.0); @@ -110,6 +119,9 @@ ARK_MRI_TABLE(ARKODE_MRI_GARK_ERK33a, { /* A. Sandu, SINUM 57:2300-2327, 2019 */ C->W[0][2][1] = TWO/SUN_RCONST(3.0); C->W[0][3][1] = -TWO/SUN_RCONST(3.0); C->W[0][3][2] = ONE; + C->W[0][4][0] = ONE/SUN_RCONST(12.0); + C->W[0][4][1] = -ONE/SUN_RCONST(3.0); + C->W[0][4][2] = SUN_RCONST(7.0)/SUN_RCONST(12.0); C->W[1][3][0] = ONE/TWO; C->W[1][3][2] = -ONE/TWO; @@ -120,7 +132,7 @@ ARK_MRI_TABLE(ARKODE_MRI_GARK_RALSTON3, { /* Roberts et al., SISC 44:A1405 - A14 MRIStepCoupling C = MRIStepCoupling_Alloc(2, 4, MRISTEP_EXPLICIT); C->q = 3; - C->p = 0; + C->p = 2; C->c[1] = ONE/TWO; C->c[2] = SUN_RCONST(3.0)/SUN_RCONST(4.0); @@ -132,6 +144,9 @@ ARK_MRI_TABLE(ARKODE_MRI_GARK_RALSTON3, { /* Roberts et al., SISC 44:A1405 - A14 C->W[0][3][0] = SUN_RCONST(47.0)/SUN_RCONST(36.0); C->W[0][3][1] = -ONE/SUN_RCONST(6.0); C->W[0][3][2] = -SUN_RCONST(8.0)/SUN_RCONST(9.0); + C->W[0][4][0] = ONE/SUN_RCONST(40.0); + C->W[0][4][1] = SUN_RCONST(7.0)/SUN_RCONST(40.0); + C->W[0][4][2] = ONE/SUN_RCONST(20.0); C->W[1][2][0] = SUN_RCONST(9.0)/TWO; C->W[1][2][1] = -SUN_RCONST(9.0)/TWO; @@ -142,10 +157,11 @@ ARK_MRI_TABLE(ARKODE_MRI_GARK_RALSTON3, { /* Roberts et al., SISC 44:A1405 - A14 }) ARK_MRI_TABLE(ARKODE_MRI_GARK_ERK45a, { /* A. Sandu, SINUM 57:2300-2327, 2019 */ + /* Embedding coefficients CORRECTED in A. Sandu, arxiv:1808.02759, 2018 */ MRIStepCoupling C = MRIStepCoupling_Alloc(2, 6, MRISTEP_EXPLICIT); C->q = 4; - C->p = 0; + C->p = 3; C->c[1] = SUN_RCONST(0.2); C->c[2] = SUN_RCONST(0.4); @@ -168,6 +184,11 @@ ARK_MRI_TABLE(ARKODE_MRI_GARK_ERK45a, { /* A. Sandu, SINUM 57:2300-2327, 2019 */ C->W[0][5][2] = -SUN_RCONST(1360217.0)/SUN_RCONST(1139280.0); C->W[0][5][3] = -SUN_RCONST(148789.0)/SUN_RCONST(56964.0); C->W[0][5][4] = SUN_RCONST(147889.0)/SUN_RCONST(45120.0); + C->W[0][6][0] = -SUN_RCONST(88227.0)/SUN_RCONST(47470.0); + C->W[0][6][1] = SUN_RCONST(756870829.0)/SUN_RCONST(340217490.0); + C->W[0][6][2] = -SUN_RCONST(713704111.0)/SUN_RCONST(1360869960.0); + C->W[0][6][3] = -SUN_RCONST(31967827.0)/SUN_RCONST(340217490.0); + C->W[0][6][4] = SUN_RCONST(129673.0)/SUN_RCONST(286680.0); C->W[1][2][0] = SUN_RCONST(503.0)/SUN_RCONST(80.0); C->W[1][2][1] = -SUN_RCONST(503.0)/SUN_RCONST(80.0); @@ -183,6 +204,8 @@ ARK_MRI_TABLE(ARKODE_MRI_GARK_ERK45a, { /* A. Sandu, SINUM 57:2300-2327, 2019 */ C->W[1][5][2] = ONE; C->W[1][5][3] = SUN_RCONST(5.0); C->W[1][5][4] = -SUN_RCONST(41933.0)/SUN_RCONST(7520.0); + C->W[1][6][0] = SUN_RCONST(6213.0)/SUN_RCONST(1880.0); + C->W[1][6][1] = -SUN_RCONST(6213.0)/SUN_RCONST(1880.0); return C; }) @@ -203,9 +226,10 @@ ARK_MRI_TABLE(ARKODE_MRI_GARK_BACKWARD_EULER, { ARK_MRI_TABLE(ARKODE_MRI_GARK_IRK21a, { /* A. Sandu, SINUM 57:2300-2327, 2019 */ MRIStepCoupling C; - ARKodeButcherTable B = ARKodeButcherTable_Alloc(3, SUNFALSE); + ARKodeButcherTable B = ARKodeButcherTable_Alloc(3, SUNTRUE); B->q=2; + B->p=1; B->c[1] = ONE; B->c[2] = ONE; @@ -217,7 +241,9 @@ ARK_MRI_TABLE(ARKODE_MRI_GARK_IRK21a, { /* A. Sandu, SINUM 57:2300-2327, 2019 */ B->b[0] = SUN_RCONST(0.5); B->b[2] = SUN_RCONST(0.5); - C = MRIStepCoupling_MIStoMRI(B, 2, 0); + B->d[2] = SUN_RCONST(1.0); + + C = MRIStepCoupling_MIStoMRI(B, B->q, B->p); ARKodeButcherTable_Free(B); return C; }) @@ -240,11 +266,11 @@ ARK_MRI_TABLE(ARKODE_MRI_GARK_IMPLICIT_MIDPOINT, { }) ARK_MRI_TABLE(ARKODE_MRI_GARK_ESDIRK34a, { /* A. Sandu, SINUM 57:2300-2327, 2019 */ - MRIStepCoupling C = MRIStepCoupling_Alloc(1, 7, MRISTEP_IMPLICIT); + MRIStepCoupling C = MRIStepCoupling_Alloc(1, 8, MRISTEP_IMPLICIT); sunrealtype beta = SUN_RCONST(0.4358665215084589994160194511935568425); C->q = 3; - C->p = 0; + C->p = 2; C->c[1] = ONE/SUN_RCONST(3.0); C->c[2] = ONE/SUN_RCONST(3.0); @@ -252,6 +278,7 @@ ARK_MRI_TABLE(ARKODE_MRI_GARK_ESDIRK34a, { /* A. Sandu, SINUM 57:2300-2327, 2019 C->c[4] = TWO/SUN_RCONST(3.0); C->c[5] = ONE; C->c[6] = ONE; + C->c[7] = ONE; C->G[0][1][0] = ONE/SUN_RCONST(3.0); C->G[0][2][0] = -beta; @@ -266,14 +293,18 @@ ARK_MRI_TABLE(ARKODE_MRI_GARK_ESDIRK34a, { /* A. Sandu, SINUM 57:2300-2327, 2019 C->G[0][5][4] = SUN_RCONST(-0.9934660860338359976640778047742273701); C->G[0][6][0] = -beta; C->G[0][6][6] = beta; + C->G[0][8][0] = SUN_RCONST(0.2453831999117524372455680781104585876241); + C->G[0][8][2] = SUN_RCONST(0.4204215033044044563073464989473988121422); + C->G[0][8][4] = -SUN_RCONST(1.576992606344066224351397232226173387157); + C->G[0][8][6] = SUN_RCONST(0.9111879031279093307984826551683159873903); return C; }) ARK_MRI_TABLE(ARKODE_MRI_GARK_ESDIRK46a, { /* A. Sandu, SINUM 57:2300-2327, 2019 */ - MRIStepCoupling C = MRIStepCoupling_Alloc(2, 11, MRISTEP_IMPLICIT); + MRIStepCoupling C = MRIStepCoupling_Alloc(2, 12, MRISTEP_IMPLICIT); C->q = 4; - C->p = 0; + C->p = 3; C->c[1] = ONE/SUN_RCONST(5.0); C->c[2] = ONE/SUN_RCONST(5.0); @@ -285,6 +316,7 @@ ARK_MRI_TABLE(ARKODE_MRI_GARK_ESDIRK46a, { /* A. Sandu, SINUM 57:2300-2327, 2019 C->c[8] = SUN_RCONST(4.0)/SUN_RCONST(5.0); C->c[9] = ONE; C->c[10] = ONE; + C->c[11] = ONE; C->G[0][1][0] = ONE/SUN_RCONST(5.0); C->G[0][2][0] = -ONE/SUN_RCONST(4.0); @@ -321,6 +353,12 @@ ARK_MRI_TABLE(ARKODE_MRI_GARK_ESDIRK46a, { /* A. Sandu, SINUM 57:2300-2327, 2019 C->G[0][10][6] = SUN_RCONST(127.0)/SUN_RCONST(300.0); C->G[0][10][8] = -SUN_RCONST(313.0)/SUN_RCONST(300.0); C->G[0][10][10] = ONE/SUN_RCONST(4.0); + C->G[0][12][0] = -ONE/SUN_RCONST(4.0); + C->G[0][12][2] = SUN_RCONST(5595.0)/SUN_RCONST(8804.0); + C->G[0][12][4] = -SUN_RCONST(2445.0)/SUN_RCONST(8804.0); + C->G[0][12][6] = -SUN_RCONST(4225.0)/SUN_RCONST(8804.0); + C->G[0][12][8] = SUN_RCONST(2205.0)/SUN_RCONST(4402.0); + C->G[0][12][10] = -SUN_RCONST(567.0)/SUN_RCONST(4402.0); C->G[1][3][0] = -SUN_RCONST(1674554930619.0)/SUN_RCONST(964681845400.0); C->G[1][3][2] = SUN_RCONST(1674554930619.0)/SUN_RCONST(964681845400.0); @@ -618,3 +656,465 @@ ARK_MRI_TABLE(ARKODE_IMEX_MRI_GARK4, { /* R. Chinomona & D. Reynolds SINUM 43(5) return C; }) +ARK_MRI_TABLE(ARKODE_IMEX_MRI_SR21, { /* A.C. Fish, D.R. Reynolds, S.B. Roberts, JCAM 438:115534, 2024 */ + MRIStepCoupling C = MRIStepCoupling_Alloc(1, 4, MRISTEP_SR); + + C->q = 2; + C->p = 1; + + C->c[1] = SUN_RCONST(3.0)/SUN_RCONST(5.0); + C->c[2] = SUN_RCONST(4.0)/SUN_RCONST(15.0); + C->c[3] = ONE; + + C->W[0][1][0] = SUN_RCONST(3.0)/SUN_RCONST(5.0); + C->W[0][2][0] = SUN_RCONST(14.0)/SUN_RCONST(165.0); + C->W[0][2][1] = SUN_RCONST(2.0)/SUN_RCONST(11.0); + C->W[0][3][0] = -SUN_RCONST(13.0)/SUN_RCONST(54.0); + C->W[0][3][1] = SUN_RCONST(137.0)/SUN_RCONST(270.0); + C->W[0][3][2] = SUN_RCONST(11.0)/SUN_RCONST(15.0); + C->W[0][4][0] = -SUN_RCONST(0.25); + C->W[0][4][1] = SUN_RCONST(0.5); + C->W[0][4][2] = SUN_RCONST(0.75); + + C->G[0][1][0] = -SUN_RCONST(11.0)/SUN_RCONST(23.0); + C->G[0][1][1] = SUN_RCONST(11.0)/SUN_RCONST(23.0); + C->G[0][2][0] = -SUN_RCONST(6692.0)/SUN_RCONST(52371.0); + C->G[0][2][1] = -SUN_RCONST(18355.0)/SUN_RCONST(52371.0); + C->G[0][2][2] = SUN_RCONST(11.0)/SUN_RCONST(23.0); + C->G[0][3][0] = SUN_RCONST(11621.0)/SUN_RCONST(90666.0); + C->G[0][3][1] = -SUN_RCONST(215249.0)/SUN_RCONST(226665.0); + C->G[0][3][2] = SUN_RCONST(17287.0)/SUN_RCONST(50370.0); + C->G[0][3][3] = SUN_RCONST(11.0)/SUN_RCONST(23.0); + C->G[0][4][0] = -SUN_RCONST(31.0)/SUN_RCONST(12.0); + C->G[0][4][1] = -ONE/SUN_RCONST(6.0); + C->G[0][4][2] = SUN_RCONST(11.0)/SUN_RCONST(4.0); + return C; + }) + +ARK_MRI_TABLE(ARKODE_IMEX_MRI_SR32, { /* A.C. Fish, D.R. Reynolds, S.B. Roberts, JCAM 438:115534, 2024 */ + MRIStepCoupling C = MRIStepCoupling_Alloc(2, 5, MRISTEP_SR); + + C->q = 3; + C->p = 2; + + C->c[1] = SUN_RCONST(23.0)/SUN_RCONST(34.0); + C->c[2] = SUN_RCONST(4.0)/SUN_RCONST(5.0); + C->c[3] = SUN_RCONST(17.0)/SUN_RCONST(15.0); + C->c[4] = ONE; + + C->W[0][1][0] = SUN_RCONST(23.0)/SUN_RCONST(34.0); + C->W[0][2][0] = SUN_RCONST(71.0)/SUN_RCONST(70.0); + C->W[0][2][1] = -SUN_RCONST(3.0)/SUN_RCONST(14.0); + C->W[0][3][0] = SUN_RCONST(124.0)/SUN_RCONST(1155.0); + C->W[0][3][1] = SUN_RCONST(4.0)/SUN_RCONST(7.0); + C->W[0][3][2] = SUN_RCONST(5.0)/SUN_RCONST(11.0); + C->W[0][4][0] = SUN_RCONST(162181.0)/SUN_RCONST(187680.0); + C->W[0][4][1] = SUN_RCONST(119.0)/SUN_RCONST(1380.0); + C->W[0][4][2] = SUN_RCONST(11.0)/SUN_RCONST(32.0); + C->W[0][4][3] = -SUN_RCONST(5.0)/SUN_RCONST(17.0); + C->W[0][5][0] = SUN_RCONST(76355.0)/SUN_RCONST(74834.0); + C->W[0][5][1] = -SUN_RCONST(46.0)/SUN_RCONST(31.0); + C->W[0][5][2] = SUN_RCONST(67.0)/SUN_RCONST(34.0); + C->W[0][5][3] = -SUN_RCONST(36.0)/SUN_RCONST(71.0); + + C->W[1][2][0] = -SUN_RCONST(14453.0)/SUN_RCONST(63825.0); + C->W[1][2][1] = SUN_RCONST(14453.0)/SUN_RCONST(63825.0); + C->W[1][3][0] = -SUN_RCONST(2101267877.0)/SUN_RCONST(1206582300.0); + C->W[1][3][1] = SUN_RCONST(2476735438.0)/SUN_RCONST(301645575.0); + C->W[1][3][2] = -SUN_RCONST(13575085.0)/SUN_RCONST(2098404.0); + C->W[1][4][0] = -SUN_RCONST(762580446799.0)/SUN_RCONST(588660102960.0); + C->W[1][4][1] = SUN_RCONST(11083240219.0)/SUN_RCONST(4328383110.0); + C->W[1][4][2] = -SUN_RCONST(211274129.0)/SUN_RCONST(100368304.0); + C->W[1][4][3] = SUN_RCONST(89562055.0)/SUN_RCONST(106641323.0); + C->W[1][5][0] = -SUN_RCONST(3732974.0)/SUN_RCONST(2278035.0); + C->W[1][5][1] = SUN_RCONST(13857574.0)/SUN_RCONST(2278035.0); + C->W[1][5][2] = -SUN_RCONST(52.0)/SUN_RCONST(9.0); + C->W[1][5][3] = SUN_RCONST(4.0)/SUN_RCONST(3.0); + + C->G[0][1][0] = -SUN_RCONST(4.0)/SUN_RCONST(7.0); + C->G[0][1][1] = SUN_RCONST(4.0)/SUN_RCONST(7.0); + C->G[0][2][0] = -SUN_RCONST(2707004.0)/SUN_RCONST(3127425.0); + C->G[0][2][1] = SUN_RCONST(919904.0)/SUN_RCONST(3127425.0); + C->G[0][2][2] = SUN_RCONST(4.0)/SUN_RCONST(7.0); + C->G[0][3][0] = SUN_RCONST(852879271.0)/SUN_RCONST(703839675.0); + C->G[0][3][1] = -SUN_RCONST(1575000496.0)/SUN_RCONST(703839675.0); + C->G[0][3][2] = SUN_RCONST(5.0)/SUN_RCONST(11.0); + C->G[0][3][3] = SUN_RCONST(4.0)/SUN_RCONST(7.0); + C->G[0][4][0] = SUN_RCONST(43136869.0)/SUN_RCONST(2019912118.0); + C->G[0][4][1] = -SUN_RCONST(73810600.0)/SUN_RCONST(1009956059.0); + C->G[0][4][2] = -SUN_RCONST(17653551.0)/SUN_RCONST(87822266.0); + C->G[0][4][3] = -SUN_RCONST(13993902.0)/SUN_RCONST(43911133.0); + C->G[0][4][4] = SUN_RCONST(4.0)/SUN_RCONST(7.0); + C->G[0][5][0] = -SUN_RCONST(179.0)/SUN_RCONST(4140.0); + C->G[0][5][1] = SUN_RCONST(799.0)/SUN_RCONST(14490.0); + C->G[0][5][2] = ONE/SUN_RCONST(14.0); + C->G[0][5][3] = -ONE/SUN_RCONST(12.0); + return C; + }) + +ARK_MRI_TABLE(ARKODE_IMEX_MRI_SR43, { /* A.C. Fish, D.R. Reynolds, S.B. Roberts, arXiv:2301.00865, 2023 */ + MRIStepCoupling C = MRIStepCoupling_Alloc(2, 7, MRISTEP_SR); + + C->q = 4; + C->p = 3; + + C->c[1] = ONE/SUN_RCONST(4.0); + C->c[2] = SUN_RCONST(3.0)/SUN_RCONST(4.0); + C->c[3] = SUN_RCONST(11.0)/SUN_RCONST(20.0); + C->c[4] = ONE/SUN_RCONST(2.0); + C->c[5] = ONE; + C->c[6] = ONE; + + C->W[0][1][0] = ONE/SUN_RCONST(4.0); + C->W[0][2][0] = SUN_RCONST(9.0)/SUN_RCONST(8.0); + C->W[0][2][1] = -SUN_RCONST(3.0)/SUN_RCONST(8.0); + C->W[0][3][0] = SUN_RCONST(187.0)/SUN_RCONST(2340.0); + C->W[0][3][1] = SUN_RCONST(7.0)/SUN_RCONST(9.0); + C->W[0][3][2] = -SUN_RCONST(4.0)/SUN_RCONST(13.0); + C->W[0][4][0] = SUN_RCONST(64.0)/SUN_RCONST(165.0); + C->W[0][4][1] = ONE/SUN_RCONST(6.0); + C->W[0][4][2] = -SUN_RCONST(3.0)/SUN_RCONST(5.0); + C->W[0][4][3] = SUN_RCONST(6.0)/SUN_RCONST(11.0); + C->W[0][5][0] = SUN_RCONST(1816283.0)/SUN_RCONST(549120.0); + C->W[0][5][1] = -SUN_RCONST(2.0)/SUN_RCONST(9.0); + C->W[0][5][2] = -SUN_RCONST(4.0)/SUN_RCONST(11.0); + C->W[0][5][3] = -ONE/SUN_RCONST(6.0); + C->W[0][5][4] = -SUN_RCONST(2561809.0)/SUN_RCONST(1647360.0); + C->W[0][6][1] = SUN_RCONST(7.0)/SUN_RCONST(11.0); + C->W[0][6][2] = -SUN_RCONST(2203.0)/SUN_RCONST(264.0); + C->W[0][6][3] = SUN_RCONST(10825.0)/SUN_RCONST(792.0); + C->W[0][6][4] = -SUN_RCONST(85.0)/SUN_RCONST(12.0); + C->W[0][6][5] = SUN_RCONST(841.0)/SUN_RCONST(396.0); + C->W[0][7][0] = ONE/SUN_RCONST(400.0); + C->W[0][7][1] = SUN_RCONST(49.0)/SUN_RCONST(12.0); + C->W[0][7][2] = SUN_RCONST(43.0)/SUN_RCONST(6.0); + C->W[0][7][3] = -SUN_RCONST(7.0)/SUN_RCONST(10.0); + C->W[0][7][4] = -SUN_RCONST(85.0)/SUN_RCONST(12.0); + C->W[0][7][5] = -SUN_RCONST(2963.0)/SUN_RCONST(1200.0); + + C->W[1][2][0] = -SUN_RCONST(11.0)/SUN_RCONST(4.0); + C->W[1][2][1] = SUN_RCONST(11.0)/SUN_RCONST(4.0); + C->W[1][3][0] = -SUN_RCONST(1228.0)/SUN_RCONST(2925.0); + C->W[1][3][1] = -SUN_RCONST(92.0)/SUN_RCONST(225.0); + C->W[1][3][2] = SUN_RCONST(808.0)/SUN_RCONST(975.0); + C->W[1][4][0] = -SUN_RCONST(2572.0)/SUN_RCONST(2805.0); + C->W[1][4][1] = SUN_RCONST(167.0)/SUN_RCONST(255.0); + C->W[1][4][2] = SUN_RCONST(199.0)/SUN_RCONST(136.0); + C->W[1][4][3] = -SUN_RCONST(1797.0)/SUN_RCONST(1496.0); + C->W[1][5][0] = -SUN_RCONST(1816283.0)/SUN_RCONST(274560.0); + C->W[1][5][1] = SUN_RCONST(253.0)/SUN_RCONST(36.0); + C->W[1][5][2] = -SUN_RCONST(23.0)/SUN_RCONST(44.0); + C->W[1][5][3] = SUN_RCONST(76.0)/SUN_RCONST(3.0); + C->W[1][5][4] = -SUN_RCONST(20775791.0)/SUN_RCONST(823680.0); + C->W[1][6][1] = SUN_RCONST(107.0)/SUN_RCONST(132.0); + C->W[1][6][2] = SUN_RCONST(1289.0)/SUN_RCONST(88.0); + C->W[1][6][3] = -SUN_RCONST(9275.0)/SUN_RCONST(792.0); + C->W[1][6][5] = -SUN_RCONST(371.0)/SUN_RCONST(99.0); + C->W[1][7][0] = -ONE/SUN_RCONST(200.0); + C->W[1][7][1] = -SUN_RCONST(137.0)/SUN_RCONST(24.0); + C->W[1][7][2] = -SUN_RCONST(235.0)/SUN_RCONST(16.0); + C->W[1][7][3] = SUN_RCONST(1237.0)/SUN_RCONST(80.0); + C->W[1][7][5] = SUN_RCONST(2963.0)/SUN_RCONST(600.0); + + C->G[0][1][0] = -ONE/SUN_RCONST(4.0); + C->G[0][1][1] = ONE/SUN_RCONST(4.0); + C->G[0][2][0] = ONE/SUN_RCONST(4.0); + C->G[0][2][1] = -ONE/SUN_RCONST(2.0); + C->G[0][2][2] = ONE/SUN_RCONST(4.0); + C->G[0][3][0] = SUN_RCONST(13.0)/SUN_RCONST(100.0); + C->G[0][3][1] = -SUN_RCONST(7.0)/SUN_RCONST(30.0); + C->G[0][3][2] = -SUN_RCONST(11.0)/SUN_RCONST(75.0); + C->G[0][3][3] = ONE/SUN_RCONST(4.0); + C->G[0][4][0] = SUN_RCONST(6.0)/SUN_RCONST(85.0); + C->G[0][4][1] = -SUN_RCONST(301.0)/SUN_RCONST(1360.0); + C->G[0][4][2] = -SUN_RCONST(99.0)/SUN_RCONST(544.0); + C->G[0][4][3] = SUN_RCONST(45.0)/SUN_RCONST(544.0); + C->G[0][4][4] = ONE/SUN_RCONST(4.0); + C->G[0][5][1] = -SUN_RCONST(9.0)/SUN_RCONST(4.0); + C->G[0][5][2] = -SUN_RCONST(19.0)/SUN_RCONST(48.0); + C->G[0][5][3] = -SUN_RCONST(75.0)/SUN_RCONST(16.0); + C->G[0][5][4] = SUN_RCONST(85.0)/SUN_RCONST(12.0); + C->G[0][5][5] = ONE/SUN_RCONST(4.0); + return C; + }) + +ARK_MRI_TABLE(ARKODE_MERK21, { /* A.C. Fish, D.R. Reynolds, S.B. Roberts, JCAM 438:115534, 2024 (embedding unpublished) */ + MRIStepCoupling C = MRIStepCoupling_Alloc(2, 3, MRISTEP_MERK); + sunrealtype c2 = SUN_RCONST(0.5); + + C->q = 2; + C->p = 1; + C->ngroup = 2; + C->group[0][0] = 1; + C->group[0][1] = 3; + C->group[1][0] = 2; + + C->c[1] = c2; + C->c[2] = ONE; + + C->W[0][1][0] = ONE; + C->W[0][2][0] = ONE; + C->W[0][3][0] = ONE; + + C->W[1][2][0] = -ONE/c2; + C->W[1][2][1] = ONE/c2; + return C; + }) + +ARK_MRI_TABLE(ARKODE_MERK32, { /* A.C. Fish, D.R. Reynolds, S.B. Roberts, JCAM 438:115534, 2024 (embedding unpublished) */ + MRIStepCoupling C = MRIStepCoupling_Alloc(2, 4, MRISTEP_MERK); + sunrealtype c2 = SUN_RCONST(0.5); + + C->q = 3; + C->p = 2; + C->ngroup = 3; + C->group[0][0] = 1; + C->group[1][0] = 2; + C->group[1][1] = 4; + C->group[2][0] = 3; + + C->c[1] = c2; + C->c[2] = SUN_RCONST(2.0)/SUN_RCONST(3.0); + C->c[3] = ONE; + + C->W[0][1][0] = ONE; + C->W[0][2][0] = ONE; + C->W[0][3][0] = ONE; + C->W[0][4][0] = ONE; + + C->W[1][2][0] = -ONE/c2; + C->W[1][2][1] = ONE/c2; + C->W[1][3][0] = -SUN_RCONST(1.5); + C->W[1][3][2] = SUN_RCONST(1.5); + C->W[1][4][0] = -ONE/c2; + C->W[1][4][1] = ONE/c2; + return C; + }) + +ARK_MRI_TABLE(ARKODE_MERK43, { /* A.C. Fish, D.R. Reynolds, S.B. Roberts, JCAM 438:115534, 2024 (embedding unpublished) */ + MRIStepCoupling C = MRIStepCoupling_Alloc(3, 7, MRISTEP_MERK); + sunrealtype c2 = SUN_RCONST(0.5); + sunrealtype c3 = SUN_RCONST(0.5); + sunrealtype c4 = ONE/SUN_RCONST(3.0); + sunrealtype c5 = SUN_RCONST(5.0)/SUN_RCONST(6.0); + sunrealtype c6 = ONE/SUN_RCONST(3.0); + + C->q = 4; + C->p = 3; + C->ngroup = 4; + C->group[0][0] = 1; + C->group[1][0] = 3; + C->group[1][1] = 2; + C->group[2][0] = 5; + C->group[2][1] = 4; + C->group[2][2] = 7; + C->group[3][0] = 6; + + C->c[1] = c2; + C->c[2] = c3; + C->c[3] = c4; + C->c[4] = c5; + C->c[5] = c6; + C->c[6] = ONE; + + C->W[0][1][0] = ONE; + C->W[0][2][0] = ONE; + C->W[0][3][0] = ONE; + C->W[0][4][0] = ONE; + C->W[0][5][0] = ONE; + C->W[0][6][0] = ONE; + C->W[0][7][0] = ONE; + + C->W[1][2][0] = -ONE/c2; + C->W[1][2][1] = ONE/c2; + C->W[1][3][0] = -ONE/c2; + C->W[1][3][1] = ONE/c2; + C->W[1][4][0] = c4/c3/(c3-c4) - c3/c4/(c3-c4); + C->W[1][4][2] = -c4/c3/(c3-c4); + C->W[1][4][3] = c3/c4/(c3-c4); + C->W[1][5][0] = c4/c3/(c3-c4) - c3/c4/(c3-c4); + C->W[1][5][2] = -c4/c3/(c3-c4); + C->W[1][5][3] = c3/c4/(c3-c4); + C->W[1][6][0] = c6/c5/(c5-c6) - c5/c6/(c5-c6); + C->W[1][6][4] = -c6/c5/(c5-c6); + C->W[1][6][5] = c5/c6/(c5-c6); + C->W[1][7][0] = c4/c3/(c3-c4) - c3/c4/(c3-c4); + C->W[1][7][2] = -c4/c3/(c3-c4); + C->W[1][7][3] = c3/c4/(c3-c4); + + C->W[2][4][0] = ONE/c4/(c3-c4) - ONE/c3/(c3-c4); + C->W[2][4][2] = ONE/c3/(c3-c4); + C->W[2][4][3] = -ONE/c4/(c3-c4); + C->W[2][5][0] = ONE/c4/(c3-c4) - ONE/c3/(c3-c4); + C->W[2][5][2] = ONE/c3/(c3-c4); + C->W[2][5][3] = -ONE/c4/(c3-c4); + C->W[2][6][0] = ONE/c6/(c5-c6) - ONE/c5/(c5-c6); + C->W[2][6][4] = ONE/c5/(c5-c6); + C->W[2][6][5] = -ONE/c6/(c5-c6); + C->W[2][7][0] = ONE/c4/(c3-c4) - ONE/c3/(c3-c4); + C->W[2][7][2] = ONE/c3/(c3-c4); + C->W[2][7][3] = -ONE/c4/(c3-c4); + + return C; + }) + +ARK_MRI_TABLE(ARKODE_MERK54, { /* A.C. Fish, D.R. Reynolds, S.B. Roberts, JCAM 438:115534, 2024 (embedding unpublished) */ + MRIStepCoupling C = MRIStepCoupling_Alloc(4, 11, MRISTEP_MERK); + sunrealtype c2 = SUN_RCONST(0.5); + sunrealtype c3 = SUN_RCONST(0.5); + sunrealtype c4 = ONE/SUN_RCONST(3.0); + sunrealtype c5 = SUN_RCONST(0.5); + sunrealtype c6 = ONE/SUN_RCONST(3.0); + sunrealtype c7 = SUN_RCONST(0.25); + sunrealtype c8 = SUN_RCONST(0.7); + sunrealtype c9 = SUN_RCONST(0.5); + sunrealtype c10 = SUN_RCONST(2.0)/SUN_RCONST(3.0); + sunrealtype a2 = ONE/c2; + sunrealtype a3 = c4/c3/(c4-c3); + sunrealtype a4 = c3/c4/(c3-c4); + sunrealtype a5 = c6*c7/c5/(c5-c6)/(c5-c7); + sunrealtype a6 = c5*c7/c6/(c6-c5)/(c6-c7); + sunrealtype a7 = c5*c6/c7/(c7-c5)/(c7-c6); + sunrealtype a8 = c9*c10/c8/(c8-c9)/(c8-c10); + sunrealtype a9 = c8*c10/c9/(c9-c8)/(c9-c10); + sunrealtype a10 = c8*c9/c10/(c10-c8)/(c10-c9); + sunrealtype b3 = ONE/c3/(c3-c4); + sunrealtype b4 = ONE/c4/(c3-c4); + sunrealtype b5 = (c6+c7)/c5/(c5-c6)/(c5-c7); + sunrealtype b6 = (c5+c7)/c6/(c6-c5)/(c6-c7); + sunrealtype b7 = (c5+c6)/c7/(c7-c5)/(c7-c6); + sunrealtype b8 = (c9+c10)/c8/(c8-c9)/(c8-c10); + sunrealtype b9 = (c8+c10)/c9/(c9-c8)/(c9-c10); + sunrealtype b10 = (c8+c9)/c10/(c10-c8)/(c10-c9); + sunrealtype g5 = ONE/c5/(c5-c6)/(c5-c7); + sunrealtype g6 = ONE/c6/(c6-c5)/(c6-c7); + sunrealtype g7 = ONE/c7/(c7-c5)/(c7-c6); + sunrealtype g8 = ONE/c8/(c8-c9)/(c8-c10); + sunrealtype g9 = ONE/c9/(c9-c8)/(c9-c10); + sunrealtype g10 = ONE/c10/(c10-c8)/(c10-c9); + + C->q = 5; + C->p = 4; + C->ngroup = 5; + C->group[0][0] = 1; + C->group[1][0] = 3; + C->group[1][1] = 2; + C->group[2][0] = 6; + C->group[2][1] = 5; + C->group[2][2] = 4; + C->group[3][0] = 8; + C->group[3][1] = 9; + C->group[3][2] = 7; + C->group[3][3] = 11; + C->group[4][0] = 10; + + C->c[1] = c2; + C->c[2] = c3; + C->c[3] = c4; + C->c[4] = c5; + C->c[5] = c6; + C->c[6] = c7; + C->c[7] = c8; + C->c[8] = c9; + C->c[9] = c10; + C->c[10] = ONE; + + C->W[0][1][0] = ONE; + C->W[0][2][0] = ONE; + C->W[0][3][0] = ONE; + C->W[0][4][0] = ONE; + C->W[0][5][0] = ONE; + C->W[0][6][0] = ONE; + C->W[0][7][0] = ONE; + C->W[0][8][0] = ONE; + C->W[0][9][0] = ONE; + C->W[0][10][0] = ONE; + C->W[0][11][0] = ONE; + + C->W[1][2][0] = -a2; + C->W[1][2][1] = a2; + C->W[1][3][0] = -a2; + C->W[1][3][1] = a2; + C->W[1][4][0] = -(a3 + a4); + C->W[1][4][2] = a3; + C->W[1][4][3] = a4; + C->W[1][5][0] = -(a3 + a4); + C->W[1][5][2] = a3; + C->W[1][5][3] = a4; + C->W[1][6][0] = -(a3 + a4); + C->W[1][6][2] = a3; + C->W[1][6][3] = a4; + C->W[1][7][0] = -(a5 + a6 + a7); + C->W[1][7][4] = a5; + C->W[1][7][5] = a6; + C->W[1][7][6] = a7; + C->W[1][8][0] = -(a5 + a6 + a7); + C->W[1][8][4] = a5; + C->W[1][8][5] = a6; + C->W[1][8][6] = a7; + C->W[1][9][0] = -(a5 + a6 + a7); + C->W[1][9][4] = a5; + C->W[1][9][5] = a6; + C->W[1][9][6] = a7; + C->W[1][10][0] = -(a8 + a9 + a10); + C->W[1][10][7] = a8; + C->W[1][10][8] = a9; + C->W[1][10][9] = a10; + C->W[1][11][0] = -(a5 + a6 + a7); + C->W[1][11][4] = a5; + C->W[1][11][5] = a6; + C->W[1][11][6] = a7; + + C->W[2][4][0] = b4 - b3; + C->W[2][4][2] = b3; + C->W[2][4][3] = -b4; + C->W[2][5][0] = b4 - b3; + C->W[2][5][2] = b3; + C->W[2][5][3] = -b4; + C->W[2][6][0] = b4 - b3; + C->W[2][6][2] = b3; + C->W[2][6][3] = -b4; + C->W[2][7][0] = b5 + b6 + b7; + C->W[2][7][4] = -b5; + C->W[2][7][5] = -b6; + C->W[2][7][6] = -b7; + C->W[2][8][0] = b5 + b6 + b7; + C->W[2][8][4] = -b5; + C->W[2][8][5] = -b6; + C->W[2][8][6] = -b7; + C->W[2][9][0] = b5 + b6 + b7; + C->W[2][9][4] = -b5; + C->W[2][9][5] = -b6; + C->W[2][9][6] = -b7; + C->W[2][10][0] = b8 + b9 + b10; + C->W[2][10][7] = -b8; + C->W[2][10][8] = -b9; + C->W[2][10][9] = -b10; + C->W[2][11][0] = b5 + b6 + b7; + C->W[2][11][4] = -b5; + C->W[2][11][5] = -b6; + C->W[2][11][6] = -b7; + + C->W[3][7][0] = -(g5 + g6 + g7); + C->W[3][7][4] = g5; + C->W[3][7][5] = g6; + C->W[3][7][6] = g7; + C->W[3][8][0] = -(g5 + g6 + g7); + C->W[3][8][4] = g5; + C->W[3][8][5] = g6; + C->W[3][8][6] = g7; + C->W[3][9][0] = -(g5 + g6 + g7); + C->W[3][9][4] = g5; + C->W[3][9][5] = g6; + C->W[3][9][6] = g7; + C->W[3][10][0] = -(g8 + g9 + g10); + C->W[3][10][7] = g8; + C->W[3][10][8] = g9; + C->W[3][10][9] = g10; + C->W[3][11][0] = -(g5 + g6 + g7); + C->W[3][11][4] = g5; + C->W[3][11][5] = g6; + C->W[3][11][6] = g7; + + return C; + }) diff --git a/src/arkode/arkode_mristep.c b/src/arkode/arkode_mristep.c index a078d19a33..823324bf81 100644 --- a/src/arkode/arkode_mristep.c +++ b/src/arkode/arkode_mristep.c @@ -110,7 +110,7 @@ void* MRIStepCreate(ARKRhsFn fse, ARKRhsFn fsi, sunrealtype t0, N_Vector y0, ark_mem->step_getgammas = mriStep_GetGammas; ark_mem->step_init = mriStep_Init; ark_mem->step_fullrhs = mriStep_FullRHS; - ark_mem->step = mriStep_TakeStep; + ark_mem->step = mriStep_TakeStepMRIGARK; ark_mem->step_setuserdata = mriStep_SetUserData; ark_mem->step_printallstats = mriStep_PrintAllStats; ark_mem->step_writeparameters = mriStep_WriteParameters; @@ -137,10 +137,14 @@ void* MRIStepCreate(ARKRhsFn fse, ARKRhsFn fsi, sunrealtype t0, N_Vector y0, ark_mem->step_getnumrhsevals = mriStep_GetNumRhsEvals; ark_mem->step_getnumlinsolvsetups = mriStep_GetNumLinSolvSetups; ark_mem->step_getcurrentgamma = mriStep_GetCurrentGamma; + ark_mem->step_setadaptcontroller = mriStep_SetAdaptController; + ark_mem->step_getestlocalerrors = mriStep_GetEstLocalErrors; ark_mem->step_getnonlinearsystemdata = mriStep_GetNonlinearSystemData; ark_mem->step_getnumnonlinsolviters = mriStep_GetNumNonlinSolvIters; ark_mem->step_getnumnonlinsolvconvfails = mriStep_GetNumNonlinSolvConvFails; ark_mem->step_getnonlinsolvstats = mriStep_GetNonlinSolvStats; + ark_mem->step_setforcing = mriStep_SetInnerForcing; + ark_mem->step_supports_adaptive = SUNTRUE; ark_mem->step_supports_implicit = SUNTRUE; ark_mem->step_mem = (void*)step_mem; @@ -159,16 +163,18 @@ void* MRIStepCreate(ARKRhsFn fse, ARKRhsFn fsi, sunrealtype t0, N_Vector y0, be allocated later on (based on the MRI method) */ /* Copy the slow RHS functions into stepper memory */ - step_mem->fse = fse; - step_mem->fsi = fsi; + step_mem->fse = fse; + step_mem->fsi = fsi; + step_mem->fse_is_current = SUNFALSE; + step_mem->fsi_is_current = SUNFALSE; /* Set implicit/explicit problem based on function pointers */ step_mem->explicit_rhs = (fse == NULL) ? SUNFALSE : SUNTRUE; step_mem->implicit_rhs = (fsi == NULL) ? SUNFALSE : SUNTRUE; /* Update the ARKODE workspace requirements */ - ark_mem->liw += 42; /* fcn/data ptr, int, long int, sunindextype, sunbooleantype */ - ark_mem->lrw += 10; + ark_mem->liw += 49; /* fcn/data ptr, int, long int, sunindextype, sunbooleantype */ + ark_mem->lrw += 14; /* Create a default Newton NLS object (just in case; will be deleted if the user attaches a nonlinear solver) */ @@ -203,22 +209,58 @@ void* MRIStepCreate(ARKRhsFn fse, ARKRhsFn fsi, sunrealtype t0, N_Vector y0, step_mem->lfree = NULL; step_mem->lmem = NULL; + /* Initialize error norm */ + step_mem->eRNrm = ONE; + /* Initialize all the counters */ - step_mem->nfse = 0; - step_mem->nfsi = 0; - step_mem->nsetups = 0; - step_mem->nstlp = 0; - step_mem->nls_iters = 0; - step_mem->nls_fails = 0; - - /* Initialize fused op work space */ - step_mem->cvals = NULL; + step_mem->nfse = 0; + step_mem->nfsi = 0; + step_mem->nsetups = 0; + step_mem->nstlp = 0; + step_mem->nls_iters = 0; + step_mem->nls_fails = 0; + step_mem->inner_fails = 0; + + /* Initialize fused op work space with sufficient storage for + at least filling the full RHS on an ImEx problem */ + step_mem->nfusedopvecs = 3; + step_mem->cvals = NULL; + step_mem->cvals = (sunrealtype*)calloc(step_mem->nfusedopvecs, + sizeof(sunrealtype)); + if (step_mem->cvals == NULL) + { + arkProcessError(ark_mem, ARK_MEM_FAIL, __LINE__, __func__, __FILE__, + "Error allocating MRIStep storage"); + ARKodeFree((void**)&ark_mem); + return (NULL); + } + ark_mem->lrw += step_mem->nfusedopvecs; step_mem->Xvecs = NULL; + step_mem->Xvecs = (N_Vector*)calloc(step_mem->nfusedopvecs, sizeof(N_Vector)); + if (step_mem->Xvecs == NULL) + { + arkProcessError(ark_mem, ARK_MEM_FAIL, __LINE__, __func__, __FILE__, + "Error allocating MRIStep storage"); + ARKodeFree((void**)&ark_mem); + return (NULL); + } + ark_mem->liw += step_mem->nfusedopvecs; + + /* Initialize adaptivity parameters */ + step_mem->inner_rtol_factor = ONE; + step_mem->inner_dsm = ONE; + step_mem->inner_rtol_factor_new = ONE; /* Initialize pre and post inner evolve functions */ step_mem->pre_inner_evolve = NULL; step_mem->post_inner_evolve = NULL; + /* Initialize external polynomial forcing data */ + step_mem->expforcing = SUNFALSE; + step_mem->impforcing = SUNFALSE; + step_mem->forcing = NULL; + step_mem->nforcing = 0; + /* Initialize main ARKODE infrastructure (allocates vectors) */ retval = arkInit(ark_mem, t0, y0, FIRST_INIT); if (retval != ARK_SUCCESS) @@ -329,15 +371,19 @@ int MRIStepReInit(void* arkode_mem, ARKRhsFn fse, ARKRhsFn fsi, sunrealtype t0, } /* Copy the input parameters into ARKODE state */ - step_mem->fse = fse; - step_mem->fsi = fsi; + step_mem->fse = fse; + step_mem->fsi = fsi; + step_mem->fse_is_current = SUNFALSE; + step_mem->fsi_is_current = SUNFALSE; /* Initialize all the counters */ - step_mem->nfse = 0; - step_mem->nfsi = 0; - step_mem->nsetups = 0; - step_mem->nstlp = 0; - step_mem->nls_iters = 0; + step_mem->nfse = 0; + step_mem->nfsi = 0; + step_mem->nsetups = 0; + step_mem->nstlp = 0; + step_mem->nls_iters = 0; + step_mem->nls_fails = 0; + step_mem->inner_fails = 0; return (ARK_SUCCESS); } @@ -384,10 +430,11 @@ int mriStep_Resize(ARKodeMem ark_mem, N_Vector y0, "Unable to resize vector"); return (ARK_MEM_FAIL); } + if (step_mem->unify_Fs) { step_mem->Fsi = step_mem->Fse; } } /* Resize Fsi */ - if (step_mem->Fsi) + if (step_mem->Fsi && !step_mem->unify_Fs) { if (!arkResizeVecArray(resize, resize_data, step_mem->nstages_allocated, y0, &(step_mem->Fsi), lrw_diff, &(ark_mem->lrw), @@ -496,7 +543,12 @@ int mriStep_Reset(ARKodeMem ark_mem, sunrealtype tR, N_Vector yR) /* Reset the inner integrator with this same state */ retval = mriStepInnerStepper_Reset(step_mem->stepper, tR, yR); - if (retval != ARK_SUCCESS) { return (ARK_INNERSTEP_FAIL); } + if (retval != ARK_SUCCESS) + { + arkProcessError(ark_mem, ARK_INNERSTEP_FAIL, __LINE__, __func__, __FILE__, + "Unable to reset the inner stepper"); + return (ARK_INNERSTEP_FAIL); + } return (ARK_SUCCESS); } @@ -548,7 +600,7 @@ void mriStep_Free(ARKodeMem ark_mem) { free(step_mem->stagetypes); step_mem->stagetypes = NULL; - ark_mem->liw -= step_mem->stages; + ark_mem->liw -= (step_mem->stages + 1); } if (step_mem->stage_map) { @@ -608,6 +660,7 @@ void mriStep_Free(ARKodeMem ark_mem) arkFreeVecArray(step_mem->nstages_allocated, &(step_mem->Fse), ark_mem->lrw1, &(ark_mem->lrw), ark_mem->liw1, &(ark_mem->liw)); + if (step_mem->unify_Fs) { step_mem->Fsi = NULL; } } if (step_mem->Fsi) @@ -663,7 +716,7 @@ void mriStep_PrintMem(ARKodeMem ark_mem, FILE* outfile) fprintf(outfile, "MRIStep: predictor = %i\n", step_mem->predictor); fprintf(outfile, "MRIStep: convfail = %i\n", step_mem->convfail); fprintf(outfile, "MRIStep: stagetypes ="); - for (i = 0; i < step_mem->stages; i++) + for (i = 0; i <= step_mem->stages; i++) { fprintf(outfile, " %i", step_mem->stagetypes[i]); } @@ -675,6 +728,8 @@ void mriStep_PrintMem(ARKodeMem ark_mem, FILE* outfile) fprintf(outfile, "MRIStep: nsetups = %li\n", step_mem->nsetups); fprintf(outfile, "MRIStep: nstlp = %li\n", step_mem->nstlp); fprintf(outfile, "MRIStep: nls_iters = %li\n", step_mem->nls_iters); + fprintf(outfile, "MRIStep: nls_fails = %li\n", step_mem->nls_fails); + fprintf(outfile, "MRIStep: inner_fails = %li\n", step_mem->inner_fails); /* output boolean quantities */ fprintf(outfile, "MRIStep: user_linear = %i\n", step_mem->linear); @@ -726,7 +781,7 @@ void mriStep_PrintMem(ARKodeMem ark_mem, FILE* outfile) fprintf(outfile, "MRIStep: Fse[%i]:\n", i); N_VPrintFile(step_mem->Fse[i], outfile); } - if (step_mem->Fsi) + if (step_mem->Fsi && !step_mem->unify_Fs) for (i = 0; i < step_mem->nstages_active; i++) { fprintf(outfile, "MRIStep: Fsi[%i]:\n", i); @@ -862,17 +917,18 @@ int mriStep_GetGammas(ARKodeMem ark_mem, sunrealtype* gamma, sunrealtype* gamrat within arkInitialSetup. With initialization types FIRST_INIT this routine: - - sets/checks the ARK Butcher tables to be used - - allocates any memory that depends on the number of ARK - stages, method order, or solver options + - sets/checks the coefficient tables to be used + - allocates any internal memory that depends on the MRI method + structure or solver options With other initialization types, this routine does nothing. ---------------------------------------------------------------*/ -int mriStep_Init(ARKodeMem ark_mem, int init_type) +int mriStep_Init(ARKodeMem ark_mem, sunrealtype tout, int init_type) { ARKodeMRIStepMem step_mem; int retval, j; sunbooleantype reset_efun; + SUNAdaptController_Type adapt_type; /* access ARKodeMRIStepMem structure */ retval = mriStep_AccessStepMem(ark_mem, __func__, &step_mem); @@ -885,10 +941,16 @@ int mriStep_Init(ARKodeMem ark_mem, int init_type) if (init_type == FIRST_INIT) { /* enforce use of arkEwtSmallReal if using a fixed step size for - an explicit method and an internal error weight function */ + an explicit method, an internal error weight function, and not performing + accumulated temporal error estimation */ reset_efun = SUNTRUE; if (step_mem->implicit_rhs) { reset_efun = SUNFALSE; } + if (!ark_mem->fixedstep) { reset_efun = SUNFALSE; } if (ark_mem->user_efun) { reset_efun = SUNFALSE; } + if (ark_mem->AccumErrorType != ARK_ACCUMERROR_NONE) + { + reset_efun = SUNFALSE; + } if (reset_efun) { ark_mem->user_efun = SUNFALSE; @@ -896,14 +958,6 @@ int mriStep_Init(ARKodeMem ark_mem, int init_type) ark_mem->e_data = ark_mem; } - /* assume fixed outer step size */ - if (!ark_mem->fixedstep) - { - arkProcessError(ark_mem, ARK_ILL_INPUT, __LINE__, __func__, - __FILE__, "Adaptive outer time stepping is not currently supported"); - return (ARK_ILL_INPUT); - } - /* Create coupling structure (if not already set) */ retval = mriStep_SetCoupling(ark_mem); if (retval != ARK_SUCCESS) @@ -922,6 +976,35 @@ int mriStep_Init(ARKodeMem ark_mem, int init_type) return (ARK_ILL_INPUT); } + /* Attach correct TakeStep routine for this coupling table */ + switch (step_mem->MRIC->type) + { + case MRISTEP_EXPLICIT: ark_mem->step = mriStep_TakeStepMRIGARK; break; + case MRISTEP_IMPLICIT: ark_mem->step = mriStep_TakeStepMRIGARK; break; + case MRISTEP_IMEX: ark_mem->step = mriStep_TakeStepMRIGARK; break; + case MRISTEP_MERK: ark_mem->step = mriStep_TakeStepMERK; break; + case MRISTEP_SR: ark_mem->step = mriStep_TakeStepMRISR; break; + default: + arkProcessError(ark_mem, ARK_ILL_INPUT, __LINE__, __func__, __FILE__, + "Unknown method type"); + return (ARK_ILL_INPUT); + } + + /* Retrieve/store method and embedding orders now that tables are finalized */ + step_mem->stages = step_mem->MRIC->stages; + step_mem->q = ark_mem->hadapt_mem->q = step_mem->MRIC->q; + step_mem->p = ark_mem->hadapt_mem->p = step_mem->MRIC->p; + + /* Ensure that if adaptivity or error accumulation is enabled, then + method includes embedding coefficients */ + if ((!ark_mem->fixedstep || (ark_mem->AccumErrorType != ARK_ACCUMERROR_NONE)) && + (step_mem->p <= 0)) + { + arkProcessError(ark_mem, ARK_ILL_INPUT, __LINE__, __func__, + __FILE__, "Temporal error estimation cannot be performed without embedding coefficients"); + return (ARK_ILL_INPUT); + } + /* allocate/fill derived quantities from MRIC structure */ /* stage map */ @@ -954,7 +1037,7 @@ int mriStep_Init(ARKodeMem ark_mem, int init_type) free(step_mem->stagetypes); ark_mem->liw -= step_mem->stages; } - step_mem->stagetypes = (int*)calloc(step_mem->MRIC->stages, + step_mem->stagetypes = (int*)calloc(step_mem->MRIC->stages + 1, sizeof(*step_mem->stagetypes)); if (step_mem->stagetypes == NULL) { @@ -962,8 +1045,8 @@ int mriStep_Init(ARKodeMem ark_mem, int init_type) MSG_ARK_MEM_FAIL); return (ARK_MEM_FAIL); } - ark_mem->liw += step_mem->MRIC->stages; - for (j = 0; j < step_mem->MRIC->stages; j++) + ark_mem->liw += (step_mem->MRIC->stages + 1); + for (j = 0; j <= step_mem->MRIC->stages; j++) { step_mem->stagetypes[j] = mriStepCoupling_GetStageType(step_mem->MRIC, j); } @@ -1011,9 +1094,9 @@ int mriStep_Init(ARKodeMem ark_mem, int init_type) free(step_mem->Xvecs); ark_mem->liw -= step_mem->nfusedopvecs; } - step_mem->nfusedopvecs = 2 * step_mem->MRIC->stages + 2; - step_mem->cvals = (sunrealtype*)calloc(step_mem->nfusedopvecs, - sizeof(*step_mem->cvals)); + step_mem->nfusedopvecs = 2 * step_mem->MRIC->stages + 2 + step_mem->nforcing; + step_mem->cvals = (sunrealtype*)calloc(step_mem->nfusedopvecs, + sizeof(*step_mem->cvals)); if (step_mem->cvals == NULL) { arkProcessError(ark_mem, ARK_MEM_FAIL, __LINE__, __func__, __FILE__, @@ -1037,6 +1120,16 @@ int mriStep_Init(ARKodeMem ark_mem, int init_type) step_mem->q = step_mem->MRIC->q; step_mem->p = step_mem->MRIC->p; + /* If an MRISR method is applied to a non-ImEx problem, we "unify" + the Fse and Fsi vectors to point at the same memory */ + step_mem->unify_Fs = SUNFALSE; + if ((step_mem->MRIC->type == MRISTEP_SR) && + ((step_mem->explicit_rhs && !step_mem->implicit_rhs) || + (!step_mem->explicit_rhs && step_mem->implicit_rhs))) + { + step_mem->unify_Fs = SUNTRUE; + } + /* Allocate MRI RHS vector memory, update storage requirements */ /* Allocate Fse[0] ... Fse[nstages_active - 1] and */ /* Fsi[0] ... Fsi[nstages_active - 1] if needed */ @@ -1049,15 +1142,17 @@ int mriStep_Init(ARKodeMem ark_mem, int init_type) arkFreeVecArray(step_mem->nstages_allocated, &(step_mem->Fse), ark_mem->lrw1, &(ark_mem->lrw), ark_mem->liw1, &(ark_mem->liw)); + if (step_mem->unify_Fs) { step_mem->Fsi = NULL; } } if (step_mem->implicit_rhs) { arkFreeVecArray(step_mem->nstages_allocated, &(step_mem->Fsi), ark_mem->lrw1, &(ark_mem->lrw), ark_mem->liw1, &(ark_mem->liw)); + if (step_mem->unify_Fs) { step_mem->Fse = NULL; } } } - if (step_mem->explicit_rhs) + if (step_mem->explicit_rhs && !step_mem->unify_Fs) { if (!arkAllocVecArray(step_mem->nstages_active, ark_mem->ewt, &(step_mem->Fse), ark_mem->lrw1, &(ark_mem->lrw), @@ -1066,7 +1161,7 @@ int mriStep_Init(ARKodeMem ark_mem, int init_type) return (ARK_MEM_FAIL); } } - if (step_mem->implicit_rhs) + if (step_mem->implicit_rhs && !step_mem->unify_Fs) { if (!arkAllocVecArray(step_mem->nstages_active, ark_mem->ewt, &(step_mem->Fsi), ark_mem->lrw1, &(ark_mem->lrw), @@ -1075,6 +1170,17 @@ int mriStep_Init(ARKodeMem ark_mem, int init_type) return (ARK_MEM_FAIL); } } + if (step_mem->unify_Fs) + { + if (!arkAllocVecArray(step_mem->nstages_active, ark_mem->ewt, + &(step_mem->Fse), ark_mem->lrw1, &(ark_mem->lrw), + ark_mem->liw1, &(ark_mem->liw))) + { + return (ARK_MEM_FAIL); + } + step_mem->Fsi = step_mem->Fse; + } + step_mem->nstages_allocated = step_mem->nstages_active; } @@ -1168,43 +1274,119 @@ int mriStep_Init(ARKodeMem ark_mem, int init_type) } } - return (ARK_SUCCESS); -} + /*** Perform timestep adaptivity checks and initial setup ***/ -/*------------------------------------------------------------------------------ - mriStep_FullRHS: + /* get timestep adaptivity type */ + adapt_type = SUNAdaptController_GetType(ark_mem->hadapt_mem->hcontroller); - This is just a wrapper to call the user-supplied RHS functions, - f(t,y) = fse(t,y) + fsi(t,y) + ff(t,y). + if (ark_mem->fixedstep) + { + /* Fixed step sizes: user must supply the initial step size */ + if (ark_mem->hin == ZERO) + { + arkProcessError(ark_mem, ARK_ILL_INPUT, __LINE__, __func__, + __FILE__, "Timestep adaptivity disabled, but missing user-defined fixed stepsize"); + return (ARK_ILL_INPUT); + } + } + else + { + /* ensure that a compatible adaptivity controller is provided */ + if ((adapt_type != SUN_ADAPTCONTROLLER_MRI_H_TOL) && + (adapt_type != SUN_ADAPTCONTROLLER_H)) + { + arkProcessError(ark_mem, ARK_ILL_INPUT, __LINE__, __func__, __FILE__, + "SUNAdaptController type is unsupported by MRIStep"); + return (ARK_ILL_INPUT); + } - This will be called in one of three 'modes': + /* Controller provides adaptivity (at least at the slow time scale): + - verify that the MRI method includes an embedding, and + - estimate initial slow step size (store in ark_mem->hin) */ + if (step_mem->MRIC->p <= 0) + { + arkProcessError(ark_mem, ARK_ILL_INPUT, __LINE__, __func__, + __FILE__, "Timestep adaptivity enabled, but non-embedded MRI table specified"); + return (ARK_ILL_INPUT); + } + if (ark_mem->hin == ZERO) + { + /* tempv1 = fslow(t0, y0) */ + if (mriStep_SlowRHS(ark_mem, ark_mem->tcur, ark_mem->yn, ark_mem->tempv1, + ARK_FULLRHS_START) != ARK_SUCCESS) + { + arkProcessError(ark_mem, ARK_RHSFUNC_FAIL, __LINE__, __func__, __FILE__, + "error calling slow RHS function(s)"); + return (ARK_RHSFUNC_FAIL); + } + retval = mriStep_Hin(ark_mem, ark_mem->tcur, tout, ark_mem->tempv1, + &(ark_mem->hin)); + if (retval != ARK_SUCCESS) + { + retval = arkHandleFailure(ark_mem, retval); + return (retval); + } + } + } - ARK_FULLRHS_START -> called at the beginning of a simulation i.e., at - (tn, yn) = (t0, y0) or (tR, yR) + /* Perform additional setup for (H,tol) controller */ + if (adapt_type == SUN_ADAPTCONTROLLER_MRI_H_TOL) + { + /* Verify that adaptivity type is supported by inner stepper */ + if (!mriStepInnerStepper_SupportsRTolAdaptivity(step_mem->stepper)) + { + arkProcessError(ark_mem, ARK_ILL_INPUT, __LINE__, __func__, + __FILE__, "MRI H-TOL SUNAdaptController provided, but unsupported by inner stepper"); + return (ARK_ILL_INPUT); + } - ARK_FULLRHS_END -> called at the end of a successful step i.e, at - (tcur, ycur) or the start of the subsequent step i.e., - at (tn, yn) = (tcur, ycur) from the end of the last - step + /* initialize fast stepper to use the same relative tolerance as MRIStep */ + step_mem->inner_rtol_factor = ONE; + } - ARK_FULLRHS_OTHER -> called elsewhere (e.g. for dense output) + return (ARK_SUCCESS); +} - If this function is called in ARK_FULLRHS_START or ARK_FULLRHS_END mode and - evaluating the RHS functions is necessary, we store the vectors fse(t,y) and - fsi(t,y) in Fse[0] and Fsi[0] for possible reuse in the first stage of the - subsequent time step. +/*------------------------------------------------------------------------------ + mriStep_FullRHS: - ARK_FULLRHS_OTHER mode is only called for dense output in-between steps, or - when estimating the initial time step size, so we strive to store the - intermediate parts so that they do not interfere with the other two modes. + This is just a wrapper to call the user-supplied RHS functions, + f(t,y) = fse(t,y) + fsi(t,y) + ff(t,y). - Presently ff(t,y) is always called with ARK_FULLRHS_OTHER mode. + Note: this relies on the utility routine mriStep_UpdateF0 to update Fse[0] + and Fsi[0] as appropriate (i.e., leveraging previous evaluations, etc.), and + merely combines the resulting values together with ff to construct the output. + + However, in ARK_FULLRHS_OTHER mode, this routine must call all slow RHS + functions directly, since that mode cannot reuse internally stored values. + + ARK_FULLRHS_OTHER -> called in the following circumstances: + (a) when estimating the initial time step size, + (b) for high-order dense output with the Hermite + interpolation module, + (c) by an "outer" stepper when MRIStep is used as an + inner solver), or + (d) when a high-order implicit predictor is requested from + the Hermite interpolation module within the time step + t_{n} \to t_{n+1}. + + While instances (a)-(c) will occur in-between MRIStep time + steps, instance (d) can occur at the start of each internal + MRIStep stage. Since the (t,y) input does not correspond + to an "official" time step, thus the RHS functions should + always be evaluated, and the values should *not* be stored + anywhere that will interfere with other reused MRIStep data + from one stage to the next (but it may use nonlinear solver + scratch space). + + Note that this routine always calls the fast RHS function, ff(t,y), in + ARK_FULLRHS_OTHER mode. ----------------------------------------------------------------------------*/ int mriStep_FullRHS(ARKodeMem ark_mem, sunrealtype t, N_Vector y, N_Vector f, int mode) { ARKodeMRIStepMem step_mem; - int retval; + int nvec, retval; /* access ARKodeMRIStepMem structure */ retval = mriStep_AccessStepMem(ark_mem, __func__, &step_mem); @@ -1213,124 +1395,48 @@ int mriStep_FullRHS(ARKodeMem ark_mem, sunrealtype t, N_Vector y, N_Vector f, /* ensure that inner stepper provides fullrhs function */ if (!(step_mem->stepper->ops->fullrhs)) { - arkProcessError(ark_mem, ARK_ILL_INPUT, __LINE__, __func__, __FILE__, + arkProcessError(ark_mem, ARK_RHSFUNC_FAIL, __LINE__, __func__, __FILE__, MSG_ARK_MISSING_FULLRHS); - return ARK_ILL_INPUT; + return ARK_RHSFUNC_FAIL; } /* perform RHS functions contingent on 'mode' argument */ switch (mode) { case ARK_FULLRHS_START: + case ARK_FULLRHS_END: - /* compute the full RHS */ - if (!(ark_mem->fn_is_current)) - { - /* compute the explicit component */ - if (step_mem->explicit_rhs) - { - retval = step_mem->fse(t, y, step_mem->Fse[0], ark_mem->user_data); - step_mem->nfse++; - if (retval != 0) - { - arkProcessError(ark_mem, ARK_RHSFUNC_FAIL, __LINE__, __func__, - __FILE__, MSG_ARK_RHSFUNC_FAILED, t); - return (ARK_RHSFUNC_FAIL); - } - } - - /* compute the implicit component */ - if (step_mem->implicit_rhs) - { - retval = step_mem->fsi(t, y, step_mem->Fsi[0], ark_mem->user_data); - step_mem->nfsi++; - if (retval != 0) - { - arkProcessError(ark_mem, ARK_RHSFUNC_FAIL, __LINE__, __func__, - __FILE__, MSG_ARK_RHSFUNC_FAILED, t); - return (ARK_RHSFUNC_FAIL); - } - } - - /* compute the fast component (force new RHS computation) */ - retval = mriStepInnerStepper_FullRhs(step_mem->stepper, t, y, f, - ARK_FULLRHS_OTHER); - if (retval != ARK_SUCCESS) - { - arkProcessError(ark_mem, ARK_RHSFUNC_FAIL, __LINE__, __func__, __FILE__, - MSG_ARK_RHSFUNC_FAILED, t); - return (ARK_RHSFUNC_FAIL); - } - } - - /* combine RHS vectors into output */ - if (step_mem->explicit_rhs && step_mem->implicit_rhs) - { - /* ImEx */ - N_VLinearSum(ONE, step_mem->Fse[0], ONE, f, f); - N_VLinearSum(ONE, step_mem->Fsi[0], ONE, f, f); - } - else if (step_mem->implicit_rhs) - { - /* implicit */ - N_VLinearSum(ONE, step_mem->Fsi[0], ONE, f, f); - } - else + /* update the internal storage for Fse[0] and Fsi[0] */ + retval = mriStep_UpdateF0(ark_mem, step_mem, t, y, mode); + if (retval != 0) { - /* explicit */ - N_VLinearSum(ONE, step_mem->Fse[0], ONE, f, f); + arkProcessError(ark_mem, ARK_RHSFUNC_FAIL, __LINE__, __func__, __FILE__, + MSG_ARK_RHSFUNC_FAILED, t); + return (ARK_RHSFUNC_FAIL); } - break; - - case ARK_FULLRHS_END: - - /* compute the full RHS */ - if (!(ark_mem->fn_is_current)) + /* evaluate fast component */ + retval = mriStepInnerStepper_FullRhs(step_mem->stepper, t, y, f, + ARK_FULLRHS_OTHER); + if (retval != ARK_SUCCESS) { - /* compute the explicit component */ - if (step_mem->explicit_rhs) - { - retval = step_mem->fse(t, y, step_mem->Fse[0], ark_mem->user_data); - step_mem->nfse++; - if (retval != 0) - { - arkProcessError(ark_mem, ARK_RHSFUNC_FAIL, __LINE__, __func__, - __FILE__, MSG_ARK_RHSFUNC_FAILED, t); - return (ARK_RHSFUNC_FAIL); - } - } - - /* compute the implicit component */ - if (step_mem->implicit_rhs) - { - retval = step_mem->fsi(t, y, step_mem->Fsi[0], ark_mem->user_data); - step_mem->nfsi++; - if (retval != 0) - { - arkProcessError(ark_mem, ARK_RHSFUNC_FAIL, __LINE__, __func__, - __FILE__, MSG_ARK_RHSFUNC_FAILED, t); - return (ARK_RHSFUNC_FAIL); - } - } - - /* compute the fast component (force new RHS computation) */ - retval = mriStepInnerStepper_FullRhs(step_mem->stepper, t, y, f, - ARK_FULLRHS_OTHER); - if (retval != ARK_SUCCESS) - { - arkProcessError(ark_mem, ARK_RHSFUNC_FAIL, __LINE__, __func__, __FILE__, - MSG_ARK_RHSFUNC_FAILED, t); - return (ARK_RHSFUNC_FAIL); - } + arkProcessError(ark_mem, ARK_RHSFUNC_FAIL, __LINE__, __func__, __FILE__, + MSG_ARK_RHSFUNC_FAILED, t); + return (ARK_RHSFUNC_FAIL); } /* combine RHS vectors into output */ if (step_mem->explicit_rhs && step_mem->implicit_rhs) { /* ImEx */ - N_VLinearSum(ONE, step_mem->Fse[0], ONE, f, f); - N_VLinearSum(ONE, step_mem->Fsi[0], ONE, f, f); + step_mem->cvals[0] = ONE; + step_mem->Xvecs[0] = f; + step_mem->cvals[1] = ONE; + step_mem->Xvecs[1] = step_mem->Fse[0]; + step_mem->cvals[2] = ONE; + step_mem->Xvecs[2] = step_mem->Fsi[0]; + nvec = 3; + N_VLinearCombination(nvec, step_mem->cvals, step_mem->Xvecs, f); } else if (step_mem->implicit_rhs) { @@ -1347,6 +1453,20 @@ int mriStep_FullRHS(ARKodeMem ark_mem, sunrealtype t, N_Vector y, N_Vector f, case ARK_FULLRHS_OTHER: + /* compute the fast component (force new RHS computation) */ + nvec = 0; + retval = mriStepInnerStepper_FullRhs(step_mem->stepper, t, y, f, + ARK_FULLRHS_OTHER); + if (retval != ARK_SUCCESS) + { + arkProcessError(ark_mem, ARK_RHSFUNC_FAIL, __LINE__, __func__, __FILE__, + MSG_ARK_RHSFUNC_FAILED, t); + return (ARK_RHSFUNC_FAIL); + } + step_mem->cvals[nvec] = ONE; + step_mem->Xvecs[nvec] = f; + nvec++; + /* compute the explicit component and store in ark_tempv2 */ if (step_mem->explicit_rhs) { @@ -1358,6 +1478,9 @@ int mriStep_FullRHS(ARKodeMem ark_mem, sunrealtype t, N_Vector y, N_Vector f, MSG_ARK_RHSFUNC_FAILED, t); return (ARK_RHSFUNC_FAIL); } + step_mem->cvals[nvec] = ONE; + step_mem->Xvecs[nvec] = ark_mem->tempv2; + nvec++; } /* compute the implicit component and store in sdata */ @@ -1371,35 +1494,19 @@ int mriStep_FullRHS(ARKodeMem ark_mem, sunrealtype t, N_Vector y, N_Vector f, MSG_ARK_RHSFUNC_FAILED, t); return (ARK_RHSFUNC_FAIL); } + step_mem->cvals[nvec] = ONE; + step_mem->Xvecs[nvec] = step_mem->sdata; + nvec++; } - /* compute the fast component (force new RHS computation) */ - retval = mriStepInnerStepper_FullRhs(step_mem->stepper, t, y, f, - ARK_FULLRHS_OTHER); - if (retval != ARK_SUCCESS) + /* Add external forcing components to linear combination */ + if (step_mem->expforcing || step_mem->impforcing) { - arkProcessError(ark_mem, ARK_RHSFUNC_FAIL, __LINE__, __func__, __FILE__, - MSG_ARK_RHSFUNC_FAILED, t); - return (ARK_RHSFUNC_FAIL); + mriStep_ApplyForcing(step_mem, t, ONE, &nvec); } /* combine RHS vectors into output */ - if (step_mem->explicit_rhs && step_mem->implicit_rhs) - { - /* ImEx */ - N_VLinearSum(ONE, ark_mem->tempv2, ONE, f, f); - N_VLinearSum(ONE, step_mem->sdata, ONE, f, f); - } - else if (step_mem->implicit_rhs) - { - /* implicit */ - N_VLinearSum(ONE, step_mem->sdata, ONE, f, f); - } - else - { - /* explicit */ - N_VLinearSum(ONE, ark_mem->tempv2, ONE, f, f); - } + N_VLinearCombination(nvec, step_mem->cvals, step_mem->Xvecs, f); break; @@ -1413,227 +1520,1451 @@ int mriStep_FullRHS(ARKodeMem ark_mem, sunrealtype t, N_Vector y, N_Vector f, return (ARK_SUCCESS); } -/*--------------------------------------------------------------- - mriStep_TakeStep: +/*------------------------------------------------------------------------------ + mriStep_UpdateF0: + + This routine is called by mriStep_FullRHS to update the internal storage for + Fse[0] and Fsi[0], incorporating forcing from a slower time scale as necessary. + This supports the ARK_FULLRHS_START and ARK_FULLRHS_END "mode" values + provided to mriStep_FullRHS, and contains all internal logic regarding whether + RHS functions must be called, versus if the relevant data can just be copied. + + ARK_FULLRHS_START -> called in the following circumstances: + (a) at the beginning of a simulation i.e., at + (tn, yn) = (t0, y0) or (tR, yR), or + (b) when transitioning between time steps t_{n-1} + \to t_{n} to fill f_{n-1} within the Hermite + interpolation module. + + In each case, we may check the fn_is_current flag to + know whether ARKODE believes the values stored in + Fse[0] and Fsi[0] are up-to-date, allowing us to copy + those values instead of recomputing. MRIStep + additionally stores internal fse_is_current and + fsi_is_current flags to denote whether it + additionally believes recomputation is necessary -- + this is because unlike ARKStep and ERKStep, when + MRIStep is used as an inner stepper for an outer + MRIStep calculation, it must store any forcing terms + *inside* its own values of one of Fse or Fsi (to + avoid a combinatorial explosion of separate forcing + vectors when used in a telescopic MRI calculation). + For whichever of Fse[0] and Fsi[0] are deemed not + current, the corresponding RHS function is + recomputed and stored in Fe[0] and/or Fi[0] for + reuse later, before copying the values into the + output vector. + + ARK_FULLRHS_END -> called in the following circumstances: + (a) when temporal root-finding is enabled, this will be + called in-between steps t_{n-1} \to t_{n} to fill f_{n}, + (b) when high-order dense output is requested from the + Hermite interpolation module in-between steps t_{n-1} + \to t_{n} to fill f_{n}, or + (c) when an implicit predictor is requested from the Hermite + interpolation module within the time step t_{n} \to + t_{n+1}, in which case f_{n} needs to be filled. + + Again, we may check the fn_is_current flags to know whether + ARKODE believes that the values stored in Fse[0] and Fsi[0] + are up-to-date, and may just be copied. We also again + verify the ability to copy by viewing the MRIStep-specific + fse_is_current and fsi_is_current flags. If one or both of + Fse[0] and Fsi[0] are determined to be not current. In all + other cases, the RHS should be recomputed and stored in + Fse[0] and Fsi[0] for reuse later, before copying the + values into the output vector. - This routine serves the primary purpose of the MRIStep module: - it performs a single MRI step (with embedding, if possible). + ----------------------------------------------------------------------------*/ +int mriStep_UpdateF0(ARKodeMem ark_mem, ARKodeMRIStepMem step_mem, + sunrealtype t, N_Vector y, int mode) +{ + int nvec, retval; - The output variable dsmPtr should contain estimate of the - weighted local error if an embedding is present; otherwise it - should be 0. + /* perform RHS functions contingent on 'mode' argument */ + switch (mode) + { + case ARK_FULLRHS_START: - The input/output variable nflagPtr is used to gauge convergence - of any algebraic solvers within the step. At the start of a new - time step, this will initially have the value FIRST_CALL. On - return from this function, nflagPtr should have a value: - 0 => algebraic solve completed successfully - >0 => solve did not converge at this step size - (but may with a smaller stepsize) - <0 => solve encountered an unrecoverable failure + /* update the RHS components */ - The return value from this routine is: - 0 => step completed successfully - >0 => step encountered recoverable failure; - reduce step and retry (if possible) - <0 => step encountered unrecoverable failure + /* explicit component */ + if (step_mem->explicit_rhs) + { + /* if either ARKODE or MRIStep consider Fse[0] stale, then recompute */ + if (!step_mem->fse_is_current || !ark_mem->fn_is_current) + { + retval = step_mem->fse(t, y, step_mem->Fse[0], ark_mem->user_data); + step_mem->nfse++; + if (retval != 0) + { + arkProcessError(ark_mem, ARK_RHSFUNC_FAIL, __LINE__, __func__, + __FILE__, MSG_ARK_RHSFUNC_FAILED, t); + return (ARK_RHSFUNC_FAIL); + } + step_mem->fse_is_current = SUNTRUE; + + /* Add external forcing, if applicable */ + if (step_mem->expforcing) + { + step_mem->cvals[0] = ONE; + step_mem->Xvecs[0] = step_mem->Fse[0]; + nvec = 1; + mriStep_ApplyForcing(step_mem, t, ONE, &nvec); + N_VLinearCombination(nvec, step_mem->cvals, step_mem->Xvecs, + step_mem->Fse[0]); + } + } + } + + /* implicit component */ + if (step_mem->implicit_rhs) + { + /* if either ARKODE or MRIStep consider Fsi[0] stale, then recompute */ + if (!step_mem->fsi_is_current || !ark_mem->fn_is_current) + { + retval = step_mem->fsi(t, y, step_mem->Fsi[0], ark_mem->user_data); + step_mem->nfsi++; + if (retval != 0) + { + arkProcessError(ark_mem, ARK_RHSFUNC_FAIL, __LINE__, __func__, + __FILE__, MSG_ARK_RHSFUNC_FAILED, t); + return (ARK_RHSFUNC_FAIL); + } + step_mem->fsi_is_current = SUNTRUE; + + /* Add external forcing, if applicable */ + if (step_mem->impforcing) + { + step_mem->cvals[0] = ONE; + step_mem->Xvecs[0] = step_mem->Fsi[0]; + nvec = 1; + mriStep_ApplyForcing(step_mem, t, ONE, &nvec); + N_VLinearCombination(nvec, step_mem->cvals, step_mem->Xvecs, + step_mem->Fsi[0]); + } + } + } + + break; + + case ARK_FULLRHS_END: + + /* compute the full RHS */ + if (!(ark_mem->fn_is_current)) + { + /* compute the explicit component */ + if (step_mem->explicit_rhs) + { + retval = step_mem->fse(t, y, step_mem->Fse[0], ark_mem->user_data); + step_mem->nfse++; + if (retval != 0) + { + arkProcessError(ark_mem, ARK_RHSFUNC_FAIL, __LINE__, __func__, + __FILE__, MSG_ARK_RHSFUNC_FAILED, t); + return (ARK_RHSFUNC_FAIL); + } + step_mem->fse_is_current = SUNTRUE; + + /* Add external forcing, as appropriate */ + if (step_mem->expforcing) + { + step_mem->cvals[0] = ONE; + step_mem->Xvecs[0] = step_mem->Fse[0]; + nvec = 1; + mriStep_ApplyForcing(step_mem, t, ONE, &nvec); + N_VLinearCombination(nvec, step_mem->cvals, step_mem->Xvecs, + step_mem->Fse[0]); + } + } + + /* compute the implicit component */ + if (step_mem->implicit_rhs) + { + retval = step_mem->fsi(t, y, step_mem->Fsi[0], ark_mem->user_data); + step_mem->nfsi++; + if (retval != 0) + { + arkProcessError(ark_mem, ARK_RHSFUNC_FAIL, __LINE__, __func__, + __FILE__, MSG_ARK_RHSFUNC_FAILED, t); + return (ARK_RHSFUNC_FAIL); + } + step_mem->fsi_is_current = SUNTRUE; + + /* Add external forcing, as appropriate */ + if (step_mem->impforcing) + { + step_mem->cvals[0] = ONE; + step_mem->Xvecs[0] = step_mem->Fsi[0]; + nvec = 1; + mriStep_ApplyForcing(step_mem, t, ONE, &nvec); + N_VLinearCombination(nvec, step_mem->cvals, step_mem->Xvecs, + step_mem->Fsi[0]); + } + } + } + + break; + + default: + /* return with RHS failure if unknown mode is requested */ + arkProcessError(ark_mem, ARK_RHSFUNC_FAIL, __LINE__, __func__, __FILE__, + "Unknown full RHS mode"); + return (ARK_RHSFUNC_FAIL); + } + + return (ARK_SUCCESS); +} + +/*--------------------------------------------------------------- + mriStep_TakeStepMRIGARK: + + This routine serves the primary purpose of the MRIStep module: + it performs a single MRI step (with embedding, if possible). + + The vector ark_mem->yn holds the previous time-step solution + on input, and the vector ark_mem->ycur should hold the result + of this step on output. + + If timestep adaptivity is enabled, this routine also computes + the error estimate y-ytilde, where ytilde is the + embedded solution, and the norm weights come from ark_ewt. + This estimate is stored in ark_mem->tempv1, in case the calling + routine wishes to examine the error locations. + + The output variable dsmPtr should contain a scalar-valued + estimate of the temporal error from this step, ||y-ytilde||_WRMS + if timestep adaptivity is enabled; otherwise it should be 0. + + The input/output variable nflagPtr is used to gauge convergence + of any algebraic solvers within the step. At the start of a new + time step, this will initially have the value FIRST_CALL. On + return from this function, nflagPtr should have a value: + 0 => algebraic solve completed successfully + >0 => solve did not converge at this step size + (but may with a smaller stepsize) + <0 => solve encountered an unrecoverable failure + Since the fast-scale evolution could be considered a different + type of "algebraic solver", we similarly report any fast-scale + evolution error as a recoverable nflagPtr value. + + The return value from this routine is: + 0 => step completed successfully + >0 => step encountered recoverable failure; + reduce step and retry (if possible) + <0 => step encountered unrecoverable failure + ---------------------------------------------------------------*/ +int mriStep_TakeStepMRIGARK(ARKodeMem ark_mem, sunrealtype* dsmPtr, int* nflagPtr) +{ + ARKodeMRIStepMem step_mem; /* outer stepper memory */ + int is; /* current stage index */ + int retval; /* reusable return flag */ + N_Vector tmp; /* N_Vector pointer */ + SUNAdaptController_Type adapt_type; /* timestep adaptivity type */ + sunrealtype t0, tf; /* start/end of each stage */ + sunbooleantype calc_fslow; + sunbooleantype need_inner_dsm; + sunbooleantype do_embedding; + sunbooleantype nested_mri; + int nvec; + + /* access the MRIStep mem structure */ + retval = mriStep_AccessStepMem(ark_mem, __func__, &step_mem); + if (retval != ARK_SUCCESS) { return (retval); } + + /* initialize algebraic solver convergence flag to success; + error estimate to zero */ + *nflagPtr = ARK_SUCCESS; + *dsmPtr = ZERO; + + /* determine whether embedding stage is needed */ + do_embedding = !ark_mem->fixedstep || + (ark_mem->AccumErrorType != ARK_ACCUMERROR_NONE); + + /* if MRI adaptivity is enabled: reset fast accumulated error, + and send appropriate control parameter to the fast integrator */ + adapt_type = SUNAdaptController_GetType(ark_mem->hadapt_mem->hcontroller); + need_inner_dsm = SUNFALSE; + if (adapt_type == SUN_ADAPTCONTROLLER_MRI_H_TOL) + { + need_inner_dsm = SUNTRUE; + step_mem->inner_dsm = ZERO; + retval = mriStepInnerStepper_ResetAccumulatedError(step_mem->stepper); + if (retval != ARK_SUCCESS) + { + arkProcessError(ark_mem, ARK_INNERSTEP_FAIL, __LINE__, __func__, __FILE__, + "Unable to reset the inner stepper error estimate"); + return (ARK_INNERSTEP_FAIL); + } + retval = mriStepInnerStepper_SetRTol(step_mem->stepper, + step_mem->inner_rtol_factor * + ark_mem->reltol); + if (retval != ARK_SUCCESS) + { + arkProcessError(ark_mem, ARK_INNERSTEP_FAIL, __LINE__, __func__, __FILE__, + "Unable to set the inner stepper tolerance"); + return (ARK_INNERSTEP_FAIL); + } + } + + /* for adaptive computations, reset the inner integrator to the beginning of this step */ + if (!ark_mem->fixedstep) + { + retval = mriStepInnerStepper_Reset(step_mem->stepper, ark_mem->tn, + ark_mem->yn); + if (retval != ARK_SUCCESS) + { + arkProcessError(ark_mem, ARK_INNERSTEP_FAIL, __LINE__, __func__, __FILE__, + "Unable to reset the inner stepper"); + return (ARK_INNERSTEP_FAIL); + } + } + + /* call nonlinear solver setup if it exists */ + if (step_mem->NLS) + { + if ((step_mem->NLS)->ops->setup) + { + N_VConst(ZERO, ark_mem->tempv3); /* set guess to 0 */ + retval = SUNNonlinSolSetup(step_mem->NLS, ark_mem->tempv3, ark_mem); + if (retval < 0) { return (ARK_NLS_SETUP_FAIL); } + if (retval > 0) { return (ARK_NLS_SETUP_RECVR); } + } + } + + /* Evaluate the slow RHS functions if needed. NOTE: we decide between calling the + full RHS function (if ark_mem->fn is non-NULL and MRIStep is not an inner + integrator) versus just updating the stored values of Fse[0] and Fsi[0]. In + either case, we use ARK_FULLRHS_START mode because MRIGARK methods do not + evaluate the RHS functions at the end of the time step (so nothing can be + leveraged). */ + nested_mri = step_mem->expforcing || step_mem->impforcing; + if (ark_mem->fn == NULL || nested_mri) + { + retval = mriStep_UpdateF0(ark_mem, step_mem, ark_mem->tn, ark_mem->yn, + ARK_FULLRHS_START); + if (retval) { return ARK_RHSFUNC_FAIL; } + + /* For a nested MRI configuration we might still need fn to create a predictor + but it should be fn only for the current nesting level which is why we use + UpdateF0 in this case rather than FullRHS */ + if (ark_mem->fn != NULL && nested_mri && step_mem->implicit_rhs) + { + if (step_mem->implicit_rhs && step_mem->explicit_rhs) + { + N_VLinearSum(ONE, step_mem->Fsi[0], ONE, step_mem->Fse[0], ark_mem->fn); + } + else { N_VScale(ONE, step_mem->Fsi[0], ark_mem->fn); } + } + } + else if (ark_mem->fn != NULL && !ark_mem->fn_is_current) + { + retval = mriStep_FullRHS(ark_mem, ark_mem->tn, ark_mem->yn, ark_mem->fn, + ARK_FULLRHS_START); + if (retval) { return ARK_RHSFUNC_FAIL; } + } + ark_mem->fn_is_current = SUNTRUE; + +#ifdef SUNDIALS_DEBUG + printf(" MRIStep step %li, stage 0, h = %" RSYM ", t_n = %" RSYM "\n", + ark_mem->nst, ark_mem->h, ark_mem->tn); +#endif + +#ifdef SUNDIALS_LOGGING_EXTRA_DEBUG + SUNLogger_QueueMsg(ARK_LOGGER, SUN_LOGLEVEL_DEBUG, "ARKODE::mriStep_TakeStep", + "slow stage", "z_0(:) =", ""); + N_VPrintFile(ark_mem->ycur, ARK_LOGGER->debug_fp); + + if (step_mem->explicit_rhs) + { + SUNLogger_QueueMsg(ARK_LOGGER, SUN_LOGLEVEL_DEBUG, "ARKODE::mriStep_TakeStep", + "slow explicit RHS", "Fse_0(:) =", ""); + N_VPrintFile(step_mem->Fse[0], ARK_LOGGER->debug_fp); + } + if (step_mem->implicit_rhs) + { + SUNLogger_QueueMsg(ARK_LOGGER, SUN_LOGLEVEL_DEBUG, "ARKODE::mriStep_TakeStep", + "slow implicit RHS", "Fsi_0(:) =", ""); + N_VPrintFile(step_mem->Fsi[0], ARK_LOGGER->debug_fp); + } +#endif + + /* The first stage is the previous time-step solution, so its RHS + is the [already-computed] slow RHS from the start of the step */ + + /* Loop over remaining internal stages */ + for (is = 1; is < step_mem->stages - 1; is++) + { + /* Set relevant stage times (including desired stage time for implicit solves) */ + t0 = ark_mem->tn + step_mem->MRIC->c[is - 1] * ark_mem->h; + tf = ark_mem->tcur = ark_mem->tn + step_mem->MRIC->c[is] * ark_mem->h; + + /* Solver diagnostics reporting */ +#if SUNDIALS_LOGGING_LEVEL >= SUNDIALS_LOGGING_DEBUG + SUNLogger_QueueMsg(ARK_LOGGER, SUN_LOGLEVEL_DEBUG, + "ARKODE::mriStep_TakeStep", "start-stage", + "step = %li, stage = %i, stage type = %d, h = %" RSYM + ", tcur = %" RSYM, + ark_mem->nst, is, step_mem->stagetypes[is], ark_mem->h, + ark_mem->tcur); +#endif + + /* Determine current stage type, and call corresponding routine; the + vector ark_mem->ycur stores the previous stage solution on input, and + should store the result of this stage solution on output. */ + switch (step_mem->stagetypes[is]) + { + case (MRISTAGE_ERK_FAST): + retval = mriStep_ComputeInnerForcing(ark_mem, step_mem, is, t0, tf); + if (retval != ARK_SUCCESS) { return retval; } + retval = mriStep_StageERKFast(ark_mem, step_mem, t0, tf, ark_mem->ycur, + ark_mem->tempv2, need_inner_dsm); + if (retval != ARK_SUCCESS) { *nflagPtr = CONV_FAIL; } + break; + case (MRISTAGE_ERK_NOFAST): + retval = mriStep_StageERKNoFast(ark_mem, step_mem, is); + break; + case (MRISTAGE_DIRK_NOFAST): + retval = mriStep_StageDIRKNoFast(ark_mem, step_mem, is, nflagPtr); + break; + case (MRISTAGE_DIRK_FAST): + retval = mriStep_StageDIRKFast(ark_mem, step_mem, is, nflagPtr); + break; + case (MRISTAGE_STIFF_ACC): retval = ARK_SUCCESS; break; + } + if (retval != ARK_SUCCESS) { return retval; } + +#ifdef SUNDIALS_LOGGING_EXTRA_DEBUG + SUNLogger_QueueMsg(ARK_LOGGER, SUN_LOGLEVEL_DEBUG, + "ARKODE::mriStep_TakeStep", "slow stage", "z_%i(:) =", is); + N_VPrintFile(ark_mem->ycur, ARK_LOGGER->debug_fp); +#endif + + /* apply user-supplied stage postprocessing function (if supplied) */ + if ((ark_mem->ProcessStage != NULL) && + (step_mem->stagetypes[is] != MRISTAGE_STIFF_ACC)) + { + retval = ark_mem->ProcessStage(ark_mem->tcur, ark_mem->ycur, + ark_mem->user_data); + if (retval != 0) { return (ARK_POSTPROCESS_STAGE_FAIL); } + } + + /* conditionally reset the inner integrator with the modified stage solution */ + if (step_mem->stagetypes[is] != MRISTAGE_STIFF_ACC) + { + if ((step_mem->stagetypes[is] != MRISTAGE_ERK_FAST) || + (ark_mem->ProcessStage != NULL)) + { + retval = mriStepInnerStepper_Reset(step_mem->stepper, tf, ark_mem->ycur); + if (retval != ARK_SUCCESS) + { + arkProcessError(ark_mem, ARK_INNERSTEP_FAIL, __LINE__, __func__, + __FILE__, "Unable to reset the inner stepper"); + return (ARK_INNERSTEP_FAIL); + } + } + } + + /* Compute updated slow RHS, except: + 1. if the stage is excluded from stage_map + 2. if the next stage has "STIFF_ACC" type, and temporal estimation is disabled */ + calc_fslow = SUNTRUE; + if (step_mem->stage_map[is] == -1) { calc_fslow = SUNFALSE; } + if (!do_embedding && (step_mem->stagetypes[is + 1] == MRISTAGE_STIFF_ACC)) + { + calc_fslow = SUNFALSE; + } + if (calc_fslow) + { + /* store explicit slow rhs */ + if (step_mem->explicit_rhs) + { + retval = step_mem->fse(ark_mem->tcur, ark_mem->ycur, + step_mem->Fse[step_mem->stage_map[is]], + ark_mem->user_data); + step_mem->nfse++; + if (retval < 0) { return (ARK_RHSFUNC_FAIL); } + if (retval > 0) { return (ARK_UNREC_RHSFUNC_ERR); } + + /* Add external forcing to Fse, if applicable */ + if (step_mem->expforcing) + { + step_mem->cvals[0] = ONE; + step_mem->Xvecs[0] = step_mem->Fse[step_mem->stage_map[is]]; + nvec = 1; + mriStep_ApplyForcing(step_mem, tf, ONE, &nvec); + N_VLinearCombination(nvec, step_mem->cvals, step_mem->Xvecs, + step_mem->Fse[step_mem->stage_map[is]]); + } + +#ifdef SUNDIALS_LOGGING_EXTRA_DEBUG + SUNLogger_QueueMsg(ARK_LOGGER, SUN_LOGLEVEL_DEBUG, + "ARKODE::mriStep_TakeStep", "slow explicit RHS", + "Fse_%i(:) =", is); + N_VPrintFile(step_mem->Fse[step_mem->stage_map[is]], + ARK_LOGGER->debug_fp); +#endif + } + + /* store implicit slow rhs */ + if (step_mem->implicit_rhs) + { + if (!step_mem->deduce_rhs || + (step_mem->stagetypes[is] != MRISTAGE_DIRK_NOFAST)) + { + retval = step_mem->fsi(ark_mem->tcur, ark_mem->ycur, + step_mem->Fsi[step_mem->stage_map[is]], + ark_mem->user_data); + step_mem->nfsi++; + + /* Add external forcing to Fsi, if applicable */ + if (step_mem->impforcing) + { + step_mem->cvals[0] = ONE; + step_mem->Xvecs[0] = step_mem->Fsi[step_mem->stage_map[is]]; + nvec = 1; + mriStep_ApplyForcing(step_mem, tf, ONE, &nvec); + N_VLinearCombination(nvec, step_mem->cvals, step_mem->Xvecs, + step_mem->Fsi[step_mem->stage_map[is]]); + } + } + else + { + N_VLinearSum(ONE / step_mem->gamma, step_mem->zcor, + -ONE / step_mem->gamma, step_mem->sdata, + step_mem->Fsi[step_mem->stage_map[is]]); + } + + if (retval < 0) { return (ARK_RHSFUNC_FAIL); } + if (retval > 0) { return (ARK_UNREC_RHSFUNC_ERR); } + +#ifdef SUNDIALS_LOGGING_EXTRA_DEBUG + SUNLogger_QueueMsg(ARK_LOGGER, SUN_LOGLEVEL_DEBUG, + "ARKODE::mriStep_TakeStep", "slow implicit RHS", + "Fsi_%i(:) =", is); + N_VPrintFile(step_mem->Fsi[step_mem->stage_map[is]], + ARK_LOGGER->debug_fp); +#endif + } + } /* compute slow RHS */ + } /* loop over stages */ + + /* perform embedded stage (if needed) */ + if (do_embedding) + { + is = step_mem->stages; + + /* Temporarily swap ark_mem->ycur and ark_mem->tempv4 pointers, copying + data so that both hold the current ark_mem->ycur value. This ensures + that during this embedding "stage": + - ark_mem->ycur will be the correct initial condition for the final stage. + - ark_mem->tempv4 will hold the embedded solution vector. */ + N_VScale(ONE, ark_mem->ycur, ark_mem->tempv4); + tmp = ark_mem->ycur; + ark_mem->ycur = ark_mem->tempv4; + ark_mem->tempv4 = tmp; + + /* Reset ark_mem->tcur as the time value corresponding with the end of the step */ + /* Set relevant stage times (including desired stage time for implicit solves) */ + t0 = ark_mem->tn + step_mem->MRIC->c[is - 2] * ark_mem->h; + tf = ark_mem->tcur = ark_mem->tn + ark_mem->h; + + /* Solver diagnostics reporting */ +#if SUNDIALS_LOGGING_LEVEL >= SUNDIALS_LOGGING_DEBUG + SUNLogger_QueueMsg(ARK_LOGGER, SUN_LOGLEVEL_DEBUG, + "ARKODE::mriStep_TakeStep", "embedding-stage", + "step = %li, stage = %i, stage type = %d, h = %" RSYM + ", tcur = %" RSYM, + ark_mem->nst, is, step_mem->stagetypes[is], ark_mem->h, + ark_mem->tcur); +#endif + + /* Determine embedding stage type, and call corresponding routine; the + vector ark_mem->ycur stores the previous stage solution on input, and + should store the result of this stage solution on output. */ + switch (step_mem->stagetypes[is]) + { + case (MRISTAGE_ERK_FAST): + retval = mriStep_ComputeInnerForcing(ark_mem, step_mem, is, t0, tf); + if (retval != ARK_SUCCESS) { return retval; } + retval = mriStep_StageERKFast(ark_mem, step_mem, t0, tf, ark_mem->ycur, + ark_mem->tempv2, SUNFALSE); + if (retval != ARK_SUCCESS) { *nflagPtr = CONV_FAIL; } + break; + case (MRISTAGE_ERK_NOFAST): + retval = mriStep_StageERKNoFast(ark_mem, step_mem, is); + break; + case (MRISTAGE_DIRK_NOFAST): + retval = mriStep_StageDIRKNoFast(ark_mem, step_mem, is, nflagPtr); + break; + case (MRISTAGE_DIRK_FAST): + retval = mriStep_StageDIRKFast(ark_mem, step_mem, is, nflagPtr); + break; + } + if (retval != ARK_SUCCESS) { return retval; } + +#ifdef SUNDIALS_LOGGING_EXTRA_DEBUG + SUNLogger_QueueMsg(ARK_LOGGER, SUN_LOGLEVEL_DEBUG, "ARKODE::mriStep_TakeStep", + "embedded solution", "ytilde(:) =", ""); + N_VPrintFile(ark_mem->ycur, ARK_LOGGER->debug_fp); +#endif + + /* Swap back ark_mem->ycur with ark_mem->tempv4, and reset the inner integrator */ + tmp = ark_mem->ycur; + ark_mem->ycur = ark_mem->tempv4; + ark_mem->tempv4 = tmp; + retval = mriStepInnerStepper_Reset(step_mem->stepper, t0, ark_mem->ycur); + if (retval != ARK_SUCCESS) + { + arkProcessError(ark_mem, ARK_INNERSTEP_FAIL, __LINE__, __func__, __FILE__, + "Unable to reset the inner stepper"); + return (ARK_INNERSTEP_FAIL); + } + } + + /* Compute final stage (for evolved solution), along with error estimate */ + { + is = step_mem->stages - 1; + + /* Set relevant stage times (including desired stage time for implicit solves) */ + t0 = ark_mem->tn + step_mem->MRIC->c[is - 1] * ark_mem->h; + tf = ark_mem->tcur = ark_mem->tn + ark_mem->h; + + /* Solver diagnostics reporting */ +#if SUNDIALS_LOGGING_LEVEL >= SUNDIALS_LOGGING_DEBUG + SUNLogger_QueueMsg(ARK_LOGGER, SUN_LOGLEVEL_DEBUG, + "ARKODE::mriStep_TakeStep", "start-stage", + "step = %li, stage = %i, stage type = %d, h = %" RSYM + ", tcur = %" RSYM, + ark_mem->nst, is, step_mem->stagetypes[is], ark_mem->h, + ark_mem->tcur); +#endif + + /* Determine final stage type, and call corresponding routine; the + vector ark_mem->ycur stores the previous stage solution on input, and + should store the result of this stage solution on output. */ + switch (step_mem->stagetypes[is]) + { + case (MRISTAGE_ERK_FAST): + retval = mriStep_ComputeInnerForcing(ark_mem, step_mem, is, t0, tf); + if (retval != ARK_SUCCESS) { return retval; } + retval = mriStep_StageERKFast(ark_mem, step_mem, t0, tf, ark_mem->ycur, + ark_mem->tempv2, need_inner_dsm); + if (retval != ARK_SUCCESS) { *nflagPtr = CONV_FAIL; } + break; + case (MRISTAGE_ERK_NOFAST): + retval = mriStep_StageERKNoFast(ark_mem, step_mem, is); + break; + case (MRISTAGE_DIRK_NOFAST): + retval = mriStep_StageDIRKNoFast(ark_mem, step_mem, is, nflagPtr); + break; + case (MRISTAGE_DIRK_FAST): + retval = mriStep_StageDIRKFast(ark_mem, step_mem, is, nflagPtr); + break; + case (MRISTAGE_STIFF_ACC): retval = ARK_SUCCESS; break; + } + if (retval != ARK_SUCCESS) { return retval; } + +#ifdef SUNDIALS_LOGGING_EXTRA_DEBUG + SUNLogger_QueueMsg(ARK_LOGGER, SUN_LOGLEVEL_DEBUG, + "ARKODE::mriStep_TakeStep", "slow stage", "z_%i(:) =", is); + N_VPrintFile(ark_mem->ycur, ARK_LOGGER->debug_fp); +#endif + + /* apply user-supplied stage postprocessing function (if supplied) */ + if ((ark_mem->ProcessStage != NULL) && + (step_mem->stagetypes[is] != MRISTAGE_STIFF_ACC)) + { + retval = ark_mem->ProcessStage(ark_mem->tcur, ark_mem->ycur, + ark_mem->user_data); + if (retval != 0) { return (ARK_POSTPROCESS_STAGE_FAIL); } + } + + /* conditionally reset the inner integrator with the modified stage solution */ + if (step_mem->stagetypes[is] != MRISTAGE_STIFF_ACC) + { + if ((step_mem->stagetypes[is] != MRISTAGE_ERK_FAST) || + (ark_mem->ProcessStage != NULL)) + { + retval = mriStepInnerStepper_Reset(step_mem->stepper, tf, ark_mem->ycur); + if (retval != ARK_SUCCESS) + { + arkProcessError(ark_mem, ARK_INNERSTEP_FAIL, __LINE__, __func__, + __FILE__, "Unable to reset the inner stepper"); + return (ARK_INNERSTEP_FAIL); + } + } + } + + /* Compute temporal error estimate via difference between step + solution and embedding, store in ark_mem->tempv1, and take norm. */ + if (do_embedding) + { + N_VLinearSum(ONE, ark_mem->tempv4, -ONE, ark_mem->ycur, ark_mem->tempv1); + *dsmPtr = N_VWrmsNorm(ark_mem->tempv1, ark_mem->ewt); + } + + } /* loop over stages */ + + /* Solver diagnostics reporting */ +#ifdef SUNDIALS_LOGGING_EXTRA_DEBUG + SUNLogger_QueueMsg(ARK_LOGGER, SUN_LOGLEVEL_DEBUG, "ARKODE::mriStep_TakeStep", + "updated solution", "ycur(:) =", ""); + N_VPrintFile(ark_mem->ycur, ARK_LOGGER->debug_fp); +#endif +#if SUNDIALS_LOGGING_LEVEL >= SUNDIALS_LOGGING_DEBUG + SUNLogger_QueueMsg(ARK_LOGGER, SUN_LOGLEVEL_DEBUG, "ARKODE::mriStep_TakeStep", + "error-test", "step = %li, h = %" RSYM ", dsm = %" RSYM, + ark_mem->nst, ark_mem->h, *dsmPtr); +#endif + + return (ARK_SUCCESS); +} + +/*--------------------------------------------------------------- + mriStep_TakeStepMRISR: + + This routine performs a single MRISR step. + + The vector ark_mem->yn holds the previous time-step solution + on input, and the vector ark_mem->ycur should hold the result + of this step on output. + + If timestep adaptivity is enabled, this routine also computes + the error estimate y-ytilde, where ytilde is the + embedded solution, and the norm weights come from ark_ewt. + This estimate is stored in ark_mem->tempv1, in case the calling + routine wishes to examine the error locations. + + The output variable dsmPtr should contain a scalar-valued + estimate of the temporal error from this step, ||y-ytilde||_WRMS + if timestep adaptivity is enabled; otherwise it should be 0. + + The input/output variable nflagPtr is used to gauge convergence + of any algebraic solvers within the step. At the start of a new + time step, this will initially have the value FIRST_CALL. On + return from this function, nflagPtr should have a value: + 0 => algebraic solve completed successfully + >0 => solve did not converge at this step size + (but may with a smaller stepsize) + <0 => solve encountered an unrecoverable failure + Since the fast-scale evolution could be considered a different + type of "algebraic solver", we similarly report any fast-scale + evolution error as a recoverable nflagPtr value. + + The return value from this routine is: + 0 => step completed successfully + >0 => step encountered recoverable failure; + reduce step and retry (if possible) + <0 => step encountered unrecoverable failure + ---------------------------------------------------------------*/ +int mriStep_TakeStepMRISR(ARKodeMem ark_mem, sunrealtype* dsmPtr, int* nflagPtr) +{ + ARKodeMRIStepMem step_mem; /* outer stepper memory */ + int stage, j; /* stage indices */ + int retval; /* reusable return flag */ + N_Vector ytilde; /* embedded solution */ + N_Vector ytemp; /* temporary vector */ + SUNAdaptController_Type adapt_type; /* timestep adaptivity type */ + sunbooleantype embedding; /* flag indicating embedding */ + sunbooleantype solution; /* or solution stages */ + sunbooleantype impl_corr; /* is slow correct. implicit? */ + sunrealtype cstage; /* current stage abscissa */ + sunbooleantype need_inner_dsm; + sunbooleantype nested_mri; + int nvec, max_stages; + const sunrealtype tol = SUN_RCONST(100.0) * SUN_UNIT_ROUNDOFF; + + /* access the MRIStep mem structure */ + retval = mriStep_AccessStepMem(ark_mem, __func__, &step_mem); + if (retval != ARK_SUCCESS) { return (retval); } + + /* initialize algebraic solver convergence flag to success; + error estimate to zero */ + *nflagPtr = ARK_SUCCESS; + *dsmPtr = ZERO; + + /* set N_Vector shortcuts */ + ytilde = ark_mem->tempv4; + ytemp = ark_mem->tempv2; + + /* if MRI adaptivity is enabled: reset fast accumulated error, + and send appropriate control parameter to the fast integrator */ + adapt_type = SUNAdaptController_GetType(ark_mem->hadapt_mem->hcontroller); + need_inner_dsm = SUNFALSE; + if (adapt_type == SUN_ADAPTCONTROLLER_MRI_H_TOL) + { + need_inner_dsm = SUNTRUE; + step_mem->inner_dsm = ZERO; + retval = mriStepInnerStepper_ResetAccumulatedError(step_mem->stepper); + if (retval != ARK_SUCCESS) + { + arkProcessError(ark_mem, ARK_INNERSTEP_FAIL, __LINE__, __func__, __FILE__, + "Unable to reset the inner stepper error estimate"); + return (ARK_INNERSTEP_FAIL); + } + retval = mriStepInnerStepper_SetRTol(step_mem->stepper, + step_mem->inner_rtol_factor * + ark_mem->reltol); + if (retval != ARK_SUCCESS) + { + arkProcessError(ark_mem, ARK_INNERSTEP_FAIL, __LINE__, __func__, __FILE__, + "Unable to set the inner stepper tolerance"); + return (ARK_INNERSTEP_FAIL); + } + } + + /* for adaptive computations, reset the inner integrator to the beginning of this step */ + if (!ark_mem->fixedstep) + { + retval = mriStepInnerStepper_Reset(step_mem->stepper, ark_mem->tn, + ark_mem->yn); + if (retval != ARK_SUCCESS) + { + arkProcessError(ark_mem, ARK_INNERSTEP_FAIL, __LINE__, __func__, __FILE__, + "Unable to reset the inner stepper"); + return (ARK_INNERSTEP_FAIL); + } + } + + /* Evaluate the slow RHS functions if needed. NOTE: we decide between calling the + full RHS function (if ark_mem->fn is non-NULL and MRIStep is not an inner + integrator) versus just updating the stored values of Fse[0] and Fsi[0]. In + either case, we use ARK_FULLRHS_START mode because MRISR methods do not + evaluate the RHS functions at the end of the time step (so nothing can be + leveraged). */ + nested_mri = step_mem->expforcing || step_mem->impforcing; + if (ark_mem->fn == NULL || nested_mri) + { + retval = mriStep_UpdateF0(ark_mem, step_mem, ark_mem->tn, ark_mem->yn, + ARK_FULLRHS_START); + if (retval) { return ARK_RHSFUNC_FAIL; } + + /* For a nested MRI configuration we might still need fn to create a predictor + but it should be fn only for the current nesting level which is why we use + UpdateF0 in this case rather than FullRHS */ + if (ark_mem->fn != NULL && nested_mri && step_mem->implicit_rhs) + { + if (step_mem->implicit_rhs && step_mem->explicit_rhs) + { + N_VLinearSum(ONE, step_mem->Fsi[0], ONE, step_mem->Fse[0], ark_mem->fn); + } + else { N_VScale(ONE, step_mem->Fsi[0], ark_mem->fn); } + } + } + if (ark_mem->fn != NULL && !ark_mem->fn_is_current) + { + retval = mriStep_FullRHS(ark_mem, ark_mem->tn, ark_mem->yn, ark_mem->fn, + ARK_FULLRHS_START); + if (retval) { return ARK_RHSFUNC_FAIL; } + } + ark_mem->fn_is_current = SUNTRUE; + + /* combine both RHS into FSE for ImEx problems, since MRISR fast forcing function + only depends on Omega coefficients */ + if (step_mem->implicit_rhs && step_mem->explicit_rhs) + { + N_VLinearSum(ONE, step_mem->Fse[0], ONE, step_mem->Fsi[0], step_mem->Fse[0]); + } + +#ifdef SUNDIALS_DEBUG + printf(" MRIStep step %li, stage 0, h = %" RSYM ", t_n = %" RSYM "\n", + ark_mem->nst, ark_mem->h, ark_mem->tn); +#endif + +#ifdef SUNDIALS_LOGGING_EXTRA_DEBUG + SUNLogger_QueueMsg(ARK_LOGGER, SUN_LOGLEVEL_DEBUG, "ARKODE::mriStep_TakeStep", + "slow stage", "z_0(:) =", ""); + N_VPrintFile(ark_mem->yn, ARK_LOGGER->debug_fp); + + if (step_mem->explicit_rhs) + { + SUNLogger_QueueMsg(ARK_LOGGER, SUN_LOGLEVEL_DEBUG, "ARKODE::mriStep_TakeStep", + "slow explicit RHS", "Fse_0(:) =", ""); + N_VPrintFile(step_mem->Fse[0], ARK_LOGGER->debug_fp); + } + + if (step_mem->implicit_rhs) + { + SUNLogger_QueueMsg(ARK_LOGGER, SUN_LOGLEVEL_DEBUG, "ARKODE::mriStep_TakeStep", + "slow implicit RHS", "Fsi_0(:) =", ""); + N_VPrintFile(step_mem->Fsi[0], ARK_LOGGER->debug_fp); + } +#endif + + /* The first stage is the previous time-step solution, so its RHS + is the [already-computed] slow RHS from the start of the step */ + + /* Determine how many stages will be needed */ + max_stages = (ark_mem->fixedstep && + (ark_mem->AccumErrorType == ARK_ACCUMERROR_NONE)) + ? step_mem->stages + : step_mem->stages + 1; + + /* Loop over stages */ + for (stage = 1; stage < max_stages; stage++) + { + /* Solver diagnostics reporting */ +#if SUNDIALS_LOGGING_LEVEL >= SUNDIALS_LOGGING_DEBUG + SUNLogger_QueueMsg(ARK_LOGGER, SUN_LOGLEVEL_DEBUG, "ARKODE::mriStep_TakeStep", + "start-stage", "step = %li, stage = %i, h = %" RSYM, + ark_mem->nst, stage, ark_mem->h); +#endif + + /* Determine if this is an "embedding" or "solution" stage */ + solution = (stage == step_mem->stages - 1); + embedding = (stage == step_mem->stages); + + /* Set initial condition for this stage */ + N_VScale(ONE, ark_mem->yn, ark_mem->ycur); + + /* Set current stage abscissa */ + cstage = (embedding) ? ONE : step_mem->MRIC->c[stage]; + + /* Compute forcing function for inner solver */ + retval = mriStep_ComputeInnerForcing(ark_mem, step_mem, stage, ark_mem->tn, + ark_mem->tn + cstage * ark_mem->h); + if (retval != ARK_SUCCESS) { return retval; } + + /* Reset the inner stepper on all but the first stage due to + "stage-restart" structure */ + if (stage > 1) + { + retval = mriStepInnerStepper_Reset(step_mem->stepper, ark_mem->tn, + ark_mem->ycur); + if (retval != ARK_SUCCESS) + { + arkProcessError(ark_mem, ARK_INNERSTEP_FAIL, __LINE__, __func__, + __FILE__, "Unable to reset the inner stepper"); + return (ARK_INNERSTEP_FAIL); + } + } + + /* Evolve fast IVP for this stage, potentially get inner dsm on + all non-embedding stages */ + retval = mriStep_StageERKFast(ark_mem, step_mem, ark_mem->tn, + ark_mem->tn + cstage * ark_mem->h, + ark_mem->ycur, ytemp, + need_inner_dsm && !embedding); + if (retval != ARK_SUCCESS) + { + *nflagPtr = CONV_FAIL; + return retval; + } + + /* set current stage time for implicit correction, postprocessing + and RHS calls */ + ark_mem->tcur = ark_mem->tn + cstage * ark_mem->h; + + /* perform MRISR slow/implicit correction */ + impl_corr = SUNFALSE; + if (step_mem->implicit_rhs) + { + /* determine whether implicit RHS correction will require an implicit solve */ + impl_corr = SUNRabs(step_mem->MRIC->G[0][stage][stage]) > tol; + + /* perform implicit solve for correction */ + if (impl_corr) + { + /* store current stage index (for an "embedded" stage, subtract 1) */ + step_mem->istage = (stage == step_mem->stages) ? stage - 1 : stage; + + /* Call predictor for current stage solution (result placed in zpred) */ + retval = mriStep_Predict(ark_mem, step_mem->istage, step_mem->zpred); + if (retval != ARK_SUCCESS) { return (retval); } + + /* If a user-supplied predictor routine is provided, call that here + Note that mriStep_Predict is *still* called, so this user-supplied + routine can just "clean up" the built-in prediction, if desired. */ + if (step_mem->stage_predict) + { + retval = step_mem->stage_predict(ark_mem->tcur, step_mem->zpred, + ark_mem->user_data); + if (retval < 0) { return (ARK_USER_PREDICT_FAIL); } + if (retval > 0) { return (TRY_AGAIN); } + } + +#ifdef SUNDIALS_LOGGING_EXTRA_DEBUG + SUNLogger_QueueMsg(ARK_LOGGER, SUN_LOGLEVEL_DEBUG, + "ARKODE::mriStep_TakeStep", "predictor", + "zpred(:) =", ""); + N_VPrintFile(step_mem->zpred, ARK_LOGGER->debug_fp); +#endif + + /* fill sdata with explicit contributions to correction */ + step_mem->cvals[0] = ONE; + step_mem->Xvecs[0] = ark_mem->ycur; + step_mem->cvals[1] = -ONE; + step_mem->Xvecs[1] = step_mem->zpred; + for (j = 0; j < stage; j++) + { + step_mem->cvals[j + 2] = ark_mem->h * step_mem->MRIC->G[0][stage][j]; + step_mem->Xvecs[j + 2] = step_mem->Fsi[j]; + } + retval = N_VLinearCombination(stage + 2, step_mem->cvals, + step_mem->Xvecs, step_mem->sdata); + if (retval != 0) { return (ARK_VECTOROP_ERR); } + +#ifdef SUNDIALS_LOGGING_EXTRA_DEBUG + SUNLogger_QueueMsg(ARK_LOGGER, SUN_LOGLEVEL_DEBUG, + "ARKODE::mriStep_TakeStep", "rhs data", + "sdata(:) =", ""); + N_VPrintFile(step_mem->sdata, ARK_LOGGER->debug_fp); +#endif + + /* Update gamma for implicit solver */ + step_mem->gamma = ark_mem->h * step_mem->MRIC->G[0][stage][stage]; + if (ark_mem->firststage) { step_mem->gammap = step_mem->gamma; } + step_mem->gamrat = + (ark_mem->firststage) ? ONE : step_mem->gamma / step_mem->gammap; + + /* perform implicit solve (result is stored in ark_mem->ycur); return + with positive value on anything but success */ + *nflagPtr = mriStep_Nls(ark_mem, *nflagPtr); + if (*nflagPtr != ARK_SUCCESS) { return (TRY_AGAIN); } + } + /* perform explicit update for correction */ + else + { + step_mem->cvals[0] = ONE; + step_mem->Xvecs[0] = ark_mem->ycur; + for (j = 0; j < stage; j++) + { + step_mem->cvals[j + 1] = ark_mem->h * step_mem->MRIC->G[0][stage][j]; + step_mem->Xvecs[j + 1] = step_mem->Fsi[j]; + } + retval = N_VLinearCombination(stage + 1, step_mem->cvals, + step_mem->Xvecs, ark_mem->ycur); + if (retval != 0) { return (ARK_VECTOROP_ERR); } + } + } + +#ifdef SUNDIALS_LOGGING_EXTRA_DEBUG + SUNLogger_QueueMsg(ARK_LOGGER, SUN_LOGLEVEL_DEBUG, "ARKODE::mriStep_TakeStep", + "slow stage", "z_%i(:) =", stage); + N_VPrintFile(ark_mem->ycur, ARK_LOGGER->debug_fp); +#endif + + /* apply user-supplied stage postprocessing function (if supplied), + and reset the inner integrator with the modified stage solution */ + if (ark_mem->ProcessStage != NULL) + { + retval = ark_mem->ProcessStage(ark_mem->tcur, ark_mem->ycur, + ark_mem->user_data); + if (retval != 0) { return (ARK_POSTPROCESS_STAGE_FAIL); } + retval = mriStepInnerStepper_Reset(step_mem->stepper, ark_mem->tcur, + ark_mem->ycur); + if (retval != ARK_SUCCESS) + { + arkProcessError(ark_mem, ARK_INNERSTEP_FAIL, __LINE__, __func__, + __FILE__, "Unable to reset the inner stepper"); + return (ARK_INNERSTEP_FAIL); + } + } + + /* Compute updated slow RHS (except for final solution or embedding) */ + if ((!solution) && (!embedding)) + { + /* store explicit slow rhs */ + if (step_mem->explicit_rhs) + { + retval = step_mem->fse(ark_mem->tcur, ark_mem->ycur, + step_mem->Fse[stage], ark_mem->user_data); + step_mem->nfse++; + if (retval < 0) { return (ARK_RHSFUNC_FAIL); } + if (retval > 0) { return (ARK_UNREC_RHSFUNC_ERR); } + + /* Add external forcing to Fse[stage], if applicable */ + if (step_mem->expforcing) + { + step_mem->cvals[0] = ONE; + step_mem->Xvecs[0] = step_mem->Fse[stage]; + nvec = 1; + mriStep_ApplyForcing(step_mem, ark_mem->tcur, ONE, &nvec); + N_VLinearCombination(nvec, step_mem->cvals, step_mem->Xvecs, + step_mem->Fse[stage]); + } + +#ifdef SUNDIALS_LOGGING_EXTRA_DEBUG + SUNLogger_QueueMsg(ARK_LOGGER, SUN_LOGLEVEL_DEBUG, + "ARKODE::mriStep_TakeStep", "slow explicit RHS", + "Fse_%i(:) =", stage); + N_VPrintFile(step_mem->Fse[stage], ARK_LOGGER->debug_fp); +#endif + } + + /* store implicit slow rhs */ + if (step_mem->implicit_rhs) + { + if (!step_mem->deduce_rhs || !impl_corr) + { + retval = step_mem->fsi(ark_mem->tcur, ark_mem->ycur, + step_mem->Fsi[stage], ark_mem->user_data); + step_mem->nfsi++; + + /* Add external forcing to Fsi[stage], if applicable */ + if (step_mem->impforcing) + { + step_mem->cvals[0] = ONE; + step_mem->Xvecs[0] = step_mem->Fsi[stage]; + nvec = 1; + mriStep_ApplyForcing(step_mem, ark_mem->tcur, ONE, &nvec); + N_VLinearCombination(nvec, step_mem->cvals, step_mem->Xvecs, + step_mem->Fsi[stage]); + } + } + else + { + N_VLinearSum(ONE / step_mem->gamma, step_mem->zcor, + -ONE / step_mem->gamma, step_mem->sdata, + step_mem->Fsi[stage]); + } + + if (retval < 0) { return (ARK_RHSFUNC_FAIL); } + if (retval > 0) { return (ARK_UNREC_RHSFUNC_ERR); } + +#ifdef SUNDIALS_LOGGING_EXTRA_DEBUG + SUNLogger_QueueMsg(ARK_LOGGER, SUN_LOGLEVEL_DEBUG, + "ARKODE::mriStep_TakeStep", "slow implicit RHS", + "Fsi_%i(:) =", stage); + N_VPrintFile(step_mem->Fsi[stage], ARK_LOGGER->debug_fp); +#endif + } + + /* combine both RHS into Fse for ImEx problems since + fast forcing function only depends on Omega coefficients */ + if (step_mem->implicit_rhs && step_mem->explicit_rhs) + { + N_VLinearSum(ONE, step_mem->Fse[stage], ONE, step_mem->Fsi[stage], + step_mem->Fse[stage]); + } + } + + /* If this is the solution stage, archive for error estimation */ + if (solution) { N_VScale(ONE, ark_mem->ycur, ytilde); } + + } /* loop over stages */ + +#ifdef SUNDIALS_LOGGING_EXTRA_DEBUG + SUNLogger_QueueMsg(ARK_LOGGER, SUN_LOGLEVEL_DEBUG, "ARKODE::mriStep_TakeStep", + "updated solution", "ycur(:) =", ""); + N_VPrintFile(ark_mem->ycur, ARK_LOGGER->debug_fp); +#endif + + /* if temporal error estimation is enabled: compute estimate via difference between + step solution and embedding, store in ark_mem->tempv1, store norm in dsmPtr, and + copy solution back to ycur */ + if (!ark_mem->fixedstep || (ark_mem->AccumErrorType != ARK_ACCUMERROR_NONE)) + { + N_VLinearSum(ONE, ytilde, -ONE, ark_mem->ycur, ark_mem->tempv1); + *dsmPtr = N_VWrmsNorm(ark_mem->tempv1, ark_mem->ewt); + N_VScale(ONE, ytilde, ark_mem->ycur); + } + + /* Solver diagnostics reporting */ +#if SUNDIALS_LOGGING_LEVEL >= SUNDIALS_LOGGING_DEBUG + SUNLogger_QueueMsg(ARK_LOGGER, SUN_LOGLEVEL_DEBUG, "ARKODE::mriStep_TakeStep", + "end-step", + "step = %li, t = %" RSYM ", h = %" RSYM ", dsm = %" RSYM, + ark_mem->nst, ark_mem->tn, ark_mem->h, *dsmPtr); +#endif + + return (ARK_SUCCESS); +} + +/*--------------------------------------------------------------- + mriStep_TakeStepMERK: + + This routine performs a single MERK step. + + The vector ark_mem->yn holds the previous time-step solution + on input, and the vector ark_mem->ycur should hold the result + of this step on output. + + If timestep adaptivity is enabled, this routine also computes + the error estimate y-ytilde, where ytilde is the + embedded solution, and the norm weights come from ark_ewt. + This estimate is stored in ark_mem->tempv1, in case the calling + routine wishes to examine the error locations. + + The output variable dsmPtr should contain a scalar-valued + estimate of the temporal error from this step, ||y-ytilde||_WRMS + if timestep adaptivity is enabled; otherwise it should be 0. + + The input/output variable nflagPtr is used to gauge convergence + of any algebraic solvers within the step. At the start of a new + time step, this will initially have the value FIRST_CALL. On + return from this function, nflagPtr should have a value: + 0 => algebraic solve completed successfully + >0 => solve did not converge at this step size + (but may with a smaller stepsize) + <0 => solve encountered an unrecoverable failure + Since the fast-scale evolution could be considered a different + type of "algebraic solver", we similarly report any fast-scale + evolution error as a recoverable nflagPtr value. + + The return value from this routine is: + 0 => step completed successfully + >0 => step encountered recoverable failure; + reduce step and retry (if possible) + <0 => step encountered unrecoverable failure ---------------------------------------------------------------*/ -int mriStep_TakeStep(ARKodeMem ark_mem, sunrealtype* dsmPtr, int* nflagPtr) +int mriStep_TakeStepMERK(ARKodeMem ark_mem, sunrealtype* dsmPtr, int* nflagPtr) { - ARKodeMRIStepMem step_mem; /* outer stepper memory */ - int is; /* current stage index */ - int retval; /* reusable return flag */ + ARKodeMRIStepMem step_mem; /* outer stepper memory */ + int ig; /* current stage group index */ + int is; /* stage index in group */ + int stage, nextstage; /* current/next stages */ + int retval; /* reusable return flag */ + N_Vector ytilde; /* embedded solution */ + N_Vector ytemp; /* temporary vector */ + SUNAdaptController_Type adapt_type; /* timestep adaptivity type */ + sunrealtype t0, tf; /* start/end of each stage */ + sunbooleantype embedding; /* flag indicating embedding */ + sunbooleantype solution; /* or solution stages */ + sunrealtype cstage; /* current stage abscissa */ + sunbooleantype need_inner_dsm; + sunbooleantype nested_mri; + int nvec; + + /* access the MRIStep mem structure */ + retval = mriStep_AccessStepMem(ark_mem, __func__, &step_mem); + if (retval != ARK_SUCCESS) { return (retval); } /* initialize algebraic solver convergence flag to success; error estimate to zero */ *nflagPtr = ARK_SUCCESS; *dsmPtr = ZERO; - /* access the MRIStep mem structure */ - retval = mriStep_AccessStepMem(ark_mem, __func__, &step_mem); - if (retval != ARK_SUCCESS) { return (retval); } + /* set N_Vector shortcuts */ + ytilde = ark_mem->tempv4; + ytemp = ark_mem->tempv2; - /* call nonlinear solver setup if it exists */ - if (step_mem->NLS) + /* initial time for step */ + t0 = ark_mem->tn; + + /* if MRI adaptivity is enabled: reset fast accumulated error, + and send appropriate control parameter to the fast integrator */ + adapt_type = SUNAdaptController_GetType(ark_mem->hadapt_mem->hcontroller); + need_inner_dsm = SUNFALSE; + if (adapt_type == SUN_ADAPTCONTROLLER_MRI_H_TOL) { - if ((step_mem->NLS)->ops->setup) + need_inner_dsm = SUNTRUE; + step_mem->inner_dsm = ZERO; + retval = mriStepInnerStepper_ResetAccumulatedError(step_mem->stepper); + if (retval != ARK_SUCCESS) { - N_VConst(ZERO, - ark_mem->tempv3); /* set guess to 0 for predictor-corrector form */ - retval = SUNNonlinSolSetup(step_mem->NLS, ark_mem->tempv3, ark_mem); - if (retval < 0) { return (ARK_NLS_SETUP_FAIL); } - if (retval > 0) { return (ARK_NLS_SETUP_RECVR); } + arkProcessError(ark_mem, ARK_INNERSTEP_FAIL, __LINE__, __func__, __FILE__, + "Unable to reset the inner stepper error estimate"); + return (ARK_INNERSTEP_FAIL); } - } - - /* Evaluate the slow RHS functions if needed. NOTE: We do not use the full RHS - function here (unlike ERKStep and ARKStep) since it does not need to check - for FSAL or SA methods and thus avoids potentially unnecessary evaluations - of the inner (fast) RHS function */ - - if (!(ark_mem->fn_is_current)) - { - /* compute the explicit component */ - if (step_mem->explicit_rhs) + retval = mriStepInnerStepper_SetRTol(step_mem->stepper, + step_mem->inner_rtol_factor * + ark_mem->reltol); + if (retval != ARK_SUCCESS) { - retval = step_mem->fse(ark_mem->tn, ark_mem->yn, step_mem->Fse[0], - ark_mem->user_data); - step_mem->nfse++; - if (retval) { return ARK_RHSFUNC_FAIL; } + arkProcessError(ark_mem, ARK_INNERSTEP_FAIL, __LINE__, __func__, __FILE__, + "Unable to set the inner stepper tolerance"); + return (ARK_INNERSTEP_FAIL); } + } - /* compute the implicit component */ - if (step_mem->implicit_rhs) + /* for adaptive computations, reset the inner integrator to the beginning of this step */ + if (!ark_mem->fixedstep) + { + retval = mriStepInnerStepper_Reset(step_mem->stepper, t0, ark_mem->yn); + if (retval != ARK_SUCCESS) { - retval = step_mem->fsi(ark_mem->tn, ark_mem->yn, step_mem->Fsi[0], - ark_mem->user_data); - step_mem->nfsi++; - if (retval) { return ARK_RHSFUNC_FAIL; } + arkProcessError(ark_mem, ARK_INNERSTEP_FAIL, __LINE__, __func__, __FILE__, + "Unable to reset the inner stepper"); + return (ARK_INNERSTEP_FAIL); } + } - ark_mem->fn_is_current = SUNTRUE; + /* Evaluate the slow RHS function if needed. NOTE: we decide between calling the + full RHS function (if ark_mem->fn is non-NULL and MRIStep is not an inner + integrator) versus just updating the stored value of Fse[0]. In either case, + we use ARK_FULLRHS_START mode because MERK methods do not evaluate Fse at the + end of the time step (so nothing can be leveraged). */ + nested_mri = step_mem->expforcing || step_mem->impforcing; + if (ark_mem->fn == NULL || nested_mri) + { + retval = mriStep_UpdateF0(ark_mem, step_mem, ark_mem->tn, ark_mem->yn, + ARK_FULLRHS_START); + if (retval) { return ARK_RHSFUNC_FAIL; } + } + if (ark_mem->fn != NULL && !ark_mem->fn_is_current) + { + retval = mriStep_FullRHS(ark_mem, ark_mem->tn, ark_mem->yn, ark_mem->fn, + ARK_FULLRHS_START); + if (retval) { return ARK_RHSFUNC_FAIL; } } + ark_mem->fn_is_current = SUNTRUE; #ifdef SUNDIALS_DEBUG printf(" MRIStep step %li, stage 0, h = %" RSYM ", t_n = %" RSYM "\n", - ark_mem->nst, ark_mem->h, ark_mem->tcur); + ark_mem->nst, ark_mem->h, t0); #endif #ifdef SUNDIALS_LOGGING_EXTRA_DEBUG SUNLogger_QueueMsg(ARK_LOGGER, SUN_LOGLEVEL_DEBUG, "ARKODE::mriStep_TakeStep", "slow stage", "z_0(:) =", ""); - N_VPrintFile(ark_mem->ycur, ARK_LOGGER->debug_fp); + N_VPrintFile(ark_mem->yn, ARK_LOGGER->debug_fp); - if (step_mem->explicit_rhs) - { - SUNLogger_QueueMsg(ARK_LOGGER, SUN_LOGLEVEL_DEBUG, "ARKODE::mriStep_TakeStep", - "slow explicit RHS", "Fse_0(:) =", ""); - N_VPrintFile(step_mem->Fse[0], ARK_LOGGER->debug_fp); - } - if (step_mem->implicit_rhs) - { - SUNLogger_QueueMsg(ARK_LOGGER, SUN_LOGLEVEL_DEBUG, "ARKODE::mriStep_TakeStep", - "slow implicit RHS", "Fsi_0(:) =", ""); - N_VPrintFile(step_mem->Fsi[0], ARK_LOGGER->debug_fp); - } + SUNLogger_QueueMsg(ARK_LOGGER, SUN_LOGLEVEL_DEBUG, "ARKODE::mriStep_TakeStep", + "slow explicit RHS", "Fse_0(:) =", ""); + N_VPrintFile(step_mem->Fse[0], ARK_LOGGER->debug_fp); #endif /* The first stage is the previous time-step solution, so its RHS is the [already-computed] slow RHS from the start of the step */ - /* Loop over remaining stages */ - for (is = 1; is < step_mem->stages; is++) + /* Loop over stage groups */ + for (ig = 0; ig < step_mem->MRIC->ngroup; ig++) { - /* Set current stage time */ - ark_mem->tcur = ark_mem->tn + step_mem->MRIC->c[is] * ark_mem->h; - /* Solver diagnostics reporting */ #if SUNDIALS_LOGGING_LEVEL >= SUNDIALS_LOGGING_DEBUG - SUNLogger_QueueMsg(ARK_LOGGER, SUN_LOGLEVEL_DEBUG, - "ARKODE::mriStep_TakeStep", "start-stage", - "step = %li, stage = %i, stage type = %d, h = %" RSYM - ", tcur = %" RSYM, - ark_mem->nst, is, step_mem->stagetypes[is], ark_mem->h, - ark_mem->tcur); + SUNLogger_QueueMsg(ARK_LOGGER, SUN_LOGLEVEL_DEBUG, "ARKODE::mriStep_TakeStep", + "start-stage", "step = %li, stage group = %i, h = %" RSYM, + ark_mem->nst, ig, ark_mem->h); #endif - /* Determine current stage type, and call corresponding routine; the - vector ark_mem->ycur stores the previous stage solution on input, and - should store the result of this stage solution on output. */ - switch (step_mem->stagetypes[is]) - { - case (MRISTAGE_ERK_FAST): - retval = mriStep_StageERKFast(ark_mem, step_mem, is); - break; - case (MRISTAGE_ERK_NOFAST): - retval = mriStep_StageERKNoFast(ark_mem, step_mem, is); - break; - case (MRISTAGE_DIRK_NOFAST): - retval = mriStep_StageDIRKNoFast(ark_mem, step_mem, is, nflagPtr); - break; - case (MRISTAGE_DIRK_FAST): - retval = mriStep_StageDIRKFast(ark_mem, step_mem, is, nflagPtr); - break; - } + /* Set up fast RHS for this stage group */ + retval = mriStep_ComputeInnerForcing(ark_mem, step_mem, + step_mem->MRIC->group[ig][0], + ark_mem->tn, ark_mem->tn + ark_mem->h); if (retval != ARK_SUCCESS) { return (retval); } -#ifdef SUNDIALS_LOGGING_EXTRA_DEBUG - SUNLogger_QueueMsg(ARK_LOGGER, SUN_LOGLEVEL_DEBUG, - "ARKODE::mriStep_TakeStep", "slow stage", "z_%i(:) =", is); - N_VPrintFile(ark_mem->ycur, ARK_LOGGER->debug_fp); -#endif - - /* apply user-supplied stage postprocessing function (if supplied) */ - if (ark_mem->ProcessStage != NULL) - { - retval = ark_mem->ProcessStage(ark_mem->tcur, ark_mem->ycur, - ark_mem->user_data); - if (retval != 0) { return (ARK_POSTPROCESS_STAGE_FAIL); } - } + /* Set initial condition for this stage group */ + N_VScale(ONE, ark_mem->yn, ark_mem->ycur); + t0 = ark_mem->tn; - /* conditionally reset the inner integrator with the modified stage solution */ - if ((step_mem->stagetypes[is] != MRISTAGE_ERK_FAST) || - (ark_mem->ProcessStage != NULL)) + /* Evolve fast IVP over each subinterval in stage group */ + for (is = 0; is < step_mem->stages; is++) { - retval = mriStepInnerStepper_Reset(step_mem->stepper, ark_mem->tcur, - ark_mem->ycur); - if (retval != ARK_SUCCESS) { return (ARK_INNERSTEP_FAIL); } - } + /* Get stage index from group; skip to the next group if + we've reached the end of this one */ + stage = step_mem->MRIC->group[ig][is]; + if (stage < 0) { break; } + nextstage = -1; + if (stage < step_mem->stages) + { + nextstage = step_mem->MRIC->group[ig][is + 1]; + } - /* Compute updated slow RHS except at last stage which is the new solution. - * The new solution RHS evaluation happens in arkCompleteStep */ - if (is < step_mem->stages - 1 && step_mem->stage_map[is] > -1) - { - /* store explicit slow rhs */ - if (step_mem->explicit_rhs) + /* Determine if this is an "embedding" or "solution" stage */ + embedding = solution = SUNFALSE; + if (ig == step_mem->MRIC->ngroup - 2) { - retval = step_mem->fse(ark_mem->tcur, ark_mem->ycur, - step_mem->Fse[step_mem->stage_map[is]], - ark_mem->user_data); - step_mem->nfse++; - if (retval < 0) { return (ARK_RHSFUNC_FAIL); } - if (retval > 0) { return (ARK_UNREC_RHSFUNC_ERR); } + if ((stage >= 0) && (nextstage < 0)) { embedding = SUNTRUE; } + } + if (ig == step_mem->MRIC->ngroup - 1) + { + if ((stage >= 0) && (nextstage < 0)) { solution = SUNTRUE; } + } -#ifdef SUNDIALS_LOGGING_EXTRA_DEBUG - SUNLogger_QueueMsg(ARK_LOGGER, SUN_LOGLEVEL_DEBUG, - "ARKODE::mriStep_TakeStep", "slow explicit RHS", - "Fse_%i(:) =", is); - N_VPrintFile(step_mem->Fse[step_mem->stage_map[is]], - ARK_LOGGER->debug_fp); -#endif + /* Skip the embedding if we're using fixed time-stepping and + temporal error estimation is disabled */ + if (ark_mem->fixedstep && embedding && + (ark_mem->AccumErrorType == ARK_ACCUMERROR_NONE)) + { + break; } - /* store implicit slow rhs */ - if (step_mem->implicit_rhs) + /* Set current stage abscissa */ + cstage = (stage >= step_mem->stages) ? ONE : step_mem->MRIC->c[stage]; + + /* Set desired output time for subinterval */ + tf = ark_mem->tn + cstage * ark_mem->h; + + /* Reset the inner stepper on the first stage within all but the + first stage group due to "stage-restart" structure */ + if ((stage > 1) && (is == 0)) { - if (!step_mem->deduce_rhs || - (step_mem->stagetypes[is] != MRISTAGE_DIRK_NOFAST)) + retval = mriStepInnerStepper_Reset(step_mem->stepper, t0, ark_mem->ycur); + if (retval != ARK_SUCCESS) { - retval = step_mem->fsi(ark_mem->tcur, ark_mem->ycur, - step_mem->Fsi[step_mem->stage_map[is]], - ark_mem->user_data); - step_mem->nfsi++; + arkProcessError(ark_mem, ARK_INNERSTEP_FAIL, __LINE__, __func__, + __FILE__, "Unable to reset the inner stepper"); + return (ARK_INNERSTEP_FAIL); } - else + } + + /* Evolve fast IVP for this stage, potentially get inner dsm on all + non-embedding stages */ + retval = mriStep_StageERKFast(ark_mem, step_mem, t0, tf, ark_mem->ycur, + ytemp, need_inner_dsm && !embedding); + if (retval != ARK_SUCCESS) + { + *nflagPtr = CONV_FAIL; + return retval; + } + + /* Update "initial time" for next stage in group */ + t0 = tf; + + /* set current stage time for postprocessing and RHS calls */ + ark_mem->tcur = tf; + +#ifdef SUNDIALS_LOGGING_EXTRA_DEBUG + SUNLogger_QueueMsg(ARK_LOGGER, SUN_LOGLEVEL_DEBUG, + "ARKODE::mriStep_TakeStep", "slow stage", + "z_%i(:) =", stage); + N_VPrintFile(ark_mem->ycur, ARK_LOGGER->debug_fp); +#endif + + /* apply user-supplied stage postprocessing function (if supplied), + and reset the inner integrator with the modified stage solution */ + if (ark_mem->ProcessStage != NULL) + { + retval = ark_mem->ProcessStage(ark_mem->tcur, ark_mem->ycur, + ark_mem->user_data); + if (retval != 0) { return (ARK_POSTPROCESS_STAGE_FAIL); } + retval = mriStepInnerStepper_Reset(step_mem->stepper, ark_mem->tcur, + ark_mem->ycur); + if (retval != ARK_SUCCESS) { - N_VLinearSum(ONE / step_mem->gamma, step_mem->zcor, - -ONE / step_mem->gamma, step_mem->sdata, - step_mem->Fsi[step_mem->stage_map[is]]); + arkProcessError(ark_mem, ARK_INNERSTEP_FAIL, __LINE__, __func__, + __FILE__, "Unable to reset the inner stepper"); + return (ARK_INNERSTEP_FAIL); } + } + /* Compute updated slow RHS (except for final solution or embedding) */ + if ((!solution) && (!embedding)) + { + /* store explicit slow rhs */ + retval = step_mem->fse(ark_mem->tcur, ark_mem->ycur, + step_mem->Fse[stage], ark_mem->user_data); + step_mem->nfse++; if (retval < 0) { return (ARK_RHSFUNC_FAIL); } if (retval > 0) { return (ARK_UNREC_RHSFUNC_ERR); } + /* Add external forcing to Fse[stage], if applicable */ + if (step_mem->expforcing) + { + step_mem->cvals[0] = ONE; + step_mem->Xvecs[0] = step_mem->Fse[stage]; + nvec = 1; + mriStep_ApplyForcing(step_mem, ark_mem->tcur, ONE, &nvec); + N_VLinearCombination(nvec, step_mem->cvals, step_mem->Xvecs, + step_mem->Fse[stage]); + } + #ifdef SUNDIALS_LOGGING_EXTRA_DEBUG SUNLogger_QueueMsg(ARK_LOGGER, SUN_LOGLEVEL_DEBUG, - "ARKODE::mriStep_TakeStep", "slow implicit RHS", - "Fsi_%i(:) =", is); - N_VPrintFile(step_mem->Fsi[step_mem->stage_map[is]], - ARK_LOGGER->debug_fp); + "ARKODE::mriStep_TakeStep", "slow explicit RHS", + "Fse_%i(:) =", is); + N_VPrintFile(step_mem->Fse[stage], ARK_LOGGER->debug_fp); #endif } - } /* compute slow RHS */ - } /* loop over stages */ + + /* If this is the embedding stage, archive solution for error estimation */ + if (embedding) { N_VScale(ONE, ark_mem->ycur, ytilde); } + + } /* loop over stages */ + + } /* loop over stage groups */ #ifdef SUNDIALS_LOGGING_EXTRA_DEBUG SUNLogger_QueueMsg(ARK_LOGGER, SUN_LOGLEVEL_DEBUG, "ARKODE::mriStep_TakeStep", @@ -1641,11 +2972,20 @@ int mriStep_TakeStep(ARKodeMem ark_mem, sunrealtype* dsmPtr, int* nflagPtr) N_VPrintFile(ark_mem->ycur, ARK_LOGGER->debug_fp); #endif + /* if temporal error estimation is enabled: compute estimate via difference between + step solution and embedding, store in ark_mem->tempv1, and store norm in dsmPtr */ + if (!ark_mem->fixedstep || (ark_mem->AccumErrorType != ARK_ACCUMERROR_NONE)) + { + N_VLinearSum(ONE, ytilde, -ONE, ark_mem->ycur, ark_mem->tempv1); + *dsmPtr = N_VWrmsNorm(ark_mem->tempv1, ark_mem->ewt); + } + /* Solver diagnostics reporting */ #if SUNDIALS_LOGGING_LEVEL >= SUNDIALS_LOGGING_DEBUG SUNLogger_QueueMsg(ARK_LOGGER, SUN_LOGLEVEL_DEBUG, "ARKODE::mriStep_TakeStep", - "error-test", "step = %li, h = %" RSYM ", dsm = %" RSYM, - ark_mem->nst, ark_mem->h, *dsmPtr); + "end-step", + "step = %li, t = %" RSYM ", h = %" RSYM ", dsm = %" RSYM, + ark_mem->nst, ark_mem->tn, ark_mem->h, *dsmPtr); #endif return (ARK_SUCCESS); @@ -1725,14 +3065,13 @@ sunbooleantype mriStep_CheckNVector(N_Vector tmpl) mriStep_SetCoupling This routine determines the MRI method to use, based on the - desired accuracy. + desired accuracy and fixed/adaptive time stepping choice. ---------------------------------------------------------------*/ int mriStep_SetCoupling(ARKodeMem ark_mem) { ARKodeMRIStepMem step_mem; sunindextype Cliw, Clrw; - int q_actual; - ARKODE_MRITableID table_id; + ARKODE_MRITableID table_id = ARKODE_MRI_NONE; /* access ARKodeMRIStepMem structure */ if (ark_mem->step_mem == NULL) @@ -1742,55 +3081,82 @@ int mriStep_SetCoupling(ARKodeMem ark_mem) return (ARK_MEM_NULL); } step_mem = (ARKodeMRIStepMem)ark_mem->step_mem; - q_actual = step_mem->q; /* if coupling has already been specified, just return */ if (step_mem->MRIC != NULL) { return (ARK_SUCCESS); } - if (q_actual < 1 || q_actual > 4) - { - arkProcessError(ark_mem, ARK_WARNING, __LINE__, __func__, __FILE__, - "No MRI method at requested order, using q=3."); - q_actual = 3; - } - /* select method based on order and type */ - - /**** ImEx methods ****/ - if (step_mem->implicit_rhs && step_mem->explicit_rhs) + if (ark_mem->fixedstep) /**** fixed-step methods ****/ { - switch (q_actual) + if (step_mem->implicit_rhs && step_mem->explicit_rhs) /**** ImEx methods ****/ { - case 1: table_id = MRISTEP_DEFAULT_IMEX_SD_1; break; - case 2: table_id = MRISTEP_DEFAULT_IMEX_SD_2; break; - case 3: table_id = MRISTEP_DEFAULT_IMEX_SD_2; break; - case 4: table_id = MRISTEP_DEFAULT_IMEX_SD_2; break; + switch (step_mem->q) + { + case 1: table_id = MRISTEP_DEFAULT_IMEX_SD_1; break; + case 2: table_id = MRISTEP_DEFAULT_IMEX_SD_2; break; + case 3: table_id = MRISTEP_DEFAULT_IMEX_SD_3; break; + case 4: table_id = MRISTEP_DEFAULT_IMEX_SD_4; break; + } } - - /**** implicit methods ****/ - } - else if (step_mem->implicit_rhs) - { - switch (q_actual) + else if (step_mem->implicit_rhs) /**** implicit methods ****/ + { + switch (step_mem->q) + { + case 1: table_id = MRISTEP_DEFAULT_IMPL_SD_1; break; + case 2: table_id = MRISTEP_DEFAULT_IMPL_SD_2; break; + case 3: table_id = MRISTEP_DEFAULT_IMPL_SD_3; break; + case 4: table_id = MRISTEP_DEFAULT_IMPL_SD_4; break; + } + } + else /**** explicit methods ****/ { - case 1: table_id = MRISTEP_DEFAULT_IMPL_SD_1; break; - case 2: table_id = MRISTEP_DEFAULT_IMPL_SD_2; break; - case 3: table_id = MRISTEP_DEFAULT_IMPL_SD_3; break; - case 4: table_id = MRISTEP_DEFAULT_IMPL_SD_4; break; + switch (step_mem->q) + { + case 1: table_id = MRISTEP_DEFAULT_EXPL_1; break; + case 2: table_id = MRISTEP_DEFAULT_EXPL_2; break; + case 3: table_id = MRISTEP_DEFAULT_EXPL_3; break; + case 4: table_id = MRISTEP_DEFAULT_EXPL_4; break; + case 5: table_id = MRISTEP_DEFAULT_EXPL_5_AD; break; + } } - - /**** explicit methods ****/ } - else + else /**** adaptive methods ****/ { - switch (q_actual) + if (step_mem->implicit_rhs && step_mem->explicit_rhs) /**** ImEx methods ****/ + { + switch (step_mem->q) + { + case 2: table_id = MRISTEP_DEFAULT_IMEX_SD_2_AD; break; + case 3: table_id = MRISTEP_DEFAULT_IMEX_SD_3_AD; break; + case 4: table_id = MRISTEP_DEFAULT_IMEX_SD_4_AD; break; + } + } + else if (step_mem->implicit_rhs) /**** implicit methods ****/ + { + switch (step_mem->q) + { + case 2: table_id = MRISTEP_DEFAULT_IMPL_SD_2; break; + case 3: table_id = MRISTEP_DEFAULT_IMPL_SD_3; break; + case 4: table_id = MRISTEP_DEFAULT_IMPL_SD_4; break; + } + } + else /**** explicit methods ****/ { - case 1: table_id = MRISTEP_DEFAULT_EXPL_1; break; - case 2: table_id = MRISTEP_DEFAULT_EXPL_2; break; - case 3: table_id = MRISTEP_DEFAULT_EXPL_3; break; - case 4: table_id = MRISTEP_DEFAULT_EXPL_4; break; + switch (step_mem->q) + { + case 2: table_id = MRISTEP_DEFAULT_EXPL_2_AD; break; + case 3: table_id = MRISTEP_DEFAULT_EXPL_3_AD; break; + case 4: table_id = MRISTEP_DEFAULT_EXPL_4_AD; break; + case 5: table_id = MRISTEP_DEFAULT_EXPL_5_AD; break; + } } } + if (table_id == ARKODE_MRI_NONE) + { + arkProcessError(ark_mem, ARK_ILL_INPUT, __LINE__, __func__, + __FILE__, "No MRI method is available for the requested configuration."); + return (ARK_ILL_INPUT); + } step_mem->MRIC = MRIStepCoupling_LoadTable(table_id); if (step_mem->MRIC == NULL) @@ -1868,8 +3234,36 @@ int mriStep_CheckCoupling(ARKodeMem ark_mem) return (ARK_INVALID_TABLE); } + /* Check that coupling table has compatible type */ + if (step_mem->implicit_rhs && step_mem->explicit_rhs && + (step_mem->MRIC->type != MRISTEP_IMEX) && + (step_mem->MRIC->type != MRISTEP_SR)) + { + arkProcessError(ark_mem, ARK_ILL_INPUT, __LINE__, __func__, __FILE__, + "Invalid coupling table for an IMEX problem!"); + return (ARK_ILL_INPUT); + } + if (step_mem->explicit_rhs && (step_mem->MRIC->type != MRISTEP_EXPLICIT) && + (step_mem->MRIC->type != MRISTEP_IMEX) && + (step_mem->MRIC->type != MRISTEP_MERK) && + (step_mem->MRIC->type != MRISTEP_SR)) + { + arkProcessError(ark_mem, ARK_ILL_INPUT, __LINE__, __func__, __FILE__, + "Invalid coupling table for an explicit problem!"); + return (ARK_ILL_INPUT); + } + if (step_mem->implicit_rhs && (step_mem->MRIC->type != MRISTEP_IMPLICIT) && + (step_mem->MRIC->type != MRISTEP_IMEX) && + (step_mem->MRIC->type != MRISTEP_SR)) + { + arkProcessError(ark_mem, ARK_ILL_INPUT, __LINE__, __func__, __FILE__, + "Invalid coupling table for an implicit problem!"); + return (ARK_ILL_INPUT); + } + /* Check that the matrices are defined appropriately */ - if (step_mem->implicit_rhs && step_mem->explicit_rhs) + if ((step_mem->MRIC->type == MRISTEP_IMEX) || + (step_mem->MRIC->type == MRISTEP_SR)) { /* ImEx */ if (!(step_mem->MRIC->W) || !(step_mem->MRIC->G)) @@ -1879,7 +3273,8 @@ int mriStep_CheckCoupling(ARKodeMem ark_mem) return (ARK_ILL_INPUT); } } - else if (step_mem->explicit_rhs) + else if ((step_mem->MRIC->type == MRISTEP_EXPLICIT) || + (step_mem->MRIC->type == MRISTEP_MERK)) { /* Explicit */ if (!(step_mem->MRIC->W) || step_mem->MRIC->G) @@ -1889,7 +3284,7 @@ int mriStep_CheckCoupling(ARKodeMem ark_mem) return (ARK_ILL_INPUT); } } - else + else if (step_mem->MRIC->type == MRISTEP_IMPLICIT) { /* Implicit */ if (step_mem->MRIC->W || !(step_mem->MRIC->G)) @@ -1944,6 +3339,39 @@ int mriStep_CheckCoupling(ARKodeMem ark_mem) } } + /* Check that MERK "groups" are structured appropriately */ + if (step_mem->MRIC->type == MRISTEP_MERK) + { + int* group_counter = (int*)calloc(step_mem->MRIC->stages + 1, sizeof(int)); + for (i = 0; i < step_mem->MRIC->ngroup; i++) + { + for (j = 0; j < step_mem->MRIC->stages; j++) + { + k = step_mem->MRIC->group[i][j]; + if (k == -1) { break; } + if ((k < 0) || (k > step_mem->MRIC->stages)) + { + free(group_counter); + arkProcessError(ark_mem, ARK_INVALID_TABLE, __LINE__, __func__, + __FILE__, "Invalid MERK group index!"); + return (ARK_INVALID_TABLE); + } + group_counter[k]++; + } + } + for (i = 1; i <= step_mem->MRIC->stages; i++) + { + if ((group_counter[i] == 0) || (group_counter[i] > 1)) + { + free(group_counter); + arkProcessError(ark_mem, ARK_INVALID_TABLE, __LINE__, __func__, + __FILE__, "Duplicated/missing stages from MERK groups!"); + return (ARK_INVALID_TABLE); + } + } + free(group_counter); + } + /* Check that no stage has MRISTAGE_DIRK_FAST type (for now) */ okay = SUNTRUE; for (i = 0; i < step_mem->MRIC->stages; i++) @@ -1960,20 +3388,25 @@ int mriStep_CheckCoupling(ARKodeMem ark_mem) return (ARK_INVALID_TABLE); } - /* check that stage times are sorted */ - okay = SUNTRUE; - for (i = 1; i < step_mem->MRIC->stages; i++) + /* check that MRI-GARK stage times are sorted */ + if ((step_mem->MRIC->type == MRISTEP_IMPLICIT) || + (step_mem->MRIC->type == MRISTEP_EXPLICIT) || + (step_mem->MRIC->type == MRISTEP_IMEX)) { - if ((step_mem->MRIC->c[i] - step_mem->MRIC->c[i - 1]) < -tol) + okay = SUNTRUE; + for (i = 1; i < step_mem->MRIC->stages; i++) { - okay = SUNFALSE; + if ((step_mem->MRIC->c[i] - step_mem->MRIC->c[i - 1]) < -tol) + { + okay = SUNFALSE; + } + } + if (!okay) + { + arkProcessError(ark_mem, ARK_INVALID_TABLE, __LINE__, __func__, __FILE__, + "Stage times must be sorted."); + return (ARK_INVALID_TABLE); } - } - if (!okay) - { - arkProcessError(ark_mem, ARK_INVALID_TABLE, __LINE__, __func__, __FILE__, - "Stage times must be sorted."); - return (ARK_INVALID_TABLE); } /* check that the first stage is just the old step solution */ @@ -2007,30 +3440,28 @@ int mriStep_CheckCoupling(ARKodeMem ark_mem) /*--------------------------------------------------------------- mriStep_StageERKFast - This routine performs a single MRI stage with explicit slow - time scale and fast time scale that requires evolution. - ---------------------------------------------------------------*/ -int mriStep_StageERKFast(ARKodeMem ark_mem, ARKodeMRIStepMem step_mem, int is) -{ - sunrealtype cdiff; /* stage time increment */ - sunrealtype t0; /* start time for stage */ - int retval; /* reusable return flag */ - -#ifdef SUNDIALS_DEBUG - printf(" MRIStep ERK fast stage\n"); -#endif + This routine performs a single MRI stage, is, with explicit + slow time scale and fast time scale that requires evolution. - /* Set initial time for fast evolution */ - t0 = ark_mem->tn + step_mem->MRIC->c[is - 1] * ark_mem->h; + On input, ycur is the initial condition for the fast IVP at t0. + On output, ycur is the solution of the fast IVP at tf. + The vector ytemp is only used if temporal adaptivity is enabled, + and the fast error is not provided by the fast integrator. - /* compute the inner forcing */ - cdiff = step_mem->MRIC->c[is] - step_mem->MRIC->c[is - 1]; - retval = mriStep_ComputeInnerForcing(ark_mem, step_mem, is, cdiff); - if (retval != ARK_SUCCESS) { return (retval); } + get_inner_dsm indicates whether this stage is one that should + accumulate an inner temporal error estimate. + ---------------------------------------------------------------*/ +int mriStep_StageERKFast(ARKodeMem ark_mem, ARKodeMRIStepMem step_mem, + sunrealtype t0, sunrealtype tf, N_Vector ycur, + SUNDIALS_MAYBE_UNUSED N_Vector ytemp, + sunbooleantype get_inner_dsm) +{ + int retval; /* reusable return flag */ + SUNAdaptController_Type adapt_type; /* timestep adaptivity type */ - /* Set inner forcing time normalization constants */ - step_mem->stepper->tshift = t0; - step_mem->stepper->tscale = cdiff * ark_mem->h; +#ifdef SUNDIALS_DEBUG + printf(" MRIStep ERK fast stage\n"); +#endif /* pre inner evolve function (if supplied) */ if (step_mem->pre_inner_evolve) @@ -2041,16 +3472,52 @@ int mriStep_StageERKFast(ARKodeMem ark_mem, ARKodeMRIStepMem step_mem, int is) if (retval != 0) { return (ARK_OUTERTOINNER_FAIL); } } + /* Get the adaptivity type (if applicable) */ + adapt_type = (get_inner_dsm) + ? SUNAdaptController_GetType(ark_mem->hadapt_mem->hcontroller) + : SUN_ADAPTCONTROLLER_NONE; + /* advance inner method in time */ - retval = mriStepInnerStepper_Evolve(step_mem->stepper, t0, ark_mem->tcur, - ark_mem->ycur); - if (retval != 0) { return (ARK_INNERSTEP_FAIL); } + retval = mriStepInnerStepper_Evolve(step_mem->stepper, t0, tf, ycur); + if (retval < 0) + { + arkProcessError(ark_mem, ARK_INNERSTEP_FAIL, __LINE__, __func__, __FILE__, + "Failure when evolving the inner stepper"); + return (ARK_INNERSTEP_FAIL); + } + if (retval > 0) + { + /* increment stepper-specific counter, and decrement ARKODE-level nonlinear + solver counter (since that will be incremented automatically by ARKODE). + Return with "TRY_AGAIN" which should cause ARKODE to cut the step size + and retry the step. */ + step_mem->inner_fails++; + ark_mem->ncfn--; + return TRY_AGAIN; + } + + /* for normal stages (i.e., not the embedding) with MRI adaptivity enabled, get an + estimate for the fast time scale error */ + if (get_inner_dsm) + { + /* if the fast integrator uses adaptive steps, retrieve the error estimate */ + if (adapt_type == SUN_ADAPTCONTROLLER_MRI_H_TOL) + { + retval = mriStepInnerStepper_GetAccumulatedError(step_mem->stepper, + &(step_mem->inner_dsm)); + if (retval != ARK_SUCCESS) + { + arkProcessError(ark_mem, ARK_INNERSTEP_FAIL, __LINE__, __func__, + __FILE__, "Unable to get accumulated error from the inner stepper"); + return (ARK_INNERSTEP_FAIL); + } + } + } /* post inner evolve function (if supplied) */ if (step_mem->post_inner_evolve) { - retval = step_mem->post_inner_evolve(ark_mem->tcur, ark_mem->ycur, - ark_mem->user_data); + retval = step_mem->post_inner_evolve(tf, ycur, ark_mem->user_data); if (retval != 0) { return (ARK_INNERTOOUTER_FAIL); } } @@ -2072,16 +3539,17 @@ int mriStep_StageERKNoFast(ARKodeMem ark_mem, ARKodeMRIStepMem step_mem, int is) printf(" MRIStep ERK stage\n"); #endif - /* determine effective ERK coefficients (store in cvals) */ + /* determine effective ERK coefficients (store in Ae_row and Ai_row) */ retval = mriStep_RKCoeffs(step_mem->MRIC, is, step_mem->stage_map, step_mem->Ae_row, step_mem->Ai_row); if (retval != ARK_SUCCESS) { return (retval); } - /* call fused vector operation to perform ERK update */ + /* call fused vector operation to perform ERK update -- bound on + j needs "SUNMIN" to handle the case of an "embedding" stage */ step_mem->cvals[0] = ONE; step_mem->Xvecs[0] = ark_mem->ycur; nvec = 1; - for (j = 0; j < is; j++) + for (j = 0; j < SUNMIN(is, step_mem->stages); j++) { if (step_mem->explicit_rhs && step_mem->stage_map[j] > -1) { @@ -2144,16 +3612,16 @@ int mriStep_StageDIRKNoFast(ARKodeMem ark_mem, ARKodeMRIStepMem step_mem, printf(" MRIStep DIRK stage\n"); #endif - /* store current stage index */ - step_mem->istage = is; + /* store current stage index (for an "embedded" stage, subtract 1) */ + step_mem->istage = (is == step_mem->stages) ? is - 1 : is; /* Call predictor for current stage solution (result placed in zpred) */ - retval = mriStep_Predict(ark_mem, is, step_mem->zpred); + retval = mriStep_Predict(ark_mem, step_mem->istage, step_mem->zpred); if (retval != ARK_SUCCESS) { return (retval); } /* If a user-supplied predictor routine is provided, call that here Note that mriStep_Predict is *still* called, so this user-supplied - routine can just 'clean up' the built-in prediction, if desired. */ + routine can just "clean up" the built-in prediction, if desired. */ if (step_mem->stage_predict) { retval = step_mem->stage_predict(ark_mem->tcur, step_mem->zpred, @@ -2197,18 +3665,19 @@ int mriStep_StageDIRKNoFast(ARKodeMem ark_mem, ARKodeMRIStepMem step_mem, mriStep_ComputeInnerForcing Constructs the 'coefficient' vectors for the forcing polynomial - for a 'fast' outer MRI stage i: + for a 'fast' outer MRI-GARK stage i: p_i(theta) = sum_{k=0}^{n-1} forcing[k] * theta^k - where theta = (t - t0) / (cdiff*h) is the mapped 'time' for + where theta = (t - t0) / (tf-t0) is the mapped 'time' for each 'fast' MRIStep evolution, with: * t0 -- the start of this outer MRIStep stage - * cdiff*h, the temporal width of this MRIStep stage + * tf-t0, the temporal width of this MRIStep stage * n -- shorthand for MRIC->nmat - explicit and solve-decoupled implicit or IMEX MRI-based methods - define this forcing polynomial for each outer stage i > 0: + Defining cdiff = (tf-t0)/h, explicit and solve-decoupled + implicit or IMEX MRI-based methods define this forcing polynomial + for each outer stage i > 0: p_i(theta) = w_i,0(theta) * fse_0 + ... + w_i,{i-1}(theta) * fse_{i-1} + g_i,0(theta) * fsi_0 + ... + g_i,{i-1}(theta) * fsi_{i-1} @@ -2244,33 +3713,76 @@ int mriStep_StageDIRKNoFast(ARKodeMem ark_mem, ARKodeMRIStepMem step_mem, ( W[k][i][0] * fse_0 + ... + W[k][i][i-1] * fse_{i-1} + ( G[k][i][0] * fsi_0 + ... + G[k][i][i-1] * fsi_{i-1} ) + We may use an identical formula for MERK methods, so long as we set t0=tn, + tf=tn+h, stage_map[j]=j (identity map), and implicit_rhs=SUNFALSE. + With this configuration: tf-t0=h, theta = (t-tn)/h, and cdiff=1. MERK methods + define the forcing polynomial for each outer stage i > 0 as: + + p_i(theta) = w_i,0(theta) * fse_0 + ... + w_i,{i-1}(theta) * fse_{i-1} + + where + + w_i,j(theta) = w_0,i,j + w_1,i,j * theta + ... + w_n,i,j * theta^{n-1}, + w_k,i,j = MRIC->W[k][i][j] + + which is equivalent to the formula above. + + We may use a similar formula for MRISR methods, so long as we set t0=tn, + tf=tn+h*ci, stage_map[j]=j (identity map), and implicit_rhs=SUNFALSE. + With this configuration: tf-t0=ci*h, theta = (t-tn)/(ci*h), and cdiff=1/ci. + MRISR methods define the forcing polynomial for each outer stage i > 0 as: + + p_i(theta) = w_i,0(theta) * fs_0 + ... + w_i,{i-1}(theta) * fs_{i-1} + + where fs_j = fse_j + fsi_j and + + w_i,j(theta) = w_0,i,j + w_1,i,j * theta + ... + w_n,i,j * theta^{n-1}, + w_k,i,j = 1/ci * MRIC->W[k][i][j] + + which is equivalent to the formula above, so long as the stage RHS vectors + Fse[j] are repurposed to instead store (fse_j + fsi_j). + This routine additionally returns a success/failure flag: ARK_SUCCESS -- successful evaluation ---------------------------------------------------------------*/ int mriStep_ComputeInnerForcing(SUNDIALS_MAYBE_UNUSED ARKodeMem ark_mem, ARKodeMRIStepMem step_mem, int stage, - sunrealtype cdiff) + sunrealtype t0, sunrealtype tf) { sunrealtype rcdiff; int j, k, nmat, nstore, retval; sunrealtype* cvals; N_Vector* Xvecs; + sunbooleantype implicit_rhs = step_mem->implicit_rhs; + sunbooleantype explicit_rhs = step_mem->explicit_rhs; /* local shortcuts for fused vector operations */ cvals = step_mem->cvals; Xvecs = step_mem->Xvecs; + /* Set inner forcing time normalization constants */ + step_mem->stepper->tshift = t0; + step_mem->stepper->tscale = tf - t0; + + /* Adjust implicit/explicit RHS flags for MRISR methods, since these + ignore the G coefficients in the forcing function */ + if (step_mem->MRIC->type == MRISTEP_SR) + { + implicit_rhs = SUNFALSE; + explicit_rhs = SUNTRUE; + } + /* compute inner forcing vectors (assumes cdiff != 0) */ nstore = 0; - for (j = 0; j < stage; j++) + for (j = 0; j < SUNMIN(stage, step_mem->stages); j++) { - if (step_mem->explicit_rhs && step_mem->stage_map[j] > -1) + if (explicit_rhs && step_mem->stage_map[j] > -1) { Xvecs[nstore] = step_mem->Fse[step_mem->stage_map[j]]; nstore += 1; } - if (step_mem->implicit_rhs && step_mem->stage_map[j] > -1) + if (implicit_rhs && step_mem->stage_map[j] > -1) { Xvecs[nstore] = step_mem->Fsi[step_mem->stage_map[j]]; nstore += 1; @@ -2278,16 +3790,16 @@ int mriStep_ComputeInnerForcing(SUNDIALS_MAYBE_UNUSED ARKodeMem ark_mem, } nmat = step_mem->MRIC->nmat; - rcdiff = ONE / cdiff; + rcdiff = ark_mem->h / (tf - t0); for (k = 0; k < nmat; k++) { nstore = 0; - for (j = 0; j < stage; j++) + for (j = 0; j < SUNMIN(stage, step_mem->stages); j++) { if (step_mem->stage_map[j] > -1) { - if (step_mem->explicit_rhs && step_mem->implicit_rhs) + if (explicit_rhs && implicit_rhs) { /* ImEx */ cvals[nstore] = rcdiff * step_mem->MRIC->W[k][stage][j]; @@ -2295,7 +3807,7 @@ int mriStep_ComputeInnerForcing(SUNDIALS_MAYBE_UNUSED ARKodeMem ark_mem, cvals[nstore] = rcdiff * step_mem->MRIC->G[k][stage][j]; nstore += 1; } - else if (step_mem->explicit_rhs) + else if (explicit_rhs) { /* explicit only */ cvals[nstore] = rcdiff * step_mem->MRIC->W[k][stage][j]; @@ -2329,9 +3841,8 @@ int mriStep_ComputeInnerForcing(SUNDIALS_MAYBE_UNUSED ARKodeMem ark_mem, } /*--------------------------------------------------------------- - Compute/return the 'effective' RK coefficients for a 'nofast' - stage. It is assumed that the array 'A' has already been - allocated to have length MRIC->stages. + Compute/return the effective RK coefficients for a "nofast" + stage. We may assume that "A" has already been allocated. ---------------------------------------------------------------*/ int mriStep_RKCoeffs(MRIStepCoupling MRIC, int is, int* stage_map, @@ -2340,7 +3851,7 @@ int mriStep_RKCoeffs(MRIStepCoupling MRIC, int is, int* stage_map, int j, k; sunrealtype kconst; - if (is < 1 || is >= MRIC->stages || !stage_map || !Ae_row || !Ai_row) + if (is < 1 || is > MRIC->stages || !stage_map || !Ae_row || !Ai_row) { return ARK_INVALID_TABLE; } @@ -2352,13 +3863,14 @@ int mriStep_RKCoeffs(MRIStepCoupling MRIC, int is, int* stage_map, Ai_row[j] = ZERO; } - /* compute RK coefficients */ + /* compute RK coefficients -- note that bounds on j need + "SUNMIN" to handle the case of an "embedding" stage */ for (k = 0; k < MRIC->nmat; k++) { kconst = ONE / (k + ONE); if (MRIC->W) { - for (j = 0; j < is; j++) + for (j = 0; j < SUNMIN(is, MRIC->stages - 1); j++) { if (stage_map[j] > -1) { @@ -2368,7 +3880,7 @@ int mriStep_RKCoeffs(MRIStepCoupling MRIC, int is, int* stage_map, } if (MRIC->G) { - for (j = 0; j <= is; j++) + for (j = 0; j <= SUNMIN(is, MRIC->stages - 1); j++) { if (stage_map[j] > -1) { @@ -2558,10 +4070,8 @@ int mriStep_StageSetup(ARKodeMem ark_mem) step_mem->gamma = ark_mem->h * step_mem->Ai_row[step_mem->stage_map[i]]; if (ark_mem->firststage) { step_mem->gammap = step_mem->gamma; } - step_mem->gamrat = (ark_mem->firststage) - ? ONE - : step_mem->gamma / - step_mem->gammap; /* protect x/x != 1.0 */ + step_mem->gamrat = (ark_mem->firststage) ? ONE + : step_mem->gamma / step_mem->gammap; /* set cvals and Xvecs for setting stage data */ cvals[0] = ONE; @@ -2595,8 +4105,123 @@ int mriStep_StageSetup(ARKodeMem ark_mem) } /*--------------------------------------------------------------- - User-callable functions for a custom inner integrator + mriStep_SlowRHS: + + Wrapper routine to call the user-supplied slow RHS functions, + f(t,y) = fse(t,y) + fsi(t,y), with API matching + ARKTimestepFullRHSFn. This is only used to determine an + initial slow time-step size to use when one is not specified + by the user (i.e., mode should correspond with + ARK_FULLRHS_START. + ---------------------------------------------------------------*/ +int mriStep_SlowRHS(ARKodeMem ark_mem, sunrealtype t, N_Vector y, N_Vector f, + SUNDIALS_MAYBE_UNUSED int mode) +{ + ARKodeMRIStepMem step_mem; + int nvec, retval; + + /* access ARKodeMRIStepMem structure */ + retval = mriStep_AccessStepMem(ark_mem, __func__, &step_mem); + if (retval != ARK_SUCCESS) { return (retval); } + + /* call fse if the problem has an explicit component */ + if (step_mem->explicit_rhs) + { + retval = step_mem->fse(t, y, step_mem->Fse[0], ark_mem->user_data); + step_mem->nfse++; + step_mem->fse_is_current = SUNTRUE; + if (retval != 0) + { + arkProcessError(ark_mem, ARK_RHSFUNC_FAIL, __LINE__, __func__, __FILE__, + MSG_ARK_RHSFUNC_FAILED, t); + return (ARK_RHSFUNC_FAIL); + } + + /* Add external forcing, if applicable */ + if (step_mem->expforcing) + { + step_mem->cvals[0] = ONE; + step_mem->Xvecs[0] = step_mem->Fse[0]; + nvec = 1; + mriStep_ApplyForcing(step_mem, t, ONE, &nvec); + N_VLinearCombination(nvec, step_mem->cvals, step_mem->Xvecs, + step_mem->Fse[0]); + } + } + + /* call fsi if the problem has an implicit component */ + if (step_mem->implicit_rhs) + { + retval = step_mem->fsi(t, y, step_mem->Fsi[0], ark_mem->user_data); + step_mem->nfsi++; + step_mem->fsi_is_current = SUNTRUE; + if (retval != 0) + { + arkProcessError(ark_mem, ARK_RHSFUNC_FAIL, __LINE__, __func__, __FILE__, + MSG_ARK_RHSFUNC_FAILED, t); + return (ARK_RHSFUNC_FAIL); + } + + /* Add external forcing, if applicable */ + if (step_mem->impforcing) + { + step_mem->cvals[0] = ONE; + step_mem->Xvecs[0] = step_mem->Fsi[0]; + nvec = 1; + mriStep_ApplyForcing(step_mem, t, ONE, &nvec); + N_VLinearCombination(nvec, step_mem->cvals, step_mem->Xvecs, + step_mem->Fsi[0]); + } + } + + /* combine RHS vectors into output */ + if (step_mem->explicit_rhs && step_mem->implicit_rhs) /* ImEx */ + { + N_VLinearSum(ONE, step_mem->Fse[0], ONE, step_mem->Fsi[0], f); + } + else + { + if (step_mem->implicit_rhs) { N_VScale(ONE, step_mem->Fsi[0], f); } + else { N_VScale(ONE, step_mem->Fse[0], f); } + } + + return (ARK_SUCCESS); +} + +/*--------------------------------------------------------------- + mriStep_Hin + + This routine computes a tentative initial step size h0. This + employs the same safeguards as ARKODE's arkHin utility routine, + but employs a simpler algorithm that estimates the first step + such that an explicit Euler step (for only the slow RHS + routine(s)) would be within user-specified tolerances of the + initial condition. ---------------------------------------------------------------*/ +int mriStep_Hin(ARKodeMem ark_mem, sunrealtype tcur, sunrealtype tout, + N_Vector fcur, sunrealtype* h) +{ + int sign; + sunrealtype tdiff, tdist, tround, fnorm, h0_inv; + + /* If tout is too close to tn, give up */ + if ((tdiff = tout - tcur) == ZERO) { return (ARK_TOO_CLOSE); } + sign = (tdiff > ZERO) ? 1 : -1; + tdist = SUNRabs(tdiff); + tround = ark_mem->uround * SUNMAX(SUNRabs(tcur), SUNRabs(tout)); + if (tdist < TWO * tround) { return (ARK_TOO_CLOSE); } + + /* h0 should bound the change due to a forward Euler step, and + include safeguard against "too-small" ||f(t0,y0)||: */ + fnorm = N_VWrmsNorm(fcur, ark_mem->ewt) / H0_BIAS; + h0_inv = SUNMAX(ONE / H0_UBFACTOR / tdist, fnorm); + *h = sign / h0_inv; + return (ARK_SUCCESS); +} + +/*=============================================================== + User-callable functions for a custom inner integrator + ===============================================================*/ int MRIStepInnerStepper_Create(SUNContext sunctx, MRIStepInnerStepper* stepper) { @@ -2762,6 +4387,72 @@ int MRIStepInnerStepper_SetResetFn(MRIStepInnerStepper stepper, return ARK_SUCCESS; } +int MRIStepInnerStepper_SetAccumulatedErrorGetFn(MRIStepInnerStepper stepper, + MRIStepInnerGetAccumulatedError fn) +{ + if (stepper == NULL) + { + arkProcessError(NULL, ARK_ILL_INPUT, __LINE__, __func__, __FILE__, + "Inner stepper memory is NULL"); + return ARK_ILL_INPUT; + } + + if (stepper->ops == NULL) + { + arkProcessError(NULL, ARK_ILL_INPUT, __LINE__, __func__, __FILE__, + "Inner stepper operations structure is NULL"); + return ARK_ILL_INPUT; + } + + stepper->ops->geterror = fn; + + return ARK_SUCCESS; +} + +int MRIStepInnerStepper_SetAccumulatedErrorResetFn( + MRIStepInnerStepper stepper, MRIStepInnerResetAccumulatedError fn) +{ + if (stepper == NULL) + { + arkProcessError(NULL, ARK_ILL_INPUT, __LINE__, __func__, __FILE__, + "Inner stepper memory is NULL"); + return ARK_ILL_INPUT; + } + + if (stepper->ops == NULL) + { + arkProcessError(NULL, ARK_ILL_INPUT, __LINE__, __func__, __FILE__, + "Inner stepper operations structure is NULL"); + return ARK_ILL_INPUT; + } + + stepper->ops->reseterror = fn; + + return ARK_SUCCESS; +} + +int MRIStepInnerStepper_SetRTolFn(MRIStepInnerStepper stepper, + MRIStepInnerSetRTol fn) +{ + if (stepper == NULL) + { + arkProcessError(NULL, ARK_ILL_INPUT, __LINE__, __func__, __FILE__, + "Inner stepper memory is NULL"); + return ARK_ILL_INPUT; + } + + if (stepper->ops == NULL) + { + arkProcessError(NULL, ARK_ILL_INPUT, __LINE__, __func__, __FILE__, + "Inner stepper operations structure is NULL"); + return ARK_ILL_INPUT; + } + + stepper->ops->setrtol = fn; + + return ARK_SUCCESS; +} + int MRIStepInnerStepper_AddForcing(MRIStepInnerStepper stepper, sunrealtype t, N_Vector f) { @@ -2828,6 +4519,19 @@ int mriStepInnerStepper_HasRequiredOps(MRIStepInnerStepper stepper) else { return ARK_ILL_INPUT; } } +/* Check whether stepper supports fast/slow tolerance adaptivity */ +sunbooleantype mriStepInnerStepper_SupportsRTolAdaptivity(MRIStepInnerStepper stepper) +{ + if (stepper == NULL) { return SUNFALSE; } + if (stepper->ops == NULL) { return SUNFALSE; } + + if (stepper->ops->geterror && stepper->ops->reseterror && stepper->ops->setrtol) + { + return SUNTRUE; + } + else { return SUNFALSE; } +} + /* Evolve the inner (fast) ODE */ int mriStepInnerStepper_Evolve(MRIStepInnerStepper stepper, sunrealtype t0, sunrealtype tout, N_Vector y) @@ -2860,14 +4564,21 @@ int mriStepInnerStepper_EvolveSUNStepper(MRIStepInnerStepper stepper, SUNStepper sunstepper = (SUNStepper)stepper->content; sunrealtype tret; - SUNErrCode err = sunstepper->ops->setstoptime(sunstepper, tout); - if (err != SUN_SUCCESS) - { - stepper->last_flag = sunstepper->last_flag; - return ARK_SUNSTEPPER_ERR; - } + SUNErrCode err = SUNStepper_SetForcing(sunstepper, stepper->tshift, + stepper->tscale, stepper->forcing, + stepper->nforcing); + stepper->last_flag = sunstepper->last_flag; + if (err != SUN_SUCCESS) { return ARK_SUNSTEPPER_ERR; } + + err = SUNStepper_SetStopTime(sunstepper, tout); + stepper->last_flag = sunstepper->last_flag; + if (err != SUN_SUCCESS) { return ARK_SUNSTEPPER_ERR; } - err = sunstepper->ops->evolve(sunstepper, tout, y, &tret); + err = SUNStepper_Evolve(sunstepper, tout, y, &tret); + stepper->last_flag = sunstepper->last_flag; + if (err != SUN_SUCCESS) { return ARK_SUNSTEPPER_ERR; } + + err = SUNStepper_SetForcing(sunstepper, ZERO, ONE, NULL, 0); stepper->last_flag = sunstepper->last_flag; if (err != SUN_SUCCESS) { return ARK_SUNSTEPPER_ERR; } @@ -2902,7 +4613,7 @@ int mriStepInnerStepper_FullRhsSUNStepper(MRIStepInnerStepper stepper, default: mode = SUN_FULLRHS_OTHER; break; } - SUNErrCode err = sunstepper->ops->fullrhs(sunstepper, t, y, f, mode); + SUNErrCode err = SUNStepper_FullRhs(sunstepper, t, y, f, mode); stepper->last_flag = sunstepper->last_flag; if (err != SUN_SUCCESS) { return ARK_SUNSTEPPER_ERR; } return ARK_SUCCESS; @@ -2933,11 +4644,62 @@ int mriStepInnerStepper_Reset(MRIStepInnerStepper stepper, sunrealtype tR, } } +/* Gets the inner (fast) stepper accumulated error */ +int mriStepInnerStepper_GetAccumulatedError(MRIStepInnerStepper stepper, + sunrealtype* accum_error) +{ + if (stepper == NULL) { return ARK_ILL_INPUT; } + if (stepper->ops == NULL) { return ARK_ILL_INPUT; } + + if (stepper->ops->geterror) + { + stepper->last_flag = stepper->ops->geterror(stepper, accum_error); + return stepper->last_flag; + } + else { return ARK_INNERSTEP_FAIL; } +} + +/* Resets the inner (fast) stepper accumulated error */ +int mriStepInnerStepper_ResetAccumulatedError(MRIStepInnerStepper stepper) +{ + if (stepper == NULL) { return ARK_ILL_INPUT; } + if (stepper->ops == NULL) { return ARK_ILL_INPUT; } + + if (stepper->ops->geterror) + { + stepper->last_flag = stepper->ops->reseterror(stepper); + return stepper->last_flag; + } + else + { + /* assume stepper provides exact solution and needs no reset */ + return ARK_SUCCESS; + } +} + +/* Sets the inner (fast) stepper relative tolerance scaling factor */ +int mriStepInnerStepper_SetRTol(MRIStepInnerStepper stepper, sunrealtype rtol) +{ + if (stepper == NULL) { return ARK_ILL_INPUT; } + if (stepper->ops == NULL) { return ARK_ILL_INPUT; } + + if (stepper->ops->setrtol) + { + stepper->last_flag = stepper->ops->setrtol(stepper, rtol); + return stepper->last_flag; + } + else + { + /* assume stepper provides exact solution */ + return ARK_SUCCESS; + } +} + int mriStepInnerStepper_ResetSUNStepper(MRIStepInnerStepper stepper, sunrealtype tR, N_Vector yR) { SUNStepper sunstepper = (SUNStepper)stepper->content; - SUNErrCode err = sunstepper->ops->reset(sunstepper, tR, yR); + SUNErrCode err = SUNStepper_Reset(sunstepper, tR, yR); stepper->last_flag = sunstepper->last_flag; if (err != SUN_SUCCESS) { return ARK_SUNSTEPPER_ERR; } return ARK_SUCCESS; @@ -3073,6 +4835,147 @@ void mriStepInnerStepper_PrintMem(MRIStepInnerStepper stepper, FILE* outfile) return; } +/*--------------------------------------------------------------- + Utility routines for MRIStep to serve as an MRIStepInnerStepper + ---------------------------------------------------------------*/ + +/*------------------------------------------------------------------------------ + mriStep_ApplyForcing + + Determines the linear combination coefficients and vectors to apply forcing + at a given value of the independent variable (t). This occurs through + appending coefficients and N_Vector pointers to the underlying cvals and Xvecs + arrays in the step_mem structure. The dereferenced input *nvec should indicate + the next available entry in the cvals/Xvecs arrays. The input 's' is a + scaling factor that should be applied to each of these coefficients. + ----------------------------------------------------------------------------*/ + +void mriStep_ApplyForcing(ARKodeMRIStepMem step_mem, sunrealtype t, + sunrealtype s, int* nvec) +{ + sunrealtype tau, taui; + int i; + + /* always append the constant forcing term */ + step_mem->cvals[*nvec] = s; + step_mem->Xvecs[*nvec] = step_mem->forcing[0]; + (*nvec) += 1; + + /* compute normalized time tau and initialize tau^i */ + tau = (t - step_mem->tshift) / (step_mem->tscale); + taui = tau; + for (i = 1; i < step_mem->nforcing; i++) + { + step_mem->cvals[*nvec] = s * taui; + step_mem->Xvecs[*nvec] = step_mem->forcing[i]; + taui *= tau; + (*nvec) += 1; + } +} + +/*------------------------------------------------------------------------------ + mriStep_SetInnerForcing + + Sets an array of coefficient vectors for a time-dependent external polynomial + forcing term in the ODE RHS i.e., y' = f(t,y) + p(t). This function is + primarily intended for using MRIStep as an inner integrator within another + [outer] instance of MRIStep, where this instance is used to solve a + modified ODE at a fast time scale. The polynomial is of the form + + p(t) = sum_{i = 0}^{nvecs - 1} forcing[i] * ((t - tshift) / (tscale))^i + + where tshift and tscale are used to normalize the time t (e.g., with MRIGARK + methods). + ----------------------------------------------------------------------------*/ + +int mriStep_SetInnerForcing(ARKodeMem ark_mem, sunrealtype tshift, + sunrealtype tscale, N_Vector* forcing, int nvecs) +{ + ARKodeMRIStepMem step_mem; + int retval; + + /* access ARKodeMRIStepMem structure */ + retval = mriStep_AccessStepMem(ark_mem, __func__, &step_mem); + if (retval != ARK_SUCCESS) { return (retval); } + + if (nvecs > 0) + { + /* enable forcing, and signal that the corresponding pre-existing RHS + vector is no longer current, since it has a stale forcing function */ + if (step_mem->explicit_rhs) + { + step_mem->expforcing = SUNTRUE; + step_mem->impforcing = SUNFALSE; + step_mem->fse_is_current = SUNFALSE; + } + else + { + step_mem->expforcing = SUNFALSE; + step_mem->impforcing = SUNTRUE; + step_mem->fsi_is_current = SUNFALSE; + } + step_mem->tshift = tshift; + step_mem->tscale = tscale; + step_mem->forcing = forcing; + step_mem->nforcing = nvecs; + + /* Signal that any pre-existing RHS vector is no longer current, since it + has a stale forcing function */ + ark_mem->fn_is_current = SUNFALSE; + + /* If cvals and Xvecs are not allocated then mriStep_Init has not been + called and the number of stages has not been set yet. These arrays will + be allocated in mriStep_Init and take into account the value of nforcing. + On subsequent calls will check if enough space has allocated in case + nforcing has increased since the original allocation. */ + if (step_mem->cvals != NULL && step_mem->Xvecs != NULL) + { + /* check if there are enough reusable arrays for fused operations */ + if ((step_mem->nfusedopvecs - nvecs) < (2 * step_mem->MRIC->stages + 2)) + { + /* free current work space */ + if (step_mem->cvals != NULL) + { + free(step_mem->cvals); + ark_mem->lrw -= step_mem->nfusedopvecs; + } + if (step_mem->Xvecs != NULL) + { + free(step_mem->Xvecs); + ark_mem->liw -= step_mem->nfusedopvecs; + } + + /* allocate reusable arrays for fused vector operations */ + step_mem->nfusedopvecs = 2 * step_mem->MRIC->stages + 2 + nvecs; + + step_mem->cvals = NULL; + step_mem->cvals = (sunrealtype*)calloc(step_mem->nfusedopvecs, + sizeof(sunrealtype)); + if (step_mem->cvals == NULL) { return (ARK_MEM_FAIL); } + ark_mem->lrw += step_mem->nfusedopvecs; + + step_mem->Xvecs = NULL; + step_mem->Xvecs = (N_Vector*)calloc(step_mem->nfusedopvecs, + sizeof(N_Vector)); + if (step_mem->Xvecs == NULL) { return (ARK_MEM_FAIL); } + ark_mem->liw += step_mem->nfusedopvecs; + } + } + } + else + { + /* disable forcing */ + step_mem->expforcing = SUNFALSE; + step_mem->impforcing = SUNFALSE; + step_mem->tshift = ZERO; + step_mem->tscale = ONE; + step_mem->forcing = NULL; + step_mem->nforcing = 0; + } + + return (ARK_SUCCESS); +} + /*=============================================================== EOF ===============================================================*/ diff --git a/src/arkode/arkode_mristep_controller.c b/src/arkode/arkode_mristep_controller.c new file mode 100644 index 0000000000..4e026c061f --- /dev/null +++ b/src/arkode/arkode_mristep_controller.c @@ -0,0 +1,142 @@ +/* ----------------------------------------------------------------------------- + * Programmer(s): Daniel R. Reynolds @ SMU + * ----------------------------------------------------------------------------- + * SUNDIALS Copyright Start + * Copyright (c) 2002-2024, Lawrence Livermore National Security + * and Southern Methodist University. + * All rights reserved. + * + * See the top-level LICENSE and NOTICE files for details. + * + * SPDX-License-Identifier: BSD-3-Clause + * SUNDIALS Copyright End + * ----------------------------------------------------------------------------- + * This is the implementation file for MRIStep's multirate adaptivity controller + * layer. + * ---------------------------------------------------------------------------*/ + +#include +#include +#include + +#include "arkode_impl.h" +#include "arkode_mristep_impl.h" + +/*-------------------------------------------- + MRIStep SUNAdaptController wrapper functions + --------------------------------------------*/ + +SUNAdaptController SUNAdaptController_MRIStep(ARKodeMem ark_mem, + SUNAdaptController CMRI) +{ + SUNAdaptController C; + mriStepControlContent content; + ARKodeMRIStepMem step_mem; + int retval; + + /* Return with failure if input controller is NULL or has + unsupported type */ + if (CMRI == NULL) { return (NULL); } + if (SUNAdaptController_GetType(CMRI) != SUN_ADAPTCONTROLLER_MRI_H_TOL) + { + return (NULL); + } + + /* Return with failure if stepper is inaccessible */ + retval = mriStep_AccessStepMem(ark_mem, __func__, &step_mem); + if (retval != ARK_SUCCESS) return (NULL); + + /* Create an empty controller object */ + C = NULL; + C = SUNAdaptController_NewEmpty(CMRI->sunctx); + if (C == NULL) { return (NULL); } + + /* Attach operations */ + C->ops->gettype = SUNAdaptController_GetType_MRIStep; + C->ops->estimatestep = SUNAdaptController_EstimateStep_MRIStep; + C->ops->reset = SUNAdaptController_Reset_MRIStep; + C->ops->write = SUNAdaptController_Write_MRIStep; + C->ops->updateh = SUNAdaptController_UpdateH_MRIStep; + C->ops->space = SUNAdaptController_Space_MRIStep; + + /* Create content */ + content = NULL; + content = (mriStepControlContent)malloc(sizeof *content); + if (content == NULL) + { + SUNAdaptController_Destroy(C); + return (NULL); + } + + /* Attach ARKODE memory, MRI stepper memory and MRI controller objects */ + content->ark_mem = ark_mem; + content->step_mem = step_mem; + content->C = CMRI; + + /* Attach content and return */ + C->content = content; + return (C); +} + +SUNErrCode SUNAdaptController_EstimateStep_MRIStep(SUNAdaptController C, + sunrealtype H, int P, + sunrealtype DSM, + sunrealtype* Hnew) +{ + /* Shortcuts to ARKODE and MRIStep memory */ + ARKodeMem ark_mem = MRICONTROL_A(C); + ARKodeMRIStepMem step_mem = MRICONTROL_S(C); + if ((ark_mem == NULL) || (step_mem == NULL)) { return SUN_ERR_MEM_FAIL; } + + /* Estimate slow stepsize from MRI controller */ + return SUNAdaptController_EstimateStepTol(MRICONTROL_C(C), H, + step_mem->inner_rtol_factor, P, DSM, + step_mem->inner_dsm, Hnew, + &(step_mem->inner_rtol_factor_new)); +} + +SUNErrCode SUNAdaptController_UpdateH_MRIStep(SUNAdaptController C, + sunrealtype H, sunrealtype DSM) +{ + /* Shortcuts to ARKODE and MRIStep memory */ + ARKodeMem ark_mem = MRICONTROL_A(C); + ARKodeMRIStepMem step_mem = MRICONTROL_S(C); + if ((ark_mem == NULL) || (step_mem == NULL)) { return SUN_ERR_MEM_FAIL; } + + /* Update MRI controller */ + SUNErrCode retval = SUNAdaptController_UpdateMRIHTol(MRICONTROL_C(C), H, + step_mem->inner_rtol_factor, + DSM, step_mem->inner_dsm); + if (retval != SUN_SUCCESS) { return (retval); } + + /* Update inner controller parameter to most-recent prediction */ + step_mem->inner_rtol_factor = step_mem->inner_rtol_factor_new; + + /* return with success*/ + return SUN_SUCCESS; +} + +SUNAdaptController_Type SUNAdaptController_GetType_MRIStep(SUNAdaptController C) +{ + return SUNAdaptController_GetType(MRICONTROL_C(C)); +} + +SUNErrCode SUNAdaptController_Reset_MRIStep(SUNAdaptController C) +{ + return SUNAdaptController_Reset(MRICONTROL_C(C)); +} + +SUNErrCode SUNAdaptController_Write_MRIStep(SUNAdaptController C, FILE* fptr) +{ + return SUNAdaptController_Write(MRICONTROL_C(C), fptr); +} + +SUNErrCode SUNAdaptController_Space_MRIStep(SUNAdaptController C, + long int* lenrw, long int* leniw) +{ + return SUNAdaptController_Space(MRICONTROL_C(C), lenrw, leniw); +} + +/*=============================================================== + EOF + ===============================================================*/ diff --git a/src/arkode/arkode_mristep_impl.h b/src/arkode/arkode_mristep_impl.h index 3ae944b12d..1fe308d863 100644 --- a/src/arkode/arkode_mristep_impl.h +++ b/src/arkode/arkode_mristep_impl.h @@ -31,6 +31,7 @@ extern "C" { #endif /* Stage type identifiers */ +#define MRISTAGE_STIFF_ACC -1 #define MRISTAGE_ERK_FAST 0 #define MRISTAGE_ERK_NOFAST 1 #define MRISTAGE_DIRK_NOFAST 2 @@ -72,8 +73,11 @@ typedef struct ARKodeMRIStepMemRec a nonlinear solve */ /* Outer RK method storage and parameters */ - N_Vector* Fse; /* explicit RHS at each stage */ - N_Vector* Fsi; /* implicit RHS at each stage */ + N_Vector* Fse; /* explicit RHS at each stage */ + N_Vector* Fsi; /* implicit RHS at each stage */ + sunbooleantype unify_Fs; /* Fse and Fsi point at the same memory */ + sunbooleantype fse_is_current; + sunbooleantype fsi_is_current; MRIStepCoupling MRIC; /* slow->fast coupling table */ int q; /* method order */ int p; /* embedding order */ @@ -103,18 +107,18 @@ typedef struct ARKodeMRIStepMemRec sunrealtype crate; /* estimated nonlin convergence rate */ sunrealtype delp; /* norm of previous nonlinear solver update */ sunrealtype eRNrm; /* estimated residual norm, used in nonlin - and linear solver convergence tests */ + and linear solver convergence tests */ sunrealtype nlscoef; /* coefficient in nonlin. convergence test */ int msbp; /* positive => max # steps between lsetup - negative => call at each Newton iter */ + negative => call at each Newton iter */ long int nstlp; /* step number of last setup call */ int maxcor; /* max num iterations for solving the - nonlinear equation */ + nonlinear equation */ int convfail; /* NLS fail flag (for interface routines) */ sunbooleantype jcur; /* is Jacobian info for lin solver current? */ - ARKStagePredictFn stage_predict; /* User-supplied stage predictor */ + ARKStagePredictFn stage_predict; /* User-supplied stage predictor */ /* Linear Solver Data */ ARKLinsolInitFn linit; @@ -130,13 +134,27 @@ typedef struct ARKodeMRIStepMemRec MRIStepPreInnerFn pre_inner_evolve; MRIStepPostInnerFn post_inner_evolve; + /* MRI adaptivity parameters */ + sunrealtype inner_rtol_factor; /* prev control parameter */ + sunrealtype inner_dsm; /* prev inner stepper accumulated error */ + sunrealtype inner_rtol_factor_new; /* upcoming control parameter */ + /* Counters */ - long int nfse; /* num fse calls */ - long int nfsi; /* num fsi calls */ - long int nsetups; /* num linear solver setup calls */ - long int nls_iters; /* num nonlinear solver iters */ - long int nls_fails; /* num nonlinear solver fails */ - int nfusedopvecs; /* length of cvals and Xvecs arrays */ + long int nfse; /* num fse calls */ + long int nfsi; /* num fsi calls */ + long int nsetups; /* num linear solver setup calls */ + long int nls_iters; /* num nonlinear solver iters */ + long int nls_fails; /* num nonlinear solver fails */ + long int inner_fails; /* num recov. inner solver fails */ + int nfusedopvecs; /* length of cvals and Xvecs arrays */ + + /* Data for using MRIStep with external polynomial forcing */ + sunbooleantype expforcing; /* add forcing to explicit RHS */ + sunbooleantype impforcing; /* add forcing to implicit RHS */ + sunrealtype tshift; /* time normalization shift */ + sunrealtype tscale; /* time normalization scaling */ + N_Vector* forcing; /* array of forcing vectors */ + int nforcing; /* number of forcing vectors */ /* Reusable arrays for fused vector operations */ sunrealtype* cvals; @@ -155,6 +173,9 @@ struct _MRIStepInnerStepper_Ops MRIStepInnerEvolveFn evolve; MRIStepInnerFullRhsFn fullrhs; MRIStepInnerResetFn reset; + MRIStepInnerGetAccumulatedError geterror; + MRIStepInnerResetAccumulatedError reseterror; + MRIStepInnerSetRTol setrtol; }; struct _MRIStepInnerStepper @@ -195,14 +216,20 @@ int mriStep_AttachLinsol(ARKodeMem ark_mem, ARKLinsolInitFn linit, ARKLinsolFreeFn lfree, SUNLinearSolver_Type lsolve_type, void* lmem); void mriStep_DisableLSetup(ARKodeMem ark_mem); -int mriStep_Init(ARKodeMem ark_mem, int init_type); +int mriStep_Init(ARKodeMem ark_mem, sunrealtype tout, int init_type); void* mriStep_GetLmem(ARKodeMem ark_mem); ARKRhsFn mriStep_GetImplicitRHS(ARKodeMem ark_mem); int mriStep_GetGammas(ARKodeMem ark_mem, sunrealtype* gamma, sunrealtype* gamrat, sunbooleantype** jcur, sunbooleantype* dgamma_fail); int mriStep_FullRHS(ARKodeMem ark_mem, sunrealtype t, N_Vector y, N_Vector f, int mode); -int mriStep_TakeStep(ARKodeMem ark_mem, sunrealtype* dsmPtr, int* nflagPtr); +int mriStep_UpdateF0(ARKodeMem ark_mem, ARKodeMRIStepMem step_mem, + sunrealtype t, N_Vector y, int mode); +int mriStep_TakeStepMRIGARK(ARKodeMem ark_mem, sunrealtype* dsmPtr, + int* nflagPtr); +int mriStep_TakeStepMRISR(ARKodeMem ark_mem, sunrealtype* dsmPtr, int* nflagPtr); +int mriStep_TakeStepMERK(ARKodeMem ark_mem, sunrealtype* dsmPtr, int* nflagPtr); +int mriStep_SetAdaptController(ARKodeMem ark_mem, SUNAdaptController C); int mriStep_SetUserData(ARKodeMem ark_mem, void* user_data); int mriStep_SetDefaults(ARKodeMem ark_mem); int mriStep_SetOrder(ARKodeMem ark_mem, int ord); @@ -219,6 +246,7 @@ int mriStep_SetMaxNonlinIters(ARKodeMem ark_mem, int maxcor); int mriStep_SetNonlinConvCoef(ARKodeMem ark_mem, sunrealtype nlscoef); int mriStep_SetStagePredictFn(ARKodeMem ark_mem, ARKStagePredictFn PredictStage); int mriStep_SetDeduceImplicitRhs(ARKodeMem ark_mem, sunbooleantype deduce); +int mriStep_GetEstLocalErrors(ARKodeMem ark_mem, N_Vector ele); int mriStep_GetNumRhsEvals(ARKodeMem ark_mem, int partition_index, long int* rhs_evals); int mriStep_GetCurrentGamma(ARKodeMem ark_mem, sunrealtype* gamma); @@ -239,6 +267,8 @@ int mriStep_Resize(ARKodeMem ark_mem, N_Vector y0, sunrealtype hscale, int mriStep_ComputeState(ARKodeMem ark_mem, N_Vector zcor, N_Vector z); void mriStep_Free(ARKodeMem ark_mem); void mriStep_PrintMem(ARKodeMem ark_mem, FILE* outfile); +int mriStep_SetInnerForcing(ARKodeMem ark_mem, sunrealtype tshift, + sunrealtype tscale, N_Vector* f, int nvecs); /* Internal utility routines */ int mriStep_AccessARKODEStepMem(void* arkode_mem, const char* fname, @@ -248,7 +278,9 @@ int mriStep_AccessStepMem(ARKodeMem ark_mem, const char* fname, sunbooleantype mriStep_CheckNVector(N_Vector tmpl); int mriStep_SetCoupling(ARKodeMem ark_mem); int mriStep_CheckCoupling(ARKodeMem ark_mem); -int mriStep_StageERKFast(ARKodeMem ark_mem, ARKodeMRIStepMem step_mem, int is); +int mriStep_StageERKFast(ARKodeMem ark_mem, ARKodeMRIStepMem step_mem, + sunrealtype t0, sunrealtype tf, N_Vector ycur, + N_Vector ytemp, sunbooleantype get_inner_dsm); int mriStep_StageERKNoFast(ARKodeMem ark_mem, ARKodeMRIStepMem step_mem, int is); int mriStep_StageDIRKFast(ARKodeMem ark_mem, ARKodeMRIStepMem step_mem, int is, int* nflagPtr); @@ -258,6 +290,12 @@ int mriStep_Predict(ARKodeMem ark_mem, int istage, N_Vector yguess); int mriStep_StageSetup(ARKodeMem ark_mem); int mriStep_NlsInit(ARKodeMem ark_mem); int mriStep_Nls(ARKodeMem ark_mem, int nflag); +int mriStep_SlowRHS(ARKodeMem ark_mem, sunrealtype t, N_Vector y, N_Vector f, + int mode); +int mriStep_Hin(ARKodeMem ark_mem, sunrealtype tcur, sunrealtype tout, + N_Vector fcur, sunrealtype* h); +void mriStep_ApplyForcing(ARKodeMRIStepMem step_mem, sunrealtype t, + sunrealtype s, int* nvec); /* private functions passed to nonlinear solver */ int mriStep_NlsResidual(N_Vector yy, N_Vector res, void* arkode_mem); @@ -270,6 +308,8 @@ int mriStep_NlsConvTest(SUNNonlinearSolver NLS, N_Vector y, N_Vector del, /* Inner stepper functions */ int mriStepInnerStepper_HasRequiredOps(MRIStepInnerStepper stepper); +sunbooleantype mriStepInnerStepper_SupportsRTolAdaptivity( + MRIStepInnerStepper stepper); int mriStepInnerStepper_Evolve(MRIStepInnerStepper stepper, sunrealtype t0, sunrealtype tout, N_Vector y); int mriStepInnerStepper_EvolveSUNStepper(MRIStepInnerStepper stepper, @@ -282,6 +322,10 @@ int mriStepInnerStepper_FullRhsSUNStepper(MRIStepInnerStepper stepper, int mode); int mriStepInnerStepper_Reset(MRIStepInnerStepper stepper, sunrealtype tR, N_Vector yR); +int mriStepInnerStepper_GetAccumulatedError(MRIStepInnerStepper stepper, + sunrealtype* accum_error); +int mriStepInnerStepper_ResetAccumulatedError(MRIStepInnerStepper stepper); +int mriStepInnerStepper_SetRTol(MRIStepInnerStepper stepper, sunrealtype rtol); int mriStepInnerStepper_ResetSUNStepper(MRIStepInnerStepper stepper, sunrealtype tR, N_Vector yR); int mriStepInnerStepper_AllocVecs(MRIStepInnerStepper stepper, int count, @@ -294,12 +338,51 @@ void mriStepInnerStepper_PrintMem(MRIStepInnerStepper stepper, FILE* outfile); /* Compute forcing for inner stepper */ int mriStep_ComputeInnerForcing(ARKodeMem ark_mem, ARKodeMRIStepMem step_mem, - int stage, sunrealtype cdiff); + int stage, sunrealtype t0, sunrealtype tf); /* Return effective RK coefficients (nofast stage) */ int mriStep_RKCoeffs(MRIStepCoupling MRIC, int is, int* stage_map, sunrealtype* Ae_row, sunrealtype* Ai_row); +/*=============================================================== + MRIStep SUNAdaptController wrapper module -- this is used to + insert MRIStep in-between ARKODE at the "slow" time scale, and + the inner-steppers that comprise the MRI time-step evolution. + Since ARKODE itself only calls single-scale controller + functions (e.g., EstimateStep and UpdateH), then this serves to + translate those single-rate controller functions to the multi- + rate context, leveraging MRIStep-specific knowledge of the + slow+fast time scale relationship to CALL multi-rate controller + functions (e.g., EstimateMRISteps, EstimateStepTol, UpdateMRIH, + and UpdateMRIHTol) provided by the underlying multi-rate + controller. + ===============================================================*/ + +typedef struct _mriStepControlContent +{ + ARKodeMem ark_mem; /* ARKODE memory pointer */ + ARKodeMRIStepMem step_mem; /* MRIStep memory pointer */ + SUNAdaptController C; /* attached controller pointer */ +}* mriStepControlContent; + +#define MRICONTROL_C(C) (((mriStepControlContent)(C->content))->C) +#define MRICONTROL_A(C) (((mriStepControlContent)(C->content))->ark_mem) +#define MRICONTROL_S(C) (((mriStepControlContent)(C->content))->step_mem) + +SUNAdaptController SUNAdaptController_MRIStep(ARKodeMem ark_mem, + SUNAdaptController C); +SUNAdaptController_Type SUNAdaptController_GetType_MRIStep(SUNAdaptController C); +SUNErrCode SUNAdaptController_EstimateStep_MRIStep(SUNAdaptController C, + sunrealtype H, int P, + sunrealtype DSM, + sunrealtype* Hnew); +SUNErrCode SUNAdaptController_Reset_MRIStep(SUNAdaptController C); +SUNErrCode SUNAdaptController_Write_MRIStep(SUNAdaptController C, FILE* fptr); +SUNErrCode SUNAdaptController_UpdateH_MRIStep(SUNAdaptController C, + sunrealtype h, sunrealtype dsm); +SUNErrCode SUNAdaptController_Space_MRIStep(SUNAdaptController C, + long int* lenrw, long int* leniw); + /*=============================================================== Reusable MRIStep Error Messages ===============================================================*/ diff --git a/src/arkode/arkode_mristep_io.c b/src/arkode/arkode_mristep_io.c index f7b75eaf9f..b4ef0d31c6 100644 --- a/src/arkode/arkode_mristep_io.c +++ b/src/arkode/arkode_mristep_io.c @@ -222,10 +222,58 @@ int MRIStepGetLastInnerStepFlag(void* arkode_mem, int* flag) return (ARK_SUCCESS); } +/*--------------------------------------------------------------- + MRIStepGetNumInnerStepperFails: + + Returns the number of recoverable failures encountered by the + inner stepper. + ---------------------------------------------------------------*/ +int MRIStepGetNumInnerStepperFails(void* arkode_mem, long int* inner_fails) +{ + ARKodeMem ark_mem; + ARKodeMRIStepMem step_mem; + int retval; + + /* access ARKodeMem and ARKodeMRIStepMem structures */ + retval = mriStep_AccessARKODEStepMem(arkode_mem, __func__, &ark_mem, &step_mem); + if (retval != ARK_SUCCESS) { return (retval); } + + /* set output from step_mem */ + *inner_fails = step_mem->inner_fails; + + return (ARK_SUCCESS); +} + /*=============================================================== Private functions attached to ARKODE ===============================================================*/ +/*--------------------------------------------------------------- + mriStep_SetAdaptController: + + Specifies a temporal adaptivity controller for MRIStep to use. + If a non-MRI controller is provided, this just passes that + through to arkReplaceAdaptController. However, if an MRI + controller is provided, then this wraps that inside a + "SUNAdaptController_MRIStep" wrapper, which will properly + interact with the fast integration module. + ---------------------------------------------------------------*/ +int mriStep_SetAdaptController(ARKodeMem ark_mem, SUNAdaptController C) +{ + /* Retrieve the controller type */ + SUNAdaptController_Type ctype = SUNAdaptController_GetType(C); + + /* If this does not have MRI type, then just pass to ARKODE */ + if (ctype != SUN_ADAPTCONTROLLER_MRI_H_TOL) + { + return (arkReplaceAdaptController(ark_mem, C)); + } + + /* Create the mriStepControl wrapper, and pass that to ARKODE */ + SUNAdaptController Cwrapper = SUNAdaptController_MRIStep(ark_mem, C); + return (arkReplaceAdaptController(ark_mem, Cwrapper)); +} + /*--------------------------------------------------------------- mriStep_SetUserData: @@ -260,7 +308,8 @@ int mriStep_SetUserData(ARKodeMem ark_mem, void* user_data) int mriStep_SetDefaults(ARKodeMem ark_mem) { ARKodeMRIStepMem step_mem; - sunindextype lenrw, leniw; + sunindextype Clenrw, Cleniw; + long int lenrw, leniw; int retval; /* access ARKodeMRIStepMem structure */ @@ -293,12 +342,47 @@ int mriStep_SetDefaults(ARKodeMem ark_mem) /* Remove pre-existing coupling table */ if (step_mem->MRIC) { - MRIStepCoupling_Space(step_mem->MRIC, &leniw, &lenrw); - ark_mem->lrw -= lenrw; - ark_mem->liw -= leniw; + MRIStepCoupling_Space(step_mem->MRIC, &Cleniw, &Clenrw); + ark_mem->lrw -= Clenrw; + ark_mem->liw -= Cleniw; MRIStepCoupling_Free(step_mem->MRIC); } step_mem->MRIC = NULL; + + /* Remove pre-existing SUNAdaptController object, and replace with "I" */ + if (ark_mem->hadapt_mem->owncontroller) + { + retval = SUNAdaptController_Space(ark_mem->hadapt_mem->hcontroller, &lenrw, + &leniw); + if (retval == SUN_SUCCESS) + { + ark_mem->liw -= leniw; + ark_mem->lrw -= lenrw; + } + retval = SUNAdaptController_Destroy(ark_mem->hadapt_mem->hcontroller); + ark_mem->hadapt_mem->owncontroller = SUNFALSE; + if (retval != SUN_SUCCESS) + { + arkProcessError(ark_mem, ARK_MEM_FAIL, __LINE__, __func__, __FILE__, + "SUNAdaptController_Destroy failure"); + return (ARK_MEM_FAIL); + } + } + ark_mem->hadapt_mem->hcontroller = SUNAdaptController_I(ark_mem->sunctx); + if (ark_mem->hadapt_mem->hcontroller == NULL) + { + arkProcessError(ark_mem, ARK_MEM_FAIL, __LINE__, __func__, __FILE__, + "SUNAdaptController_I allocation failure"); + return (ARK_MEM_FAIL); + } + ark_mem->hadapt_mem->owncontroller = SUNTRUE; + retval = SUNAdaptController_Space(ark_mem->hadapt_mem->hcontroller, &lenrw, + &leniw); + if (retval == SUN_SUCCESS) + { + ark_mem->liw += leniw; + ark_mem->lrw += lenrw; + } return (ARK_SUCCESS); } @@ -624,6 +708,29 @@ int mriStep_GetCurrentGamma(ARKodeMem ark_mem, sunrealtype* gamma) return (retval); } +/*--------------------------------------------------------------- + mriStep_GetEstLocalErrors: Returns the current local truncation + error estimate vector + ---------------------------------------------------------------*/ +int mriStep_GetEstLocalErrors(ARKodeMem ark_mem, N_Vector ele) +{ + int retval; + ARKodeMRIStepMem step_mem; + retval = mriStep_AccessStepMem(ark_mem, __func__, &step_mem); + if (retval != ARK_SUCCESS) { return (retval); } + + /* return an error if local truncation error is not computed */ + if ((ark_mem->fixedstep && (ark_mem->AccumErrorType == ARK_ACCUMERROR_NONE)) || + (step_mem->p <= 0)) + { + return (ARK_STEPPER_UNSUPPORTED); + } + + /* otherwise, copy local truncation error vector to output */ + N_VScale(ONE, ark_mem->tempv1, ele); + return (ARK_SUCCESS); +} + /*--------------------------------------------------------------- mriStep_GetNumLinSolvSetups: @@ -726,7 +833,9 @@ int mriStep_PrintAllStats(ARKodeMem ark_mem, FILE* outfile, SUNOutputFormat fmt) fprintf(outfile, "Explicit slow RHS fn evals = %ld\n", step_mem->nfse); fprintf(outfile, "Implicit slow RHS fn evals = %ld\n", step_mem->nfsi); - /* nonlinear solver stats */ + /* inner stepper and nonlinear solver stats */ + fprintf(outfile, "Inner stepper failures = %ld\n", + step_mem->inner_fails); fprintf(outfile, "NLS iters = %ld\n", step_mem->nls_iters); fprintf(outfile, "NLS fails = %ld\n", step_mem->nls_fails); if (ark_mem->nst > 0) @@ -767,7 +876,8 @@ int mriStep_PrintAllStats(ARKodeMem ark_mem, FILE* outfile, SUNOutputFormat fmt) fprintf(outfile, ",Explicit slow RHS fn evals,%ld", step_mem->nfse); fprintf(outfile, ",Implicit slow RHS fn evals,%ld", step_mem->nfsi); - /* nonlinear solver stats */ + /* inner stepper and nonlinear solver stats */ + fprintf(outfile, ",Inner stepper failures,%ld", step_mem->inner_fails); fprintf(outfile, ",NLS iters,%ld", step_mem->nls_iters); fprintf(outfile, ",NLS fails,%ld", step_mem->nls_fails); if (ark_mem->nst > 0) diff --git a/src/arkode/arkode_sprkstep.c b/src/arkode/arkode_sprkstep.c index 6c3cf4a669..4e4ff84465 100644 --- a/src/arkode/arkode_sprkstep.c +++ b/src/arkode/arkode_sprkstep.c @@ -362,7 +362,8 @@ void sprkStep_Free(ARKodeMem ark_mem) With initialization type RESET_INIT, this routine does nothing. ---------------------------------------------------------------*/ -int sprkStep_Init(ARKodeMem ark_mem, int init_type) +int sprkStep_Init(ARKodeMem ark_mem, SUNDIALS_MAYBE_UNUSED sunrealtype tout, + int init_type) { ARKodeSPRKStepMem step_mem = NULL; int retval = 0; diff --git a/src/arkode/arkode_sprkstep_impl.h b/src/arkode/arkode_sprkstep_impl.h index d94f5c5c80..543adc5ef5 100644 --- a/src/arkode/arkode_sprkstep_impl.h +++ b/src/arkode/arkode_sprkstep_impl.h @@ -67,7 +67,7 @@ typedef struct ARKodeSPRKStepMemRec ===============================================================*/ /* Interface routines supplied to ARKODE */ -int sprkStep_Init(ARKodeMem ark_mem, int init_type); +int sprkStep_Init(ARKodeMem ark_mem, sunrealtype tout, int init_type); int sprkStep_FullRHS(ARKodeMem ark_mem, sunrealtype t, N_Vector y, N_Vector f, int mode); int sprkStep_TakeStep(ARKodeMem ark_mem, sunrealtype* dsmPtr, int* nflagPtr); diff --git a/src/arkode/fmod_int32/farkode_mod.c b/src/arkode/fmod_int32/farkode_mod.c index 4bfdf17364..77798fc2b7 100644 --- a/src/arkode/fmod_int32/farkode_mod.c +++ b/src/arkode/fmod_int32/farkode_mod.c @@ -353,6 +353,20 @@ SWIGEXPORT int _wrap_FARKodeReset(void *farg1, double const *farg2, N_Vector far } +SWIGEXPORT int _wrap_FARKodeCreateMRIStepInnerStepper(void *farg1, void *farg2) { + int fresult ; + void *arg1 = (void *) 0 ; + MRIStepInnerStepper *arg2 = (MRIStepInnerStepper *) 0 ; + int result; + + arg1 = (void *)(farg1); + arg2 = (MRIStepInnerStepper *)(farg2); + result = (int)ARKodeCreateMRIStepInnerStepper(arg1,arg2); + fresult = (int)(result); + return fresult; +} + + SWIGEXPORT int _wrap_FARKodeSStolerances(void *farg1, double const *farg2, double const *farg3) { int fresult ; void *arg1 = (void *) 0 ; @@ -1139,6 +1153,32 @@ SWIGEXPORT int _wrap_FARKodeSetMaxNumConstrFails(void *farg1, int const *farg2) } +SWIGEXPORT int _wrap_FARKodeSetAccumulatedErrorType(void *farg1, int const *farg2) { + int fresult ; + void *arg1 = (void *) 0 ; + ARKAccumError arg2 ; + int result; + + arg1 = (void *)(farg1); + arg2 = (ARKAccumError)(*farg2); + result = (int)ARKodeSetAccumulatedErrorType(arg1,arg2); + fresult = (int)(result); + return fresult; +} + + +SWIGEXPORT int _wrap_FARKodeResetAccumulatedError(void *farg1) { + int fresult ; + void *arg1 = (void *) 0 ; + int result; + + arg1 = (void *)(farg1); + result = (int)ARKodeResetAccumulatedError(arg1); + fresult = (int)(result); + return fresult; +} + + SWIGEXPORT int _wrap_FARKodeEvolve(void *farg1, double const *farg2, N_Vector farg3, double *farg4, int const *farg5) { int fresult ; void *arg1 = (void *) 0 ; @@ -1500,6 +1540,20 @@ SWIGEXPORT int _wrap_FARKodeGetStepStats(void *farg1, long *farg2, double *farg3 } +SWIGEXPORT int _wrap_FARKodeGetAccumulatedError(void *farg1, double *farg2) { + int fresult ; + void *arg1 = (void *) 0 ; + sunrealtype *arg2 = (sunrealtype *) 0 ; + int result; + + arg1 = (void *)(farg1); + arg2 = (sunrealtype *)(farg2); + result = (int)ARKodeGetAccumulatedError(arg1,arg2); + fresult = (int)(result); + return fresult; +} + + SWIGEXPORT int _wrap_FARKodeGetNumLinSolvSetups(void *farg1, long *farg2) { int fresult ; void *arg1 = (void *) 0 ; diff --git a/src/arkode/fmod_int32/farkode_mod.f90 b/src/arkode/fmod_int32/farkode_mod.f90 index 3cd700fa7e..ce6af7d24f 100644 --- a/src/arkode/fmod_int32/farkode_mod.f90 +++ b/src/arkode/fmod_int32/farkode_mod.f90 @@ -105,8 +105,18 @@ module farkode_mod end enum integer, parameter, public :: ARKRelaxSolver = kind(ARK_RELAX_BRENT) public :: ARK_RELAX_BRENT, ARK_RELAX_NEWTON + ! typedef enum ARKAccumError + enum, bind(c) + enumerator :: ARK_ACCUMERROR_NONE + enumerator :: ARK_ACCUMERROR_MAX + enumerator :: ARK_ACCUMERROR_SUM + enumerator :: ARK_ACCUMERROR_AVG + end enum + integer, parameter, public :: ARKAccumError = kind(ARK_ACCUMERROR_NONE) + public :: ARK_ACCUMERROR_NONE, ARK_ACCUMERROR_MAX, ARK_ACCUMERROR_SUM, ARK_ACCUMERROR_AVG public :: FARKodeResize public :: FARKodeReset + public :: FARKodeCreateMRIStepInnerStepper public :: FARKodeSStolerances public :: FARKodeSVtolerances public :: FARKodeWFtolerances @@ -163,6 +173,8 @@ module farkode_mod public :: FARKodeSetMinStep public :: FARKodeSetMaxStep public :: FARKodeSetMaxNumConstrFails + public :: FARKodeSetAccumulatedErrorType + public :: FARKodeResetAccumulatedError public :: FARKodeEvolve public :: FARKodeGetDky public :: FARKodeComputeState @@ -191,6 +203,7 @@ module farkode_mod public :: FARKodeGetTolScaleFactor public :: FARKodeGetNumConstrFails public :: FARKodeGetStepStats + public :: FARKodeGetAccumulatedError public :: FARKodeGetNumLinSolvSetups public :: FARKodeGetCurrentTime public :: FARKodeGetCurrentState @@ -486,6 +499,15 @@ function swigc_FARKodeReset(farg1, farg2, farg3) & integer(C_INT) :: fresult end function +function swigc_FARKodeCreateMRIStepInnerStepper(farg1, farg2) & +bind(C, name="_wrap_FARKodeCreateMRIStepInnerStepper") & +result(fresult) +use, intrinsic :: ISO_C_BINDING +type(C_PTR), value :: farg1 +type(C_PTR), value :: farg2 +integer(C_INT) :: fresult +end function + function swigc_FARKodeSStolerances(farg1, farg2, farg3) & bind(C, name="_wrap_FARKodeSStolerances") & result(fresult) @@ -991,6 +1013,23 @@ function swigc_FARKodeSetMaxNumConstrFails(farg1, farg2) & integer(C_INT) :: fresult end function +function swigc_FARKodeSetAccumulatedErrorType(farg1, farg2) & +bind(C, name="_wrap_FARKodeSetAccumulatedErrorType") & +result(fresult) +use, intrinsic :: ISO_C_BINDING +type(C_PTR), value :: farg1 +integer(C_INT), intent(in) :: farg2 +integer(C_INT) :: fresult +end function + +function swigc_FARKodeResetAccumulatedError(farg1) & +bind(C, name="_wrap_FARKodeResetAccumulatedError") & +result(fresult) +use, intrinsic :: ISO_C_BINDING +type(C_PTR), value :: farg1 +integer(C_INT) :: fresult +end function + function swigc_FARKodeEvolve(farg1, farg2, farg3, farg4, farg5) & bind(C, name="_wrap_FARKodeEvolve") & result(fresult) @@ -1225,6 +1264,15 @@ function swigc_FARKodeGetStepStats(farg1, farg2, farg3, farg4, farg5, farg6) & integer(C_INT) :: fresult end function +function swigc_FARKodeGetAccumulatedError(farg1, farg2) & +bind(C, name="_wrap_FARKodeGetAccumulatedError") & +result(fresult) +use, intrinsic :: ISO_C_BINDING +type(C_PTR), value :: farg1 +type(C_PTR), value :: farg2 +integer(C_INT) :: fresult +end function + function swigc_FARKodeGetNumLinSolvSetups(farg1, farg2) & bind(C, name="_wrap_FARKodeGetNumLinSolvSetups") & result(fresult) @@ -2440,6 +2488,22 @@ function FARKodeReset(arkode_mem, tr, yr) & swig_result = fresult end function +function FARKodeCreateMRIStepInnerStepper(arkode_mem, stepper) & +result(swig_result) +use, intrinsic :: ISO_C_BINDING +integer(C_INT) :: swig_result +type(C_PTR) :: arkode_mem +type(C_PTR), target, intent(inout) :: stepper +integer(C_INT) :: fresult +type(C_PTR) :: farg1 +type(C_PTR) :: farg2 + +farg1 = arkode_mem +farg2 = c_loc(stepper) +fresult = swigc_FARKodeCreateMRIStepInnerStepper(farg1, farg2) +swig_result = fresult +end function + function FARKodeSStolerances(arkode_mem, reltol, abstol) & result(swig_result) use, intrinsic :: ISO_C_BINDING @@ -3339,6 +3403,35 @@ function FARKodeSetMaxNumConstrFails(arkode_mem, maxfails) & swig_result = fresult end function +function FARKodeSetAccumulatedErrorType(arkode_mem, accum_type) & +result(swig_result) +use, intrinsic :: ISO_C_BINDING +integer(C_INT) :: swig_result +type(C_PTR) :: arkode_mem +integer(ARKAccumError), intent(in) :: accum_type +integer(C_INT) :: fresult +type(C_PTR) :: farg1 +integer(C_INT) :: farg2 + +farg1 = arkode_mem +farg2 = accum_type +fresult = swigc_FARKodeSetAccumulatedErrorType(farg1, farg2) +swig_result = fresult +end function + +function FARKodeResetAccumulatedError(arkode_mem) & +result(swig_result) +use, intrinsic :: ISO_C_BINDING +integer(C_INT) :: swig_result +type(C_PTR) :: arkode_mem +integer(C_INT) :: fresult +type(C_PTR) :: farg1 + +farg1 = arkode_mem +fresult = swigc_FARKodeResetAccumulatedError(farg1) +swig_result = fresult +end function + function FARKodeEvolve(arkode_mem, tout, yout, tret, itask) & result(swig_result) use, intrinsic :: ISO_C_BINDING @@ -3774,6 +3867,22 @@ function FARKodeGetStepStats(arkode_mem, nsteps, hinused, hlast, hcur, tcur) & swig_result = fresult end function +function FARKodeGetAccumulatedError(arkode_mem, accum_error) & +result(swig_result) +use, intrinsic :: ISO_C_BINDING +integer(C_INT) :: swig_result +type(C_PTR) :: arkode_mem +real(C_DOUBLE), dimension(*), target, intent(inout) :: accum_error +integer(C_INT) :: fresult +type(C_PTR) :: farg1 +type(C_PTR) :: farg2 + +farg1 = arkode_mem +farg2 = c_loc(accum_error(1)) +fresult = swigc_FARKodeGetAccumulatedError(farg1, farg2) +swig_result = fresult +end function + function FARKodeGetNumLinSolvSetups(arkode_mem, nlinsetups) & result(swig_result) use, intrinsic :: ISO_C_BINDING diff --git a/src/arkode/fmod_int32/farkode_mristep_mod.c b/src/arkode/fmod_int32/farkode_mristep_mod.c index b454003c6d..378b438a2c 100644 --- a/src/arkode/fmod_int32/farkode_mristep_mod.c +++ b/src/arkode/fmod_int32/farkode_mristep_mod.c @@ -308,6 +308,30 @@ SWIGINTERN SwigArrayWrapper SwigArrayWrapper_uninitialized() { return result; } +SWIGEXPORT void _wrap_MRIStepCouplingMem_type_set(SwigClassWrapper const *farg1, int const *farg2) { + struct MRIStepCouplingMem *arg1 = (struct MRIStepCouplingMem *) 0 ; + MRISTEP_METHOD_TYPE arg2 ; + + SWIG_check_mutable_nonnull(*farg1, "struct MRIStepCouplingMem *", "MRIStepCouplingMem", "MRIStepCouplingMem::type", return ); + arg1 = (struct MRIStepCouplingMem *)(farg1->cptr); + arg2 = (MRISTEP_METHOD_TYPE)(*farg2); + if (arg1) (arg1)->type = arg2; +} + + +SWIGEXPORT int _wrap_MRIStepCouplingMem_type_get(SwigClassWrapper const *farg1) { + int fresult ; + struct MRIStepCouplingMem *arg1 = (struct MRIStepCouplingMem *) 0 ; + MRISTEP_METHOD_TYPE result; + + SWIG_check_mutable_nonnull(*farg1, "struct MRIStepCouplingMem *", "MRIStepCouplingMem", "MRIStepCouplingMem::type", return 0); + arg1 = (struct MRIStepCouplingMem *)(farg1->cptr); + result = (MRISTEP_METHOD_TYPE) ((arg1)->type); + fresult = (int)(result); + return fresult; +} + + SWIGEXPORT void _wrap_MRIStepCouplingMem_nmat_set(SwigClassWrapper const *farg1, int const *farg2) { struct MRIStepCouplingMem *arg1 = (struct MRIStepCouplingMem *) 0 ; int arg2 ; @@ -476,6 +500,54 @@ SWIGEXPORT void * _wrap_MRIStepCouplingMem_G_get(SwigClassWrapper const *farg1) } +SWIGEXPORT void _wrap_MRIStepCouplingMem_ngroup_set(SwigClassWrapper const *farg1, int const *farg2) { + struct MRIStepCouplingMem *arg1 = (struct MRIStepCouplingMem *) 0 ; + int arg2 ; + + SWIG_check_mutable_nonnull(*farg1, "struct MRIStepCouplingMem *", "MRIStepCouplingMem", "MRIStepCouplingMem::ngroup", return ); + arg1 = (struct MRIStepCouplingMem *)(farg1->cptr); + arg2 = (int)(*farg2); + if (arg1) (arg1)->ngroup = arg2; +} + + +SWIGEXPORT int _wrap_MRIStepCouplingMem_ngroup_get(SwigClassWrapper const *farg1) { + int fresult ; + struct MRIStepCouplingMem *arg1 = (struct MRIStepCouplingMem *) 0 ; + int result; + + SWIG_check_mutable_nonnull(*farg1, "struct MRIStepCouplingMem *", "MRIStepCouplingMem", "MRIStepCouplingMem::ngroup", return 0); + arg1 = (struct MRIStepCouplingMem *)(farg1->cptr); + result = (int) ((arg1)->ngroup); + fresult = (int)(result); + return fresult; +} + + +SWIGEXPORT void _wrap_MRIStepCouplingMem_group_set(SwigClassWrapper const *farg1, void *farg2) { + struct MRIStepCouplingMem *arg1 = (struct MRIStepCouplingMem *) 0 ; + int **arg2 = (int **) 0 ; + + SWIG_check_mutable_nonnull(*farg1, "struct MRIStepCouplingMem *", "MRIStepCouplingMem", "MRIStepCouplingMem::group", return ); + arg1 = (struct MRIStepCouplingMem *)(farg1->cptr); + arg2 = (int **)(farg2); + if (arg1) (arg1)->group = arg2; +} + + +SWIGEXPORT void * _wrap_MRIStepCouplingMem_group_get(SwigClassWrapper const *farg1) { + void * fresult ; + struct MRIStepCouplingMem *arg1 = (struct MRIStepCouplingMem *) 0 ; + int **result = 0 ; + + SWIG_check_mutable_nonnull(*farg1, "struct MRIStepCouplingMem *", "MRIStepCouplingMem", "MRIStepCouplingMem::group", return 0); + arg1 = (struct MRIStepCouplingMem *)(farg1->cptr); + result = (int **) ((arg1)->group); + fresult = result; + return fresult; +} + + SWIGEXPORT SwigClassWrapper _wrap_new_MRIStepCouplingMem() { SwigClassWrapper fresult ; struct MRIStepCouplingMem *result = 0 ; @@ -741,6 +813,20 @@ SWIGEXPORT int _wrap_FMRIStepGetLastInnerStepFlag(void *farg1, int *farg2) { } +SWIGEXPORT int _wrap_FMRIStepGetNumInnerStepperFails(void *farg1, long *farg2) { + int fresult ; + void *arg1 = (void *) 0 ; + long *arg2 = (long *) 0 ; + int result; + + arg1 = (void *)(farg1); + arg2 = (long *)(farg2); + result = (int)MRIStepGetNumInnerStepperFails(arg1,arg2); + fresult = (int)(result); + return fresult; +} + + SWIGEXPORT int _wrap_FMRIStepInnerStepper_Create(void *farg1, void *farg2) { int fresult ; SUNContext arg1 = (SUNContext) 0 ; @@ -851,6 +937,48 @@ SWIGEXPORT int _wrap_FMRIStepInnerStepper_SetResetFn(void *farg1, MRIStepInnerRe } +SWIGEXPORT int _wrap_FMRIStepInnerStepper_SetAccumulatedErrorGetFn(void *farg1, MRIStepInnerGetAccumulatedError farg2) { + int fresult ; + MRIStepInnerStepper arg1 = (MRIStepInnerStepper) 0 ; + MRIStepInnerGetAccumulatedError arg2 = (MRIStepInnerGetAccumulatedError) 0 ; + int result; + + arg1 = (MRIStepInnerStepper)(farg1); + arg2 = (MRIStepInnerGetAccumulatedError)(farg2); + result = (int)MRIStepInnerStepper_SetAccumulatedErrorGetFn(arg1,arg2); + fresult = (int)(result); + return fresult; +} + + +SWIGEXPORT int _wrap_FMRIStepInnerStepper_SetAccumulatedErrorResetFn(void *farg1, MRIStepInnerResetAccumulatedError farg2) { + int fresult ; + MRIStepInnerStepper arg1 = (MRIStepInnerStepper) 0 ; + MRIStepInnerResetAccumulatedError arg2 = (MRIStepInnerResetAccumulatedError) 0 ; + int result; + + arg1 = (MRIStepInnerStepper)(farg1); + arg2 = (MRIStepInnerResetAccumulatedError)(farg2); + result = (int)MRIStepInnerStepper_SetAccumulatedErrorResetFn(arg1,arg2); + fresult = (int)(result); + return fresult; +} + + +SWIGEXPORT int _wrap_FMRIStepInnerStepper_SetRTolFn(void *farg1, MRIStepInnerSetRTol farg2) { + int fresult ; + MRIStepInnerStepper arg1 = (MRIStepInnerStepper) 0 ; + MRIStepInnerSetRTol arg2 = (MRIStepInnerSetRTol) 0 ; + int result; + + arg1 = (MRIStepInnerStepper)(farg1); + arg2 = (MRIStepInnerSetRTol)(farg2); + result = (int)MRIStepInnerStepper_SetRTolFn(arg1,arg2); + fresult = (int)(result); + return fresult; +} + + SWIGEXPORT int _wrap_FMRIStepInnerStepper_AddForcing(void *farg1, double const *farg2, N_Vector farg3) { int fresult ; MRIStepInnerStepper arg1 = (MRIStepInnerStepper) 0 ; diff --git a/src/arkode/fmod_int32/farkode_mristep_mod.f90 b/src/arkode/fmod_int32/farkode_mristep_mod.f90 index 9505d486cb..6d50d60f17 100644 --- a/src/arkode/fmod_int32/farkode_mristep_mod.f90 +++ b/src/arkode/fmod_int32/farkode_mristep_mod.f90 @@ -31,9 +31,11 @@ module farkode_mristep_mod enumerator :: MRISTEP_EXPLICIT enumerator :: MRISTEP_IMPLICIT enumerator :: MRISTEP_IMEX + enumerator :: MRISTEP_MERK + enumerator :: MRISTEP_SR end enum integer, parameter, public :: MRISTEP_METHOD_TYPE = kind(MRISTEP_EXPLICIT) - public :: MRISTEP_EXPLICIT, MRISTEP_IMPLICIT, MRISTEP_IMEX + public :: MRISTEP_EXPLICIT, MRISTEP_IMPLICIT, MRISTEP_IMEX, MRISTEP_MERK, MRISTEP_SR ! typedef enum ARKODE_MRITableID enum, bind(c) enumerator :: ARKODE_MRI_NONE = -1 @@ -57,7 +59,14 @@ module farkode_mristep_mod enumerator :: ARKODE_IMEX_MRI_GARK_EULER enumerator :: ARKODE_IMEX_MRI_GARK_TRAPEZOIDAL enumerator :: ARKODE_IMEX_MRI_GARK_MIDPOINT - enumerator :: ARKODE_MAX_MRI_NUM = ARKODE_IMEX_MRI_GARK_MIDPOINT + enumerator :: ARKODE_MERK21 + enumerator :: ARKODE_MERK32 + enumerator :: ARKODE_MERK43 + enumerator :: ARKODE_MERK54 + enumerator :: ARKODE_IMEX_MRI_SR21 + enumerator :: ARKODE_IMEX_MRI_SR32 + enumerator :: ARKODE_IMEX_MRI_SR43 + enumerator :: ARKODE_MAX_MRI_NUM = ARKODE_IMEX_MRI_SR43 end enum integer, parameter, public :: ARKODE_MRITableID = kind(ARKODE_MRI_NONE) public :: ARKODE_MRI_NONE, ARKODE_MIN_MRI_NUM, ARKODE_MIS_KW3, ARKODE_MRI_GARK_ERK33a, ARKODE_MRI_GARK_ERK45a, & @@ -65,11 +74,16 @@ module farkode_mristep_mod ARKODE_IMEX_MRI_GARK3b, ARKODE_IMEX_MRI_GARK4, ARKODE_MRI_GARK_FORWARD_EULER, ARKODE_MRI_GARK_RALSTON2, & ARKODE_MRI_GARK_ERK22a, ARKODE_MRI_GARK_ERK22b, ARKODE_MRI_GARK_RALSTON3, ARKODE_MRI_GARK_BACKWARD_EULER, & ARKODE_MRI_GARK_IMPLICIT_MIDPOINT, ARKODE_IMEX_MRI_GARK_EULER, ARKODE_IMEX_MRI_GARK_TRAPEZOIDAL, & - ARKODE_IMEX_MRI_GARK_MIDPOINT, ARKODE_MAX_MRI_NUM + ARKODE_IMEX_MRI_GARK_MIDPOINT, ARKODE_MERK21, ARKODE_MERK32, ARKODE_MERK43, ARKODE_MERK54, ARKODE_IMEX_MRI_SR21, & + ARKODE_IMEX_MRI_SR32, ARKODE_IMEX_MRI_SR43, ARKODE_MAX_MRI_NUM integer(C_INT), parameter, public :: MRISTEP_DEFAULT_EXPL_1 = ARKODE_MRI_GARK_FORWARD_EULER integer(C_INT), parameter, public :: MRISTEP_DEFAULT_EXPL_2 = ARKODE_MRI_GARK_ERK22b integer(C_INT), parameter, public :: MRISTEP_DEFAULT_EXPL_3 = ARKODE_MIS_KW3 integer(C_INT), parameter, public :: MRISTEP_DEFAULT_EXPL_4 = ARKODE_MRI_GARK_ERK45a + integer(C_INT), parameter, public :: MRISTEP_DEFAULT_EXPL_2_AD = ARKODE_MRI_GARK_ERK22b + integer(C_INT), parameter, public :: MRISTEP_DEFAULT_EXPL_3_AD = ARKODE_MRI_GARK_ERK33a + integer(C_INT), parameter, public :: MRISTEP_DEFAULT_EXPL_4_AD = ARKODE_MRI_GARK_ERK45a + integer(C_INT), parameter, public :: MRISTEP_DEFAULT_EXPL_5_AD = ARKODE_MERK54 integer(C_INT), parameter, public :: MRISTEP_DEFAULT_IMPL_SD_1 = ARKODE_MRI_GARK_BACKWARD_EULER integer(C_INT), parameter, public :: MRISTEP_DEFAULT_IMPL_SD_2 = ARKODE_MRI_GARK_IRK21a integer(C_INT), parameter, public :: MRISTEP_DEFAULT_IMPL_SD_3 = ARKODE_MRI_GARK_ESDIRK34a @@ -78,6 +92,9 @@ module farkode_mristep_mod integer(C_INT), parameter, public :: MRISTEP_DEFAULT_IMEX_SD_2 = ARKODE_IMEX_MRI_GARK_TRAPEZOIDAL integer(C_INT), parameter, public :: MRISTEP_DEFAULT_IMEX_SD_3 = ARKODE_IMEX_MRI_GARK3b integer(C_INT), parameter, public :: MRISTEP_DEFAULT_IMEX_SD_4 = ARKODE_IMEX_MRI_GARK4 + integer(C_INT), parameter, public :: MRISTEP_DEFAULT_IMEX_SD_2_AD = ARKODE_IMEX_MRI_SR21 + integer(C_INT), parameter, public :: MRISTEP_DEFAULT_IMEX_SD_3_AD = ARKODE_IMEX_MRI_SR32 + integer(C_INT), parameter, public :: MRISTEP_DEFAULT_IMEX_SD_4_AD = ARKODE_IMEX_MRI_SR43 integer, parameter :: swig_cmem_own_bit = 0 integer, parameter :: swig_cmem_rvalue_bit = 1 @@ -90,6 +107,8 @@ module farkode_mristep_mod type, public :: MRIStepCouplingMem type(SwigClassWrapper), public :: swigdata contains + procedure :: set_type => swigf_MRIStepCouplingMem_type_set + procedure :: get_type => swigf_MRIStepCouplingMem_type_get procedure :: set_nmat => swigf_MRIStepCouplingMem_nmat_set procedure :: get_nmat => swigf_MRIStepCouplingMem_nmat_get procedure :: set_stages => swigf_MRIStepCouplingMem_stages_set @@ -104,6 +123,10 @@ module farkode_mristep_mod procedure :: get_W => swigf_MRIStepCouplingMem_W_get procedure :: set_G => swigf_MRIStepCouplingMem_G_set procedure :: get_G => swigf_MRIStepCouplingMem_G_get + procedure :: set_ngroup => swigf_MRIStepCouplingMem_ngroup_set + procedure :: get_ngroup => swigf_MRIStepCouplingMem_ngroup_get + procedure :: set_group => swigf_MRIStepCouplingMem_group_set + procedure :: get_group => swigf_MRIStepCouplingMem_group_get procedure :: release => swigf_release_MRIStepCouplingMem procedure, private :: swigf_MRIStepCouplingMem_op_assign__ generic :: assignment(=) => swigf_MRIStepCouplingMem_op_assign__ @@ -131,6 +154,7 @@ module farkode_mristep_mod public :: FMRIStepSetPostInnerFn public :: FMRIStepGetCurrentCoupling public :: FMRIStepGetLastInnerStepFlag + public :: FMRIStepGetNumInnerStepperFails public :: FMRIStepInnerStepper_Create public :: FMRIStepInnerStepper_CreateFromSUNStepper public :: FMRIStepInnerStepper_Free @@ -139,6 +163,9 @@ module farkode_mristep_mod public :: FMRIStepInnerStepper_SetEvolveFn public :: FMRIStepInnerStepper_SetFullRhsFn public :: FMRIStepInnerStepper_SetResetFn + public :: FMRIStepInnerStepper_SetAccumulatedErrorGetFn + public :: FMRIStepInnerStepper_SetAccumulatedErrorResetFn + public :: FMRIStepInnerStepper_SetRTolFn public :: FMRIStepInnerStepper_AddForcing public :: FMRIStepInnerStepper_GetForcingData public :: FMRIStepResize @@ -230,6 +257,23 @@ module farkode_mristep_mod ! WRAPPER DECLARATIONS interface +subroutine swigc_MRIStepCouplingMem_type_set(farg1, farg2) & +bind(C, name="_wrap_MRIStepCouplingMem_type_set") +use, intrinsic :: ISO_C_BINDING +import :: swigclasswrapper +type(SwigClassWrapper) :: farg1 +integer(C_INT), intent(in) :: farg2 +end subroutine + +function swigc_MRIStepCouplingMem_type_get(farg1) & +bind(C, name="_wrap_MRIStepCouplingMem_type_get") & +result(fresult) +use, intrinsic :: ISO_C_BINDING +import :: swigclasswrapper +type(SwigClassWrapper) :: farg1 +integer(C_INT) :: fresult +end function + subroutine swigc_MRIStepCouplingMem_nmat_set(farg1, farg2) & bind(C, name="_wrap_MRIStepCouplingMem_nmat_set") use, intrinsic :: ISO_C_BINDING @@ -349,6 +393,40 @@ function swigc_MRIStepCouplingMem_G_get(farg1) & type(C_PTR) :: fresult end function +subroutine swigc_MRIStepCouplingMem_ngroup_set(farg1, farg2) & +bind(C, name="_wrap_MRIStepCouplingMem_ngroup_set") +use, intrinsic :: ISO_C_BINDING +import :: swigclasswrapper +type(SwigClassWrapper) :: farg1 +integer(C_INT), intent(in) :: farg2 +end subroutine + +function swigc_MRIStepCouplingMem_ngroup_get(farg1) & +bind(C, name="_wrap_MRIStepCouplingMem_ngroup_get") & +result(fresult) +use, intrinsic :: ISO_C_BINDING +import :: swigclasswrapper +type(SwigClassWrapper) :: farg1 +integer(C_INT) :: fresult +end function + +subroutine swigc_MRIStepCouplingMem_group_set(farg1, farg2) & +bind(C, name="_wrap_MRIStepCouplingMem_group_set") +use, intrinsic :: ISO_C_BINDING +import :: swigclasswrapper +type(SwigClassWrapper) :: farg1 +type(C_PTR), value :: farg2 +end subroutine + +function swigc_MRIStepCouplingMem_group_get(farg1) & +bind(C, name="_wrap_MRIStepCouplingMem_group_get") & +result(fresult) +use, intrinsic :: ISO_C_BINDING +import :: swigclasswrapper +type(SwigClassWrapper) :: farg1 +type(C_PTR) :: fresult +end function + function swigc_new_MRIStepCouplingMem() & bind(C, name="_wrap_new_MRIStepCouplingMem") & result(fresult) @@ -522,6 +600,15 @@ function swigc_FMRIStepGetLastInnerStepFlag(farg1, farg2) & integer(C_INT) :: fresult end function +function swigc_FMRIStepGetNumInnerStepperFails(farg1, farg2) & +bind(C, name="_wrap_FMRIStepGetNumInnerStepperFails") & +result(fresult) +use, intrinsic :: ISO_C_BINDING +type(C_PTR), value :: farg1 +type(C_PTR), value :: farg2 +integer(C_INT) :: fresult +end function + function swigc_FMRIStepInnerStepper_Create(farg1, farg2) & bind(C, name="_wrap_FMRIStepInnerStepper_Create") & result(fresult) @@ -593,6 +680,33 @@ function swigc_FMRIStepInnerStepper_SetResetFn(farg1, farg2) & integer(C_INT) :: fresult end function +function swigc_FMRIStepInnerStepper_SetAccumulatedErrorGetFn(farg1, farg2) & +bind(C, name="_wrap_FMRIStepInnerStepper_SetAccumulatedErrorGetFn") & +result(fresult) +use, intrinsic :: ISO_C_BINDING +type(C_PTR), value :: farg1 +type(C_FUNPTR), value :: farg2 +integer(C_INT) :: fresult +end function + +function swigc_FMRIStepInnerStepper_SetAccumulatedErrorResetFn(farg1, farg2) & +bind(C, name="_wrap_FMRIStepInnerStepper_SetAccumulatedErrorResetFn") & +result(fresult) +use, intrinsic :: ISO_C_BINDING +type(C_PTR), value :: farg1 +type(C_FUNPTR), value :: farg2 +integer(C_INT) :: fresult +end function + +function swigc_FMRIStepInnerStepper_SetRTolFn(farg1, farg2) & +bind(C, name="_wrap_FMRIStepInnerStepper_SetRTolFn") & +result(fresult) +use, intrinsic :: ISO_C_BINDING +type(C_PTR), value :: farg1 +type(C_FUNPTR), value :: farg2 +integer(C_INT) :: fresult +end function + function swigc_FMRIStepInnerStepper_AddForcing(farg1, farg2, farg3) & bind(C, name="_wrap_FMRIStepInnerStepper_AddForcing") & result(fresult) @@ -1417,6 +1531,31 @@ function swigc_FMRIStepGetNumRhsEvals(farg1, farg2, farg3) & contains ! MODULE SUBPROGRAMS +subroutine swigf_MRIStepCouplingMem_type_set(self, type) +use, intrinsic :: ISO_C_BINDING +class(MRIStepCouplingMem), intent(in) :: self +integer(MRISTEP_METHOD_TYPE), intent(in) :: type +type(SwigClassWrapper) :: farg1 +integer(C_INT) :: farg2 + +farg1 = self%swigdata +farg2 = type +call swigc_MRIStepCouplingMem_type_set(farg1, farg2) +end subroutine + +function swigf_MRIStepCouplingMem_type_get(self) & +result(swig_result) +use, intrinsic :: ISO_C_BINDING +integer(MRISTEP_METHOD_TYPE) :: swig_result +class(MRIStepCouplingMem), intent(in) :: self +integer(C_INT) :: fresult +type(SwigClassWrapper) :: farg1 + +farg1 = self%swigdata +fresult = swigc_MRIStepCouplingMem_type_get(farg1) +swig_result = fresult +end function + subroutine swigf_MRIStepCouplingMem_nmat_set(self, nmat) use, intrinsic :: ISO_C_BINDING class(MRIStepCouplingMem), intent(in) :: self @@ -1592,6 +1731,56 @@ function swigf_MRIStepCouplingMem_G_get(self) & call c_f_pointer(fresult, swig_result) end function +subroutine swigf_MRIStepCouplingMem_ngroup_set(self, ngroup) +use, intrinsic :: ISO_C_BINDING +class(MRIStepCouplingMem), intent(in) :: self +integer(C_INT), intent(in) :: ngroup +type(SwigClassWrapper) :: farg1 +integer(C_INT) :: farg2 + +farg1 = self%swigdata +farg2 = ngroup +call swigc_MRIStepCouplingMem_ngroup_set(farg1, farg2) +end subroutine + +function swigf_MRIStepCouplingMem_ngroup_get(self) & +result(swig_result) +use, intrinsic :: ISO_C_BINDING +integer(C_INT) :: swig_result +class(MRIStepCouplingMem), intent(in) :: self +integer(C_INT) :: fresult +type(SwigClassWrapper) :: farg1 + +farg1 = self%swigdata +fresult = swigc_MRIStepCouplingMem_ngroup_get(farg1) +swig_result = fresult +end function + +subroutine swigf_MRIStepCouplingMem_group_set(self, group) +use, intrinsic :: ISO_C_BINDING +class(MRIStepCouplingMem), intent(in) :: self +type(C_PTR), target, intent(inout) :: group +type(SwigClassWrapper) :: farg1 +type(C_PTR) :: farg2 + +farg1 = self%swigdata +farg2 = c_loc(group) +call swigc_MRIStepCouplingMem_group_set(farg1, farg2) +end subroutine + +function swigf_MRIStepCouplingMem_group_get(self) & +result(swig_result) +use, intrinsic :: ISO_C_BINDING +type(C_PTR), pointer :: swig_result +class(MRIStepCouplingMem), intent(in) :: self +type(C_PTR) :: fresult +type(SwigClassWrapper) :: farg1 + +farg1 = self%swigdata +fresult = swigc_MRIStepCouplingMem_group_get(farg1) +call c_f_pointer(fresult, swig_result) +end function + function swigf_create_MRIStepCouplingMem() & result(self) use, intrinsic :: ISO_C_BINDING @@ -1925,6 +2114,22 @@ function FMRIStepGetLastInnerStepFlag(arkode_mem, flag) & swig_result = fresult end function +function FMRIStepGetNumInnerStepperFails(arkode_mem, inner_fails) & +result(swig_result) +use, intrinsic :: ISO_C_BINDING +integer(C_INT) :: swig_result +type(C_PTR) :: arkode_mem +integer(C_LONG), dimension(*), target, intent(inout) :: inner_fails +integer(C_INT) :: fresult +type(C_PTR) :: farg1 +type(C_PTR) :: farg2 + +farg1 = arkode_mem +farg2 = c_loc(inner_fails(1)) +fresult = swigc_FMRIStepGetNumInnerStepperFails(farg1, farg2) +swig_result = fresult +end function + function FMRIStepInnerStepper_Create(sunctx, stepper) & result(swig_result) use, intrinsic :: ISO_C_BINDING @@ -2050,6 +2255,54 @@ function FMRIStepInnerStepper_SetResetFn(stepper, fn) & swig_result = fresult end function +function FMRIStepInnerStepper_SetAccumulatedErrorGetFn(stepper, fn) & +result(swig_result) +use, intrinsic :: ISO_C_BINDING +integer(C_INT) :: swig_result +type(C_PTR) :: stepper +type(C_FUNPTR), intent(in), value :: fn +integer(C_INT) :: fresult +type(C_PTR) :: farg1 +type(C_FUNPTR) :: farg2 + +farg1 = stepper +farg2 = fn +fresult = swigc_FMRIStepInnerStepper_SetAccumulatedErrorGetFn(farg1, farg2) +swig_result = fresult +end function + +function FMRIStepInnerStepper_SetAccumulatedErrorResetFn(stepper, fn) & +result(swig_result) +use, intrinsic :: ISO_C_BINDING +integer(C_INT) :: swig_result +type(C_PTR) :: stepper +type(C_FUNPTR), intent(in), value :: fn +integer(C_INT) :: fresult +type(C_PTR) :: farg1 +type(C_FUNPTR) :: farg2 + +farg1 = stepper +farg2 = fn +fresult = swigc_FMRIStepInnerStepper_SetAccumulatedErrorResetFn(farg1, farg2) +swig_result = fresult +end function + +function FMRIStepInnerStepper_SetRTolFn(stepper, fn) & +result(swig_result) +use, intrinsic :: ISO_C_BINDING +integer(C_INT) :: swig_result +type(C_PTR) :: stepper +type(C_FUNPTR), intent(in), value :: fn +integer(C_INT) :: fresult +type(C_PTR) :: farg1 +type(C_FUNPTR) :: farg2 + +farg1 = stepper +farg2 = fn +fresult = swigc_FMRIStepInnerStepper_SetRTolFn(farg1, farg2) +swig_result = fresult +end function + function FMRIStepInnerStepper_AddForcing(stepper, t, f) & result(swig_result) use, intrinsic :: ISO_C_BINDING diff --git a/src/arkode/fmod_int64/farkode_mod.c b/src/arkode/fmod_int64/farkode_mod.c index 5a63d50210..dcc19f5c3c 100644 --- a/src/arkode/fmod_int64/farkode_mod.c +++ b/src/arkode/fmod_int64/farkode_mod.c @@ -353,6 +353,20 @@ SWIGEXPORT int _wrap_FARKodeReset(void *farg1, double const *farg2, N_Vector far } +SWIGEXPORT int _wrap_FARKodeCreateMRIStepInnerStepper(void *farg1, void *farg2) { + int fresult ; + void *arg1 = (void *) 0 ; + MRIStepInnerStepper *arg2 = (MRIStepInnerStepper *) 0 ; + int result; + + arg1 = (void *)(farg1); + arg2 = (MRIStepInnerStepper *)(farg2); + result = (int)ARKodeCreateMRIStepInnerStepper(arg1,arg2); + fresult = (int)(result); + return fresult; +} + + SWIGEXPORT int _wrap_FARKodeSStolerances(void *farg1, double const *farg2, double const *farg3) { int fresult ; void *arg1 = (void *) 0 ; @@ -1139,6 +1153,32 @@ SWIGEXPORT int _wrap_FARKodeSetMaxNumConstrFails(void *farg1, int const *farg2) } +SWIGEXPORT int _wrap_FARKodeSetAccumulatedErrorType(void *farg1, int const *farg2) { + int fresult ; + void *arg1 = (void *) 0 ; + ARKAccumError arg2 ; + int result; + + arg1 = (void *)(farg1); + arg2 = (ARKAccumError)(*farg2); + result = (int)ARKodeSetAccumulatedErrorType(arg1,arg2); + fresult = (int)(result); + return fresult; +} + + +SWIGEXPORT int _wrap_FARKodeResetAccumulatedError(void *farg1) { + int fresult ; + void *arg1 = (void *) 0 ; + int result; + + arg1 = (void *)(farg1); + result = (int)ARKodeResetAccumulatedError(arg1); + fresult = (int)(result); + return fresult; +} + + SWIGEXPORT int _wrap_FARKodeEvolve(void *farg1, double const *farg2, N_Vector farg3, double *farg4, int const *farg5) { int fresult ; void *arg1 = (void *) 0 ; @@ -1500,6 +1540,20 @@ SWIGEXPORT int _wrap_FARKodeGetStepStats(void *farg1, long *farg2, double *farg3 } +SWIGEXPORT int _wrap_FARKodeGetAccumulatedError(void *farg1, double *farg2) { + int fresult ; + void *arg1 = (void *) 0 ; + sunrealtype *arg2 = (sunrealtype *) 0 ; + int result; + + arg1 = (void *)(farg1); + arg2 = (sunrealtype *)(farg2); + result = (int)ARKodeGetAccumulatedError(arg1,arg2); + fresult = (int)(result); + return fresult; +} + + SWIGEXPORT int _wrap_FARKodeGetNumLinSolvSetups(void *farg1, long *farg2) { int fresult ; void *arg1 = (void *) 0 ; diff --git a/src/arkode/fmod_int64/farkode_mod.f90 b/src/arkode/fmod_int64/farkode_mod.f90 index 3b255deb0d..9f15a8f8d7 100644 --- a/src/arkode/fmod_int64/farkode_mod.f90 +++ b/src/arkode/fmod_int64/farkode_mod.f90 @@ -105,8 +105,18 @@ module farkode_mod end enum integer, parameter, public :: ARKRelaxSolver = kind(ARK_RELAX_BRENT) public :: ARK_RELAX_BRENT, ARK_RELAX_NEWTON + ! typedef enum ARKAccumError + enum, bind(c) + enumerator :: ARK_ACCUMERROR_NONE + enumerator :: ARK_ACCUMERROR_MAX + enumerator :: ARK_ACCUMERROR_SUM + enumerator :: ARK_ACCUMERROR_AVG + end enum + integer, parameter, public :: ARKAccumError = kind(ARK_ACCUMERROR_NONE) + public :: ARK_ACCUMERROR_NONE, ARK_ACCUMERROR_MAX, ARK_ACCUMERROR_SUM, ARK_ACCUMERROR_AVG public :: FARKodeResize public :: FARKodeReset + public :: FARKodeCreateMRIStepInnerStepper public :: FARKodeSStolerances public :: FARKodeSVtolerances public :: FARKodeWFtolerances @@ -163,6 +173,8 @@ module farkode_mod public :: FARKodeSetMinStep public :: FARKodeSetMaxStep public :: FARKodeSetMaxNumConstrFails + public :: FARKodeSetAccumulatedErrorType + public :: FARKodeResetAccumulatedError public :: FARKodeEvolve public :: FARKodeGetDky public :: FARKodeComputeState @@ -191,6 +203,7 @@ module farkode_mod public :: FARKodeGetTolScaleFactor public :: FARKodeGetNumConstrFails public :: FARKodeGetStepStats + public :: FARKodeGetAccumulatedError public :: FARKodeGetNumLinSolvSetups public :: FARKodeGetCurrentTime public :: FARKodeGetCurrentState @@ -486,6 +499,15 @@ function swigc_FARKodeReset(farg1, farg2, farg3) & integer(C_INT) :: fresult end function +function swigc_FARKodeCreateMRIStepInnerStepper(farg1, farg2) & +bind(C, name="_wrap_FARKodeCreateMRIStepInnerStepper") & +result(fresult) +use, intrinsic :: ISO_C_BINDING +type(C_PTR), value :: farg1 +type(C_PTR), value :: farg2 +integer(C_INT) :: fresult +end function + function swigc_FARKodeSStolerances(farg1, farg2, farg3) & bind(C, name="_wrap_FARKodeSStolerances") & result(fresult) @@ -991,6 +1013,23 @@ function swigc_FARKodeSetMaxNumConstrFails(farg1, farg2) & integer(C_INT) :: fresult end function +function swigc_FARKodeSetAccumulatedErrorType(farg1, farg2) & +bind(C, name="_wrap_FARKodeSetAccumulatedErrorType") & +result(fresult) +use, intrinsic :: ISO_C_BINDING +type(C_PTR), value :: farg1 +integer(C_INT), intent(in) :: farg2 +integer(C_INT) :: fresult +end function + +function swigc_FARKodeResetAccumulatedError(farg1) & +bind(C, name="_wrap_FARKodeResetAccumulatedError") & +result(fresult) +use, intrinsic :: ISO_C_BINDING +type(C_PTR), value :: farg1 +integer(C_INT) :: fresult +end function + function swigc_FARKodeEvolve(farg1, farg2, farg3, farg4, farg5) & bind(C, name="_wrap_FARKodeEvolve") & result(fresult) @@ -1225,6 +1264,15 @@ function swigc_FARKodeGetStepStats(farg1, farg2, farg3, farg4, farg5, farg6) & integer(C_INT) :: fresult end function +function swigc_FARKodeGetAccumulatedError(farg1, farg2) & +bind(C, name="_wrap_FARKodeGetAccumulatedError") & +result(fresult) +use, intrinsic :: ISO_C_BINDING +type(C_PTR), value :: farg1 +type(C_PTR), value :: farg2 +integer(C_INT) :: fresult +end function + function swigc_FARKodeGetNumLinSolvSetups(farg1, farg2) & bind(C, name="_wrap_FARKodeGetNumLinSolvSetups") & result(fresult) @@ -2440,6 +2488,22 @@ function FARKodeReset(arkode_mem, tr, yr) & swig_result = fresult end function +function FARKodeCreateMRIStepInnerStepper(arkode_mem, stepper) & +result(swig_result) +use, intrinsic :: ISO_C_BINDING +integer(C_INT) :: swig_result +type(C_PTR) :: arkode_mem +type(C_PTR), target, intent(inout) :: stepper +integer(C_INT) :: fresult +type(C_PTR) :: farg1 +type(C_PTR) :: farg2 + +farg1 = arkode_mem +farg2 = c_loc(stepper) +fresult = swigc_FARKodeCreateMRIStepInnerStepper(farg1, farg2) +swig_result = fresult +end function + function FARKodeSStolerances(arkode_mem, reltol, abstol) & result(swig_result) use, intrinsic :: ISO_C_BINDING @@ -3339,6 +3403,35 @@ function FARKodeSetMaxNumConstrFails(arkode_mem, maxfails) & swig_result = fresult end function +function FARKodeSetAccumulatedErrorType(arkode_mem, accum_type) & +result(swig_result) +use, intrinsic :: ISO_C_BINDING +integer(C_INT) :: swig_result +type(C_PTR) :: arkode_mem +integer(ARKAccumError), intent(in) :: accum_type +integer(C_INT) :: fresult +type(C_PTR) :: farg1 +integer(C_INT) :: farg2 + +farg1 = arkode_mem +farg2 = accum_type +fresult = swigc_FARKodeSetAccumulatedErrorType(farg1, farg2) +swig_result = fresult +end function + +function FARKodeResetAccumulatedError(arkode_mem) & +result(swig_result) +use, intrinsic :: ISO_C_BINDING +integer(C_INT) :: swig_result +type(C_PTR) :: arkode_mem +integer(C_INT) :: fresult +type(C_PTR) :: farg1 + +farg1 = arkode_mem +fresult = swigc_FARKodeResetAccumulatedError(farg1) +swig_result = fresult +end function + function FARKodeEvolve(arkode_mem, tout, yout, tret, itask) & result(swig_result) use, intrinsic :: ISO_C_BINDING @@ -3774,6 +3867,22 @@ function FARKodeGetStepStats(arkode_mem, nsteps, hinused, hlast, hcur, tcur) & swig_result = fresult end function +function FARKodeGetAccumulatedError(arkode_mem, accum_error) & +result(swig_result) +use, intrinsic :: ISO_C_BINDING +integer(C_INT) :: swig_result +type(C_PTR) :: arkode_mem +real(C_DOUBLE), dimension(*), target, intent(inout) :: accum_error +integer(C_INT) :: fresult +type(C_PTR) :: farg1 +type(C_PTR) :: farg2 + +farg1 = arkode_mem +farg2 = c_loc(accum_error(1)) +fresult = swigc_FARKodeGetAccumulatedError(farg1, farg2) +swig_result = fresult +end function + function FARKodeGetNumLinSolvSetups(arkode_mem, nlinsetups) & result(swig_result) use, intrinsic :: ISO_C_BINDING diff --git a/src/arkode/fmod_int64/farkode_mristep_mod.c b/src/arkode/fmod_int64/farkode_mristep_mod.c index d5597bea4f..303a28af2f 100644 --- a/src/arkode/fmod_int64/farkode_mristep_mod.c +++ b/src/arkode/fmod_int64/farkode_mristep_mod.c @@ -308,6 +308,30 @@ SWIGINTERN SwigArrayWrapper SwigArrayWrapper_uninitialized() { return result; } +SWIGEXPORT void _wrap_MRIStepCouplingMem_type_set(SwigClassWrapper const *farg1, int const *farg2) { + struct MRIStepCouplingMem *arg1 = (struct MRIStepCouplingMem *) 0 ; + MRISTEP_METHOD_TYPE arg2 ; + + SWIG_check_mutable_nonnull(*farg1, "struct MRIStepCouplingMem *", "MRIStepCouplingMem", "MRIStepCouplingMem::type", return ); + arg1 = (struct MRIStepCouplingMem *)(farg1->cptr); + arg2 = (MRISTEP_METHOD_TYPE)(*farg2); + if (arg1) (arg1)->type = arg2; +} + + +SWIGEXPORT int _wrap_MRIStepCouplingMem_type_get(SwigClassWrapper const *farg1) { + int fresult ; + struct MRIStepCouplingMem *arg1 = (struct MRIStepCouplingMem *) 0 ; + MRISTEP_METHOD_TYPE result; + + SWIG_check_mutable_nonnull(*farg1, "struct MRIStepCouplingMem *", "MRIStepCouplingMem", "MRIStepCouplingMem::type", return 0); + arg1 = (struct MRIStepCouplingMem *)(farg1->cptr); + result = (MRISTEP_METHOD_TYPE) ((arg1)->type); + fresult = (int)(result); + return fresult; +} + + SWIGEXPORT void _wrap_MRIStepCouplingMem_nmat_set(SwigClassWrapper const *farg1, int const *farg2) { struct MRIStepCouplingMem *arg1 = (struct MRIStepCouplingMem *) 0 ; int arg2 ; @@ -476,6 +500,54 @@ SWIGEXPORT void * _wrap_MRIStepCouplingMem_G_get(SwigClassWrapper const *farg1) } +SWIGEXPORT void _wrap_MRIStepCouplingMem_ngroup_set(SwigClassWrapper const *farg1, int const *farg2) { + struct MRIStepCouplingMem *arg1 = (struct MRIStepCouplingMem *) 0 ; + int arg2 ; + + SWIG_check_mutable_nonnull(*farg1, "struct MRIStepCouplingMem *", "MRIStepCouplingMem", "MRIStepCouplingMem::ngroup", return ); + arg1 = (struct MRIStepCouplingMem *)(farg1->cptr); + arg2 = (int)(*farg2); + if (arg1) (arg1)->ngroup = arg2; +} + + +SWIGEXPORT int _wrap_MRIStepCouplingMem_ngroup_get(SwigClassWrapper const *farg1) { + int fresult ; + struct MRIStepCouplingMem *arg1 = (struct MRIStepCouplingMem *) 0 ; + int result; + + SWIG_check_mutable_nonnull(*farg1, "struct MRIStepCouplingMem *", "MRIStepCouplingMem", "MRIStepCouplingMem::ngroup", return 0); + arg1 = (struct MRIStepCouplingMem *)(farg1->cptr); + result = (int) ((arg1)->ngroup); + fresult = (int)(result); + return fresult; +} + + +SWIGEXPORT void _wrap_MRIStepCouplingMem_group_set(SwigClassWrapper const *farg1, void *farg2) { + struct MRIStepCouplingMem *arg1 = (struct MRIStepCouplingMem *) 0 ; + int **arg2 = (int **) 0 ; + + SWIG_check_mutable_nonnull(*farg1, "struct MRIStepCouplingMem *", "MRIStepCouplingMem", "MRIStepCouplingMem::group", return ); + arg1 = (struct MRIStepCouplingMem *)(farg1->cptr); + arg2 = (int **)(farg2); + if (arg1) (arg1)->group = arg2; +} + + +SWIGEXPORT void * _wrap_MRIStepCouplingMem_group_get(SwigClassWrapper const *farg1) { + void * fresult ; + struct MRIStepCouplingMem *arg1 = (struct MRIStepCouplingMem *) 0 ; + int **result = 0 ; + + SWIG_check_mutable_nonnull(*farg1, "struct MRIStepCouplingMem *", "MRIStepCouplingMem", "MRIStepCouplingMem::group", return 0); + arg1 = (struct MRIStepCouplingMem *)(farg1->cptr); + result = (int **) ((arg1)->group); + fresult = result; + return fresult; +} + + SWIGEXPORT SwigClassWrapper _wrap_new_MRIStepCouplingMem() { SwigClassWrapper fresult ; struct MRIStepCouplingMem *result = 0 ; @@ -741,6 +813,20 @@ SWIGEXPORT int _wrap_FMRIStepGetLastInnerStepFlag(void *farg1, int *farg2) { } +SWIGEXPORT int _wrap_FMRIStepGetNumInnerStepperFails(void *farg1, long *farg2) { + int fresult ; + void *arg1 = (void *) 0 ; + long *arg2 = (long *) 0 ; + int result; + + arg1 = (void *)(farg1); + arg2 = (long *)(farg2); + result = (int)MRIStepGetNumInnerStepperFails(arg1,arg2); + fresult = (int)(result); + return fresult; +} + + SWIGEXPORT int _wrap_FMRIStepInnerStepper_Create(void *farg1, void *farg2) { int fresult ; SUNContext arg1 = (SUNContext) 0 ; @@ -851,6 +937,48 @@ SWIGEXPORT int _wrap_FMRIStepInnerStepper_SetResetFn(void *farg1, MRIStepInnerRe } +SWIGEXPORT int _wrap_FMRIStepInnerStepper_SetAccumulatedErrorGetFn(void *farg1, MRIStepInnerGetAccumulatedError farg2) { + int fresult ; + MRIStepInnerStepper arg1 = (MRIStepInnerStepper) 0 ; + MRIStepInnerGetAccumulatedError arg2 = (MRIStepInnerGetAccumulatedError) 0 ; + int result; + + arg1 = (MRIStepInnerStepper)(farg1); + arg2 = (MRIStepInnerGetAccumulatedError)(farg2); + result = (int)MRIStepInnerStepper_SetAccumulatedErrorGetFn(arg1,arg2); + fresult = (int)(result); + return fresult; +} + + +SWIGEXPORT int _wrap_FMRIStepInnerStepper_SetAccumulatedErrorResetFn(void *farg1, MRIStepInnerResetAccumulatedError farg2) { + int fresult ; + MRIStepInnerStepper arg1 = (MRIStepInnerStepper) 0 ; + MRIStepInnerResetAccumulatedError arg2 = (MRIStepInnerResetAccumulatedError) 0 ; + int result; + + arg1 = (MRIStepInnerStepper)(farg1); + arg2 = (MRIStepInnerResetAccumulatedError)(farg2); + result = (int)MRIStepInnerStepper_SetAccumulatedErrorResetFn(arg1,arg2); + fresult = (int)(result); + return fresult; +} + + +SWIGEXPORT int _wrap_FMRIStepInnerStepper_SetRTolFn(void *farg1, MRIStepInnerSetRTol farg2) { + int fresult ; + MRIStepInnerStepper arg1 = (MRIStepInnerStepper) 0 ; + MRIStepInnerSetRTol arg2 = (MRIStepInnerSetRTol) 0 ; + int result; + + arg1 = (MRIStepInnerStepper)(farg1); + arg2 = (MRIStepInnerSetRTol)(farg2); + result = (int)MRIStepInnerStepper_SetRTolFn(arg1,arg2); + fresult = (int)(result); + return fresult; +} + + SWIGEXPORT int _wrap_FMRIStepInnerStepper_AddForcing(void *farg1, double const *farg2, N_Vector farg3) { int fresult ; MRIStepInnerStepper arg1 = (MRIStepInnerStepper) 0 ; diff --git a/src/arkode/fmod_int64/farkode_mristep_mod.f90 b/src/arkode/fmod_int64/farkode_mristep_mod.f90 index e2202c73da..2563b41dd7 100644 --- a/src/arkode/fmod_int64/farkode_mristep_mod.f90 +++ b/src/arkode/fmod_int64/farkode_mristep_mod.f90 @@ -31,9 +31,11 @@ module farkode_mristep_mod enumerator :: MRISTEP_EXPLICIT enumerator :: MRISTEP_IMPLICIT enumerator :: MRISTEP_IMEX + enumerator :: MRISTEP_MERK + enumerator :: MRISTEP_SR end enum integer, parameter, public :: MRISTEP_METHOD_TYPE = kind(MRISTEP_EXPLICIT) - public :: MRISTEP_EXPLICIT, MRISTEP_IMPLICIT, MRISTEP_IMEX + public :: MRISTEP_EXPLICIT, MRISTEP_IMPLICIT, MRISTEP_IMEX, MRISTEP_MERK, MRISTEP_SR ! typedef enum ARKODE_MRITableID enum, bind(c) enumerator :: ARKODE_MRI_NONE = -1 @@ -57,7 +59,14 @@ module farkode_mristep_mod enumerator :: ARKODE_IMEX_MRI_GARK_EULER enumerator :: ARKODE_IMEX_MRI_GARK_TRAPEZOIDAL enumerator :: ARKODE_IMEX_MRI_GARK_MIDPOINT - enumerator :: ARKODE_MAX_MRI_NUM = ARKODE_IMEX_MRI_GARK_MIDPOINT + enumerator :: ARKODE_MERK21 + enumerator :: ARKODE_MERK32 + enumerator :: ARKODE_MERK43 + enumerator :: ARKODE_MERK54 + enumerator :: ARKODE_IMEX_MRI_SR21 + enumerator :: ARKODE_IMEX_MRI_SR32 + enumerator :: ARKODE_IMEX_MRI_SR43 + enumerator :: ARKODE_MAX_MRI_NUM = ARKODE_IMEX_MRI_SR43 end enum integer, parameter, public :: ARKODE_MRITableID = kind(ARKODE_MRI_NONE) public :: ARKODE_MRI_NONE, ARKODE_MIN_MRI_NUM, ARKODE_MIS_KW3, ARKODE_MRI_GARK_ERK33a, ARKODE_MRI_GARK_ERK45a, & @@ -65,11 +74,16 @@ module farkode_mristep_mod ARKODE_IMEX_MRI_GARK3b, ARKODE_IMEX_MRI_GARK4, ARKODE_MRI_GARK_FORWARD_EULER, ARKODE_MRI_GARK_RALSTON2, & ARKODE_MRI_GARK_ERK22a, ARKODE_MRI_GARK_ERK22b, ARKODE_MRI_GARK_RALSTON3, ARKODE_MRI_GARK_BACKWARD_EULER, & ARKODE_MRI_GARK_IMPLICIT_MIDPOINT, ARKODE_IMEX_MRI_GARK_EULER, ARKODE_IMEX_MRI_GARK_TRAPEZOIDAL, & - ARKODE_IMEX_MRI_GARK_MIDPOINT, ARKODE_MAX_MRI_NUM + ARKODE_IMEX_MRI_GARK_MIDPOINT, ARKODE_MERK21, ARKODE_MERK32, ARKODE_MERK43, ARKODE_MERK54, ARKODE_IMEX_MRI_SR21, & + ARKODE_IMEX_MRI_SR32, ARKODE_IMEX_MRI_SR43, ARKODE_MAX_MRI_NUM integer(C_INT), parameter, public :: MRISTEP_DEFAULT_EXPL_1 = ARKODE_MRI_GARK_FORWARD_EULER integer(C_INT), parameter, public :: MRISTEP_DEFAULT_EXPL_2 = ARKODE_MRI_GARK_ERK22b integer(C_INT), parameter, public :: MRISTEP_DEFAULT_EXPL_3 = ARKODE_MIS_KW3 integer(C_INT), parameter, public :: MRISTEP_DEFAULT_EXPL_4 = ARKODE_MRI_GARK_ERK45a + integer(C_INT), parameter, public :: MRISTEP_DEFAULT_EXPL_2_AD = ARKODE_MRI_GARK_ERK22b + integer(C_INT), parameter, public :: MRISTEP_DEFAULT_EXPL_3_AD = ARKODE_MRI_GARK_ERK33a + integer(C_INT), parameter, public :: MRISTEP_DEFAULT_EXPL_4_AD = ARKODE_MRI_GARK_ERK45a + integer(C_INT), parameter, public :: MRISTEP_DEFAULT_EXPL_5_AD = ARKODE_MERK54 integer(C_INT), parameter, public :: MRISTEP_DEFAULT_IMPL_SD_1 = ARKODE_MRI_GARK_BACKWARD_EULER integer(C_INT), parameter, public :: MRISTEP_DEFAULT_IMPL_SD_2 = ARKODE_MRI_GARK_IRK21a integer(C_INT), parameter, public :: MRISTEP_DEFAULT_IMPL_SD_3 = ARKODE_MRI_GARK_ESDIRK34a @@ -78,6 +92,9 @@ module farkode_mristep_mod integer(C_INT), parameter, public :: MRISTEP_DEFAULT_IMEX_SD_2 = ARKODE_IMEX_MRI_GARK_TRAPEZOIDAL integer(C_INT), parameter, public :: MRISTEP_DEFAULT_IMEX_SD_3 = ARKODE_IMEX_MRI_GARK3b integer(C_INT), parameter, public :: MRISTEP_DEFAULT_IMEX_SD_4 = ARKODE_IMEX_MRI_GARK4 + integer(C_INT), parameter, public :: MRISTEP_DEFAULT_IMEX_SD_2_AD = ARKODE_IMEX_MRI_SR21 + integer(C_INT), parameter, public :: MRISTEP_DEFAULT_IMEX_SD_3_AD = ARKODE_IMEX_MRI_SR32 + integer(C_INT), parameter, public :: MRISTEP_DEFAULT_IMEX_SD_4_AD = ARKODE_IMEX_MRI_SR43 integer, parameter :: swig_cmem_own_bit = 0 integer, parameter :: swig_cmem_rvalue_bit = 1 @@ -90,6 +107,8 @@ module farkode_mristep_mod type, public :: MRIStepCouplingMem type(SwigClassWrapper), public :: swigdata contains + procedure :: set_type => swigf_MRIStepCouplingMem_type_set + procedure :: get_type => swigf_MRIStepCouplingMem_type_get procedure :: set_nmat => swigf_MRIStepCouplingMem_nmat_set procedure :: get_nmat => swigf_MRIStepCouplingMem_nmat_get procedure :: set_stages => swigf_MRIStepCouplingMem_stages_set @@ -104,6 +123,10 @@ module farkode_mristep_mod procedure :: get_W => swigf_MRIStepCouplingMem_W_get procedure :: set_G => swigf_MRIStepCouplingMem_G_set procedure :: get_G => swigf_MRIStepCouplingMem_G_get + procedure :: set_ngroup => swigf_MRIStepCouplingMem_ngroup_set + procedure :: get_ngroup => swigf_MRIStepCouplingMem_ngroup_get + procedure :: set_group => swigf_MRIStepCouplingMem_group_set + procedure :: get_group => swigf_MRIStepCouplingMem_group_get procedure :: release => swigf_release_MRIStepCouplingMem procedure, private :: swigf_MRIStepCouplingMem_op_assign__ generic :: assignment(=) => swigf_MRIStepCouplingMem_op_assign__ @@ -131,6 +154,7 @@ module farkode_mristep_mod public :: FMRIStepSetPostInnerFn public :: FMRIStepGetCurrentCoupling public :: FMRIStepGetLastInnerStepFlag + public :: FMRIStepGetNumInnerStepperFails public :: FMRIStepInnerStepper_Create public :: FMRIStepInnerStepper_CreateFromSUNStepper public :: FMRIStepInnerStepper_Free @@ -139,6 +163,9 @@ module farkode_mristep_mod public :: FMRIStepInnerStepper_SetEvolveFn public :: FMRIStepInnerStepper_SetFullRhsFn public :: FMRIStepInnerStepper_SetResetFn + public :: FMRIStepInnerStepper_SetAccumulatedErrorGetFn + public :: FMRIStepInnerStepper_SetAccumulatedErrorResetFn + public :: FMRIStepInnerStepper_SetRTolFn public :: FMRIStepInnerStepper_AddForcing public :: FMRIStepInnerStepper_GetForcingData public :: FMRIStepResize @@ -230,6 +257,23 @@ module farkode_mristep_mod ! WRAPPER DECLARATIONS interface +subroutine swigc_MRIStepCouplingMem_type_set(farg1, farg2) & +bind(C, name="_wrap_MRIStepCouplingMem_type_set") +use, intrinsic :: ISO_C_BINDING +import :: swigclasswrapper +type(SwigClassWrapper) :: farg1 +integer(C_INT), intent(in) :: farg2 +end subroutine + +function swigc_MRIStepCouplingMem_type_get(farg1) & +bind(C, name="_wrap_MRIStepCouplingMem_type_get") & +result(fresult) +use, intrinsic :: ISO_C_BINDING +import :: swigclasswrapper +type(SwigClassWrapper) :: farg1 +integer(C_INT) :: fresult +end function + subroutine swigc_MRIStepCouplingMem_nmat_set(farg1, farg2) & bind(C, name="_wrap_MRIStepCouplingMem_nmat_set") use, intrinsic :: ISO_C_BINDING @@ -349,6 +393,40 @@ function swigc_MRIStepCouplingMem_G_get(farg1) & type(C_PTR) :: fresult end function +subroutine swigc_MRIStepCouplingMem_ngroup_set(farg1, farg2) & +bind(C, name="_wrap_MRIStepCouplingMem_ngroup_set") +use, intrinsic :: ISO_C_BINDING +import :: swigclasswrapper +type(SwigClassWrapper) :: farg1 +integer(C_INT), intent(in) :: farg2 +end subroutine + +function swigc_MRIStepCouplingMem_ngroup_get(farg1) & +bind(C, name="_wrap_MRIStepCouplingMem_ngroup_get") & +result(fresult) +use, intrinsic :: ISO_C_BINDING +import :: swigclasswrapper +type(SwigClassWrapper) :: farg1 +integer(C_INT) :: fresult +end function + +subroutine swigc_MRIStepCouplingMem_group_set(farg1, farg2) & +bind(C, name="_wrap_MRIStepCouplingMem_group_set") +use, intrinsic :: ISO_C_BINDING +import :: swigclasswrapper +type(SwigClassWrapper) :: farg1 +type(C_PTR), value :: farg2 +end subroutine + +function swigc_MRIStepCouplingMem_group_get(farg1) & +bind(C, name="_wrap_MRIStepCouplingMem_group_get") & +result(fresult) +use, intrinsic :: ISO_C_BINDING +import :: swigclasswrapper +type(SwigClassWrapper) :: farg1 +type(C_PTR) :: fresult +end function + function swigc_new_MRIStepCouplingMem() & bind(C, name="_wrap_new_MRIStepCouplingMem") & result(fresult) @@ -522,6 +600,15 @@ function swigc_FMRIStepGetLastInnerStepFlag(farg1, farg2) & integer(C_INT) :: fresult end function +function swigc_FMRIStepGetNumInnerStepperFails(farg1, farg2) & +bind(C, name="_wrap_FMRIStepGetNumInnerStepperFails") & +result(fresult) +use, intrinsic :: ISO_C_BINDING +type(C_PTR), value :: farg1 +type(C_PTR), value :: farg2 +integer(C_INT) :: fresult +end function + function swigc_FMRIStepInnerStepper_Create(farg1, farg2) & bind(C, name="_wrap_FMRIStepInnerStepper_Create") & result(fresult) @@ -593,6 +680,33 @@ function swigc_FMRIStepInnerStepper_SetResetFn(farg1, farg2) & integer(C_INT) :: fresult end function +function swigc_FMRIStepInnerStepper_SetAccumulatedErrorGetFn(farg1, farg2) & +bind(C, name="_wrap_FMRIStepInnerStepper_SetAccumulatedErrorGetFn") & +result(fresult) +use, intrinsic :: ISO_C_BINDING +type(C_PTR), value :: farg1 +type(C_FUNPTR), value :: farg2 +integer(C_INT) :: fresult +end function + +function swigc_FMRIStepInnerStepper_SetAccumulatedErrorResetFn(farg1, farg2) & +bind(C, name="_wrap_FMRIStepInnerStepper_SetAccumulatedErrorResetFn") & +result(fresult) +use, intrinsic :: ISO_C_BINDING +type(C_PTR), value :: farg1 +type(C_FUNPTR), value :: farg2 +integer(C_INT) :: fresult +end function + +function swigc_FMRIStepInnerStepper_SetRTolFn(farg1, farg2) & +bind(C, name="_wrap_FMRIStepInnerStepper_SetRTolFn") & +result(fresult) +use, intrinsic :: ISO_C_BINDING +type(C_PTR), value :: farg1 +type(C_FUNPTR), value :: farg2 +integer(C_INT) :: fresult +end function + function swigc_FMRIStepInnerStepper_AddForcing(farg1, farg2, farg3) & bind(C, name="_wrap_FMRIStepInnerStepper_AddForcing") & result(fresult) @@ -1417,6 +1531,31 @@ function swigc_FMRIStepGetNumRhsEvals(farg1, farg2, farg3) & contains ! MODULE SUBPROGRAMS +subroutine swigf_MRIStepCouplingMem_type_set(self, type) +use, intrinsic :: ISO_C_BINDING +class(MRIStepCouplingMem), intent(in) :: self +integer(MRISTEP_METHOD_TYPE), intent(in) :: type +type(SwigClassWrapper) :: farg1 +integer(C_INT) :: farg2 + +farg1 = self%swigdata +farg2 = type +call swigc_MRIStepCouplingMem_type_set(farg1, farg2) +end subroutine + +function swigf_MRIStepCouplingMem_type_get(self) & +result(swig_result) +use, intrinsic :: ISO_C_BINDING +integer(MRISTEP_METHOD_TYPE) :: swig_result +class(MRIStepCouplingMem), intent(in) :: self +integer(C_INT) :: fresult +type(SwigClassWrapper) :: farg1 + +farg1 = self%swigdata +fresult = swigc_MRIStepCouplingMem_type_get(farg1) +swig_result = fresult +end function + subroutine swigf_MRIStepCouplingMem_nmat_set(self, nmat) use, intrinsic :: ISO_C_BINDING class(MRIStepCouplingMem), intent(in) :: self @@ -1592,6 +1731,56 @@ function swigf_MRIStepCouplingMem_G_get(self) & call c_f_pointer(fresult, swig_result) end function +subroutine swigf_MRIStepCouplingMem_ngroup_set(self, ngroup) +use, intrinsic :: ISO_C_BINDING +class(MRIStepCouplingMem), intent(in) :: self +integer(C_INT), intent(in) :: ngroup +type(SwigClassWrapper) :: farg1 +integer(C_INT) :: farg2 + +farg1 = self%swigdata +farg2 = ngroup +call swigc_MRIStepCouplingMem_ngroup_set(farg1, farg2) +end subroutine + +function swigf_MRIStepCouplingMem_ngroup_get(self) & +result(swig_result) +use, intrinsic :: ISO_C_BINDING +integer(C_INT) :: swig_result +class(MRIStepCouplingMem), intent(in) :: self +integer(C_INT) :: fresult +type(SwigClassWrapper) :: farg1 + +farg1 = self%swigdata +fresult = swigc_MRIStepCouplingMem_ngroup_get(farg1) +swig_result = fresult +end function + +subroutine swigf_MRIStepCouplingMem_group_set(self, group) +use, intrinsic :: ISO_C_BINDING +class(MRIStepCouplingMem), intent(in) :: self +type(C_PTR), target, intent(inout) :: group +type(SwigClassWrapper) :: farg1 +type(C_PTR) :: farg2 + +farg1 = self%swigdata +farg2 = c_loc(group) +call swigc_MRIStepCouplingMem_group_set(farg1, farg2) +end subroutine + +function swigf_MRIStepCouplingMem_group_get(self) & +result(swig_result) +use, intrinsic :: ISO_C_BINDING +type(C_PTR), pointer :: swig_result +class(MRIStepCouplingMem), intent(in) :: self +type(C_PTR) :: fresult +type(SwigClassWrapper) :: farg1 + +farg1 = self%swigdata +fresult = swigc_MRIStepCouplingMem_group_get(farg1) +call c_f_pointer(fresult, swig_result) +end function + function swigf_create_MRIStepCouplingMem() & result(self) use, intrinsic :: ISO_C_BINDING @@ -1925,6 +2114,22 @@ function FMRIStepGetLastInnerStepFlag(arkode_mem, flag) & swig_result = fresult end function +function FMRIStepGetNumInnerStepperFails(arkode_mem, inner_fails) & +result(swig_result) +use, intrinsic :: ISO_C_BINDING +integer(C_INT) :: swig_result +type(C_PTR) :: arkode_mem +integer(C_LONG), dimension(*), target, intent(inout) :: inner_fails +integer(C_INT) :: fresult +type(C_PTR) :: farg1 +type(C_PTR) :: farg2 + +farg1 = arkode_mem +farg2 = c_loc(inner_fails(1)) +fresult = swigc_FMRIStepGetNumInnerStepperFails(farg1, farg2) +swig_result = fresult +end function + function FMRIStepInnerStepper_Create(sunctx, stepper) & result(swig_result) use, intrinsic :: ISO_C_BINDING @@ -2050,6 +2255,54 @@ function FMRIStepInnerStepper_SetResetFn(stepper, fn) & swig_result = fresult end function +function FMRIStepInnerStepper_SetAccumulatedErrorGetFn(stepper, fn) & +result(swig_result) +use, intrinsic :: ISO_C_BINDING +integer(C_INT) :: swig_result +type(C_PTR) :: stepper +type(C_FUNPTR), intent(in), value :: fn +integer(C_INT) :: fresult +type(C_PTR) :: farg1 +type(C_FUNPTR) :: farg2 + +farg1 = stepper +farg2 = fn +fresult = swigc_FMRIStepInnerStepper_SetAccumulatedErrorGetFn(farg1, farg2) +swig_result = fresult +end function + +function FMRIStepInnerStepper_SetAccumulatedErrorResetFn(stepper, fn) & +result(swig_result) +use, intrinsic :: ISO_C_BINDING +integer(C_INT) :: swig_result +type(C_PTR) :: stepper +type(C_FUNPTR), intent(in), value :: fn +integer(C_INT) :: fresult +type(C_PTR) :: farg1 +type(C_FUNPTR) :: farg2 + +farg1 = stepper +farg2 = fn +fresult = swigc_FMRIStepInnerStepper_SetAccumulatedErrorResetFn(farg1, farg2) +swig_result = fresult +end function + +function FMRIStepInnerStepper_SetRTolFn(stepper, fn) & +result(swig_result) +use, intrinsic :: ISO_C_BINDING +integer(C_INT) :: swig_result +type(C_PTR) :: stepper +type(C_FUNPTR), intent(in), value :: fn +integer(C_INT) :: fresult +type(C_PTR) :: farg1 +type(C_FUNPTR) :: farg2 + +farg1 = stepper +farg2 = fn +fresult = swigc_FMRIStepInnerStepper_SetRTolFn(farg1, farg2) +swig_result = fresult +end function + function FMRIStepInnerStepper_AddForcing(stepper, t, f) & result(swig_result) use, intrinsic :: ISO_C_BINDING diff --git a/src/sunadaptcontroller/CMakeLists.txt b/src/sunadaptcontroller/CMakeLists.txt index f82df5e169..2a5c3db1a5 100644 --- a/src/sunadaptcontroller/CMakeLists.txt +++ b/src/sunadaptcontroller/CMakeLists.txt @@ -11,9 +11,10 @@ # SPDX-License-Identifier: BSD-3-Clause # SUNDIALS Copyright End # ------------------------------------------------------------------------------ -# controller level CMakeLists.txt for SUNDIALS +# adaptivity controller level CMakeLists.txt for SUNDIALS # ------------------------------------------------------------------------------ -# required native matrices +# required native adaptivity controllers add_subdirectory(imexgus) add_subdirectory(soderlind) +add_subdirectory(mrihtol) diff --git a/src/sunadaptcontroller/mrihtol/CMakeLists.txt b/src/sunadaptcontroller/mrihtol/CMakeLists.txt new file mode 100644 index 0000000000..1702a5f664 --- /dev/null +++ b/src/sunadaptcontroller/mrihtol/CMakeLists.txt @@ -0,0 +1,28 @@ +# --------------------------------------------------------------- +# Programmer(s): Daniel R. Reynolds @ SMU +# --------------------------------------------------------------- +# SUNDIALS Copyright Start +# Copyright (c) 2002-2024, Lawrence Livermore National Security +# and Southern Methodist University. +# All rights reserved. +# +# See the top-level LICENSE and NOTICE files for details. +# +# SPDX-License-Identifier: BSD-3-Clause +# SUNDIALS Copyright End +# --------------------------------------------------------------- + +# Create a library out of the generic sundials modules +sundials_add_library( + sundials_sunadaptcontrollermrihtol + SOURCES sunadaptcontroller_mrihtol.c + HEADERS + ${SUNDIALS_SOURCE_DIR}/include/sunadaptcontroller/sunadaptcontroller_mrihtol.h + LINK_LIBRARIES PUBLIC sundials_core + INCLUDE_SUBDIR sunadaptcontroller + OBJECT_LIB_ONLY) + +# Add F2003 module if the interface is enabled +if(BUILD_FORTRAN_MODULE_INTERFACE) + add_subdirectory("fmod_int${SUNDIALS_INDEX_SIZE}") +endif() diff --git a/src/sunadaptcontroller/mrihtol/fmod_int32/CMakeLists.txt b/src/sunadaptcontroller/mrihtol/fmod_int32/CMakeLists.txt new file mode 100644 index 0000000000..befc6cb2ed --- /dev/null +++ b/src/sunadaptcontroller/mrihtol/fmod_int32/CMakeLists.txt @@ -0,0 +1,21 @@ +# --------------------------------------------------------------- +# Programmer(s): Daniel R. Reynolds @ SMU +# --------------------------------------------------------------- +# SUNDIALS Copyright Start +# Copyright (c) 2002-2024, Lawrence Livermore National Security +# and Southern Methodist University. +# All rights reserved. +# +# See the top-level LICENSE and NOTICE files for details. +# +# SPDX-License-Identifier: BSD-3-Clause +# SUNDIALS Copyright End +# --------------------------------------------------------------- + +sundials_add_f2003_library( + sundials_fsunadaptcontrollermrihtol_mod + SOURCES fsunadaptcontroller_mrihtol_mod.f90 fsunadaptcontroller_mrihtol_mod.c + LINK_LIBRARIES PUBLIC sundials_fcore_mod + OUTPUT_NAME sundials_fsunadaptcontrollermrihtol_mod OBJECT_LIB_ONLY) + +message(STATUS "Added SUNAdaptController_MRIHTol F2003 interface") diff --git a/src/sunadaptcontroller/mrihtol/fmod_int32/fsunadaptcontroller_mrihtol_mod.c b/src/sunadaptcontroller/mrihtol/fmod_int32/fsunadaptcontroller_mrihtol_mod.c new file mode 100644 index 0000000000..f01662c5a8 --- /dev/null +++ b/src/sunadaptcontroller/mrihtol/fmod_int32/fsunadaptcontroller_mrihtol_mod.c @@ -0,0 +1,639 @@ +/* ---------------------------------------------------------------------------- + * This file was automatically generated by SWIG (http://www.swig.org). + * Version 4.0.0 + * + * This file is not intended to be easily readable and contains a number of + * coding conventions designed to improve portability and efficiency. Do not make + * changes to this file unless you know what you are doing--modify the SWIG + * interface file instead. + * ----------------------------------------------------------------------------- */ + +/* --------------------------------------------------------------- + * Programmer(s): Auto-generated by swig. + * --------------------------------------------------------------- + * SUNDIALS Copyright Start + * Copyright (c) 2002-2024, Lawrence Livermore National Security + * and Southern Methodist University. + * All rights reserved. + * + * See the top-level LICENSE and NOTICE files for details. + * + * SPDX-License-Identifier: BSD-3-Clause + * SUNDIALS Copyright End + * -------------------------------------------------------------*/ + +/* ----------------------------------------------------------------------------- + * This section contains generic SWIG labels for method/variable + * declarations/attributes, and other compiler dependent labels. + * ----------------------------------------------------------------------------- */ + +/* template workaround for compilers that cannot correctly implement the C++ standard */ +#ifndef SWIGTEMPLATEDISAMBIGUATOR +# if defined(__SUNPRO_CC) && (__SUNPRO_CC <= 0x560) +# define SWIGTEMPLATEDISAMBIGUATOR template +# elif defined(__HP_aCC) +/* Needed even with `aCC -AA' when `aCC -V' reports HP ANSI C++ B3910B A.03.55 */ +/* If we find a maximum version that requires this, the test would be __HP_aCC <= 35500 for A.03.55 */ +# define SWIGTEMPLATEDISAMBIGUATOR template +# else +# define SWIGTEMPLATEDISAMBIGUATOR +# endif +#endif + +/* inline attribute */ +#ifndef SWIGINLINE +# if defined(__cplusplus) || (defined(__GNUC__) && !defined(__STRICT_ANSI__)) +# define SWIGINLINE inline +# else +# define SWIGINLINE +# endif +#endif + +/* attribute recognised by some compilers to avoid 'unused' warnings */ +#ifndef SWIGUNUSED +# if defined(__GNUC__) +# if !(defined(__cplusplus)) || (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4)) +# define SWIGUNUSED __attribute__ ((__unused__)) +# else +# define SWIGUNUSED +# endif +# elif defined(__ICC) +# define SWIGUNUSED __attribute__ ((__unused__)) +# else +# define SWIGUNUSED +# endif +#endif + +#ifndef SWIG_MSC_UNSUPPRESS_4505 +# if defined(_MSC_VER) +# pragma warning(disable : 4505) /* unreferenced local function has been removed */ +# endif +#endif + +#ifndef SWIGUNUSEDPARM +# ifdef __cplusplus +# define SWIGUNUSEDPARM(p) +# else +# define SWIGUNUSEDPARM(p) p SWIGUNUSED +# endif +#endif + +/* internal SWIG method */ +#ifndef SWIGINTERN +# define SWIGINTERN static SWIGUNUSED +#endif + +/* internal inline SWIG method */ +#ifndef SWIGINTERNINLINE +# define SWIGINTERNINLINE SWIGINTERN SWIGINLINE +#endif + +/* qualifier for exported *const* global data variables*/ +#ifndef SWIGEXTERN +# ifdef __cplusplus +# define SWIGEXTERN extern +# else +# define SWIGEXTERN +# endif +#endif + +/* exporting methods */ +#if defined(__GNUC__) +# if (__GNUC__ >= 4) || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) +# ifndef GCC_HASCLASSVISIBILITY +# define GCC_HASCLASSVISIBILITY +# endif +# endif +#endif + +#ifndef SWIGEXPORT +# if defined(_WIN32) || defined(__WIN32__) || defined(__CYGWIN__) +# if defined(STATIC_LINKED) +# define SWIGEXPORT +# else +# define SWIGEXPORT __declspec(dllexport) +# endif +# else +# if defined(__GNUC__) && defined(GCC_HASCLASSVISIBILITY) +# define SWIGEXPORT __attribute__ ((visibility("default"))) +# else +# define SWIGEXPORT +# endif +# endif +#endif + +/* calling conventions for Windows */ +#ifndef SWIGSTDCALL +# if defined(_WIN32) || defined(__WIN32__) || defined(__CYGWIN__) +# define SWIGSTDCALL __stdcall +# else +# define SWIGSTDCALL +# endif +#endif + +/* Deal with Microsoft's attempt at deprecating C standard runtime functions */ +#if !defined(SWIG_NO_CRT_SECURE_NO_DEPRECATE) && defined(_MSC_VER) && !defined(_CRT_SECURE_NO_DEPRECATE) +# define _CRT_SECURE_NO_DEPRECATE +#endif + +/* Deal with Microsoft's attempt at deprecating methods in the standard C++ library */ +#if !defined(SWIG_NO_SCL_SECURE_NO_DEPRECATE) && defined(_MSC_VER) && !defined(_SCL_SECURE_NO_DEPRECATE) +# define _SCL_SECURE_NO_DEPRECATE +#endif + +/* Deal with Apple's deprecated 'AssertMacros.h' from Carbon-framework */ +#if defined(__APPLE__) && !defined(__ASSERT_MACROS_DEFINE_VERSIONS_WITHOUT_UNDERSCORES) +# define __ASSERT_MACROS_DEFINE_VERSIONS_WITHOUT_UNDERSCORES 0 +#endif + +/* Intel's compiler complains if a variable which was never initialised is + * cast to void, which is a common idiom which we use to indicate that we + * are aware a variable isn't used. So we just silence that warning. + * See: https://github.com/swig/swig/issues/192 for more discussion. + */ +#ifdef __INTEL_COMPILER +# pragma warning disable 592 +#endif + +/* Errors in SWIG */ +#define SWIG_UnknownError -1 +#define SWIG_IOError -2 +#define SWIG_RuntimeError -3 +#define SWIG_IndexError -4 +#define SWIG_TypeError -5 +#define SWIG_DivisionByZero -6 +#define SWIG_OverflowError -7 +#define SWIG_SyntaxError -8 +#define SWIG_ValueError -9 +#define SWIG_SystemError -10 +#define SWIG_AttributeError -11 +#define SWIG_MemoryError -12 +#define SWIG_NullReferenceError -13 + + + + +#include +#define SWIG_exception_impl(DECL, CODE, MSG, RETURNNULL) \ + { printf("In " DECL ": " MSG); assert(0); RETURNNULL; } + + +enum { + SWIG_MEM_OWN = 0x01, + SWIG_MEM_RVALUE = 0x02, + SWIG_MEM_CONST = 0x04 +}; + + +#define SWIG_check_mutable(SWIG_CLASS_WRAPPER, TYPENAME, FNAME, FUNCNAME, RETURNNULL) \ + if ((SWIG_CLASS_WRAPPER).cmemflags & SWIG_MEM_CONST) { \ + SWIG_exception_impl(FUNCNAME, SWIG_TypeError, \ + "Cannot pass const " TYPENAME " (class " FNAME ") " \ + "as a mutable reference", \ + RETURNNULL); \ + } + + +#define SWIG_check_nonnull(SWIG_CLASS_WRAPPER, TYPENAME, FNAME, FUNCNAME, RETURNNULL) \ + if (!(SWIG_CLASS_WRAPPER).cptr) { \ + SWIG_exception_impl(FUNCNAME, SWIG_TypeError, \ + "Cannot pass null " TYPENAME " (class " FNAME ") " \ + "as a reference", RETURNNULL); \ + } + + +#define SWIG_check_mutable_nonnull(SWIG_CLASS_WRAPPER, TYPENAME, FNAME, FUNCNAME, RETURNNULL) \ + SWIG_check_nonnull(SWIG_CLASS_WRAPPER, TYPENAME, FNAME, FUNCNAME, RETURNNULL); \ + SWIG_check_mutable(SWIG_CLASS_WRAPPER, TYPENAME, FNAME, FUNCNAME, RETURNNULL); + + +#include +#if defined(_MSC_VER) || defined(__BORLANDC__) || defined(_WATCOM) +# ifndef snprintf +# define snprintf _snprintf +# endif +#endif + + +/* Support for the `contract` feature. + * + * Note that RETURNNULL is first because it's inserted via a 'Replaceall' in + * the fortran.cxx file. + */ +#define SWIG_contract_assert(RETURNNULL, EXPR, MSG) \ + if (!(EXPR)) { SWIG_exception_impl("$decl", SWIG_ValueError, MSG, RETURNNULL); } + + +#define SWIGVERSION 0x040000 +#define SWIG_VERSION SWIGVERSION + + +#define SWIG_as_voidptr(a) (void *)((const void *)(a)) +#define SWIG_as_voidptrptr(a) ((void)SWIG_as_voidptr(*a),(void**)(a)) + + +#include "sundials/sundials_adaptcontroller.h" + + +#include "sunadaptcontroller/sunadaptcontroller_mrihtol.h" + + +typedef struct { + void* cptr; + int cmemflags; +} SwigClassWrapper; + + +SWIGINTERN SwigClassWrapper SwigClassWrapper_uninitialized() { + SwigClassWrapper result; + result.cptr = NULL; + result.cmemflags = 0; + return result; +} + + +#include +#ifdef _MSC_VER +# ifndef strtoull +# define strtoull _strtoui64 +# endif +# ifndef strtoll +# define strtoll _strtoi64 +# endif +#endif + + +#include + + +SWIGINTERN void SWIG_assign(SwigClassWrapper* self, SwigClassWrapper other) { + if (self->cptr == NULL) { + /* LHS is unassigned */ + if (other.cmemflags & SWIG_MEM_RVALUE) { + /* Capture pointer from RHS, clear 'moving' flag */ + self->cptr = other.cptr; + self->cmemflags = other.cmemflags & (~SWIG_MEM_RVALUE); + } else { + /* Become a reference to the other object */ + self->cptr = other.cptr; + self->cmemflags = other.cmemflags & (~SWIG_MEM_OWN); + } + } else if (other.cptr == NULL) { + /* Replace LHS with a null pointer */ + free(self->cptr); + *self = SwigClassWrapper_uninitialized(); + } else { + if (self->cmemflags & SWIG_MEM_OWN) { + free(self->cptr); + } + self->cptr = other.cptr; + if (other.cmemflags & SWIG_MEM_RVALUE) { + /* Capture RHS */ + self->cmemflags = other.cmemflags & ~SWIG_MEM_RVALUE; + } else { + /* Point to RHS */ + self->cmemflags = other.cmemflags & ~SWIG_MEM_OWN; + } + } +} + +SWIGEXPORT void _wrap_SUNAdaptControllerContent_MRIHTol__HControl_set(SwigClassWrapper const *farg1, SUNAdaptController farg2) { + struct SUNAdaptControllerContent_MRIHTol_ *arg1 = (struct SUNAdaptControllerContent_MRIHTol_ *) 0 ; + SUNAdaptController arg2 = (SUNAdaptController) 0 ; + + SWIG_check_mutable_nonnull(*farg1, "struct SUNAdaptControllerContent_MRIHTol_ *", "SUNAdaptControllerContent_MRIHTol_", "SUNAdaptControllerContent_MRIHTol_::HControl", return ); + arg1 = (struct SUNAdaptControllerContent_MRIHTol_ *)(farg1->cptr); + arg2 = (SUNAdaptController)(farg2); + if (arg1) (arg1)->HControl = arg2; +} + + +SWIGEXPORT SUNAdaptController _wrap_SUNAdaptControllerContent_MRIHTol__HControl_get(SwigClassWrapper const *farg1) { + SUNAdaptController fresult ; + struct SUNAdaptControllerContent_MRIHTol_ *arg1 = (struct SUNAdaptControllerContent_MRIHTol_ *) 0 ; + SUNAdaptController result; + + SWIG_check_mutable_nonnull(*farg1, "struct SUNAdaptControllerContent_MRIHTol_ *", "SUNAdaptControllerContent_MRIHTol_", "SUNAdaptControllerContent_MRIHTol_::HControl", return 0); + arg1 = (struct SUNAdaptControllerContent_MRIHTol_ *)(farg1->cptr); + result = (SUNAdaptController) ((arg1)->HControl); + fresult = result; + return fresult; +} + + +SWIGEXPORT void _wrap_SUNAdaptControllerContent_MRIHTol__TolControl_set(SwigClassWrapper const *farg1, SUNAdaptController farg2) { + struct SUNAdaptControllerContent_MRIHTol_ *arg1 = (struct SUNAdaptControllerContent_MRIHTol_ *) 0 ; + SUNAdaptController arg2 = (SUNAdaptController) 0 ; + + SWIG_check_mutable_nonnull(*farg1, "struct SUNAdaptControllerContent_MRIHTol_ *", "SUNAdaptControllerContent_MRIHTol_", "SUNAdaptControllerContent_MRIHTol_::TolControl", return ); + arg1 = (struct SUNAdaptControllerContent_MRIHTol_ *)(farg1->cptr); + arg2 = (SUNAdaptController)(farg2); + if (arg1) (arg1)->TolControl = arg2; +} + + +SWIGEXPORT SUNAdaptController _wrap_SUNAdaptControllerContent_MRIHTol__TolControl_get(SwigClassWrapper const *farg1) { + SUNAdaptController fresult ; + struct SUNAdaptControllerContent_MRIHTol_ *arg1 = (struct SUNAdaptControllerContent_MRIHTol_ *) 0 ; + SUNAdaptController result; + + SWIG_check_mutable_nonnull(*farg1, "struct SUNAdaptControllerContent_MRIHTol_ *", "SUNAdaptControllerContent_MRIHTol_", "SUNAdaptControllerContent_MRIHTol_::TolControl", return 0); + arg1 = (struct SUNAdaptControllerContent_MRIHTol_ *)(farg1->cptr); + result = (SUNAdaptController) ((arg1)->TolControl); + fresult = result; + return fresult; +} + + +SWIGEXPORT void _wrap_SUNAdaptControllerContent_MRIHTol__inner_max_relch_set(SwigClassWrapper const *farg1, double const *farg2) { + struct SUNAdaptControllerContent_MRIHTol_ *arg1 = (struct SUNAdaptControllerContent_MRIHTol_ *) 0 ; + sunrealtype arg2 ; + + SWIG_check_mutable_nonnull(*farg1, "struct SUNAdaptControllerContent_MRIHTol_ *", "SUNAdaptControllerContent_MRIHTol_", "SUNAdaptControllerContent_MRIHTol_::inner_max_relch", return ); + arg1 = (struct SUNAdaptControllerContent_MRIHTol_ *)(farg1->cptr); + arg2 = (sunrealtype)(*farg2); + if (arg1) (arg1)->inner_max_relch = arg2; +} + + +SWIGEXPORT double _wrap_SUNAdaptControllerContent_MRIHTol__inner_max_relch_get(SwigClassWrapper const *farg1) { + double fresult ; + struct SUNAdaptControllerContent_MRIHTol_ *arg1 = (struct SUNAdaptControllerContent_MRIHTol_ *) 0 ; + sunrealtype result; + + SWIG_check_mutable_nonnull(*farg1, "struct SUNAdaptControllerContent_MRIHTol_ *", "SUNAdaptControllerContent_MRIHTol_", "SUNAdaptControllerContent_MRIHTol_::inner_max_relch", return 0); + arg1 = (struct SUNAdaptControllerContent_MRIHTol_ *)(farg1->cptr); + result = (sunrealtype) ((arg1)->inner_max_relch); + fresult = (sunrealtype)(result); + return fresult; +} + + +SWIGEXPORT void _wrap_SUNAdaptControllerContent_MRIHTol__inner_min_tolfac_set(SwigClassWrapper const *farg1, double const *farg2) { + struct SUNAdaptControllerContent_MRIHTol_ *arg1 = (struct SUNAdaptControllerContent_MRIHTol_ *) 0 ; + sunrealtype arg2 ; + + SWIG_check_mutable_nonnull(*farg1, "struct SUNAdaptControllerContent_MRIHTol_ *", "SUNAdaptControllerContent_MRIHTol_", "SUNAdaptControllerContent_MRIHTol_::inner_min_tolfac", return ); + arg1 = (struct SUNAdaptControllerContent_MRIHTol_ *)(farg1->cptr); + arg2 = (sunrealtype)(*farg2); + if (arg1) (arg1)->inner_min_tolfac = arg2; +} + + +SWIGEXPORT double _wrap_SUNAdaptControllerContent_MRIHTol__inner_min_tolfac_get(SwigClassWrapper const *farg1) { + double fresult ; + struct SUNAdaptControllerContent_MRIHTol_ *arg1 = (struct SUNAdaptControllerContent_MRIHTol_ *) 0 ; + sunrealtype result; + + SWIG_check_mutable_nonnull(*farg1, "struct SUNAdaptControllerContent_MRIHTol_ *", "SUNAdaptControllerContent_MRIHTol_", "SUNAdaptControllerContent_MRIHTol_::inner_min_tolfac", return 0); + arg1 = (struct SUNAdaptControllerContent_MRIHTol_ *)(farg1->cptr); + result = (sunrealtype) ((arg1)->inner_min_tolfac); + fresult = (sunrealtype)(result); + return fresult; +} + + +SWIGEXPORT void _wrap_SUNAdaptControllerContent_MRIHTol__inner_max_tolfac_set(SwigClassWrapper const *farg1, double const *farg2) { + struct SUNAdaptControllerContent_MRIHTol_ *arg1 = (struct SUNAdaptControllerContent_MRIHTol_ *) 0 ; + sunrealtype arg2 ; + + SWIG_check_mutable_nonnull(*farg1, "struct SUNAdaptControllerContent_MRIHTol_ *", "SUNAdaptControllerContent_MRIHTol_", "SUNAdaptControllerContent_MRIHTol_::inner_max_tolfac", return ); + arg1 = (struct SUNAdaptControllerContent_MRIHTol_ *)(farg1->cptr); + arg2 = (sunrealtype)(*farg2); + if (arg1) (arg1)->inner_max_tolfac = arg2; +} + + +SWIGEXPORT double _wrap_SUNAdaptControllerContent_MRIHTol__inner_max_tolfac_get(SwigClassWrapper const *farg1) { + double fresult ; + struct SUNAdaptControllerContent_MRIHTol_ *arg1 = (struct SUNAdaptControllerContent_MRIHTol_ *) 0 ; + sunrealtype result; + + SWIG_check_mutable_nonnull(*farg1, "struct SUNAdaptControllerContent_MRIHTol_ *", "SUNAdaptControllerContent_MRIHTol_", "SUNAdaptControllerContent_MRIHTol_::inner_max_tolfac", return 0); + arg1 = (struct SUNAdaptControllerContent_MRIHTol_ *)(farg1->cptr); + result = (sunrealtype) ((arg1)->inner_max_tolfac); + fresult = (sunrealtype)(result); + return fresult; +} + + +SWIGEXPORT SwigClassWrapper _wrap_new_SUNAdaptControllerContent_MRIHTol_() { + SwigClassWrapper fresult ; + struct SUNAdaptControllerContent_MRIHTol_ *result = 0 ; + + result = (struct SUNAdaptControllerContent_MRIHTol_ *)calloc(1, sizeof(struct SUNAdaptControllerContent_MRIHTol_)); + fresult.cptr = result; + fresult.cmemflags = SWIG_MEM_RVALUE | (1 ? SWIG_MEM_OWN : 0); + return fresult; +} + + +SWIGEXPORT void _wrap_delete_SUNAdaptControllerContent_MRIHTol_(SwigClassWrapper *farg1) { + struct SUNAdaptControllerContent_MRIHTol_ *arg1 = (struct SUNAdaptControllerContent_MRIHTol_ *) 0 ; + + SWIG_check_mutable(*farg1, "struct SUNAdaptControllerContent_MRIHTol_ *", "SUNAdaptControllerContent_MRIHTol_", "SUNAdaptControllerContent_MRIHTol_::~SUNAdaptControllerContent_MRIHTol_()", return ); + arg1 = (struct SUNAdaptControllerContent_MRIHTol_ *)(farg1->cptr); + free((char *) arg1); +} + + +SWIGEXPORT void _wrap_SUNAdaptControllerContent_MRIHTol__op_assign__(SwigClassWrapper *farg1, SwigClassWrapper const *farg2) { + struct SUNAdaptControllerContent_MRIHTol_ *arg1 = (struct SUNAdaptControllerContent_MRIHTol_ *) 0 ; + struct SUNAdaptControllerContent_MRIHTol_ *arg2 = 0 ; + + (void)sizeof(arg1); + (void)sizeof(arg2); + SWIG_assign(farg1, *farg2); + +} + + +SWIGEXPORT SUNAdaptController _wrap_FSUNAdaptController_MRIHTol(SUNAdaptController farg1, SUNAdaptController farg2, void *farg3) { + SUNAdaptController fresult ; + SUNAdaptController arg1 = (SUNAdaptController) 0 ; + SUNAdaptController arg2 = (SUNAdaptController) 0 ; + SUNContext arg3 = (SUNContext) 0 ; + SUNAdaptController result; + + arg1 = (SUNAdaptController)(farg1); + arg2 = (SUNAdaptController)(farg2); + arg3 = (SUNContext)(farg3); + result = (SUNAdaptController)SUNAdaptController_MRIHTol(arg1,arg2,arg3); + fresult = result; + return fresult; +} + + +SWIGEXPORT int _wrap_FSUNAdaptController_SetParams_MRIHTol(SUNAdaptController farg1, double const *farg2, double const *farg3, double const *farg4) { + int fresult ; + SUNAdaptController arg1 = (SUNAdaptController) 0 ; + sunrealtype arg2 ; + sunrealtype arg3 ; + sunrealtype arg4 ; + SUNErrCode result; + + arg1 = (SUNAdaptController)(farg1); + arg2 = (sunrealtype)(*farg2); + arg3 = (sunrealtype)(*farg3); + arg4 = (sunrealtype)(*farg4); + result = (SUNErrCode)SUNAdaptController_SetParams_MRIHTol(arg1,arg2,arg3,arg4); + fresult = (SUNErrCode)(result); + return fresult; +} + + +SWIGEXPORT int _wrap_FSUNAdaptController_GetSlowController_MRIHTol(SUNAdaptController farg1, void *farg2) { + int fresult ; + SUNAdaptController arg1 = (SUNAdaptController) 0 ; + SUNAdaptController *arg2 = (SUNAdaptController *) 0 ; + SUNErrCode result; + + arg1 = (SUNAdaptController)(farg1); + arg2 = (SUNAdaptController *)(farg2); + result = (SUNErrCode)SUNAdaptController_GetSlowController_MRIHTol(arg1,arg2); + fresult = (SUNErrCode)(result); + return fresult; +} + + +SWIGEXPORT int _wrap_FSUNAdaptController_GetFastController_MRIHTol(SUNAdaptController farg1, void *farg2) { + int fresult ; + SUNAdaptController arg1 = (SUNAdaptController) 0 ; + SUNAdaptController *arg2 = (SUNAdaptController *) 0 ; + SUNErrCode result; + + arg1 = (SUNAdaptController)(farg1); + arg2 = (SUNAdaptController *)(farg2); + result = (SUNErrCode)SUNAdaptController_GetFastController_MRIHTol(arg1,arg2); + fresult = (SUNErrCode)(result); + return fresult; +} + + +SWIGEXPORT int _wrap_FSUNAdaptController_GetType_MRIHTol(SUNAdaptController farg1) { + int fresult ; + SUNAdaptController arg1 = (SUNAdaptController) 0 ; + SUNAdaptController_Type result; + + arg1 = (SUNAdaptController)(farg1); + result = (SUNAdaptController_Type)SUNAdaptController_GetType_MRIHTol(arg1); + fresult = (int)(result); + return fresult; +} + + +SWIGEXPORT int _wrap_FSUNAdaptController_EstimateStepTol_MRIHTol(SUNAdaptController farg1, double const *farg2, double const *farg3, int const *farg4, double const *farg5, double const *farg6, double *farg7, double *farg8) { + int fresult ; + SUNAdaptController arg1 = (SUNAdaptController) 0 ; + sunrealtype arg2 ; + sunrealtype arg3 ; + int arg4 ; + sunrealtype arg5 ; + sunrealtype arg6 ; + sunrealtype *arg7 = (sunrealtype *) 0 ; + sunrealtype *arg8 = (sunrealtype *) 0 ; + int result; + + arg1 = (SUNAdaptController)(farg1); + arg2 = (sunrealtype)(*farg2); + arg3 = (sunrealtype)(*farg3); + arg4 = (int)(*farg4); + arg5 = (sunrealtype)(*farg5); + arg6 = (sunrealtype)(*farg6); + arg7 = (sunrealtype *)(farg7); + arg8 = (sunrealtype *)(farg8); + result = (int)SUNAdaptController_EstimateStepTol_MRIHTol(arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8); + fresult = (int)(result); + return fresult; +} + + +SWIGEXPORT int _wrap_FSUNAdaptController_Reset_MRIHTol(SUNAdaptController farg1) { + int fresult ; + SUNAdaptController arg1 = (SUNAdaptController) 0 ; + int result; + + arg1 = (SUNAdaptController)(farg1); + result = (int)SUNAdaptController_Reset_MRIHTol(arg1); + fresult = (int)(result); + return fresult; +} + + +SWIGEXPORT int _wrap_FSUNAdaptController_SetDefaults_MRIHTol(SUNAdaptController farg1) { + int fresult ; + SUNAdaptController arg1 = (SUNAdaptController) 0 ; + int result; + + arg1 = (SUNAdaptController)(farg1); + result = (int)SUNAdaptController_SetDefaults_MRIHTol(arg1); + fresult = (int)(result); + return fresult; +} + + +SWIGEXPORT int _wrap_FSUNAdaptController_Write_MRIHTol(SUNAdaptController farg1, void *farg2) { + int fresult ; + SUNAdaptController arg1 = (SUNAdaptController) 0 ; + FILE *arg2 = (FILE *) 0 ; + int result; + + arg1 = (SUNAdaptController)(farg1); + arg2 = (FILE *)(farg2); + result = (int)SUNAdaptController_Write_MRIHTol(arg1,arg2); + fresult = (int)(result); + return fresult; +} + + +SWIGEXPORT int _wrap_FSUNAdaptController_SetErrorBias_MRIHTol(SUNAdaptController farg1, double const *farg2) { + int fresult ; + SUNAdaptController arg1 = (SUNAdaptController) 0 ; + sunrealtype arg2 ; + int result; + + arg1 = (SUNAdaptController)(farg1); + arg2 = (sunrealtype)(*farg2); + result = (int)SUNAdaptController_SetErrorBias_MRIHTol(arg1,arg2); + fresult = (int)(result); + return fresult; +} + + +SWIGEXPORT int _wrap_FSUNAdaptController_UpdateMRIHTol_MRIHTol(SUNAdaptController farg1, double const *farg2, double const *farg3, double const *farg4, double const *farg5) { + int fresult ; + SUNAdaptController arg1 = (SUNAdaptController) 0 ; + sunrealtype arg2 ; + sunrealtype arg3 ; + sunrealtype arg4 ; + sunrealtype arg5 ; + int result; + + arg1 = (SUNAdaptController)(farg1); + arg2 = (sunrealtype)(*farg2); + arg3 = (sunrealtype)(*farg3); + arg4 = (sunrealtype)(*farg4); + arg5 = (sunrealtype)(*farg5); + result = (int)SUNAdaptController_UpdateMRIHTol_MRIHTol(arg1,arg2,arg3,arg4,arg5); + fresult = (int)(result); + return fresult; +} + + +SWIGEXPORT int _wrap_FSUNAdaptController_Space_MRIHTol(SUNAdaptController farg1, long *farg2, long *farg3) { + int fresult ; + SUNAdaptController arg1 = (SUNAdaptController) 0 ; + long *arg2 = (long *) 0 ; + long *arg3 = (long *) 0 ; + int result; + + arg1 = (SUNAdaptController)(farg1); + arg2 = (long *)(farg2); + arg3 = (long *)(farg3); + result = (int)SUNAdaptController_Space_MRIHTol(arg1,arg2,arg3); + fresult = (int)(result); + return fresult; +} + + + diff --git a/src/sunadaptcontroller/mrihtol/fmod_int32/fsunadaptcontroller_mrihtol_mod.f90 b/src/sunadaptcontroller/mrihtol/fmod_int32/fsunadaptcontroller_mrihtol_mod.f90 new file mode 100644 index 0000000000..5d38166728 --- /dev/null +++ b/src/sunadaptcontroller/mrihtol/fmod_int32/fsunadaptcontroller_mrihtol_mod.f90 @@ -0,0 +1,688 @@ +! This file was automatically generated by SWIG (http://www.swig.org). +! Version 4.0.0 +! +! Do not make changes to this file unless you know what you are doing--modify +! the SWIG interface file instead. + +! --------------------------------------------------------------- +! Programmer(s): Auto-generated by swig. +! --------------------------------------------------------------- +! SUNDIALS Copyright Start +! Copyright (c) 2002-2024, Lawrence Livermore National Security +! and Southern Methodist University. +! All rights reserved. +! +! See the top-level LICENSE and NOTICE files for details. +! +! SPDX-License-Identifier: BSD-3-Clause +! SUNDIALS Copyright End +! --------------------------------------------------------------- + +module fsunadaptcontroller_mrihtol_mod + use, intrinsic :: ISO_C_BINDING + use fsundials_core_mod + implicit none + private + + ! DECLARATION CONSTRUCTS + + integer, parameter :: swig_cmem_own_bit = 0 + integer, parameter :: swig_cmem_rvalue_bit = 1 + integer, parameter :: swig_cmem_const_bit = 2 + type, bind(C) :: SwigClassWrapper + type(C_PTR), public :: cptr = C_NULL_PTR + integer(C_INT), public :: cmemflags = 0 + end type + ! struct struct SUNAdaptControllerContent_MRIHTol_ + type, public :: SUNAdaptControllerContent_MRIHTol_ + type(SwigClassWrapper), public :: swigdata + contains + procedure :: set_HControl => swigf_SUNAdaptControllerContent_MRIHTol__HControl_set + procedure :: get_HControl => swigf_SUNAdaptControllerContent_MRIHTol__HControl_get + procedure :: set_TolControl => swigf_SUNAdaptControllerContent_MRIHTol__TolControl_set + procedure :: get_TolControl => swigf_SUNAdaptControllerContent_MRIHTol__TolControl_get + procedure :: set_inner_max_relch => swigf_SUNAdaptControllerContent_MRIHTol__inner_max_relch_set + procedure :: get_inner_max_relch => swigf_SUNAdaptControllerContent_MRIHTol__inner_max_relch_get + procedure :: set_inner_min_tolfac => swigf_SUNAdaptControllerContent_MRIHTol__inner_min_tolfac_set + procedure :: get_inner_min_tolfac => swigf_SUNAdaptControllerContent_MRIHTol__inner_min_tolfac_get + procedure :: set_inner_max_tolfac => swigf_SUNAdaptControllerContent_MRIHTol__inner_max_tolfac_set + procedure :: get_inner_max_tolfac => swigf_SUNAdaptControllerContent_MRIHTol__inner_max_tolfac_get + procedure :: release => swigf_release_SUNAdaptControllerContent_MRIHTol_ + procedure, private :: swigf_SUNAdaptControllerContent_MRIHTol__op_assign__ + generic :: assignment(=) => swigf_SUNAdaptControllerContent_MRIHTol__op_assign__ + end type SUNAdaptControllerContent_MRIHTol_ + interface SUNAdaptControllerContent_MRIHTol_ + module procedure swigf_create_SUNAdaptControllerContent_MRIHTol_ + end interface + public :: FSUNAdaptController_MRIHTol + public :: FSUNAdaptController_SetParams_MRIHTol + public :: FSUNAdaptController_GetSlowController_MRIHTol + public :: FSUNAdaptController_GetFastController_MRIHTol + public :: FSUNAdaptController_GetType_MRIHTol + public :: FSUNAdaptController_EstimateStepTol_MRIHTol + public :: FSUNAdaptController_Reset_MRIHTol + public :: FSUNAdaptController_SetDefaults_MRIHTol + public :: FSUNAdaptController_Write_MRIHTol + public :: FSUNAdaptController_SetErrorBias_MRIHTol + public :: FSUNAdaptController_UpdateMRIHTol_MRIHTol + public :: FSUNAdaptController_Space_MRIHTol + +! WRAPPER DECLARATIONS +interface +subroutine swigc_SUNAdaptControllerContent_MRIHTol__HControl_set(farg1, farg2) & +bind(C, name="_wrap_SUNAdaptControllerContent_MRIHTol__HControl_set") +use, intrinsic :: ISO_C_BINDING +import :: swigclasswrapper +type(SwigClassWrapper) :: farg1 +type(C_PTR), value :: farg2 +end subroutine + +function swigc_SUNAdaptControllerContent_MRIHTol__HControl_get(farg1) & +bind(C, name="_wrap_SUNAdaptControllerContent_MRIHTol__HControl_get") & +result(fresult) +use, intrinsic :: ISO_C_BINDING +import :: swigclasswrapper +type(SwigClassWrapper) :: farg1 +type(C_PTR) :: fresult +end function + +subroutine swigc_SUNAdaptControllerContent_MRIHTol__TolControl_set(farg1, farg2) & +bind(C, name="_wrap_SUNAdaptControllerContent_MRIHTol__TolControl_set") +use, intrinsic :: ISO_C_BINDING +import :: swigclasswrapper +type(SwigClassWrapper) :: farg1 +type(C_PTR), value :: farg2 +end subroutine + +function swigc_SUNAdaptControllerContent_MRIHTol__TolControl_get(farg1) & +bind(C, name="_wrap_SUNAdaptControllerContent_MRIHTol__TolControl_get") & +result(fresult) +use, intrinsic :: ISO_C_BINDING +import :: swigclasswrapper +type(SwigClassWrapper) :: farg1 +type(C_PTR) :: fresult +end function + +subroutine swigc_SUNAdaptControllerContent_MRIHTol__inner_max_relch_set(farg1, farg2) & +bind(C, name="_wrap_SUNAdaptControllerContent_MRIHTol__inner_max_relch_set") +use, intrinsic :: ISO_C_BINDING +import :: swigclasswrapper +type(SwigClassWrapper) :: farg1 +real(C_DOUBLE), intent(in) :: farg2 +end subroutine + +function swigc_SUNAdaptControllerContent_MRIHTol__inner_max_relch_get(farg1) & +bind(C, name="_wrap_SUNAdaptControllerContent_MRIHTol__inner_max_relch_get") & +result(fresult) +use, intrinsic :: ISO_C_BINDING +import :: swigclasswrapper +type(SwigClassWrapper) :: farg1 +real(C_DOUBLE) :: fresult +end function + +subroutine swigc_SUNAdaptControllerContent_MRIHTol__inner_min_tolfac_set(farg1, farg2) & +bind(C, name="_wrap_SUNAdaptControllerContent_MRIHTol__inner_min_tolfac_set") +use, intrinsic :: ISO_C_BINDING +import :: swigclasswrapper +type(SwigClassWrapper) :: farg1 +real(C_DOUBLE), intent(in) :: farg2 +end subroutine + +function swigc_SUNAdaptControllerContent_MRIHTol__inner_min_tolfac_get(farg1) & +bind(C, name="_wrap_SUNAdaptControllerContent_MRIHTol__inner_min_tolfac_get") & +result(fresult) +use, intrinsic :: ISO_C_BINDING +import :: swigclasswrapper +type(SwigClassWrapper) :: farg1 +real(C_DOUBLE) :: fresult +end function + +subroutine swigc_SUNAdaptControllerContent_MRIHTol__inner_max_tolfac_set(farg1, farg2) & +bind(C, name="_wrap_SUNAdaptControllerContent_MRIHTol__inner_max_tolfac_set") +use, intrinsic :: ISO_C_BINDING +import :: swigclasswrapper +type(SwigClassWrapper) :: farg1 +real(C_DOUBLE), intent(in) :: farg2 +end subroutine + +function swigc_SUNAdaptControllerContent_MRIHTol__inner_max_tolfac_get(farg1) & +bind(C, name="_wrap_SUNAdaptControllerContent_MRIHTol__inner_max_tolfac_get") & +result(fresult) +use, intrinsic :: ISO_C_BINDING +import :: swigclasswrapper +type(SwigClassWrapper) :: farg1 +real(C_DOUBLE) :: fresult +end function + +function swigc_new_SUNAdaptControllerContent_MRIHTol_() & +bind(C, name="_wrap_new_SUNAdaptControllerContent_MRIHTol_") & +result(fresult) +use, intrinsic :: ISO_C_BINDING +import :: swigclasswrapper +type(SwigClassWrapper) :: fresult +end function + +subroutine swigc_delete_SUNAdaptControllerContent_MRIHTol_(farg1) & +bind(C, name="_wrap_delete_SUNAdaptControllerContent_MRIHTol_") +use, intrinsic :: ISO_C_BINDING +import :: swigclasswrapper +type(SwigClassWrapper), intent(inout) :: farg1 +end subroutine + +subroutine swigc_SUNAdaptControllerContent_MRIHTol__op_assign__(farg1, farg2) & +bind(C, name="_wrap_SUNAdaptControllerContent_MRIHTol__op_assign__") +use, intrinsic :: ISO_C_BINDING +import :: swigclasswrapper +type(SwigClassWrapper), intent(inout) :: farg1 +type(SwigClassWrapper) :: farg2 +end subroutine + +function swigc_FSUNAdaptController_MRIHTol(farg1, farg2, farg3) & +bind(C, name="_wrap_FSUNAdaptController_MRIHTol") & +result(fresult) +use, intrinsic :: ISO_C_BINDING +type(C_PTR), value :: farg1 +type(C_PTR), value :: farg2 +type(C_PTR), value :: farg3 +type(C_PTR) :: fresult +end function + +function swigc_FSUNAdaptController_SetParams_MRIHTol(farg1, farg2, farg3, farg4) & +bind(C, name="_wrap_FSUNAdaptController_SetParams_MRIHTol") & +result(fresult) +use, intrinsic :: ISO_C_BINDING +type(C_PTR), value :: farg1 +real(C_DOUBLE), intent(in) :: farg2 +real(C_DOUBLE), intent(in) :: farg3 +real(C_DOUBLE), intent(in) :: farg4 +integer(C_INT) :: fresult +end function + +function swigc_FSUNAdaptController_GetSlowController_MRIHTol(farg1, farg2) & +bind(C, name="_wrap_FSUNAdaptController_GetSlowController_MRIHTol") & +result(fresult) +use, intrinsic :: ISO_C_BINDING +type(C_PTR), value :: farg1 +type(C_PTR), value :: farg2 +integer(C_INT) :: fresult +end function + +function swigc_FSUNAdaptController_GetFastController_MRIHTol(farg1, farg2) & +bind(C, name="_wrap_FSUNAdaptController_GetFastController_MRIHTol") & +result(fresult) +use, intrinsic :: ISO_C_BINDING +type(C_PTR), value :: farg1 +type(C_PTR), value :: farg2 +integer(C_INT) :: fresult +end function + +function swigc_FSUNAdaptController_GetType_MRIHTol(farg1) & +bind(C, name="_wrap_FSUNAdaptController_GetType_MRIHTol") & +result(fresult) +use, intrinsic :: ISO_C_BINDING +type(C_PTR), value :: farg1 +integer(C_INT) :: fresult +end function + +function swigc_FSUNAdaptController_EstimateStepTol_MRIHTol(farg1, farg2, farg3, farg4, farg5, farg6, farg7, farg8) & +bind(C, name="_wrap_FSUNAdaptController_EstimateStepTol_MRIHTol") & +result(fresult) +use, intrinsic :: ISO_C_BINDING +type(C_PTR), value :: farg1 +real(C_DOUBLE), intent(in) :: farg2 +real(C_DOUBLE), intent(in) :: farg3 +integer(C_INT), intent(in) :: farg4 +real(C_DOUBLE), intent(in) :: farg5 +real(C_DOUBLE), intent(in) :: farg6 +type(C_PTR), value :: farg7 +type(C_PTR), value :: farg8 +integer(C_INT) :: fresult +end function + +function swigc_FSUNAdaptController_Reset_MRIHTol(farg1) & +bind(C, name="_wrap_FSUNAdaptController_Reset_MRIHTol") & +result(fresult) +use, intrinsic :: ISO_C_BINDING +type(C_PTR), value :: farg1 +integer(C_INT) :: fresult +end function + +function swigc_FSUNAdaptController_SetDefaults_MRIHTol(farg1) & +bind(C, name="_wrap_FSUNAdaptController_SetDefaults_MRIHTol") & +result(fresult) +use, intrinsic :: ISO_C_BINDING +type(C_PTR), value :: farg1 +integer(C_INT) :: fresult +end function + +function swigc_FSUNAdaptController_Write_MRIHTol(farg1, farg2) & +bind(C, name="_wrap_FSUNAdaptController_Write_MRIHTol") & +result(fresult) +use, intrinsic :: ISO_C_BINDING +type(C_PTR), value :: farg1 +type(C_PTR), value :: farg2 +integer(C_INT) :: fresult +end function + +function swigc_FSUNAdaptController_SetErrorBias_MRIHTol(farg1, farg2) & +bind(C, name="_wrap_FSUNAdaptController_SetErrorBias_MRIHTol") & +result(fresult) +use, intrinsic :: ISO_C_BINDING +type(C_PTR), value :: farg1 +real(C_DOUBLE), intent(in) :: farg2 +integer(C_INT) :: fresult +end function + +function swigc_FSUNAdaptController_UpdateMRIHTol_MRIHTol(farg1, farg2, farg3, farg4, farg5) & +bind(C, name="_wrap_FSUNAdaptController_UpdateMRIHTol_MRIHTol") & +result(fresult) +use, intrinsic :: ISO_C_BINDING +type(C_PTR), value :: farg1 +real(C_DOUBLE), intent(in) :: farg2 +real(C_DOUBLE), intent(in) :: farg3 +real(C_DOUBLE), intent(in) :: farg4 +real(C_DOUBLE), intent(in) :: farg5 +integer(C_INT) :: fresult +end function + +function swigc_FSUNAdaptController_Space_MRIHTol(farg1, farg2, farg3) & +bind(C, name="_wrap_FSUNAdaptController_Space_MRIHTol") & +result(fresult) +use, intrinsic :: ISO_C_BINDING +type(C_PTR), value :: farg1 +type(C_PTR), value :: farg2 +type(C_PTR), value :: farg3 +integer(C_INT) :: fresult +end function + +end interface + + +contains + ! MODULE SUBPROGRAMS +subroutine swigf_SUNAdaptControllerContent_MRIHTol__HControl_set(self, hcontrol) +use, intrinsic :: ISO_C_BINDING +class(SUNAdaptControllerContent_MRIHTol_), intent(in) :: self +type(SUNAdaptController), target, intent(inout) :: hcontrol +type(SwigClassWrapper) :: farg1 +type(C_PTR) :: farg2 + +farg1 = self%swigdata +farg2 = c_loc(hcontrol) +call swigc_SUNAdaptControllerContent_MRIHTol__HControl_set(farg1, farg2) +end subroutine + +function swigf_SUNAdaptControllerContent_MRIHTol__HControl_get(self) & +result(swig_result) +use, intrinsic :: ISO_C_BINDING +type(SUNAdaptController), pointer :: swig_result +class(SUNAdaptControllerContent_MRIHTol_), intent(in) :: self +type(C_PTR) :: fresult +type(SwigClassWrapper) :: farg1 + +farg1 = self%swigdata +fresult = swigc_SUNAdaptControllerContent_MRIHTol__HControl_get(farg1) +call c_f_pointer(fresult, swig_result) +end function + +subroutine swigf_SUNAdaptControllerContent_MRIHTol__TolControl_set(self, tolcontrol) +use, intrinsic :: ISO_C_BINDING +class(SUNAdaptControllerContent_MRIHTol_), intent(in) :: self +type(SUNAdaptController), target, intent(inout) :: tolcontrol +type(SwigClassWrapper) :: farg1 +type(C_PTR) :: farg2 + +farg1 = self%swigdata +farg2 = c_loc(tolcontrol) +call swigc_SUNAdaptControllerContent_MRIHTol__TolControl_set(farg1, farg2) +end subroutine + +function swigf_SUNAdaptControllerContent_MRIHTol__TolControl_get(self) & +result(swig_result) +use, intrinsic :: ISO_C_BINDING +type(SUNAdaptController), pointer :: swig_result +class(SUNAdaptControllerContent_MRIHTol_), intent(in) :: self +type(C_PTR) :: fresult +type(SwigClassWrapper) :: farg1 + +farg1 = self%swigdata +fresult = swigc_SUNAdaptControllerContent_MRIHTol__TolControl_get(farg1) +call c_f_pointer(fresult, swig_result) +end function + +subroutine swigf_SUNAdaptControllerContent_MRIHTol__inner_max_relch_set(self, inner_max_relch) +use, intrinsic :: ISO_C_BINDING +class(SUNAdaptControllerContent_MRIHTol_), intent(in) :: self +real(C_DOUBLE), intent(in) :: inner_max_relch +type(SwigClassWrapper) :: farg1 +real(C_DOUBLE) :: farg2 + +farg1 = self%swigdata +farg2 = inner_max_relch +call swigc_SUNAdaptControllerContent_MRIHTol__inner_max_relch_set(farg1, farg2) +end subroutine + +function swigf_SUNAdaptControllerContent_MRIHTol__inner_max_relch_get(self) & +result(swig_result) +use, intrinsic :: ISO_C_BINDING +real(C_DOUBLE) :: swig_result +class(SUNAdaptControllerContent_MRIHTol_), intent(in) :: self +real(C_DOUBLE) :: fresult +type(SwigClassWrapper) :: farg1 + +farg1 = self%swigdata +fresult = swigc_SUNAdaptControllerContent_MRIHTol__inner_max_relch_get(farg1) +swig_result = fresult +end function + +subroutine swigf_SUNAdaptControllerContent_MRIHTol__inner_min_tolfac_set(self, inner_min_tolfac) +use, intrinsic :: ISO_C_BINDING +class(SUNAdaptControllerContent_MRIHTol_), intent(in) :: self +real(C_DOUBLE), intent(in) :: inner_min_tolfac +type(SwigClassWrapper) :: farg1 +real(C_DOUBLE) :: farg2 + +farg1 = self%swigdata +farg2 = inner_min_tolfac +call swigc_SUNAdaptControllerContent_MRIHTol__inner_min_tolfac_set(farg1, farg2) +end subroutine + +function swigf_SUNAdaptControllerContent_MRIHTol__inner_min_tolfac_get(self) & +result(swig_result) +use, intrinsic :: ISO_C_BINDING +real(C_DOUBLE) :: swig_result +class(SUNAdaptControllerContent_MRIHTol_), intent(in) :: self +real(C_DOUBLE) :: fresult +type(SwigClassWrapper) :: farg1 + +farg1 = self%swigdata +fresult = swigc_SUNAdaptControllerContent_MRIHTol__inner_min_tolfac_get(farg1) +swig_result = fresult +end function + +subroutine swigf_SUNAdaptControllerContent_MRIHTol__inner_max_tolfac_set(self, inner_max_tolfac) +use, intrinsic :: ISO_C_BINDING +class(SUNAdaptControllerContent_MRIHTol_), intent(in) :: self +real(C_DOUBLE), intent(in) :: inner_max_tolfac +type(SwigClassWrapper) :: farg1 +real(C_DOUBLE) :: farg2 + +farg1 = self%swigdata +farg2 = inner_max_tolfac +call swigc_SUNAdaptControllerContent_MRIHTol__inner_max_tolfac_set(farg1, farg2) +end subroutine + +function swigf_SUNAdaptControllerContent_MRIHTol__inner_max_tolfac_get(self) & +result(swig_result) +use, intrinsic :: ISO_C_BINDING +real(C_DOUBLE) :: swig_result +class(SUNAdaptControllerContent_MRIHTol_), intent(in) :: self +real(C_DOUBLE) :: fresult +type(SwigClassWrapper) :: farg1 + +farg1 = self%swigdata +fresult = swigc_SUNAdaptControllerContent_MRIHTol__inner_max_tolfac_get(farg1) +swig_result = fresult +end function + +function swigf_create_SUNAdaptControllerContent_MRIHTol_() & +result(self) +use, intrinsic :: ISO_C_BINDING +type(SUNAdaptControllerContent_MRIHTol_) :: self +type(SwigClassWrapper) :: fresult + +fresult = swigc_new_SUNAdaptControllerContent_MRIHTol_() +self%swigdata = fresult +end function + +subroutine swigf_release_SUNAdaptControllerContent_MRIHTol_(self) +use, intrinsic :: ISO_C_BINDING +class(SUNAdaptControllerContent_MRIHTol_), intent(inout) :: self +type(SwigClassWrapper) :: farg1 + +farg1 = self%swigdata +if (btest(farg1%cmemflags, swig_cmem_own_bit)) then +call swigc_delete_SUNAdaptControllerContent_MRIHTol_(farg1) +endif +farg1%cptr = C_NULL_PTR +farg1%cmemflags = 0 +self%swigdata = farg1 +end subroutine + +subroutine swigf_SUNAdaptControllerContent_MRIHTol__op_assign__(self, other) +use, intrinsic :: ISO_C_BINDING +class(SUNAdaptControllerContent_MRIHTol_), intent(inout) :: self +type(SUNAdaptControllerContent_MRIHTol_), intent(in) :: other +type(SwigClassWrapper) :: farg1 +type(SwigClassWrapper) :: farg2 + +farg1 = self%swigdata +farg2 = other%swigdata +call swigc_SUNAdaptControllerContent_MRIHTol__op_assign__(farg1, farg2) +self%swigdata = farg1 +end subroutine + +function FSUNAdaptController_MRIHTol(hcontrol, tolcontrol, sunctx) & +result(swig_result) +use, intrinsic :: ISO_C_BINDING +type(SUNAdaptController), pointer :: swig_result +type(SUNAdaptController), target, intent(inout) :: hcontrol +type(SUNAdaptController), target, intent(inout) :: tolcontrol +type(C_PTR) :: sunctx +type(C_PTR) :: fresult +type(C_PTR) :: farg1 +type(C_PTR) :: farg2 +type(C_PTR) :: farg3 + +farg1 = c_loc(hcontrol) +farg2 = c_loc(tolcontrol) +farg3 = sunctx +fresult = swigc_FSUNAdaptController_MRIHTol(farg1, farg2, farg3) +call c_f_pointer(fresult, swig_result) +end function + +function FSUNAdaptController_SetParams_MRIHTol(c, inner_max_relch, inner_min_tolfac, inner_max_tolfac) & +result(swig_result) +use, intrinsic :: ISO_C_BINDING +integer(C_INT) :: swig_result +type(SUNAdaptController), target, intent(inout) :: c +real(C_DOUBLE), intent(in) :: inner_max_relch +real(C_DOUBLE), intent(in) :: inner_min_tolfac +real(C_DOUBLE), intent(in) :: inner_max_tolfac +integer(C_INT) :: fresult +type(C_PTR) :: farg1 +real(C_DOUBLE) :: farg2 +real(C_DOUBLE) :: farg3 +real(C_DOUBLE) :: farg4 + +farg1 = c_loc(c) +farg2 = inner_max_relch +farg3 = inner_min_tolfac +farg4 = inner_max_tolfac +fresult = swigc_FSUNAdaptController_SetParams_MRIHTol(farg1, farg2, farg3, farg4) +swig_result = fresult +end function + +function FSUNAdaptController_GetSlowController_MRIHTol(c, cslow) & +result(swig_result) +use, intrinsic :: ISO_C_BINDING +integer(C_INT) :: swig_result +type(SUNAdaptController), target, intent(inout) :: c +type(C_PTR), target, intent(inout) :: cslow +integer(C_INT) :: fresult +type(C_PTR) :: farg1 +type(C_PTR) :: farg2 + +farg1 = c_loc(c) +farg2 = c_loc(cslow) +fresult = swigc_FSUNAdaptController_GetSlowController_MRIHTol(farg1, farg2) +swig_result = fresult +end function + +function FSUNAdaptController_GetFastController_MRIHTol(c, cfast) & +result(swig_result) +use, intrinsic :: ISO_C_BINDING +integer(C_INT) :: swig_result +type(SUNAdaptController), target, intent(inout) :: c +type(C_PTR), target, intent(inout) :: cfast +integer(C_INT) :: fresult +type(C_PTR) :: farg1 +type(C_PTR) :: farg2 + +farg1 = c_loc(c) +farg2 = c_loc(cfast) +fresult = swigc_FSUNAdaptController_GetFastController_MRIHTol(farg1, farg2) +swig_result = fresult +end function + +function FSUNAdaptController_GetType_MRIHTol(c) & +result(swig_result) +use, intrinsic :: ISO_C_BINDING +integer(SUNAdaptController_Type) :: swig_result +type(SUNAdaptController), target, intent(inout) :: c +integer(C_INT) :: fresult +type(C_PTR) :: farg1 + +farg1 = c_loc(c) +fresult = swigc_FSUNAdaptController_GetType_MRIHTol(farg1) +swig_result = fresult +end function + +function FSUNAdaptController_EstimateStepTol_MRIHTol(c, h, tolfac, p, dsm, dsm5, hnew, tolfacnew) & +result(swig_result) +use, intrinsic :: ISO_C_BINDING +integer(C_INT) :: swig_result +type(SUNAdaptController), target, intent(inout) :: c +real(C_DOUBLE), intent(in) :: h +real(C_DOUBLE), intent(in) :: tolfac +integer(C_INT), intent(in) :: p +real(C_DOUBLE), intent(in) :: dsm +real(C_DOUBLE), intent(in) :: dsm5 +real(C_DOUBLE), dimension(*), target, intent(inout) :: hnew +real(C_DOUBLE), dimension(*), target, intent(inout) :: tolfacnew +integer(C_INT) :: fresult +type(C_PTR) :: farg1 +real(C_DOUBLE) :: farg2 +real(C_DOUBLE) :: farg3 +integer(C_INT) :: farg4 +real(C_DOUBLE) :: farg5 +real(C_DOUBLE) :: farg6 +type(C_PTR) :: farg7 +type(C_PTR) :: farg8 + +farg1 = c_loc(c) +farg2 = h +farg3 = tolfac +farg4 = p +farg5 = dsm +farg6 = dsm5 +farg7 = c_loc(hnew(1)) +farg8 = c_loc(tolfacnew(1)) +fresult = swigc_FSUNAdaptController_EstimateStepTol_MRIHTol(farg1, farg2, farg3, farg4, farg5, farg6, farg7, farg8) +swig_result = fresult +end function + +function FSUNAdaptController_Reset_MRIHTol(c) & +result(swig_result) +use, intrinsic :: ISO_C_BINDING +integer(C_INT) :: swig_result +type(SUNAdaptController), target, intent(inout) :: c +integer(C_INT) :: fresult +type(C_PTR) :: farg1 + +farg1 = c_loc(c) +fresult = swigc_FSUNAdaptController_Reset_MRIHTol(farg1) +swig_result = fresult +end function + +function FSUNAdaptController_SetDefaults_MRIHTol(c) & +result(swig_result) +use, intrinsic :: ISO_C_BINDING +integer(C_INT) :: swig_result +type(SUNAdaptController), target, intent(inout) :: c +integer(C_INT) :: fresult +type(C_PTR) :: farg1 + +farg1 = c_loc(c) +fresult = swigc_FSUNAdaptController_SetDefaults_MRIHTol(farg1) +swig_result = fresult +end function + +function FSUNAdaptController_Write_MRIHTol(c, fptr) & +result(swig_result) +use, intrinsic :: ISO_C_BINDING +integer(C_INT) :: swig_result +type(SUNAdaptController), target, intent(inout) :: c +type(C_PTR) :: fptr +integer(C_INT) :: fresult +type(C_PTR) :: farg1 +type(C_PTR) :: farg2 + +farg1 = c_loc(c) +farg2 = fptr +fresult = swigc_FSUNAdaptController_Write_MRIHTol(farg1, farg2) +swig_result = fresult +end function + +function FSUNAdaptController_SetErrorBias_MRIHTol(c, bias) & +result(swig_result) +use, intrinsic :: ISO_C_BINDING +integer(C_INT) :: swig_result +type(SUNAdaptController), target, intent(inout) :: c +real(C_DOUBLE), intent(in) :: bias +integer(C_INT) :: fresult +type(C_PTR) :: farg1 +real(C_DOUBLE) :: farg2 + +farg1 = c_loc(c) +farg2 = bias +fresult = swigc_FSUNAdaptController_SetErrorBias_MRIHTol(farg1, farg2) +swig_result = fresult +end function + +function FSUNAdaptController_UpdateMRIHTol_MRIHTol(c, h, tolfac, dsm, dsm4) & +result(swig_result) +use, intrinsic :: ISO_C_BINDING +integer(C_INT) :: swig_result +type(SUNAdaptController), target, intent(inout) :: c +real(C_DOUBLE), intent(in) :: h +real(C_DOUBLE), intent(in) :: tolfac +real(C_DOUBLE), intent(in) :: dsm +real(C_DOUBLE), intent(in) :: dsm4 +integer(C_INT) :: fresult +type(C_PTR) :: farg1 +real(C_DOUBLE) :: farg2 +real(C_DOUBLE) :: farg3 +real(C_DOUBLE) :: farg4 +real(C_DOUBLE) :: farg5 + +farg1 = c_loc(c) +farg2 = h +farg3 = tolfac +farg4 = dsm +farg5 = dsm4 +fresult = swigc_FSUNAdaptController_UpdateMRIHTol_MRIHTol(farg1, farg2, farg3, farg4, farg5) +swig_result = fresult +end function + +function FSUNAdaptController_Space_MRIHTol(c, lenrw, leniw) & +result(swig_result) +use, intrinsic :: ISO_C_BINDING +integer(C_INT) :: swig_result +type(SUNAdaptController), target, intent(inout) :: c +integer(C_LONG), dimension(*), target, intent(inout) :: lenrw +integer(C_LONG), dimension(*), target, intent(inout) :: leniw +integer(C_INT) :: fresult +type(C_PTR) :: farg1 +type(C_PTR) :: farg2 +type(C_PTR) :: farg3 + +farg1 = c_loc(c) +farg2 = c_loc(lenrw(1)) +farg3 = c_loc(leniw(1)) +fresult = swigc_FSUNAdaptController_Space_MRIHTol(farg1, farg2, farg3) +swig_result = fresult +end function + + +end module diff --git a/src/sunadaptcontroller/mrihtol/fmod_int64/CMakeLists.txt b/src/sunadaptcontroller/mrihtol/fmod_int64/CMakeLists.txt new file mode 100644 index 0000000000..befc6cb2ed --- /dev/null +++ b/src/sunadaptcontroller/mrihtol/fmod_int64/CMakeLists.txt @@ -0,0 +1,21 @@ +# --------------------------------------------------------------- +# Programmer(s): Daniel R. Reynolds @ SMU +# --------------------------------------------------------------- +# SUNDIALS Copyright Start +# Copyright (c) 2002-2024, Lawrence Livermore National Security +# and Southern Methodist University. +# All rights reserved. +# +# See the top-level LICENSE and NOTICE files for details. +# +# SPDX-License-Identifier: BSD-3-Clause +# SUNDIALS Copyright End +# --------------------------------------------------------------- + +sundials_add_f2003_library( + sundials_fsunadaptcontrollermrihtol_mod + SOURCES fsunadaptcontroller_mrihtol_mod.f90 fsunadaptcontroller_mrihtol_mod.c + LINK_LIBRARIES PUBLIC sundials_fcore_mod + OUTPUT_NAME sundials_fsunadaptcontrollermrihtol_mod OBJECT_LIB_ONLY) + +message(STATUS "Added SUNAdaptController_MRIHTol F2003 interface") diff --git a/src/sunadaptcontroller/mrihtol/fmod_int64/fsunadaptcontroller_mrihtol_mod.c b/src/sunadaptcontroller/mrihtol/fmod_int64/fsunadaptcontroller_mrihtol_mod.c new file mode 100644 index 0000000000..f01662c5a8 --- /dev/null +++ b/src/sunadaptcontroller/mrihtol/fmod_int64/fsunadaptcontroller_mrihtol_mod.c @@ -0,0 +1,639 @@ +/* ---------------------------------------------------------------------------- + * This file was automatically generated by SWIG (http://www.swig.org). + * Version 4.0.0 + * + * This file is not intended to be easily readable and contains a number of + * coding conventions designed to improve portability and efficiency. Do not make + * changes to this file unless you know what you are doing--modify the SWIG + * interface file instead. + * ----------------------------------------------------------------------------- */ + +/* --------------------------------------------------------------- + * Programmer(s): Auto-generated by swig. + * --------------------------------------------------------------- + * SUNDIALS Copyright Start + * Copyright (c) 2002-2024, Lawrence Livermore National Security + * and Southern Methodist University. + * All rights reserved. + * + * See the top-level LICENSE and NOTICE files for details. + * + * SPDX-License-Identifier: BSD-3-Clause + * SUNDIALS Copyright End + * -------------------------------------------------------------*/ + +/* ----------------------------------------------------------------------------- + * This section contains generic SWIG labels for method/variable + * declarations/attributes, and other compiler dependent labels. + * ----------------------------------------------------------------------------- */ + +/* template workaround for compilers that cannot correctly implement the C++ standard */ +#ifndef SWIGTEMPLATEDISAMBIGUATOR +# if defined(__SUNPRO_CC) && (__SUNPRO_CC <= 0x560) +# define SWIGTEMPLATEDISAMBIGUATOR template +# elif defined(__HP_aCC) +/* Needed even with `aCC -AA' when `aCC -V' reports HP ANSI C++ B3910B A.03.55 */ +/* If we find a maximum version that requires this, the test would be __HP_aCC <= 35500 for A.03.55 */ +# define SWIGTEMPLATEDISAMBIGUATOR template +# else +# define SWIGTEMPLATEDISAMBIGUATOR +# endif +#endif + +/* inline attribute */ +#ifndef SWIGINLINE +# if defined(__cplusplus) || (defined(__GNUC__) && !defined(__STRICT_ANSI__)) +# define SWIGINLINE inline +# else +# define SWIGINLINE +# endif +#endif + +/* attribute recognised by some compilers to avoid 'unused' warnings */ +#ifndef SWIGUNUSED +# if defined(__GNUC__) +# if !(defined(__cplusplus)) || (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4)) +# define SWIGUNUSED __attribute__ ((__unused__)) +# else +# define SWIGUNUSED +# endif +# elif defined(__ICC) +# define SWIGUNUSED __attribute__ ((__unused__)) +# else +# define SWIGUNUSED +# endif +#endif + +#ifndef SWIG_MSC_UNSUPPRESS_4505 +# if defined(_MSC_VER) +# pragma warning(disable : 4505) /* unreferenced local function has been removed */ +# endif +#endif + +#ifndef SWIGUNUSEDPARM +# ifdef __cplusplus +# define SWIGUNUSEDPARM(p) +# else +# define SWIGUNUSEDPARM(p) p SWIGUNUSED +# endif +#endif + +/* internal SWIG method */ +#ifndef SWIGINTERN +# define SWIGINTERN static SWIGUNUSED +#endif + +/* internal inline SWIG method */ +#ifndef SWIGINTERNINLINE +# define SWIGINTERNINLINE SWIGINTERN SWIGINLINE +#endif + +/* qualifier for exported *const* global data variables*/ +#ifndef SWIGEXTERN +# ifdef __cplusplus +# define SWIGEXTERN extern +# else +# define SWIGEXTERN +# endif +#endif + +/* exporting methods */ +#if defined(__GNUC__) +# if (__GNUC__ >= 4) || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) +# ifndef GCC_HASCLASSVISIBILITY +# define GCC_HASCLASSVISIBILITY +# endif +# endif +#endif + +#ifndef SWIGEXPORT +# if defined(_WIN32) || defined(__WIN32__) || defined(__CYGWIN__) +# if defined(STATIC_LINKED) +# define SWIGEXPORT +# else +# define SWIGEXPORT __declspec(dllexport) +# endif +# else +# if defined(__GNUC__) && defined(GCC_HASCLASSVISIBILITY) +# define SWIGEXPORT __attribute__ ((visibility("default"))) +# else +# define SWIGEXPORT +# endif +# endif +#endif + +/* calling conventions for Windows */ +#ifndef SWIGSTDCALL +# if defined(_WIN32) || defined(__WIN32__) || defined(__CYGWIN__) +# define SWIGSTDCALL __stdcall +# else +# define SWIGSTDCALL +# endif +#endif + +/* Deal with Microsoft's attempt at deprecating C standard runtime functions */ +#if !defined(SWIG_NO_CRT_SECURE_NO_DEPRECATE) && defined(_MSC_VER) && !defined(_CRT_SECURE_NO_DEPRECATE) +# define _CRT_SECURE_NO_DEPRECATE +#endif + +/* Deal with Microsoft's attempt at deprecating methods in the standard C++ library */ +#if !defined(SWIG_NO_SCL_SECURE_NO_DEPRECATE) && defined(_MSC_VER) && !defined(_SCL_SECURE_NO_DEPRECATE) +# define _SCL_SECURE_NO_DEPRECATE +#endif + +/* Deal with Apple's deprecated 'AssertMacros.h' from Carbon-framework */ +#if defined(__APPLE__) && !defined(__ASSERT_MACROS_DEFINE_VERSIONS_WITHOUT_UNDERSCORES) +# define __ASSERT_MACROS_DEFINE_VERSIONS_WITHOUT_UNDERSCORES 0 +#endif + +/* Intel's compiler complains if a variable which was never initialised is + * cast to void, which is a common idiom which we use to indicate that we + * are aware a variable isn't used. So we just silence that warning. + * See: https://github.com/swig/swig/issues/192 for more discussion. + */ +#ifdef __INTEL_COMPILER +# pragma warning disable 592 +#endif + +/* Errors in SWIG */ +#define SWIG_UnknownError -1 +#define SWIG_IOError -2 +#define SWIG_RuntimeError -3 +#define SWIG_IndexError -4 +#define SWIG_TypeError -5 +#define SWIG_DivisionByZero -6 +#define SWIG_OverflowError -7 +#define SWIG_SyntaxError -8 +#define SWIG_ValueError -9 +#define SWIG_SystemError -10 +#define SWIG_AttributeError -11 +#define SWIG_MemoryError -12 +#define SWIG_NullReferenceError -13 + + + + +#include +#define SWIG_exception_impl(DECL, CODE, MSG, RETURNNULL) \ + { printf("In " DECL ": " MSG); assert(0); RETURNNULL; } + + +enum { + SWIG_MEM_OWN = 0x01, + SWIG_MEM_RVALUE = 0x02, + SWIG_MEM_CONST = 0x04 +}; + + +#define SWIG_check_mutable(SWIG_CLASS_WRAPPER, TYPENAME, FNAME, FUNCNAME, RETURNNULL) \ + if ((SWIG_CLASS_WRAPPER).cmemflags & SWIG_MEM_CONST) { \ + SWIG_exception_impl(FUNCNAME, SWIG_TypeError, \ + "Cannot pass const " TYPENAME " (class " FNAME ") " \ + "as a mutable reference", \ + RETURNNULL); \ + } + + +#define SWIG_check_nonnull(SWIG_CLASS_WRAPPER, TYPENAME, FNAME, FUNCNAME, RETURNNULL) \ + if (!(SWIG_CLASS_WRAPPER).cptr) { \ + SWIG_exception_impl(FUNCNAME, SWIG_TypeError, \ + "Cannot pass null " TYPENAME " (class " FNAME ") " \ + "as a reference", RETURNNULL); \ + } + + +#define SWIG_check_mutable_nonnull(SWIG_CLASS_WRAPPER, TYPENAME, FNAME, FUNCNAME, RETURNNULL) \ + SWIG_check_nonnull(SWIG_CLASS_WRAPPER, TYPENAME, FNAME, FUNCNAME, RETURNNULL); \ + SWIG_check_mutable(SWIG_CLASS_WRAPPER, TYPENAME, FNAME, FUNCNAME, RETURNNULL); + + +#include +#if defined(_MSC_VER) || defined(__BORLANDC__) || defined(_WATCOM) +# ifndef snprintf +# define snprintf _snprintf +# endif +#endif + + +/* Support for the `contract` feature. + * + * Note that RETURNNULL is first because it's inserted via a 'Replaceall' in + * the fortran.cxx file. + */ +#define SWIG_contract_assert(RETURNNULL, EXPR, MSG) \ + if (!(EXPR)) { SWIG_exception_impl("$decl", SWIG_ValueError, MSG, RETURNNULL); } + + +#define SWIGVERSION 0x040000 +#define SWIG_VERSION SWIGVERSION + + +#define SWIG_as_voidptr(a) (void *)((const void *)(a)) +#define SWIG_as_voidptrptr(a) ((void)SWIG_as_voidptr(*a),(void**)(a)) + + +#include "sundials/sundials_adaptcontroller.h" + + +#include "sunadaptcontroller/sunadaptcontroller_mrihtol.h" + + +typedef struct { + void* cptr; + int cmemflags; +} SwigClassWrapper; + + +SWIGINTERN SwigClassWrapper SwigClassWrapper_uninitialized() { + SwigClassWrapper result; + result.cptr = NULL; + result.cmemflags = 0; + return result; +} + + +#include +#ifdef _MSC_VER +# ifndef strtoull +# define strtoull _strtoui64 +# endif +# ifndef strtoll +# define strtoll _strtoi64 +# endif +#endif + + +#include + + +SWIGINTERN void SWIG_assign(SwigClassWrapper* self, SwigClassWrapper other) { + if (self->cptr == NULL) { + /* LHS is unassigned */ + if (other.cmemflags & SWIG_MEM_RVALUE) { + /* Capture pointer from RHS, clear 'moving' flag */ + self->cptr = other.cptr; + self->cmemflags = other.cmemflags & (~SWIG_MEM_RVALUE); + } else { + /* Become a reference to the other object */ + self->cptr = other.cptr; + self->cmemflags = other.cmemflags & (~SWIG_MEM_OWN); + } + } else if (other.cptr == NULL) { + /* Replace LHS with a null pointer */ + free(self->cptr); + *self = SwigClassWrapper_uninitialized(); + } else { + if (self->cmemflags & SWIG_MEM_OWN) { + free(self->cptr); + } + self->cptr = other.cptr; + if (other.cmemflags & SWIG_MEM_RVALUE) { + /* Capture RHS */ + self->cmemflags = other.cmemflags & ~SWIG_MEM_RVALUE; + } else { + /* Point to RHS */ + self->cmemflags = other.cmemflags & ~SWIG_MEM_OWN; + } + } +} + +SWIGEXPORT void _wrap_SUNAdaptControllerContent_MRIHTol__HControl_set(SwigClassWrapper const *farg1, SUNAdaptController farg2) { + struct SUNAdaptControllerContent_MRIHTol_ *arg1 = (struct SUNAdaptControllerContent_MRIHTol_ *) 0 ; + SUNAdaptController arg2 = (SUNAdaptController) 0 ; + + SWIG_check_mutable_nonnull(*farg1, "struct SUNAdaptControllerContent_MRIHTol_ *", "SUNAdaptControllerContent_MRIHTol_", "SUNAdaptControllerContent_MRIHTol_::HControl", return ); + arg1 = (struct SUNAdaptControllerContent_MRIHTol_ *)(farg1->cptr); + arg2 = (SUNAdaptController)(farg2); + if (arg1) (arg1)->HControl = arg2; +} + + +SWIGEXPORT SUNAdaptController _wrap_SUNAdaptControllerContent_MRIHTol__HControl_get(SwigClassWrapper const *farg1) { + SUNAdaptController fresult ; + struct SUNAdaptControllerContent_MRIHTol_ *arg1 = (struct SUNAdaptControllerContent_MRIHTol_ *) 0 ; + SUNAdaptController result; + + SWIG_check_mutable_nonnull(*farg1, "struct SUNAdaptControllerContent_MRIHTol_ *", "SUNAdaptControllerContent_MRIHTol_", "SUNAdaptControllerContent_MRIHTol_::HControl", return 0); + arg1 = (struct SUNAdaptControllerContent_MRIHTol_ *)(farg1->cptr); + result = (SUNAdaptController) ((arg1)->HControl); + fresult = result; + return fresult; +} + + +SWIGEXPORT void _wrap_SUNAdaptControllerContent_MRIHTol__TolControl_set(SwigClassWrapper const *farg1, SUNAdaptController farg2) { + struct SUNAdaptControllerContent_MRIHTol_ *arg1 = (struct SUNAdaptControllerContent_MRIHTol_ *) 0 ; + SUNAdaptController arg2 = (SUNAdaptController) 0 ; + + SWIG_check_mutable_nonnull(*farg1, "struct SUNAdaptControllerContent_MRIHTol_ *", "SUNAdaptControllerContent_MRIHTol_", "SUNAdaptControllerContent_MRIHTol_::TolControl", return ); + arg1 = (struct SUNAdaptControllerContent_MRIHTol_ *)(farg1->cptr); + arg2 = (SUNAdaptController)(farg2); + if (arg1) (arg1)->TolControl = arg2; +} + + +SWIGEXPORT SUNAdaptController _wrap_SUNAdaptControllerContent_MRIHTol__TolControl_get(SwigClassWrapper const *farg1) { + SUNAdaptController fresult ; + struct SUNAdaptControllerContent_MRIHTol_ *arg1 = (struct SUNAdaptControllerContent_MRIHTol_ *) 0 ; + SUNAdaptController result; + + SWIG_check_mutable_nonnull(*farg1, "struct SUNAdaptControllerContent_MRIHTol_ *", "SUNAdaptControllerContent_MRIHTol_", "SUNAdaptControllerContent_MRIHTol_::TolControl", return 0); + arg1 = (struct SUNAdaptControllerContent_MRIHTol_ *)(farg1->cptr); + result = (SUNAdaptController) ((arg1)->TolControl); + fresult = result; + return fresult; +} + + +SWIGEXPORT void _wrap_SUNAdaptControllerContent_MRIHTol__inner_max_relch_set(SwigClassWrapper const *farg1, double const *farg2) { + struct SUNAdaptControllerContent_MRIHTol_ *arg1 = (struct SUNAdaptControllerContent_MRIHTol_ *) 0 ; + sunrealtype arg2 ; + + SWIG_check_mutable_nonnull(*farg1, "struct SUNAdaptControllerContent_MRIHTol_ *", "SUNAdaptControllerContent_MRIHTol_", "SUNAdaptControllerContent_MRIHTol_::inner_max_relch", return ); + arg1 = (struct SUNAdaptControllerContent_MRIHTol_ *)(farg1->cptr); + arg2 = (sunrealtype)(*farg2); + if (arg1) (arg1)->inner_max_relch = arg2; +} + + +SWIGEXPORT double _wrap_SUNAdaptControllerContent_MRIHTol__inner_max_relch_get(SwigClassWrapper const *farg1) { + double fresult ; + struct SUNAdaptControllerContent_MRIHTol_ *arg1 = (struct SUNAdaptControllerContent_MRIHTol_ *) 0 ; + sunrealtype result; + + SWIG_check_mutable_nonnull(*farg1, "struct SUNAdaptControllerContent_MRIHTol_ *", "SUNAdaptControllerContent_MRIHTol_", "SUNAdaptControllerContent_MRIHTol_::inner_max_relch", return 0); + arg1 = (struct SUNAdaptControllerContent_MRIHTol_ *)(farg1->cptr); + result = (sunrealtype) ((arg1)->inner_max_relch); + fresult = (sunrealtype)(result); + return fresult; +} + + +SWIGEXPORT void _wrap_SUNAdaptControllerContent_MRIHTol__inner_min_tolfac_set(SwigClassWrapper const *farg1, double const *farg2) { + struct SUNAdaptControllerContent_MRIHTol_ *arg1 = (struct SUNAdaptControllerContent_MRIHTol_ *) 0 ; + sunrealtype arg2 ; + + SWIG_check_mutable_nonnull(*farg1, "struct SUNAdaptControllerContent_MRIHTol_ *", "SUNAdaptControllerContent_MRIHTol_", "SUNAdaptControllerContent_MRIHTol_::inner_min_tolfac", return ); + arg1 = (struct SUNAdaptControllerContent_MRIHTol_ *)(farg1->cptr); + arg2 = (sunrealtype)(*farg2); + if (arg1) (arg1)->inner_min_tolfac = arg2; +} + + +SWIGEXPORT double _wrap_SUNAdaptControllerContent_MRIHTol__inner_min_tolfac_get(SwigClassWrapper const *farg1) { + double fresult ; + struct SUNAdaptControllerContent_MRIHTol_ *arg1 = (struct SUNAdaptControllerContent_MRIHTol_ *) 0 ; + sunrealtype result; + + SWIG_check_mutable_nonnull(*farg1, "struct SUNAdaptControllerContent_MRIHTol_ *", "SUNAdaptControllerContent_MRIHTol_", "SUNAdaptControllerContent_MRIHTol_::inner_min_tolfac", return 0); + arg1 = (struct SUNAdaptControllerContent_MRIHTol_ *)(farg1->cptr); + result = (sunrealtype) ((arg1)->inner_min_tolfac); + fresult = (sunrealtype)(result); + return fresult; +} + + +SWIGEXPORT void _wrap_SUNAdaptControllerContent_MRIHTol__inner_max_tolfac_set(SwigClassWrapper const *farg1, double const *farg2) { + struct SUNAdaptControllerContent_MRIHTol_ *arg1 = (struct SUNAdaptControllerContent_MRIHTol_ *) 0 ; + sunrealtype arg2 ; + + SWIG_check_mutable_nonnull(*farg1, "struct SUNAdaptControllerContent_MRIHTol_ *", "SUNAdaptControllerContent_MRIHTol_", "SUNAdaptControllerContent_MRIHTol_::inner_max_tolfac", return ); + arg1 = (struct SUNAdaptControllerContent_MRIHTol_ *)(farg1->cptr); + arg2 = (sunrealtype)(*farg2); + if (arg1) (arg1)->inner_max_tolfac = arg2; +} + + +SWIGEXPORT double _wrap_SUNAdaptControllerContent_MRIHTol__inner_max_tolfac_get(SwigClassWrapper const *farg1) { + double fresult ; + struct SUNAdaptControllerContent_MRIHTol_ *arg1 = (struct SUNAdaptControllerContent_MRIHTol_ *) 0 ; + sunrealtype result; + + SWIG_check_mutable_nonnull(*farg1, "struct SUNAdaptControllerContent_MRIHTol_ *", "SUNAdaptControllerContent_MRIHTol_", "SUNAdaptControllerContent_MRIHTol_::inner_max_tolfac", return 0); + arg1 = (struct SUNAdaptControllerContent_MRIHTol_ *)(farg1->cptr); + result = (sunrealtype) ((arg1)->inner_max_tolfac); + fresult = (sunrealtype)(result); + return fresult; +} + + +SWIGEXPORT SwigClassWrapper _wrap_new_SUNAdaptControllerContent_MRIHTol_() { + SwigClassWrapper fresult ; + struct SUNAdaptControllerContent_MRIHTol_ *result = 0 ; + + result = (struct SUNAdaptControllerContent_MRIHTol_ *)calloc(1, sizeof(struct SUNAdaptControllerContent_MRIHTol_)); + fresult.cptr = result; + fresult.cmemflags = SWIG_MEM_RVALUE | (1 ? SWIG_MEM_OWN : 0); + return fresult; +} + + +SWIGEXPORT void _wrap_delete_SUNAdaptControllerContent_MRIHTol_(SwigClassWrapper *farg1) { + struct SUNAdaptControllerContent_MRIHTol_ *arg1 = (struct SUNAdaptControllerContent_MRIHTol_ *) 0 ; + + SWIG_check_mutable(*farg1, "struct SUNAdaptControllerContent_MRIHTol_ *", "SUNAdaptControllerContent_MRIHTol_", "SUNAdaptControllerContent_MRIHTol_::~SUNAdaptControllerContent_MRIHTol_()", return ); + arg1 = (struct SUNAdaptControllerContent_MRIHTol_ *)(farg1->cptr); + free((char *) arg1); +} + + +SWIGEXPORT void _wrap_SUNAdaptControllerContent_MRIHTol__op_assign__(SwigClassWrapper *farg1, SwigClassWrapper const *farg2) { + struct SUNAdaptControllerContent_MRIHTol_ *arg1 = (struct SUNAdaptControllerContent_MRIHTol_ *) 0 ; + struct SUNAdaptControllerContent_MRIHTol_ *arg2 = 0 ; + + (void)sizeof(arg1); + (void)sizeof(arg2); + SWIG_assign(farg1, *farg2); + +} + + +SWIGEXPORT SUNAdaptController _wrap_FSUNAdaptController_MRIHTol(SUNAdaptController farg1, SUNAdaptController farg2, void *farg3) { + SUNAdaptController fresult ; + SUNAdaptController arg1 = (SUNAdaptController) 0 ; + SUNAdaptController arg2 = (SUNAdaptController) 0 ; + SUNContext arg3 = (SUNContext) 0 ; + SUNAdaptController result; + + arg1 = (SUNAdaptController)(farg1); + arg2 = (SUNAdaptController)(farg2); + arg3 = (SUNContext)(farg3); + result = (SUNAdaptController)SUNAdaptController_MRIHTol(arg1,arg2,arg3); + fresult = result; + return fresult; +} + + +SWIGEXPORT int _wrap_FSUNAdaptController_SetParams_MRIHTol(SUNAdaptController farg1, double const *farg2, double const *farg3, double const *farg4) { + int fresult ; + SUNAdaptController arg1 = (SUNAdaptController) 0 ; + sunrealtype arg2 ; + sunrealtype arg3 ; + sunrealtype arg4 ; + SUNErrCode result; + + arg1 = (SUNAdaptController)(farg1); + arg2 = (sunrealtype)(*farg2); + arg3 = (sunrealtype)(*farg3); + arg4 = (sunrealtype)(*farg4); + result = (SUNErrCode)SUNAdaptController_SetParams_MRIHTol(arg1,arg2,arg3,arg4); + fresult = (SUNErrCode)(result); + return fresult; +} + + +SWIGEXPORT int _wrap_FSUNAdaptController_GetSlowController_MRIHTol(SUNAdaptController farg1, void *farg2) { + int fresult ; + SUNAdaptController arg1 = (SUNAdaptController) 0 ; + SUNAdaptController *arg2 = (SUNAdaptController *) 0 ; + SUNErrCode result; + + arg1 = (SUNAdaptController)(farg1); + arg2 = (SUNAdaptController *)(farg2); + result = (SUNErrCode)SUNAdaptController_GetSlowController_MRIHTol(arg1,arg2); + fresult = (SUNErrCode)(result); + return fresult; +} + + +SWIGEXPORT int _wrap_FSUNAdaptController_GetFastController_MRIHTol(SUNAdaptController farg1, void *farg2) { + int fresult ; + SUNAdaptController arg1 = (SUNAdaptController) 0 ; + SUNAdaptController *arg2 = (SUNAdaptController *) 0 ; + SUNErrCode result; + + arg1 = (SUNAdaptController)(farg1); + arg2 = (SUNAdaptController *)(farg2); + result = (SUNErrCode)SUNAdaptController_GetFastController_MRIHTol(arg1,arg2); + fresult = (SUNErrCode)(result); + return fresult; +} + + +SWIGEXPORT int _wrap_FSUNAdaptController_GetType_MRIHTol(SUNAdaptController farg1) { + int fresult ; + SUNAdaptController arg1 = (SUNAdaptController) 0 ; + SUNAdaptController_Type result; + + arg1 = (SUNAdaptController)(farg1); + result = (SUNAdaptController_Type)SUNAdaptController_GetType_MRIHTol(arg1); + fresult = (int)(result); + return fresult; +} + + +SWIGEXPORT int _wrap_FSUNAdaptController_EstimateStepTol_MRIHTol(SUNAdaptController farg1, double const *farg2, double const *farg3, int const *farg4, double const *farg5, double const *farg6, double *farg7, double *farg8) { + int fresult ; + SUNAdaptController arg1 = (SUNAdaptController) 0 ; + sunrealtype arg2 ; + sunrealtype arg3 ; + int arg4 ; + sunrealtype arg5 ; + sunrealtype arg6 ; + sunrealtype *arg7 = (sunrealtype *) 0 ; + sunrealtype *arg8 = (sunrealtype *) 0 ; + int result; + + arg1 = (SUNAdaptController)(farg1); + arg2 = (sunrealtype)(*farg2); + arg3 = (sunrealtype)(*farg3); + arg4 = (int)(*farg4); + arg5 = (sunrealtype)(*farg5); + arg6 = (sunrealtype)(*farg6); + arg7 = (sunrealtype *)(farg7); + arg8 = (sunrealtype *)(farg8); + result = (int)SUNAdaptController_EstimateStepTol_MRIHTol(arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8); + fresult = (int)(result); + return fresult; +} + + +SWIGEXPORT int _wrap_FSUNAdaptController_Reset_MRIHTol(SUNAdaptController farg1) { + int fresult ; + SUNAdaptController arg1 = (SUNAdaptController) 0 ; + int result; + + arg1 = (SUNAdaptController)(farg1); + result = (int)SUNAdaptController_Reset_MRIHTol(arg1); + fresult = (int)(result); + return fresult; +} + + +SWIGEXPORT int _wrap_FSUNAdaptController_SetDefaults_MRIHTol(SUNAdaptController farg1) { + int fresult ; + SUNAdaptController arg1 = (SUNAdaptController) 0 ; + int result; + + arg1 = (SUNAdaptController)(farg1); + result = (int)SUNAdaptController_SetDefaults_MRIHTol(arg1); + fresult = (int)(result); + return fresult; +} + + +SWIGEXPORT int _wrap_FSUNAdaptController_Write_MRIHTol(SUNAdaptController farg1, void *farg2) { + int fresult ; + SUNAdaptController arg1 = (SUNAdaptController) 0 ; + FILE *arg2 = (FILE *) 0 ; + int result; + + arg1 = (SUNAdaptController)(farg1); + arg2 = (FILE *)(farg2); + result = (int)SUNAdaptController_Write_MRIHTol(arg1,arg2); + fresult = (int)(result); + return fresult; +} + + +SWIGEXPORT int _wrap_FSUNAdaptController_SetErrorBias_MRIHTol(SUNAdaptController farg1, double const *farg2) { + int fresult ; + SUNAdaptController arg1 = (SUNAdaptController) 0 ; + sunrealtype arg2 ; + int result; + + arg1 = (SUNAdaptController)(farg1); + arg2 = (sunrealtype)(*farg2); + result = (int)SUNAdaptController_SetErrorBias_MRIHTol(arg1,arg2); + fresult = (int)(result); + return fresult; +} + + +SWIGEXPORT int _wrap_FSUNAdaptController_UpdateMRIHTol_MRIHTol(SUNAdaptController farg1, double const *farg2, double const *farg3, double const *farg4, double const *farg5) { + int fresult ; + SUNAdaptController arg1 = (SUNAdaptController) 0 ; + sunrealtype arg2 ; + sunrealtype arg3 ; + sunrealtype arg4 ; + sunrealtype arg5 ; + int result; + + arg1 = (SUNAdaptController)(farg1); + arg2 = (sunrealtype)(*farg2); + arg3 = (sunrealtype)(*farg3); + arg4 = (sunrealtype)(*farg4); + arg5 = (sunrealtype)(*farg5); + result = (int)SUNAdaptController_UpdateMRIHTol_MRIHTol(arg1,arg2,arg3,arg4,arg5); + fresult = (int)(result); + return fresult; +} + + +SWIGEXPORT int _wrap_FSUNAdaptController_Space_MRIHTol(SUNAdaptController farg1, long *farg2, long *farg3) { + int fresult ; + SUNAdaptController arg1 = (SUNAdaptController) 0 ; + long *arg2 = (long *) 0 ; + long *arg3 = (long *) 0 ; + int result; + + arg1 = (SUNAdaptController)(farg1); + arg2 = (long *)(farg2); + arg3 = (long *)(farg3); + result = (int)SUNAdaptController_Space_MRIHTol(arg1,arg2,arg3); + fresult = (int)(result); + return fresult; +} + + + diff --git a/src/sunadaptcontroller/mrihtol/fmod_int64/fsunadaptcontroller_mrihtol_mod.f90 b/src/sunadaptcontroller/mrihtol/fmod_int64/fsunadaptcontroller_mrihtol_mod.f90 new file mode 100644 index 0000000000..5d38166728 --- /dev/null +++ b/src/sunadaptcontroller/mrihtol/fmod_int64/fsunadaptcontroller_mrihtol_mod.f90 @@ -0,0 +1,688 @@ +! This file was automatically generated by SWIG (http://www.swig.org). +! Version 4.0.0 +! +! Do not make changes to this file unless you know what you are doing--modify +! the SWIG interface file instead. + +! --------------------------------------------------------------- +! Programmer(s): Auto-generated by swig. +! --------------------------------------------------------------- +! SUNDIALS Copyright Start +! Copyright (c) 2002-2024, Lawrence Livermore National Security +! and Southern Methodist University. +! All rights reserved. +! +! See the top-level LICENSE and NOTICE files for details. +! +! SPDX-License-Identifier: BSD-3-Clause +! SUNDIALS Copyright End +! --------------------------------------------------------------- + +module fsunadaptcontroller_mrihtol_mod + use, intrinsic :: ISO_C_BINDING + use fsundials_core_mod + implicit none + private + + ! DECLARATION CONSTRUCTS + + integer, parameter :: swig_cmem_own_bit = 0 + integer, parameter :: swig_cmem_rvalue_bit = 1 + integer, parameter :: swig_cmem_const_bit = 2 + type, bind(C) :: SwigClassWrapper + type(C_PTR), public :: cptr = C_NULL_PTR + integer(C_INT), public :: cmemflags = 0 + end type + ! struct struct SUNAdaptControllerContent_MRIHTol_ + type, public :: SUNAdaptControllerContent_MRIHTol_ + type(SwigClassWrapper), public :: swigdata + contains + procedure :: set_HControl => swigf_SUNAdaptControllerContent_MRIHTol__HControl_set + procedure :: get_HControl => swigf_SUNAdaptControllerContent_MRIHTol__HControl_get + procedure :: set_TolControl => swigf_SUNAdaptControllerContent_MRIHTol__TolControl_set + procedure :: get_TolControl => swigf_SUNAdaptControllerContent_MRIHTol__TolControl_get + procedure :: set_inner_max_relch => swigf_SUNAdaptControllerContent_MRIHTol__inner_max_relch_set + procedure :: get_inner_max_relch => swigf_SUNAdaptControllerContent_MRIHTol__inner_max_relch_get + procedure :: set_inner_min_tolfac => swigf_SUNAdaptControllerContent_MRIHTol__inner_min_tolfac_set + procedure :: get_inner_min_tolfac => swigf_SUNAdaptControllerContent_MRIHTol__inner_min_tolfac_get + procedure :: set_inner_max_tolfac => swigf_SUNAdaptControllerContent_MRIHTol__inner_max_tolfac_set + procedure :: get_inner_max_tolfac => swigf_SUNAdaptControllerContent_MRIHTol__inner_max_tolfac_get + procedure :: release => swigf_release_SUNAdaptControllerContent_MRIHTol_ + procedure, private :: swigf_SUNAdaptControllerContent_MRIHTol__op_assign__ + generic :: assignment(=) => swigf_SUNAdaptControllerContent_MRIHTol__op_assign__ + end type SUNAdaptControllerContent_MRIHTol_ + interface SUNAdaptControllerContent_MRIHTol_ + module procedure swigf_create_SUNAdaptControllerContent_MRIHTol_ + end interface + public :: FSUNAdaptController_MRIHTol + public :: FSUNAdaptController_SetParams_MRIHTol + public :: FSUNAdaptController_GetSlowController_MRIHTol + public :: FSUNAdaptController_GetFastController_MRIHTol + public :: FSUNAdaptController_GetType_MRIHTol + public :: FSUNAdaptController_EstimateStepTol_MRIHTol + public :: FSUNAdaptController_Reset_MRIHTol + public :: FSUNAdaptController_SetDefaults_MRIHTol + public :: FSUNAdaptController_Write_MRIHTol + public :: FSUNAdaptController_SetErrorBias_MRIHTol + public :: FSUNAdaptController_UpdateMRIHTol_MRIHTol + public :: FSUNAdaptController_Space_MRIHTol + +! WRAPPER DECLARATIONS +interface +subroutine swigc_SUNAdaptControllerContent_MRIHTol__HControl_set(farg1, farg2) & +bind(C, name="_wrap_SUNAdaptControllerContent_MRIHTol__HControl_set") +use, intrinsic :: ISO_C_BINDING +import :: swigclasswrapper +type(SwigClassWrapper) :: farg1 +type(C_PTR), value :: farg2 +end subroutine + +function swigc_SUNAdaptControllerContent_MRIHTol__HControl_get(farg1) & +bind(C, name="_wrap_SUNAdaptControllerContent_MRIHTol__HControl_get") & +result(fresult) +use, intrinsic :: ISO_C_BINDING +import :: swigclasswrapper +type(SwigClassWrapper) :: farg1 +type(C_PTR) :: fresult +end function + +subroutine swigc_SUNAdaptControllerContent_MRIHTol__TolControl_set(farg1, farg2) & +bind(C, name="_wrap_SUNAdaptControllerContent_MRIHTol__TolControl_set") +use, intrinsic :: ISO_C_BINDING +import :: swigclasswrapper +type(SwigClassWrapper) :: farg1 +type(C_PTR), value :: farg2 +end subroutine + +function swigc_SUNAdaptControllerContent_MRIHTol__TolControl_get(farg1) & +bind(C, name="_wrap_SUNAdaptControllerContent_MRIHTol__TolControl_get") & +result(fresult) +use, intrinsic :: ISO_C_BINDING +import :: swigclasswrapper +type(SwigClassWrapper) :: farg1 +type(C_PTR) :: fresult +end function + +subroutine swigc_SUNAdaptControllerContent_MRIHTol__inner_max_relch_set(farg1, farg2) & +bind(C, name="_wrap_SUNAdaptControllerContent_MRIHTol__inner_max_relch_set") +use, intrinsic :: ISO_C_BINDING +import :: swigclasswrapper +type(SwigClassWrapper) :: farg1 +real(C_DOUBLE), intent(in) :: farg2 +end subroutine + +function swigc_SUNAdaptControllerContent_MRIHTol__inner_max_relch_get(farg1) & +bind(C, name="_wrap_SUNAdaptControllerContent_MRIHTol__inner_max_relch_get") & +result(fresult) +use, intrinsic :: ISO_C_BINDING +import :: swigclasswrapper +type(SwigClassWrapper) :: farg1 +real(C_DOUBLE) :: fresult +end function + +subroutine swigc_SUNAdaptControllerContent_MRIHTol__inner_min_tolfac_set(farg1, farg2) & +bind(C, name="_wrap_SUNAdaptControllerContent_MRIHTol__inner_min_tolfac_set") +use, intrinsic :: ISO_C_BINDING +import :: swigclasswrapper +type(SwigClassWrapper) :: farg1 +real(C_DOUBLE), intent(in) :: farg2 +end subroutine + +function swigc_SUNAdaptControllerContent_MRIHTol__inner_min_tolfac_get(farg1) & +bind(C, name="_wrap_SUNAdaptControllerContent_MRIHTol__inner_min_tolfac_get") & +result(fresult) +use, intrinsic :: ISO_C_BINDING +import :: swigclasswrapper +type(SwigClassWrapper) :: farg1 +real(C_DOUBLE) :: fresult +end function + +subroutine swigc_SUNAdaptControllerContent_MRIHTol__inner_max_tolfac_set(farg1, farg2) & +bind(C, name="_wrap_SUNAdaptControllerContent_MRIHTol__inner_max_tolfac_set") +use, intrinsic :: ISO_C_BINDING +import :: swigclasswrapper +type(SwigClassWrapper) :: farg1 +real(C_DOUBLE), intent(in) :: farg2 +end subroutine + +function swigc_SUNAdaptControllerContent_MRIHTol__inner_max_tolfac_get(farg1) & +bind(C, name="_wrap_SUNAdaptControllerContent_MRIHTol__inner_max_tolfac_get") & +result(fresult) +use, intrinsic :: ISO_C_BINDING +import :: swigclasswrapper +type(SwigClassWrapper) :: farg1 +real(C_DOUBLE) :: fresult +end function + +function swigc_new_SUNAdaptControllerContent_MRIHTol_() & +bind(C, name="_wrap_new_SUNAdaptControllerContent_MRIHTol_") & +result(fresult) +use, intrinsic :: ISO_C_BINDING +import :: swigclasswrapper +type(SwigClassWrapper) :: fresult +end function + +subroutine swigc_delete_SUNAdaptControllerContent_MRIHTol_(farg1) & +bind(C, name="_wrap_delete_SUNAdaptControllerContent_MRIHTol_") +use, intrinsic :: ISO_C_BINDING +import :: swigclasswrapper +type(SwigClassWrapper), intent(inout) :: farg1 +end subroutine + +subroutine swigc_SUNAdaptControllerContent_MRIHTol__op_assign__(farg1, farg2) & +bind(C, name="_wrap_SUNAdaptControllerContent_MRIHTol__op_assign__") +use, intrinsic :: ISO_C_BINDING +import :: swigclasswrapper +type(SwigClassWrapper), intent(inout) :: farg1 +type(SwigClassWrapper) :: farg2 +end subroutine + +function swigc_FSUNAdaptController_MRIHTol(farg1, farg2, farg3) & +bind(C, name="_wrap_FSUNAdaptController_MRIHTol") & +result(fresult) +use, intrinsic :: ISO_C_BINDING +type(C_PTR), value :: farg1 +type(C_PTR), value :: farg2 +type(C_PTR), value :: farg3 +type(C_PTR) :: fresult +end function + +function swigc_FSUNAdaptController_SetParams_MRIHTol(farg1, farg2, farg3, farg4) & +bind(C, name="_wrap_FSUNAdaptController_SetParams_MRIHTol") & +result(fresult) +use, intrinsic :: ISO_C_BINDING +type(C_PTR), value :: farg1 +real(C_DOUBLE), intent(in) :: farg2 +real(C_DOUBLE), intent(in) :: farg3 +real(C_DOUBLE), intent(in) :: farg4 +integer(C_INT) :: fresult +end function + +function swigc_FSUNAdaptController_GetSlowController_MRIHTol(farg1, farg2) & +bind(C, name="_wrap_FSUNAdaptController_GetSlowController_MRIHTol") & +result(fresult) +use, intrinsic :: ISO_C_BINDING +type(C_PTR), value :: farg1 +type(C_PTR), value :: farg2 +integer(C_INT) :: fresult +end function + +function swigc_FSUNAdaptController_GetFastController_MRIHTol(farg1, farg2) & +bind(C, name="_wrap_FSUNAdaptController_GetFastController_MRIHTol") & +result(fresult) +use, intrinsic :: ISO_C_BINDING +type(C_PTR), value :: farg1 +type(C_PTR), value :: farg2 +integer(C_INT) :: fresult +end function + +function swigc_FSUNAdaptController_GetType_MRIHTol(farg1) & +bind(C, name="_wrap_FSUNAdaptController_GetType_MRIHTol") & +result(fresult) +use, intrinsic :: ISO_C_BINDING +type(C_PTR), value :: farg1 +integer(C_INT) :: fresult +end function + +function swigc_FSUNAdaptController_EstimateStepTol_MRIHTol(farg1, farg2, farg3, farg4, farg5, farg6, farg7, farg8) & +bind(C, name="_wrap_FSUNAdaptController_EstimateStepTol_MRIHTol") & +result(fresult) +use, intrinsic :: ISO_C_BINDING +type(C_PTR), value :: farg1 +real(C_DOUBLE), intent(in) :: farg2 +real(C_DOUBLE), intent(in) :: farg3 +integer(C_INT), intent(in) :: farg4 +real(C_DOUBLE), intent(in) :: farg5 +real(C_DOUBLE), intent(in) :: farg6 +type(C_PTR), value :: farg7 +type(C_PTR), value :: farg8 +integer(C_INT) :: fresult +end function + +function swigc_FSUNAdaptController_Reset_MRIHTol(farg1) & +bind(C, name="_wrap_FSUNAdaptController_Reset_MRIHTol") & +result(fresult) +use, intrinsic :: ISO_C_BINDING +type(C_PTR), value :: farg1 +integer(C_INT) :: fresult +end function + +function swigc_FSUNAdaptController_SetDefaults_MRIHTol(farg1) & +bind(C, name="_wrap_FSUNAdaptController_SetDefaults_MRIHTol") & +result(fresult) +use, intrinsic :: ISO_C_BINDING +type(C_PTR), value :: farg1 +integer(C_INT) :: fresult +end function + +function swigc_FSUNAdaptController_Write_MRIHTol(farg1, farg2) & +bind(C, name="_wrap_FSUNAdaptController_Write_MRIHTol") & +result(fresult) +use, intrinsic :: ISO_C_BINDING +type(C_PTR), value :: farg1 +type(C_PTR), value :: farg2 +integer(C_INT) :: fresult +end function + +function swigc_FSUNAdaptController_SetErrorBias_MRIHTol(farg1, farg2) & +bind(C, name="_wrap_FSUNAdaptController_SetErrorBias_MRIHTol") & +result(fresult) +use, intrinsic :: ISO_C_BINDING +type(C_PTR), value :: farg1 +real(C_DOUBLE), intent(in) :: farg2 +integer(C_INT) :: fresult +end function + +function swigc_FSUNAdaptController_UpdateMRIHTol_MRIHTol(farg1, farg2, farg3, farg4, farg5) & +bind(C, name="_wrap_FSUNAdaptController_UpdateMRIHTol_MRIHTol") & +result(fresult) +use, intrinsic :: ISO_C_BINDING +type(C_PTR), value :: farg1 +real(C_DOUBLE), intent(in) :: farg2 +real(C_DOUBLE), intent(in) :: farg3 +real(C_DOUBLE), intent(in) :: farg4 +real(C_DOUBLE), intent(in) :: farg5 +integer(C_INT) :: fresult +end function + +function swigc_FSUNAdaptController_Space_MRIHTol(farg1, farg2, farg3) & +bind(C, name="_wrap_FSUNAdaptController_Space_MRIHTol") & +result(fresult) +use, intrinsic :: ISO_C_BINDING +type(C_PTR), value :: farg1 +type(C_PTR), value :: farg2 +type(C_PTR), value :: farg3 +integer(C_INT) :: fresult +end function + +end interface + + +contains + ! MODULE SUBPROGRAMS +subroutine swigf_SUNAdaptControllerContent_MRIHTol__HControl_set(self, hcontrol) +use, intrinsic :: ISO_C_BINDING +class(SUNAdaptControllerContent_MRIHTol_), intent(in) :: self +type(SUNAdaptController), target, intent(inout) :: hcontrol +type(SwigClassWrapper) :: farg1 +type(C_PTR) :: farg2 + +farg1 = self%swigdata +farg2 = c_loc(hcontrol) +call swigc_SUNAdaptControllerContent_MRIHTol__HControl_set(farg1, farg2) +end subroutine + +function swigf_SUNAdaptControllerContent_MRIHTol__HControl_get(self) & +result(swig_result) +use, intrinsic :: ISO_C_BINDING +type(SUNAdaptController), pointer :: swig_result +class(SUNAdaptControllerContent_MRIHTol_), intent(in) :: self +type(C_PTR) :: fresult +type(SwigClassWrapper) :: farg1 + +farg1 = self%swigdata +fresult = swigc_SUNAdaptControllerContent_MRIHTol__HControl_get(farg1) +call c_f_pointer(fresult, swig_result) +end function + +subroutine swigf_SUNAdaptControllerContent_MRIHTol__TolControl_set(self, tolcontrol) +use, intrinsic :: ISO_C_BINDING +class(SUNAdaptControllerContent_MRIHTol_), intent(in) :: self +type(SUNAdaptController), target, intent(inout) :: tolcontrol +type(SwigClassWrapper) :: farg1 +type(C_PTR) :: farg2 + +farg1 = self%swigdata +farg2 = c_loc(tolcontrol) +call swigc_SUNAdaptControllerContent_MRIHTol__TolControl_set(farg1, farg2) +end subroutine + +function swigf_SUNAdaptControllerContent_MRIHTol__TolControl_get(self) & +result(swig_result) +use, intrinsic :: ISO_C_BINDING +type(SUNAdaptController), pointer :: swig_result +class(SUNAdaptControllerContent_MRIHTol_), intent(in) :: self +type(C_PTR) :: fresult +type(SwigClassWrapper) :: farg1 + +farg1 = self%swigdata +fresult = swigc_SUNAdaptControllerContent_MRIHTol__TolControl_get(farg1) +call c_f_pointer(fresult, swig_result) +end function + +subroutine swigf_SUNAdaptControllerContent_MRIHTol__inner_max_relch_set(self, inner_max_relch) +use, intrinsic :: ISO_C_BINDING +class(SUNAdaptControllerContent_MRIHTol_), intent(in) :: self +real(C_DOUBLE), intent(in) :: inner_max_relch +type(SwigClassWrapper) :: farg1 +real(C_DOUBLE) :: farg2 + +farg1 = self%swigdata +farg2 = inner_max_relch +call swigc_SUNAdaptControllerContent_MRIHTol__inner_max_relch_set(farg1, farg2) +end subroutine + +function swigf_SUNAdaptControllerContent_MRIHTol__inner_max_relch_get(self) & +result(swig_result) +use, intrinsic :: ISO_C_BINDING +real(C_DOUBLE) :: swig_result +class(SUNAdaptControllerContent_MRIHTol_), intent(in) :: self +real(C_DOUBLE) :: fresult +type(SwigClassWrapper) :: farg1 + +farg1 = self%swigdata +fresult = swigc_SUNAdaptControllerContent_MRIHTol__inner_max_relch_get(farg1) +swig_result = fresult +end function + +subroutine swigf_SUNAdaptControllerContent_MRIHTol__inner_min_tolfac_set(self, inner_min_tolfac) +use, intrinsic :: ISO_C_BINDING +class(SUNAdaptControllerContent_MRIHTol_), intent(in) :: self +real(C_DOUBLE), intent(in) :: inner_min_tolfac +type(SwigClassWrapper) :: farg1 +real(C_DOUBLE) :: farg2 + +farg1 = self%swigdata +farg2 = inner_min_tolfac +call swigc_SUNAdaptControllerContent_MRIHTol__inner_min_tolfac_set(farg1, farg2) +end subroutine + +function swigf_SUNAdaptControllerContent_MRIHTol__inner_min_tolfac_get(self) & +result(swig_result) +use, intrinsic :: ISO_C_BINDING +real(C_DOUBLE) :: swig_result +class(SUNAdaptControllerContent_MRIHTol_), intent(in) :: self +real(C_DOUBLE) :: fresult +type(SwigClassWrapper) :: farg1 + +farg1 = self%swigdata +fresult = swigc_SUNAdaptControllerContent_MRIHTol__inner_min_tolfac_get(farg1) +swig_result = fresult +end function + +subroutine swigf_SUNAdaptControllerContent_MRIHTol__inner_max_tolfac_set(self, inner_max_tolfac) +use, intrinsic :: ISO_C_BINDING +class(SUNAdaptControllerContent_MRIHTol_), intent(in) :: self +real(C_DOUBLE), intent(in) :: inner_max_tolfac +type(SwigClassWrapper) :: farg1 +real(C_DOUBLE) :: farg2 + +farg1 = self%swigdata +farg2 = inner_max_tolfac +call swigc_SUNAdaptControllerContent_MRIHTol__inner_max_tolfac_set(farg1, farg2) +end subroutine + +function swigf_SUNAdaptControllerContent_MRIHTol__inner_max_tolfac_get(self) & +result(swig_result) +use, intrinsic :: ISO_C_BINDING +real(C_DOUBLE) :: swig_result +class(SUNAdaptControllerContent_MRIHTol_), intent(in) :: self +real(C_DOUBLE) :: fresult +type(SwigClassWrapper) :: farg1 + +farg1 = self%swigdata +fresult = swigc_SUNAdaptControllerContent_MRIHTol__inner_max_tolfac_get(farg1) +swig_result = fresult +end function + +function swigf_create_SUNAdaptControllerContent_MRIHTol_() & +result(self) +use, intrinsic :: ISO_C_BINDING +type(SUNAdaptControllerContent_MRIHTol_) :: self +type(SwigClassWrapper) :: fresult + +fresult = swigc_new_SUNAdaptControllerContent_MRIHTol_() +self%swigdata = fresult +end function + +subroutine swigf_release_SUNAdaptControllerContent_MRIHTol_(self) +use, intrinsic :: ISO_C_BINDING +class(SUNAdaptControllerContent_MRIHTol_), intent(inout) :: self +type(SwigClassWrapper) :: farg1 + +farg1 = self%swigdata +if (btest(farg1%cmemflags, swig_cmem_own_bit)) then +call swigc_delete_SUNAdaptControllerContent_MRIHTol_(farg1) +endif +farg1%cptr = C_NULL_PTR +farg1%cmemflags = 0 +self%swigdata = farg1 +end subroutine + +subroutine swigf_SUNAdaptControllerContent_MRIHTol__op_assign__(self, other) +use, intrinsic :: ISO_C_BINDING +class(SUNAdaptControllerContent_MRIHTol_), intent(inout) :: self +type(SUNAdaptControllerContent_MRIHTol_), intent(in) :: other +type(SwigClassWrapper) :: farg1 +type(SwigClassWrapper) :: farg2 + +farg1 = self%swigdata +farg2 = other%swigdata +call swigc_SUNAdaptControllerContent_MRIHTol__op_assign__(farg1, farg2) +self%swigdata = farg1 +end subroutine + +function FSUNAdaptController_MRIHTol(hcontrol, tolcontrol, sunctx) & +result(swig_result) +use, intrinsic :: ISO_C_BINDING +type(SUNAdaptController), pointer :: swig_result +type(SUNAdaptController), target, intent(inout) :: hcontrol +type(SUNAdaptController), target, intent(inout) :: tolcontrol +type(C_PTR) :: sunctx +type(C_PTR) :: fresult +type(C_PTR) :: farg1 +type(C_PTR) :: farg2 +type(C_PTR) :: farg3 + +farg1 = c_loc(hcontrol) +farg2 = c_loc(tolcontrol) +farg3 = sunctx +fresult = swigc_FSUNAdaptController_MRIHTol(farg1, farg2, farg3) +call c_f_pointer(fresult, swig_result) +end function + +function FSUNAdaptController_SetParams_MRIHTol(c, inner_max_relch, inner_min_tolfac, inner_max_tolfac) & +result(swig_result) +use, intrinsic :: ISO_C_BINDING +integer(C_INT) :: swig_result +type(SUNAdaptController), target, intent(inout) :: c +real(C_DOUBLE), intent(in) :: inner_max_relch +real(C_DOUBLE), intent(in) :: inner_min_tolfac +real(C_DOUBLE), intent(in) :: inner_max_tolfac +integer(C_INT) :: fresult +type(C_PTR) :: farg1 +real(C_DOUBLE) :: farg2 +real(C_DOUBLE) :: farg3 +real(C_DOUBLE) :: farg4 + +farg1 = c_loc(c) +farg2 = inner_max_relch +farg3 = inner_min_tolfac +farg4 = inner_max_tolfac +fresult = swigc_FSUNAdaptController_SetParams_MRIHTol(farg1, farg2, farg3, farg4) +swig_result = fresult +end function + +function FSUNAdaptController_GetSlowController_MRIHTol(c, cslow) & +result(swig_result) +use, intrinsic :: ISO_C_BINDING +integer(C_INT) :: swig_result +type(SUNAdaptController), target, intent(inout) :: c +type(C_PTR), target, intent(inout) :: cslow +integer(C_INT) :: fresult +type(C_PTR) :: farg1 +type(C_PTR) :: farg2 + +farg1 = c_loc(c) +farg2 = c_loc(cslow) +fresult = swigc_FSUNAdaptController_GetSlowController_MRIHTol(farg1, farg2) +swig_result = fresult +end function + +function FSUNAdaptController_GetFastController_MRIHTol(c, cfast) & +result(swig_result) +use, intrinsic :: ISO_C_BINDING +integer(C_INT) :: swig_result +type(SUNAdaptController), target, intent(inout) :: c +type(C_PTR), target, intent(inout) :: cfast +integer(C_INT) :: fresult +type(C_PTR) :: farg1 +type(C_PTR) :: farg2 + +farg1 = c_loc(c) +farg2 = c_loc(cfast) +fresult = swigc_FSUNAdaptController_GetFastController_MRIHTol(farg1, farg2) +swig_result = fresult +end function + +function FSUNAdaptController_GetType_MRIHTol(c) & +result(swig_result) +use, intrinsic :: ISO_C_BINDING +integer(SUNAdaptController_Type) :: swig_result +type(SUNAdaptController), target, intent(inout) :: c +integer(C_INT) :: fresult +type(C_PTR) :: farg1 + +farg1 = c_loc(c) +fresult = swigc_FSUNAdaptController_GetType_MRIHTol(farg1) +swig_result = fresult +end function + +function FSUNAdaptController_EstimateStepTol_MRIHTol(c, h, tolfac, p, dsm, dsm5, hnew, tolfacnew) & +result(swig_result) +use, intrinsic :: ISO_C_BINDING +integer(C_INT) :: swig_result +type(SUNAdaptController), target, intent(inout) :: c +real(C_DOUBLE), intent(in) :: h +real(C_DOUBLE), intent(in) :: tolfac +integer(C_INT), intent(in) :: p +real(C_DOUBLE), intent(in) :: dsm +real(C_DOUBLE), intent(in) :: dsm5 +real(C_DOUBLE), dimension(*), target, intent(inout) :: hnew +real(C_DOUBLE), dimension(*), target, intent(inout) :: tolfacnew +integer(C_INT) :: fresult +type(C_PTR) :: farg1 +real(C_DOUBLE) :: farg2 +real(C_DOUBLE) :: farg3 +integer(C_INT) :: farg4 +real(C_DOUBLE) :: farg5 +real(C_DOUBLE) :: farg6 +type(C_PTR) :: farg7 +type(C_PTR) :: farg8 + +farg1 = c_loc(c) +farg2 = h +farg3 = tolfac +farg4 = p +farg5 = dsm +farg6 = dsm5 +farg7 = c_loc(hnew(1)) +farg8 = c_loc(tolfacnew(1)) +fresult = swigc_FSUNAdaptController_EstimateStepTol_MRIHTol(farg1, farg2, farg3, farg4, farg5, farg6, farg7, farg8) +swig_result = fresult +end function + +function FSUNAdaptController_Reset_MRIHTol(c) & +result(swig_result) +use, intrinsic :: ISO_C_BINDING +integer(C_INT) :: swig_result +type(SUNAdaptController), target, intent(inout) :: c +integer(C_INT) :: fresult +type(C_PTR) :: farg1 + +farg1 = c_loc(c) +fresult = swigc_FSUNAdaptController_Reset_MRIHTol(farg1) +swig_result = fresult +end function + +function FSUNAdaptController_SetDefaults_MRIHTol(c) & +result(swig_result) +use, intrinsic :: ISO_C_BINDING +integer(C_INT) :: swig_result +type(SUNAdaptController), target, intent(inout) :: c +integer(C_INT) :: fresult +type(C_PTR) :: farg1 + +farg1 = c_loc(c) +fresult = swigc_FSUNAdaptController_SetDefaults_MRIHTol(farg1) +swig_result = fresult +end function + +function FSUNAdaptController_Write_MRIHTol(c, fptr) & +result(swig_result) +use, intrinsic :: ISO_C_BINDING +integer(C_INT) :: swig_result +type(SUNAdaptController), target, intent(inout) :: c +type(C_PTR) :: fptr +integer(C_INT) :: fresult +type(C_PTR) :: farg1 +type(C_PTR) :: farg2 + +farg1 = c_loc(c) +farg2 = fptr +fresult = swigc_FSUNAdaptController_Write_MRIHTol(farg1, farg2) +swig_result = fresult +end function + +function FSUNAdaptController_SetErrorBias_MRIHTol(c, bias) & +result(swig_result) +use, intrinsic :: ISO_C_BINDING +integer(C_INT) :: swig_result +type(SUNAdaptController), target, intent(inout) :: c +real(C_DOUBLE), intent(in) :: bias +integer(C_INT) :: fresult +type(C_PTR) :: farg1 +real(C_DOUBLE) :: farg2 + +farg1 = c_loc(c) +farg2 = bias +fresult = swigc_FSUNAdaptController_SetErrorBias_MRIHTol(farg1, farg2) +swig_result = fresult +end function + +function FSUNAdaptController_UpdateMRIHTol_MRIHTol(c, h, tolfac, dsm, dsm4) & +result(swig_result) +use, intrinsic :: ISO_C_BINDING +integer(C_INT) :: swig_result +type(SUNAdaptController), target, intent(inout) :: c +real(C_DOUBLE), intent(in) :: h +real(C_DOUBLE), intent(in) :: tolfac +real(C_DOUBLE), intent(in) :: dsm +real(C_DOUBLE), intent(in) :: dsm4 +integer(C_INT) :: fresult +type(C_PTR) :: farg1 +real(C_DOUBLE) :: farg2 +real(C_DOUBLE) :: farg3 +real(C_DOUBLE) :: farg4 +real(C_DOUBLE) :: farg5 + +farg1 = c_loc(c) +farg2 = h +farg3 = tolfac +farg4 = dsm +farg5 = dsm4 +fresult = swigc_FSUNAdaptController_UpdateMRIHTol_MRIHTol(farg1, farg2, farg3, farg4, farg5) +swig_result = fresult +end function + +function FSUNAdaptController_Space_MRIHTol(c, lenrw, leniw) & +result(swig_result) +use, intrinsic :: ISO_C_BINDING +integer(C_INT) :: swig_result +type(SUNAdaptController), target, intent(inout) :: c +integer(C_LONG), dimension(*), target, intent(inout) :: lenrw +integer(C_LONG), dimension(*), target, intent(inout) :: leniw +integer(C_INT) :: fresult +type(C_PTR) :: farg1 +type(C_PTR) :: farg2 +type(C_PTR) :: farg3 + +farg1 = c_loc(c) +farg2 = c_loc(lenrw(1)) +farg3 = c_loc(leniw(1)) +fresult = swigc_FSUNAdaptController_Space_MRIHTol(farg1, farg2, farg3) +swig_result = fresult +end function + + +end module diff --git a/src/sunadaptcontroller/mrihtol/sunadaptcontroller_mrihtol.c b/src/sunadaptcontroller/mrihtol/sunadaptcontroller_mrihtol.c new file mode 100644 index 0000000000..774bb87be9 --- /dev/null +++ b/src/sunadaptcontroller/mrihtol/sunadaptcontroller_mrihtol.c @@ -0,0 +1,274 @@ +/* ----------------------------------------------------------------- + * Programmer(s): Daniel R. Reynolds @ SMU + * ----------------------------------------------------------------- + * SUNDIALS Copyright Start + * Copyright (c) 2002-2024, Lawrence Livermore National Security + * and Southern Methodist University. + * All rights reserved. + * + * See the top-level LICENSE and NOTICE files for details. + * + * SPDX-License-Identifier: BSD-3-Clause + * SUNDIALS Copyright End + * ----------------------------------------------------------------- + * This is the implementation file for the + * SUNAdaptController_MRIHTol module. + * -----------------------------------------------------------------*/ + +#include +#include + +#include +#include +#include "sundials/priv/sundials_errors_impl.h" +#include "sundials/sundials_errors.h" + +#include "sundials_macros.h" + +/* ------------------ + * Default parameters + * ------------------ */ + +/* maximum relative change for inner tolerance factor */ +#define INNER_MAX_RELCH SUN_RCONST(20.0) +/* minimum tolerance factor for inner solver */ +#define INNER_MIN_TOLFAC SUN_RCONST(1.e-5) +/* maximum tolerance factor for inner solver */ +#define INNER_MAX_TOLFAC SUN_RCONST(1.0) + +/* --------------- + * Macro accessors + * --------------- */ + +#define MRIHTOL_CONTENT(C) ((SUNAdaptControllerContent_MRIHTol)(C->content)) +#define MRIHTOL_CSLOW(C) (MRIHTOL_CONTENT(C)->HControl) +#define MRIHTOL_CFAST(C) (MRIHTOL_CONTENT(C)->TolControl) +#define MRIHTOL_INNER_MAX_RELCH(C) (MRIHTOL_CONTENT(C)->inner_max_relch) +#define MRIHTOL_INNER_MIN_TOLFAC(C) (MRIHTOL_CONTENT(C)->inner_min_tolfac) +#define MRIHTOL_INNER_MAX_TOLFAC(C) (MRIHTOL_CONTENT(C)->inner_max_tolfac) + +/* ----------------------------------------------------------------- + * exported functions + * ----------------------------------------------------------------- */ + +/* ----------------------------------------------------------------- + * Function to create a new MRIHTol controller + */ + +SUNAdaptController SUNAdaptController_MRIHTol(SUNAdaptController HControl, + SUNAdaptController TolControl, + SUNContext sunctx) +{ + SUNFunctionBegin(sunctx); + + SUNAdaptController C; + SUNAdaptControllerContent_MRIHTol content; + + /* Verify that input controllers have the appropriate type */ + SUNAssertNull(SUNAdaptController_GetType(HControl) == SUN_ADAPTCONTROLLER_H, + SUN_ERR_ARG_INCOMPATIBLE); + SUNAssertNull(SUNAdaptController_GetType(TolControl) == SUN_ADAPTCONTROLLER_H, + SUN_ERR_ARG_INCOMPATIBLE); + + /* Create an empty controller object */ + C = NULL; + C = SUNAdaptController_NewEmpty(sunctx); + SUNCheckLastErrNull(); + + /* Attach operations */ + C->ops->gettype = SUNAdaptController_GetType_MRIHTol; + C->ops->estimatesteptol = SUNAdaptController_EstimateStepTol_MRIHTol; + C->ops->reset = SUNAdaptController_Reset_MRIHTol; + C->ops->setdefaults = SUNAdaptController_SetDefaults_MRIHTol; + C->ops->write = SUNAdaptController_Write_MRIHTol; + C->ops->seterrorbias = SUNAdaptController_SetErrorBias_MRIHTol; + C->ops->updatemrihtol = SUNAdaptController_UpdateMRIHTol_MRIHTol; + C->ops->space = SUNAdaptController_Space_MRIHTol; + + /* Create content */ + content = NULL; + content = (SUNAdaptControllerContent_MRIHTol)malloc(sizeof *content); + SUNAssertNull(content, SUN_ERR_MALLOC_FAIL); + + /* Attach input controllers */ + content->HControl = HControl; + content->TolControl = TolControl; + + /* Set parameters to default values */ + content->inner_max_relch = INNER_MAX_RELCH; + content->inner_min_tolfac = INNER_MIN_TOLFAC; + content->inner_max_tolfac = INNER_MAX_TOLFAC; + + /* Attach content */ + C->content = content; + + return C; +} + +/* ----------------------------------------------------------------- + * Function to set MRIHTol parameters + */ + +SUNErrCode SUNAdaptController_SetParams_MRIHTol(SUNAdaptController C, + sunrealtype inner_max_relch, + sunrealtype inner_min_tolfac, + sunrealtype inner_max_tolfac) +{ + SUNFunctionBegin(C->sunctx); + SUNAssert(inner_max_tolfac > inner_min_tolfac, SUN_ERR_ARG_OUTOFRANGE); + if (inner_max_relch < SUN_RCONST(1.0)) + { + MRIHTOL_INNER_MAX_RELCH(C) = INNER_MAX_RELCH; + } + else { MRIHTOL_INNER_MAX_RELCH(C) = inner_max_relch; } + if (inner_min_tolfac <= SUN_RCONST(0.0)) + { + MRIHTOL_INNER_MIN_TOLFAC(C) = INNER_MIN_TOLFAC; + } + else { MRIHTOL_INNER_MIN_TOLFAC(C) = inner_min_tolfac; } + if ((inner_max_tolfac <= SUN_RCONST(0.0)) || + (inner_max_tolfac > SUN_RCONST(1.0))) + { + MRIHTOL_INNER_MAX_TOLFAC(C) = INNER_MAX_TOLFAC; + } + else { MRIHTOL_INNER_MAX_TOLFAC(C) = inner_max_tolfac; } + return SUN_SUCCESS; +} + +/* ----------------------------------------------------------------- + * Function to get slow and fast sub-controllers + */ + +SUNErrCode SUNAdaptController_GetSlowController_MRIHTol(SUNAdaptController C, + SUNAdaptController* Cslow) +{ + SUNFunctionBegin(C->sunctx); + SUNAssert(Cslow, SUN_ERR_ARG_CORRUPT); + *Cslow = MRIHTOL_CSLOW(C); + return SUN_SUCCESS; +} + +SUNErrCode SUNAdaptController_GetFastController_MRIHTol(SUNAdaptController C, + SUNAdaptController* Cfast) +{ + SUNFunctionBegin(C->sunctx); + SUNAssert(Cfast, SUN_ERR_ARG_CORRUPT); + *Cfast = MRIHTOL_CFAST(C); + return SUN_SUCCESS; +} + +/* ----------------------------------------------------------------- + * implementation of controller operations + * ----------------------------------------------------------------- */ + +SUNAdaptController_Type SUNAdaptController_GetType_MRIHTol( + SUNDIALS_MAYBE_UNUSED SUNAdaptController C) +{ + return SUN_ADAPTCONTROLLER_MRI_H_TOL; +} + +SUNErrCode SUNAdaptController_EstimateStepTol_MRIHTol( + SUNAdaptController C, sunrealtype H, sunrealtype tolfac, int P, + sunrealtype DSM, sunrealtype dsm, sunrealtype* Hnew, sunrealtype* tolfacnew) +{ + SUNFunctionBegin(C->sunctx); + SUNAssert(Hnew, SUN_ERR_ARG_CORRUPT); + SUNAssert(tolfacnew, SUN_ERR_ARG_CORRUPT); + sunrealtype tolfacest; + + /* Call slow time scale sub-controller to fill Hnew -- note that all heuristics + bounds on Hnew will be enforced by the time integrator itself */ + SUNCheckCall(SUNAdaptController_EstimateStep(MRIHTOL_CSLOW(C), H, P, DSM, Hnew)); + + /* Call fast time scale sub-controller with order=1: no matter the integrator + order, we expect its error to be proportional to the tolerance factor */ + SUNCheckCall(SUNAdaptController_EstimateStep(MRIHTOL_CFAST(C), tolfac, 0, dsm, + &tolfacest)); + + /* Enforce bounds on estimated tolerance factor */ + /* keep relative change within bounds */ + tolfacest = SUNMAX(tolfacest, tolfac / MRIHTOL_INNER_MAX_RELCH(C)); + tolfacest = SUNMIN(tolfacest, tolfac * MRIHTOL_INNER_MAX_RELCH(C)); + /* enforce absolute min/max bounds */ + tolfacest = SUNMAX(tolfacest, MRIHTOL_INNER_MIN_TOLFAC(C)); + tolfacest = SUNMIN(tolfacest, MRIHTOL_INNER_MAX_TOLFAC(C)); + + /* Set result and return */ + *tolfacnew = tolfacest; + return SUN_SUCCESS; +} + +SUNErrCode SUNAdaptController_Reset_MRIHTol(SUNAdaptController C) +{ + SUNFunctionBegin(C->sunctx); + SUNCheckCall(SUNAdaptController_Reset(MRIHTOL_CSLOW(C))); + SUNCheckCall(SUNAdaptController_Reset(MRIHTOL_CFAST(C))); + return SUN_SUCCESS; +} + +SUNErrCode SUNAdaptController_SetDefaults_MRIHTol(SUNAdaptController C) +{ + SUNFunctionBegin(C->sunctx); + SUNCheckCall(SUNAdaptController_SetDefaults(MRIHTOL_CSLOW(C))); + SUNCheckCall(SUNAdaptController_SetDefaults(MRIHTOL_CFAST(C))); + MRIHTOL_INNER_MAX_RELCH(C) = INNER_MAX_RELCH; + MRIHTOL_INNER_MIN_TOLFAC(C) = INNER_MIN_TOLFAC; + MRIHTOL_INNER_MAX_TOLFAC(C) = INNER_MAX_TOLFAC; + return SUN_SUCCESS; +} + +SUNErrCode SUNAdaptController_Write_MRIHTol(SUNAdaptController C, FILE* fptr) +{ + SUNFunctionBegin(C->sunctx); + SUNAssert(fptr, SUN_ERR_ARG_CORRUPT); + fprintf(fptr, "Multirate H-Tol SUNAdaptController module:\n"); +#if defined(SUNDIALS_EXTENDED_PRECISION) + fprintf(fptr, " inner_max_relch = %32Lg\n", MRIHTOL_INNER_MAX_RELCH(C)); + fprintf(fptr, " inner_min_tolfac = %32Lg\n", MRIHTOL_INNER_MIN_TOLFAC(C)); + fprintf(fptr, " inner_max_tolfac = %32Lg\n", MRIHTOL_INNER_MAX_TOLFAC(C)); +#else + fprintf(fptr, " inner_max_relch = %16g\n", MRIHTOL_INNER_MAX_RELCH(C)); + fprintf(fptr, " inner_min_tolfac = %16g\n", MRIHTOL_INNER_MIN_TOLFAC(C)); + fprintf(fptr, " inner_max_tolfac = %16g\n", MRIHTOL_INNER_MAX_TOLFAC(C)); +#endif + fprintf(fptr, "\nSlow step controller:\n"); + SUNCheckCall(SUNAdaptController_Write(MRIHTOL_CSLOW(C), fptr)); + fprintf(fptr, "\nFast tolerance controller:\n"); + SUNCheckCall(SUNAdaptController_Write(MRIHTOL_CFAST(C), fptr)); + return SUN_SUCCESS; +} + +SUNErrCode SUNAdaptController_SetErrorBias_MRIHTol(SUNAdaptController C, + sunrealtype bias) +{ + SUNFunctionBegin(C->sunctx); + SUNCheckCall(SUNAdaptController_SetErrorBias(MRIHTOL_CSLOW(C), bias)); + SUNCheckCall(SUNAdaptController_SetErrorBias(MRIHTOL_CFAST(C), bias)); + return SUN_SUCCESS; +} + +SUNErrCode SUNAdaptController_UpdateMRIHTol_MRIHTol(SUNAdaptController C, + sunrealtype H, + sunrealtype tolfac, + sunrealtype DSM, + sunrealtype dsm) +{ + SUNFunctionBegin(C->sunctx); + SUNCheckCall(SUNAdaptController_UpdateH(MRIHTOL_CSLOW(C), H, DSM)); + SUNCheckCall(SUNAdaptController_UpdateH(MRIHTOL_CFAST(C), tolfac, dsm)); + return SUN_SUCCESS; +} + +SUNErrCode SUNAdaptController_Space_MRIHTol(SUNAdaptController C, + long int* lenrw, long int* leniw) +{ + SUNFunctionBegin(C->sunctx); + SUNAssert(lenrw, SUN_ERR_ARG_CORRUPT); + SUNAssert(leniw, SUN_ERR_ARG_CORRUPT); + long int lrw, liw; + SUNCheckCall(SUNAdaptController_Space(MRIHTOL_CSLOW(C), lenrw, leniw)); + SUNCheckCall(SUNAdaptController_Space(MRIHTOL_CFAST(C), &lrw, &liw)); + *lenrw += lrw; + *leniw += liw; + return SUN_SUCCESS; +} diff --git a/src/sundials/fmod_int32/fsundials_core_mod.c b/src/sundials/fmod_int32/fsundials_core_mod.c index 9cec8422c8..43855b4e60 100644 --- a/src/sundials/fmod_int32/fsundials_core_mod.c +++ b/src/sundials/fmod_int32/fsundials_core_mod.c @@ -2560,6 +2560,32 @@ SWIGEXPORT int _wrap_FSUNAdaptController_EstimateStep(SUNAdaptController farg1, } +SWIGEXPORT int _wrap_FSUNAdaptController_EstimateStepTol(SUNAdaptController farg1, double const *farg2, double const *farg3, int const *farg4, double const *farg5, double const *farg6, double *farg7, double *farg8) { + int fresult ; + SUNAdaptController arg1 = (SUNAdaptController) 0 ; + sunrealtype arg2 ; + sunrealtype arg3 ; + int arg4 ; + sunrealtype arg5 ; + sunrealtype arg6 ; + sunrealtype *arg7 = (sunrealtype *) 0 ; + sunrealtype *arg8 = (sunrealtype *) 0 ; + SUNErrCode result; + + arg1 = (SUNAdaptController)(farg1); + arg2 = (sunrealtype)(*farg2); + arg3 = (sunrealtype)(*farg3); + arg4 = (int)(*farg4); + arg5 = (sunrealtype)(*farg5); + arg6 = (sunrealtype)(*farg6); + arg7 = (sunrealtype *)(farg7); + arg8 = (sunrealtype *)(farg8); + result = (SUNErrCode)SUNAdaptController_EstimateStepTol(arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8); + fresult = (SUNErrCode)(result); + return fresult; +} + + SWIGEXPORT int _wrap_FSUNAdaptController_Reset(SUNAdaptController farg1) { int fresult ; SUNAdaptController arg1 = (SUNAdaptController) 0 ; @@ -2628,6 +2654,26 @@ SWIGEXPORT int _wrap_FSUNAdaptController_UpdateH(SUNAdaptController farg1, doubl } +SWIGEXPORT int _wrap_FSUNAdaptController_UpdateMRIHTol(SUNAdaptController farg1, double const *farg2, double const *farg3, double const *farg4, double const *farg5) { + int fresult ; + SUNAdaptController arg1 = (SUNAdaptController) 0 ; + sunrealtype arg2 ; + sunrealtype arg3 ; + sunrealtype arg4 ; + sunrealtype arg5 ; + SUNErrCode result; + + arg1 = (SUNAdaptController)(farg1); + arg2 = (sunrealtype)(*farg2); + arg3 = (sunrealtype)(*farg3); + arg4 = (sunrealtype)(*farg4); + arg5 = (sunrealtype)(*farg5); + result = (SUNErrCode)SUNAdaptController_UpdateMRIHTol(arg1,arg2,arg3,arg4,arg5); + fresult = (SUNErrCode)(result); + return fresult; +} + + SWIGEXPORT int _wrap_FSUNAdaptController_Space(SUNAdaptController farg1, long *farg2, long *farg3) { int fresult ; SUNAdaptController arg1 = (SUNAdaptController) 0 ; diff --git a/src/sundials/fmod_int32/fsundials_core_mod.f90 b/src/sundials/fmod_int32/fsundials_core_mod.f90 index 0b95e5c880..bc425ba37b 100644 --- a/src/sundials/fmod_int32/fsundials_core_mod.f90 +++ b/src/sundials/fmod_int32/fsundials_core_mod.f90 @@ -511,19 +511,22 @@ module fsundials_core_mod enum, bind(c) enumerator :: SUN_ADAPTCONTROLLER_NONE enumerator :: SUN_ADAPTCONTROLLER_H + enumerator :: SUN_ADAPTCONTROLLER_MRI_H_TOL end enum integer, parameter, public :: SUNAdaptController_Type = kind(SUN_ADAPTCONTROLLER_NONE) - public :: SUN_ADAPTCONTROLLER_NONE, SUN_ADAPTCONTROLLER_H + public :: SUN_ADAPTCONTROLLER_NONE, SUN_ADAPTCONTROLLER_H, SUN_ADAPTCONTROLLER_MRI_H_TOL ! struct struct _generic_SUNAdaptController_Ops type, bind(C), public :: SUNAdaptController_Ops type(C_FUNPTR), public :: gettype type(C_FUNPTR), public :: estimatestep + type(C_FUNPTR), public :: estimatesteptol type(C_FUNPTR), public :: destroy type(C_FUNPTR), public :: reset type(C_FUNPTR), public :: setdefaults type(C_FUNPTR), public :: write type(C_FUNPTR), public :: seterrorbias type(C_FUNPTR), public :: updateh + type(C_FUNPTR), public :: updatemrihtol type(C_FUNPTR), public :: space end type SUNAdaptController_Ops ! struct struct _generic_SUNAdaptController @@ -537,11 +540,13 @@ module fsundials_core_mod public :: FSUNAdaptController_GetType public :: FSUNAdaptController_Destroy public :: FSUNAdaptController_EstimateStep + public :: FSUNAdaptController_EstimateStepTol public :: FSUNAdaptController_Reset public :: FSUNAdaptController_SetDefaults public :: FSUNAdaptController_Write public :: FSUNAdaptController_SetErrorBias public :: FSUNAdaptController_UpdateH + public :: FSUNAdaptController_UpdateMRIHTol public :: FSUNAdaptController_Space ! typedef enum SUNFullRhsMode enum, bind(c) @@ -2014,6 +2019,21 @@ function swigc_FSUNAdaptController_EstimateStep(farg1, farg2, farg3, farg4, farg integer(C_INT) :: fresult end function +function swigc_FSUNAdaptController_EstimateStepTol(farg1, farg2, farg3, farg4, farg5, farg6, farg7, farg8) & +bind(C, name="_wrap_FSUNAdaptController_EstimateStepTol") & +result(fresult) +use, intrinsic :: ISO_C_BINDING +type(C_PTR), value :: farg1 +real(C_DOUBLE), intent(in) :: farg2 +real(C_DOUBLE), intent(in) :: farg3 +integer(C_INT), intent(in) :: farg4 +real(C_DOUBLE), intent(in) :: farg5 +real(C_DOUBLE), intent(in) :: farg6 +type(C_PTR), value :: farg7 +type(C_PTR), value :: farg8 +integer(C_INT) :: fresult +end function + function swigc_FSUNAdaptController_Reset(farg1) & bind(C, name="_wrap_FSUNAdaptController_Reset") & result(fresult) @@ -2058,6 +2078,18 @@ function swigc_FSUNAdaptController_UpdateH(farg1, farg2, farg3) & integer(C_INT) :: fresult end function +function swigc_FSUNAdaptController_UpdateMRIHTol(farg1, farg2, farg3, farg4, farg5) & +bind(C, name="_wrap_FSUNAdaptController_UpdateMRIHTol") & +result(fresult) +use, intrinsic :: ISO_C_BINDING +type(C_PTR), value :: farg1 +real(C_DOUBLE), intent(in) :: farg2 +real(C_DOUBLE), intent(in) :: farg3 +real(C_DOUBLE), intent(in) :: farg4 +real(C_DOUBLE), intent(in) :: farg5 +integer(C_INT) :: fresult +end function + function swigc_FSUNAdaptController_Space(farg1, farg2, farg3) & bind(C, name="_wrap_FSUNAdaptController_Space") & result(fresult) @@ -4894,6 +4926,40 @@ function FSUNAdaptController_EstimateStep(c, h, p, dsm, hnew) & swig_result = fresult end function +function FSUNAdaptController_EstimateStepTol(c, h, tolfac, p, dsm, dsm5, hnew, tolfacnew) & +result(swig_result) +use, intrinsic :: ISO_C_BINDING +integer(C_INT) :: swig_result +type(SUNAdaptController), target, intent(inout) :: c +real(C_DOUBLE), intent(in) :: h +real(C_DOUBLE), intent(in) :: tolfac +integer(C_INT), intent(in) :: p +real(C_DOUBLE), intent(in) :: dsm +real(C_DOUBLE), intent(in) :: dsm5 +real(C_DOUBLE), dimension(*), target, intent(inout) :: hnew +real(C_DOUBLE), dimension(*), target, intent(inout) :: tolfacnew +integer(C_INT) :: fresult +type(C_PTR) :: farg1 +real(C_DOUBLE) :: farg2 +real(C_DOUBLE) :: farg3 +integer(C_INT) :: farg4 +real(C_DOUBLE) :: farg5 +real(C_DOUBLE) :: farg6 +type(C_PTR) :: farg7 +type(C_PTR) :: farg8 + +farg1 = c_loc(c) +farg2 = h +farg3 = tolfac +farg4 = p +farg5 = dsm +farg6 = dsm5 +farg7 = c_loc(hnew(1)) +farg8 = c_loc(tolfacnew(1)) +fresult = swigc_FSUNAdaptController_EstimateStepTol(farg1, farg2, farg3, farg4, farg5, farg6, farg7, farg8) +swig_result = fresult +end function + function FSUNAdaptController_Reset(c) & result(swig_result) use, intrinsic :: ISO_C_BINDING @@ -4971,6 +5037,31 @@ function FSUNAdaptController_UpdateH(c, h, dsm) & swig_result = fresult end function +function FSUNAdaptController_UpdateMRIHTol(c, h, tolfac, dsm, dsm4) & +result(swig_result) +use, intrinsic :: ISO_C_BINDING +integer(C_INT) :: swig_result +type(SUNAdaptController), target, intent(inout) :: c +real(C_DOUBLE), intent(in) :: h +real(C_DOUBLE), intent(in) :: tolfac +real(C_DOUBLE), intent(in) :: dsm +real(C_DOUBLE), intent(in) :: dsm4 +integer(C_INT) :: fresult +type(C_PTR) :: farg1 +real(C_DOUBLE) :: farg2 +real(C_DOUBLE) :: farg3 +real(C_DOUBLE) :: farg4 +real(C_DOUBLE) :: farg5 + +farg1 = c_loc(c) +farg2 = h +farg3 = tolfac +farg4 = dsm +farg5 = dsm4 +fresult = swigc_FSUNAdaptController_UpdateMRIHTol(farg1, farg2, farg3, farg4, farg5) +swig_result = fresult +end function + function FSUNAdaptController_Space(c, lenrw, leniw) & result(swig_result) use, intrinsic :: ISO_C_BINDING diff --git a/src/sundials/fmod_int64/fsundials_core_mod.c b/src/sundials/fmod_int64/fsundials_core_mod.c index b1f96d2b55..7062f9a507 100644 --- a/src/sundials/fmod_int64/fsundials_core_mod.c +++ b/src/sundials/fmod_int64/fsundials_core_mod.c @@ -2560,6 +2560,32 @@ SWIGEXPORT int _wrap_FSUNAdaptController_EstimateStep(SUNAdaptController farg1, } +SWIGEXPORT int _wrap_FSUNAdaptController_EstimateStepTol(SUNAdaptController farg1, double const *farg2, double const *farg3, int const *farg4, double const *farg5, double const *farg6, double *farg7, double *farg8) { + int fresult ; + SUNAdaptController arg1 = (SUNAdaptController) 0 ; + sunrealtype arg2 ; + sunrealtype arg3 ; + int arg4 ; + sunrealtype arg5 ; + sunrealtype arg6 ; + sunrealtype *arg7 = (sunrealtype *) 0 ; + sunrealtype *arg8 = (sunrealtype *) 0 ; + SUNErrCode result; + + arg1 = (SUNAdaptController)(farg1); + arg2 = (sunrealtype)(*farg2); + arg3 = (sunrealtype)(*farg3); + arg4 = (int)(*farg4); + arg5 = (sunrealtype)(*farg5); + arg6 = (sunrealtype)(*farg6); + arg7 = (sunrealtype *)(farg7); + arg8 = (sunrealtype *)(farg8); + result = (SUNErrCode)SUNAdaptController_EstimateStepTol(arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8); + fresult = (SUNErrCode)(result); + return fresult; +} + + SWIGEXPORT int _wrap_FSUNAdaptController_Reset(SUNAdaptController farg1) { int fresult ; SUNAdaptController arg1 = (SUNAdaptController) 0 ; @@ -2628,6 +2654,26 @@ SWIGEXPORT int _wrap_FSUNAdaptController_UpdateH(SUNAdaptController farg1, doubl } +SWIGEXPORT int _wrap_FSUNAdaptController_UpdateMRIHTol(SUNAdaptController farg1, double const *farg2, double const *farg3, double const *farg4, double const *farg5) { + int fresult ; + SUNAdaptController arg1 = (SUNAdaptController) 0 ; + sunrealtype arg2 ; + sunrealtype arg3 ; + sunrealtype arg4 ; + sunrealtype arg5 ; + SUNErrCode result; + + arg1 = (SUNAdaptController)(farg1); + arg2 = (sunrealtype)(*farg2); + arg3 = (sunrealtype)(*farg3); + arg4 = (sunrealtype)(*farg4); + arg5 = (sunrealtype)(*farg5); + result = (SUNErrCode)SUNAdaptController_UpdateMRIHTol(arg1,arg2,arg3,arg4,arg5); + fresult = (SUNErrCode)(result); + return fresult; +} + + SWIGEXPORT int _wrap_FSUNAdaptController_Space(SUNAdaptController farg1, long *farg2, long *farg3) { int fresult ; SUNAdaptController arg1 = (SUNAdaptController) 0 ; diff --git a/src/sundials/fmod_int64/fsundials_core_mod.f90 b/src/sundials/fmod_int64/fsundials_core_mod.f90 index 13be2c2a2a..e16ea3b306 100644 --- a/src/sundials/fmod_int64/fsundials_core_mod.f90 +++ b/src/sundials/fmod_int64/fsundials_core_mod.f90 @@ -511,19 +511,22 @@ module fsundials_core_mod enum, bind(c) enumerator :: SUN_ADAPTCONTROLLER_NONE enumerator :: SUN_ADAPTCONTROLLER_H + enumerator :: SUN_ADAPTCONTROLLER_MRI_H_TOL end enum integer, parameter, public :: SUNAdaptController_Type = kind(SUN_ADAPTCONTROLLER_NONE) - public :: SUN_ADAPTCONTROLLER_NONE, SUN_ADAPTCONTROLLER_H + public :: SUN_ADAPTCONTROLLER_NONE, SUN_ADAPTCONTROLLER_H, SUN_ADAPTCONTROLLER_MRI_H_TOL ! struct struct _generic_SUNAdaptController_Ops type, bind(C), public :: SUNAdaptController_Ops type(C_FUNPTR), public :: gettype type(C_FUNPTR), public :: estimatestep + type(C_FUNPTR), public :: estimatesteptol type(C_FUNPTR), public :: destroy type(C_FUNPTR), public :: reset type(C_FUNPTR), public :: setdefaults type(C_FUNPTR), public :: write type(C_FUNPTR), public :: seterrorbias type(C_FUNPTR), public :: updateh + type(C_FUNPTR), public :: updatemrihtol type(C_FUNPTR), public :: space end type SUNAdaptController_Ops ! struct struct _generic_SUNAdaptController @@ -537,11 +540,13 @@ module fsundials_core_mod public :: FSUNAdaptController_GetType public :: FSUNAdaptController_Destroy public :: FSUNAdaptController_EstimateStep + public :: FSUNAdaptController_EstimateStepTol public :: FSUNAdaptController_Reset public :: FSUNAdaptController_SetDefaults public :: FSUNAdaptController_Write public :: FSUNAdaptController_SetErrorBias public :: FSUNAdaptController_UpdateH + public :: FSUNAdaptController_UpdateMRIHTol public :: FSUNAdaptController_Space ! typedef enum SUNFullRhsMode enum, bind(c) @@ -2014,6 +2019,21 @@ function swigc_FSUNAdaptController_EstimateStep(farg1, farg2, farg3, farg4, farg integer(C_INT) :: fresult end function +function swigc_FSUNAdaptController_EstimateStepTol(farg1, farg2, farg3, farg4, farg5, farg6, farg7, farg8) & +bind(C, name="_wrap_FSUNAdaptController_EstimateStepTol") & +result(fresult) +use, intrinsic :: ISO_C_BINDING +type(C_PTR), value :: farg1 +real(C_DOUBLE), intent(in) :: farg2 +real(C_DOUBLE), intent(in) :: farg3 +integer(C_INT), intent(in) :: farg4 +real(C_DOUBLE), intent(in) :: farg5 +real(C_DOUBLE), intent(in) :: farg6 +type(C_PTR), value :: farg7 +type(C_PTR), value :: farg8 +integer(C_INT) :: fresult +end function + function swigc_FSUNAdaptController_Reset(farg1) & bind(C, name="_wrap_FSUNAdaptController_Reset") & result(fresult) @@ -2058,6 +2078,18 @@ function swigc_FSUNAdaptController_UpdateH(farg1, farg2, farg3) & integer(C_INT) :: fresult end function +function swigc_FSUNAdaptController_UpdateMRIHTol(farg1, farg2, farg3, farg4, farg5) & +bind(C, name="_wrap_FSUNAdaptController_UpdateMRIHTol") & +result(fresult) +use, intrinsic :: ISO_C_BINDING +type(C_PTR), value :: farg1 +real(C_DOUBLE), intent(in) :: farg2 +real(C_DOUBLE), intent(in) :: farg3 +real(C_DOUBLE), intent(in) :: farg4 +real(C_DOUBLE), intent(in) :: farg5 +integer(C_INT) :: fresult +end function + function swigc_FSUNAdaptController_Space(farg1, farg2, farg3) & bind(C, name="_wrap_FSUNAdaptController_Space") & result(fresult) @@ -4894,6 +4926,40 @@ function FSUNAdaptController_EstimateStep(c, h, p, dsm, hnew) & swig_result = fresult end function +function FSUNAdaptController_EstimateStepTol(c, h, tolfac, p, dsm, dsm5, hnew, tolfacnew) & +result(swig_result) +use, intrinsic :: ISO_C_BINDING +integer(C_INT) :: swig_result +type(SUNAdaptController), target, intent(inout) :: c +real(C_DOUBLE), intent(in) :: h +real(C_DOUBLE), intent(in) :: tolfac +integer(C_INT), intent(in) :: p +real(C_DOUBLE), intent(in) :: dsm +real(C_DOUBLE), intent(in) :: dsm5 +real(C_DOUBLE), dimension(*), target, intent(inout) :: hnew +real(C_DOUBLE), dimension(*), target, intent(inout) :: tolfacnew +integer(C_INT) :: fresult +type(C_PTR) :: farg1 +real(C_DOUBLE) :: farg2 +real(C_DOUBLE) :: farg3 +integer(C_INT) :: farg4 +real(C_DOUBLE) :: farg5 +real(C_DOUBLE) :: farg6 +type(C_PTR) :: farg7 +type(C_PTR) :: farg8 + +farg1 = c_loc(c) +farg2 = h +farg3 = tolfac +farg4 = p +farg5 = dsm +farg6 = dsm5 +farg7 = c_loc(hnew(1)) +farg8 = c_loc(tolfacnew(1)) +fresult = swigc_FSUNAdaptController_EstimateStepTol(farg1, farg2, farg3, farg4, farg5, farg6, farg7, farg8) +swig_result = fresult +end function + function FSUNAdaptController_Reset(c) & result(swig_result) use, intrinsic :: ISO_C_BINDING @@ -4971,6 +5037,31 @@ function FSUNAdaptController_UpdateH(c, h, dsm) & swig_result = fresult end function +function FSUNAdaptController_UpdateMRIHTol(c, h, tolfac, dsm, dsm4) & +result(swig_result) +use, intrinsic :: ISO_C_BINDING +integer(C_INT) :: swig_result +type(SUNAdaptController), target, intent(inout) :: c +real(C_DOUBLE), intent(in) :: h +real(C_DOUBLE), intent(in) :: tolfac +real(C_DOUBLE), intent(in) :: dsm +real(C_DOUBLE), intent(in) :: dsm4 +integer(C_INT) :: fresult +type(C_PTR) :: farg1 +real(C_DOUBLE) :: farg2 +real(C_DOUBLE) :: farg3 +real(C_DOUBLE) :: farg4 +real(C_DOUBLE) :: farg5 + +farg1 = c_loc(c) +farg2 = h +farg3 = tolfac +farg4 = dsm +farg5 = dsm4 +fresult = swigc_FSUNAdaptController_UpdateMRIHTol(farg1, farg2, farg3, farg4, farg5) +swig_result = fresult +end function + function FSUNAdaptController_Space(c, lenrw, leniw) & result(swig_result) use, intrinsic :: ISO_C_BINDING diff --git a/src/sundials/sundials_adaptcontroller.c b/src/sundials/sundials_adaptcontroller.c index 39a56480d0..4641f1751c 100644 --- a/src/sundials/sundials_adaptcontroller.c +++ b/src/sundials/sundials_adaptcontroller.c @@ -46,15 +46,17 @@ SUNAdaptController SUNAdaptController_NewEmpty(SUNContext sunctx) SUNAssertNull(ops, SUN_ERR_MALLOC_FAIL); /* initialize operations to NULL */ - ops->gettype = NULL; - ops->destroy = NULL; - ops->reset = NULL; - ops->estimatestep = NULL; - ops->setdefaults = NULL; - ops->write = NULL; - ops->seterrorbias = NULL; - ops->updateh = NULL; - ops->space = NULL; + ops->gettype = NULL; + ops->destroy = NULL; + ops->reset = NULL; + ops->estimatestep = NULL; + ops->estimatesteptol = NULL; + ops->setdefaults = NULL; + ops->write = NULL; + ops->seterrorbias = NULL; + ops->updateh = NULL; + ops->updatemrihtol = NULL; + ops->space = NULL; /* attach ops and initialize content to NULL */ C->ops = ops; @@ -137,6 +139,26 @@ SUNErrCode SUNAdaptController_EstimateStep(SUNAdaptController C, sunrealtype h, return (ier); } +SUNErrCode SUNAdaptController_EstimateStepTol(SUNAdaptController C, + sunrealtype H, sunrealtype tolfac, + int P, sunrealtype DSM, + sunrealtype dsm, sunrealtype* Hnew, + sunrealtype* tolfacnew) +{ + SUNErrCode ier = SUN_SUCCESS; + if (C == NULL) { return SUN_ERR_ARG_CORRUPT; } + SUNFunctionBegin(C->sunctx); + SUNAssert(Hnew, SUN_ERR_ARG_CORRUPT); + SUNAssert(tolfacnew, SUN_ERR_ARG_CORRUPT); + *Hnew = H; /* initialize outputs with identity */ + *tolfacnew = tolfac; + if (C->ops->estimatesteptol) + { + ier = C->ops->estimatesteptol(C, H, tolfac, P, DSM, dsm, Hnew, tolfacnew); + } + return (ier); +} + SUNErrCode SUNAdaptController_Reset(SUNAdaptController C) { SUNErrCode ier = SUN_SUCCESS; @@ -184,6 +206,20 @@ SUNErrCode SUNAdaptController_UpdateH(SUNAdaptController C, sunrealtype h, return (ier); } +SUNErrCode SUNAdaptController_UpdateMRIHTol(SUNAdaptController C, sunrealtype H, + sunrealtype tolfac, sunrealtype DSM, + sunrealtype dsm) +{ + SUNErrCode ier = SUN_SUCCESS; + if (C == NULL) { return SUN_ERR_ARG_CORRUPT; } + SUNFunctionBegin(C->sunctx); + if (C->ops->updatemrihtol) + { + ier = C->ops->updatemrihtol(C, H, tolfac, DSM, dsm); + } + return (ier); +} + SUNErrCode SUNAdaptController_Space(SUNAdaptController C, long int* lenrw, long int* leniw) { diff --git a/swig/Makefile b/swig/Makefile index 4bcefe8423..424d4857a4 100644 --- a/swig/Makefile +++ b/swig/Makefile @@ -27,7 +27,7 @@ NVECTOR=openmp pthreads serial parallel manyvector mpiplusx SUNMATRIX=band dense sparse SUNLINSOL=band dense lapackdense klu spbcgs spfgmr spgmr sptfqmr pcg SUNNONLINSOL=newton fixedpoint -SUNADAPTCONTROLLER=imexgus soderlind +SUNADAPTCONTROLLER=imexgus soderlind mrihtol INCLUDES=-I../include diff --git a/swig/sunadaptcontroller/fsunadaptcontroller_mrihtol_mod.i b/swig/sunadaptcontroller/fsunadaptcontroller_mrihtol_mod.i new file mode 100644 index 0000000000..feb54e4bf1 --- /dev/null +++ b/swig/sunadaptcontroller/fsunadaptcontroller_mrihtol_mod.i @@ -0,0 +1,29 @@ +// --------------------------------------------------------------- +// Programmer: Daniel R. Reynolds @ SMU +// --------------------------------------------------------------- +// SUNDIALS Copyright Start +// Copyright (c) 2002-2024, Lawrence Livermore National Security +// and Southern Methodist University. +// All rights reserved. +// +// See the top-level LICENSE and NOTICE files for details. +// +// SPDX-License-Identifier: BSD-3-Clause +// SUNDIALS Copyright End +// --------------------------------------------------------------- +// Swig interface file +// --------------------------------------------------------------- + +%module fsunadaptcontroller_mrihtol_mod + +// include code common to all implementations +%include "fsunadaptcontroller.i" + +%{ +#include "sunadaptcontroller/sunadaptcontroller_mrihtol.h" +%} + +%sunadaptcontroller_impl(MRIHTol) + +// Process and wrap functions in the following files +%include "sunadaptcontroller/sunadaptcontroller_mrihtol.h" diff --git a/test/answers b/test/answers index 5dca98a66d..294c370633 160000 --- a/test/answers +++ b/test/answers @@ -1 +1 @@ -Subproject commit 5dca98a66d4f833c19a4fd63163f466ac5f50b56 +Subproject commit 294c3706336ef84e9719b419a4e29d9a551e7294 diff --git a/test/test_driver.sh b/test/test_driver.sh index 3a1d25f4ec..4faee8b8ea 100755 --- a/test/test_driver.sh +++ b/test/test_driver.sh @@ -374,7 +374,7 @@ args_phase=() case "$testtype" in BRANCH) - # Don't creat tarballs + # Don't create tarballs tarball=NONE # Address sanitizer tests (TPLs OFF) diff --git a/test/unit_tests/arkode/CXX_parallel/ark_test_heat2D_mri.cpp b/test/unit_tests/arkode/CXX_parallel/ark_test_heat2D_mri.cpp index 303d85f057..c4f9757a29 100644 --- a/test/unit_tests/arkode/CXX_parallel/ark_test_heat2D_mri.cpp +++ b/test/unit_tests/arkode/CXX_parallel/ark_test_heat2D_mri.cpp @@ -225,8 +225,8 @@ int main(int argc, char* argv[]) if (check_flag((void*)inner_mem, "ARKStepCreate", 0)) { return 1; } MRIStepInnerStepper inner_stepper = NULL; - flag = ARKStepCreateMRIStepInnerStepper(inner_mem, &inner_stepper); - if (check_flag(&flag, "ARKStepCreateMRIStepInnerStepper", 1)) { return 1; } + flag = ARKodeCreateMRIStepInnerStepper(inner_mem, &inner_stepper); + if (check_flag(&flag, "ARKodeCreateMRIStepInnerStepper", 1)) { return 1; } mristep_mem = MRIStepCreate(NULL, f, T0, y, inner_stepper, ctx); if (check_flag((void*)mristep_mem, "MRIStepCreate", 0)) { return 1; } diff --git a/test/unit_tests/arkode/CXX_parallel/ark_test_heat2D_mri_0.out b/test/unit_tests/arkode/CXX_parallel/ark_test_heat2D_mri_0.out index a78e16c9fd..9ca728ed54 100644 --- a/test/unit_tests/arkode/CXX_parallel/ark_test_heat2D_mri_0.out +++ b/test/unit_tests/arkode/CXX_parallel/ark_test_heat2D_mri_0.out @@ -28,10 +28,10 @@ MRIStep Solver Statistics: Internal solver steps = 1000 Total RHS evals: Fe = 2769 Total linear solver setups = 50 - Total linear iterations = 6250 - Total number of Jacobian-vector products = 6250 + Total linear iterations = 6234 + Total number of Jacobian-vector products = 6234 Total number of Preconditioner setups = 50 - Total number of Preconditioner solves = 6250 + Total number of Preconditioner solves = 6234 Total number of linear solver convergence failures = 0 Total number of Newton iterations = 1768 Total number of nonlinear solver convergence failures = 0 diff --git a/test/unit_tests/arkode/CXX_parallel/ark_test_heat2D_mri_1.out b/test/unit_tests/arkode/CXX_parallel/ark_test_heat2D_mri_1.out index bbf3267c89..d0a8f738c5 100644 --- a/test/unit_tests/arkode/CXX_parallel/ark_test_heat2D_mri_1.out +++ b/test/unit_tests/arkode/CXX_parallel/ark_test_heat2D_mri_1.out @@ -28,10 +28,10 @@ MRIStep Solver Statistics: Internal solver steps = 1000 Total RHS evals: Fe = 2001 Total linear solver setups = 1 - Total linear iterations = 4731 - Total number of Jacobian-vector products = 4731 + Total linear iterations = 4722 + Total number of Jacobian-vector products = 4722 Total number of Preconditioner setups = 1 - Total number of Preconditioner solves = 4731 + Total number of Preconditioner solves = 4722 Total number of linear solver convergence failures = 0 Total number of Newton iterations = 1000 Total number of nonlinear solver convergence failures = 0 diff --git a/test/unit_tests/arkode/CXX_serial/CMakeLists.txt b/test/unit_tests/arkode/CXX_serial/CMakeLists.txt index c1f22fc6bc..c62580c508 100644 --- a/test/unit_tests/arkode/CXX_serial/CMakeLists.txt +++ b/test/unit_tests/arkode/CXX_serial/CMakeLists.txt @@ -11,37 +11,49 @@ # SPDX-License-Identifier: BSD-3-Clause # SUNDIALS Copyright End # --------------------------------------------------------------- -# ARKode C++ serial unit_tests +# ARKODE C++ serial unit_tests # --------------------------------------------------------------- -# List of test tuples of the form "name\;args" +# List of test tuples of the form "name\;args\;type" where the type is 'develop' +# for tests excluded from 'make test' in releases set(unit_tests - "ark_test_analytic_sys_mri.cpp\;0" - "ark_test_analytic_sys_mri.cpp\;1" - "ark_test_dahlquist_ark.cpp\;0 -1 0" - "ark_test_dahlquist_ark.cpp\;0 0 0" - "ark_test_dahlquist_ark.cpp\;0 0 1" - "ark_test_dahlquist_ark.cpp\;0 1 0" - "ark_test_dahlquist_ark.cpp\;0 1 1" - "ark_test_dahlquist_ark.cpp\;1 -1 0" - "ark_test_dahlquist_ark.cpp\;1 0 0" - "ark_test_dahlquist_ark.cpp\;1 0 1" - "ark_test_dahlquist_ark.cpp\;1 1 0" - "ark_test_dahlquist_ark.cpp\;1 1 1" - "ark_test_dahlquist_ark.cpp\;2 -1 0" - "ark_test_dahlquist_ark.cpp\;2 0 0" - "ark_test_dahlquist_ark.cpp\;2 0 1" - "ark_test_dahlquist_ark.cpp\;2 1 0" - "ark_test_dahlquist_ark.cpp\;2 1 1" - "ark_test_dahlquist_erk.cpp\;-1" - "ark_test_dahlquist_erk.cpp\;0" - "ark_test_dahlquist_erk.cpp\;1" - "ark_test_dahlquist_mri.cpp\;-1" - "ark_test_dahlquist_mri.cpp\;0" - "ark_test_dahlquist_mri.cpp\;1" - "ark_test_butcher.cpp\;" - "ark_test_getjac.cpp\;" - "ark_test_getjac_mri.cpp\;") + "ark_test_accumerror_brusselator.cpp\;20 3 1\;exclude-single" + "ark_test_accumerror_brusselator.cpp\;20 -4 0\;exclude-single" + "ark_test_accumerror_brusselator.cpp\;20 5 0\;exclude-single" + "ark_test_accumerror_kpr.cpp\;20 2 0\;exclude-single" + "ark_test_accumerror_kpr.cpp\;20 3 1\;exclude-single" + "ark_test_accumerror_kpr.cpp\;20 -4 1\;exclude-single" + "ark_test_analytic_sys_mri.cpp\;0\;develop" + "ark_test_analytic_sys_mri.cpp\;1\;develop" + "ark_test_dahlquist_ark.cpp\;0 -1 0\;develop" + "ark_test_dahlquist_ark.cpp\;0 0 0\;develop" + "ark_test_dahlquist_ark.cpp\;0 0 1\;develop" + "ark_test_dahlquist_ark.cpp\;0 1 0\;develop" + "ark_test_dahlquist_ark.cpp\;0 1 1\;develop" + "ark_test_dahlquist_ark.cpp\;1 -1 0\;develop" + "ark_test_dahlquist_ark.cpp\;1 0 0\;develop" + "ark_test_dahlquist_ark.cpp\;1 0 1\;develop" + "ark_test_dahlquist_ark.cpp\;1 1 0\;develop" + "ark_test_dahlquist_ark.cpp\;1 1 1\;develop" + "ark_test_dahlquist_ark.cpp\;2 -1 0\;develop" + "ark_test_dahlquist_ark.cpp\;2 0 0\;develop" + "ark_test_dahlquist_ark.cpp\;2 0 1\;develop" + "ark_test_dahlquist_ark.cpp\;2 1 0\;develop" + "ark_test_dahlquist_ark.cpp\;2 1 1\;develop" + "ark_test_dahlquist_erk.cpp\;-1\;develop" + "ark_test_dahlquist_erk.cpp\;0\;develop" + "ark_test_dahlquist_erk.cpp\;1\;develop" + "ark_test_dahlquist_mri.cpp\;-1\;develop" + "ark_test_dahlquist_mri.cpp\;0\;develop" + "ark_test_dahlquist_mri.cpp\;1\;develop" + "ark_test_butcher.cpp\;\;develop" + "ark_test_getjac.cpp\;\;develop" + "ark_test_getjac_mri.cpp\;\;develop" + "ark_test_kpr_mriadapt.cpp\;--hs 0.002 --rtol 0.000004 --scontrol 0\;exclude-single" + "ark_test_brusselator_mriadapt.cpp\;--rtol 0.000004 --scontrol 0\;exclude-single" + "ark_test_slowerror_brusselator.cpp\;\;exclude-single" + "ark_test_slowerror_kpr.cpp\;\;exclude-single" + "ark_test_slowerror_polynomial.cpp\;\;exclude-single") # Add the build and install targets for each test foreach(test_tuple ${unit_tests}) @@ -49,6 +61,7 @@ foreach(test_tuple ${unit_tests}) # Parse the test tuple list(GET test_tuple 0 test) list(GET test_tuple 1 test_args) + list(GET test_tuple 2 test_type) # Extract the file name without extension get_filename_component(test_target ${test} NAME_WE) @@ -83,6 +96,7 @@ foreach(test_tuple ${unit_tests}) sundials_sunnonlinsolfixedpoint_obj sundials_sunadaptcontrollerimexgus_obj sundials_sunadaptcontrollersoderlind_obj + sundials_sunadaptcontrollermrihtol_obj ${EXE_EXTRA_LINK_LIBS}) # Tell CMake that we depend on the ARKODE library since it does not pick @@ -110,7 +124,7 @@ foreach(test_tuple ${unit_tests}) TEST_ARGS ${test_args} ANSWER_DIR ${CMAKE_CURRENT_SOURCE_DIR} ANSWER_FILE ${test_name}.out - EXAMPLE_TYPE "develop" ${diff_output}) + EXAMPLE_TYPE ${test_type} ${diff_output}) endforeach() diff --git a/test/unit_tests/arkode/CXX_serial/ark_test_accumerror_brusselator.cpp b/test/unit_tests/arkode/CXX_serial/ark_test_accumerror_brusselator.cpp new file mode 100644 index 0000000000..2d01042362 --- /dev/null +++ b/test/unit_tests/arkode/CXX_serial/ark_test_accumerror_brusselator.cpp @@ -0,0 +1,717 @@ +/*----------------------------------------------------------------- + * Programmer(s): Daniel R. Reynolds @ SMU + *--------------------------------------------------------------- + * SUNDIALS Copyright Start + * Copyright (c) 2002-2024, Lawrence Livermore National Security + * and Southern Methodist University. + * All rights reserved. + * + * See the top-level LICENSE and NOTICE files for details. + * + * SPDX-License-Identifier: BSD-3-Clause + * SUNDIALS Copyright End + *--------------------------------------------------------------- + * Routine to test the accumulated temporal error estimation + * approaches from ARKStep. Uses the + * "stiff Brusselator" test problem with 3 components, + * du/dt = a - (w+1)*u + v*u^2 + * dv/dt = w*u - v*u^2 + * dw/dt = (b-w)/ep - w*u + * for t in the interval [0.0, 10.0], with initial conditions + * Y0 = [u0,v0,w0]. + * + * The stiffness of the problem is essentially determined + * by ep, wherein if the dynamical time step is given by H and + * the explicit time step size is given by h, then H/h = 1/(100 ep), + * i.e., the stability-limited step takes over at values of + * ep < 1e-2. This file defaults to a moderately stiff setup with + * ep = 1/2500. + * + * We may run the problem in one of 3 different testing scenarios: + * + * Test 1: u0=3.9, v0=1.1, w0=2.8, a=1.2, b=2.5 + * Here, all three components exhibit a rapid transient change + * during the first 0.2 time units, followed by a slow and + * smooth evolution. + * + * Test 2 [default]: u0=1.2, v0=3.1, w0=3, a=1, b=3.5 + * Here, w experiences a fast initial transient, jumping 0.5 + * within a few steps. All values proceed smoothly until + * around t=6.5, when both u and v undergo a sharp transition, + * with u increaseing from around 0.5 to 5 and v decreasing + * from around 6 to 1 in less than 0.5 time units. After this + * transition, both u and v continue to evolve somewhat + * rapidly for another 1.4 time units, and finish off smoothly. + * + * Test 3: u0=3, v0=3, w0=3.5, a=0.5, b=3 + * Here, all components undergo very rapid initial transients + * during the first 0.3 time units, and all then proceed very + * smoothly for the remainder of the simulation. + * + * We partition the full time integration interval, 0 < t < 5, into + * Npart pieces, and run the accumulation test over each. + * + * We use either the ARKStep/DIRK/Newton/Dense solver (0) or + * the ARKStep/ERK solver (1). Either defaults to using a + * 4th-order method. + * + * By default, all runs use temporal adaptivity; however, if the + * requested 'ord' command-line input is negative, we run with + * order |ord|, using fixed step sizes. + * + * The program should be run with arguments in the following order: + * $ a.out Npart ord method ep test + * Not all arguments are required, but these must be omitted from + * end-to-beginning, i.e. any one of + * $ a.out Npart ord method ep + * $ a.out Npart ord method + * $ a.out Npart ord + * $ a.out Npart + * $ a.out + * are acceptable. We require: + * * method = {0, 1} + * * test = {1, 2, 3} + * * ep > 0 + * * Npart > 0 + * + * For either temporally adaptive (ord >= 0) or fixed-step (ord < 0) + * runs, we test a variety of tolerances/step sizes, and compare + * the error at the end of each partition (computed via a reference + * solution) against the integrator-reported accumulated error + * estimate. + *-----------------------------------------------------------------*/ + +// Header files +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#if defined(SUNDIALS_EXTENDED_PRECISION) +#define GSYM "Lg" +#define ESYM "Le" +#define FSYM "Lf" +#else +#define GSYM "g" +#define ESYM "e" +#define FSYM "f" +#endif + +#define ZERO SUN_RCONST(0.0) +#define ONE SUN_RCONST(1.0) +#define TWO SUN_RCONST(2.0) + +using namespace std; + +// User data structure +struct UserData +{ + sunrealtype a; + sunrealtype b; + sunrealtype ep; + int Npart; +}; + +// User-supplied Functions Called by the Solver +static int fn(sunrealtype t, N_Vector y, N_Vector ydot, void* user_data); +static int Jac(sunrealtype t, N_Vector y, N_Vector fy, SUNMatrix J, + void* user_data, N_Vector tmp1, N_Vector tmp2, N_Vector tmp3); + +// Private utility functions +static int adaptive_run(void* arkode_mem, N_Vector y, sunrealtype T0, + sunrealtype Tf, int rk_type, int order, N_Vector* yref, + UserData& udata); +static int fixed_run(void* arkode_mem, N_Vector y, sunrealtype T0, sunrealtype Tf, + int rk_type, int order, N_Vector* yref, UserData& udata); +static int computeErrorWeights(N_Vector ycur, N_Vector weight, sunrealtype rtol, + sunrealtype atol, N_Vector vtemp); +static int check_retval(void* returnvalue, const char* funcname, int opt); + +// Main Program +int main(int argc, char* argv[]) +{ + // general problem parameters + sunrealtype T0 = SUN_RCONST(0.0); // initial time + sunrealtype Tf = SUN_RCONST(10.0); // final time + sunindextype NEQ = 3; // number of dependent vars. + int rk_type = 1; // type of RK method [DIRK=0, ERK=1] + int order = 4; // order of accuracy for RK method + int test = 2; // test problem to run + sunbooleantype adaptive = SUNTRUE; // adaptive run vs convergence order + sunrealtype u0, v0, w0; // parameters + + // general problem variables + int retval; // reusable error-checking flag + N_Vector y = NULL; // empty vector for storing solution + N_Vector* yref = NULL; // empty vectors for storing reference solution + void* arkode_mem = NULL; // empty ARKStep memory structure + void* arkode_ref = NULL; // empty ARKStep memory structure for reference solution + SUNMatrix A = NULL; // empty matrix for solver + SUNLinearSolver LS = NULL; // empty linear solver object + UserData udata; // user-data structure + sunrealtype* ydata = NULL; + udata.ep = SUN_RCONST(0.0004); // stiffness parameter + udata.Npart = 20; // partition size + + // + // Initialization + // + + // Retrieve the command-line options: Npart ord method ep test + if (argc > 1) udata.Npart = atoi(argv[1]); + if (argc > 2) order = atoi(argv[2]); + if (argc > 3) rk_type = atoi(argv[3]); + if (argc > 4) udata.ep = SUNStrToReal(argv[4]); + if (argc > 5) test = atoi(argv[5]); + + // Check arguments for validity + // method = {0, 1} + // test = {1, 2, 3} + // ep > 0 + // Npart > 0 + if ((rk_type < 0) || (rk_type > 1)) + { + cerr << "ERROR: RK type be an integer in {0,1} \n"; + return (-1); + } + if ((test < 1) || (test > 3)) + { + cerr << "ERROR: test type be an integer in {1,2,3} \n"; + return (-1); + } + if (udata.ep <= ZERO) + { + cerr << "ERROR: ep must be a positive real number\n"; + return (-1); + } + if (udata.Npart < 1) + { + cerr << "ERROR: Npart must be a positive integer\n"; + return (-1); + } + + // Handle adaptive run vs order-of-convergence run + if (order < 0) + { + adaptive = SUNFALSE; + order = abs(order); + } + if (order == 0) order = 4; + + // set up the test problem according to the desired test + if (test == 1) + { + u0 = SUN_RCONST(3.9); + v0 = SUN_RCONST(1.1); + w0 = SUN_RCONST(2.8); + udata.a = SUN_RCONST(1.2); + udata.b = SUN_RCONST(2.5); + } + else if (test == 3) + { + u0 = SUN_RCONST(3.0); + v0 = SUN_RCONST(3.0); + w0 = SUN_RCONST(3.5); + udata.a = SUN_RCONST(0.5); + udata.b = SUN_RCONST(3.0); + } + else + { + u0 = SUN_RCONST(1.2); + v0 = SUN_RCONST(3.1); + w0 = SUN_RCONST(3.0); + udata.a = SUN_RCONST(1.0); + udata.b = SUN_RCONST(3.5); + } + + // Initial problem output (and set implicit solver tolerances as needed) + cout + << "\nAccumulated error estimation test (stiff Brusselator ODE problem):\n"; + cout << " time domain: (" << T0 << "," << Tf << "]\n"; + cout << " partition size = " << udata.Npart << endl; + cout << " initial conditions: u0 = " << u0 << ", v0 = " << v0 + << ", w0 = " << w0 << endl; + cout << " problem parameters: a = " << udata.a << ", b = " << udata.b + << ", ep = " << udata.ep << endl; + if (rk_type == 0) { cout << " DIRK solver, order = " << order << endl; } + else if (rk_type == 1) + { + cout << " ERK solver, order = " << order << endl; + } + + // + // Problem Setup + // + + // Create SUNDIALS context + sundials::Context ctx; + + // Create serial vectors for the solution and reference + y = N_VNew_Serial(NEQ, ctx); + if (check_retval((void*)y, "N_VNew_Serial", 0)) return 1; + yref = N_VCloneVectorArray(udata.Npart + 1, y); + if (check_retval((void*)yref, "N_VNew_Serial", 0)) return 1; + ydata = N_VGetArrayPointer(y); + if (check_retval((void*)ydata, "N_VGetArrayPointer", 0)) return 1; + + // Generate reference solution + ydata[0] = u0; + ydata[1] = v0; + ydata[2] = w0; + arkode_ref = ARKStepCreate(fn, NULL, T0, y, ctx); + if (check_retval((void*)arkode_ref, "ARKStepCreate", 0)) return 1; + retval = ARKodeSetUserData(arkode_ref, (void*)&udata); + if (check_retval(&retval, "ARKodeSetUserData", 1)) return 1; + retval = ARKodeSetOrder(arkode_ref, 5); + if (check_retval(&retval, "ARKodeSetOrder", 1)) return 1; + retval = ARKodeSStolerances(arkode_ref, SUN_RCONST(1.e-10), SUN_RCONST(1.e-12)); + if (check_retval(&retval, "ARKodeSStolerances", 1)) return 1; + retval = ARKodeSetMaxNumSteps(arkode_ref, 1000000); + if (check_retval(&retval, "ARKodeSetMaxNumSteps", 1)) return (1); + N_VScale(ONE, y, yref[0]); + sunrealtype hpart = (Tf - T0) / udata.Npart; + for (int ipart = 0; ipart < udata.Npart; ipart++) + { + sunrealtype t = T0 + ipart * hpart; + retval = ARKodeSetStopTime(arkode_ref, t + hpart); + if (check_retval(&retval, "ARKodeSetStopTime", 1)) return 1; + retval = ARKodeEvolve(arkode_ref, t + hpart, y, &t, ARK_NORMAL); + if (check_retval(&retval, "ARKodeEvolve", 1)) return 1; + N_VScale(ONE, y, yref[ipart + 1]); + } + ARKodeFree(&arkode_ref); + + // Set up ARKStep integrator + ydata[0] = u0; + ydata[1] = v0; + ydata[2] = w0; + if (rk_type == 0) + { // DIRK method + arkode_mem = ARKStepCreate(NULL, fn, T0, y, ctx); + } + else + { // ERK method + arkode_mem = ARKStepCreate(fn, NULL, T0, y, ctx); + } + if (check_retval((void*)arkode_mem, "ARKStepCreate", 0)) return 1; + retval = ARKodeSetUserData(arkode_mem, (void*)&udata); + if (check_retval(&retval, "ARKodeSetUserData", 1)) return 1; + retval = ARKodeSetOrder(arkode_mem, order); + if (check_retval(&retval, "ARKodeSetOrder", 1)) return 1; + retval = ARKodeSStolerances(arkode_mem, SUN_RCONST(1.e-4), SUN_RCONST(1.e-9)); + if (check_retval(&retval, "ARKodeSStolerances", 1)) return 1; + if (rk_type == 0) + { // DIRK method + A = SUNDenseMatrix(NEQ, NEQ, ctx); + if (check_retval((void*)A, "SUNDenseMatrix", 0)) return 1; + LS = SUNLinSol_Dense(y, A, ctx); + if (check_retval((void*)LS, "SUNLinSol_Dense", 0)) return 1; + retval = ARKodeSetLinearSolver(arkode_mem, LS, A); + if (check_retval(&retval, "ARKodeSetLinearSolver", 1)) return 1; + retval = ARKodeSetJacFn(arkode_mem, Jac); + if (check_retval(&retval, "ARKodeSetJacFn", 1)) return 1; + } + else + { // ERK method + retval = ARKodeSetMaxNumSteps(arkode_mem, 1000000); + if (check_retval(&retval, "ARKodeSetMaxNumSteps", 1)) return (1); + } + + // Integrate ODE, based on run type + if (adaptive) + { + retval = adaptive_run(arkode_mem, y, T0, Tf, rk_type, order, yref, udata); + if (check_retval(&retval, "adaptive_run", 1)) return 1; + } + else + { + retval = fixed_run(arkode_mem, y, T0, Tf, rk_type, order, yref, udata); + if (check_retval(&retval, "fixed_run", 1)) return 1; + } + + // Clean up and return + ARKodeFree(&arkode_mem); + if (LS) { SUNLinSolFree(LS); } // free system linear solver + if (A) { SUNMatDestroy(A); } // free system matrix + N_VDestroy(y); // Free y and yref vectors + N_VDestroyVectorArray(yref, udata.Npart + 1); + return 0; +} + +//------------------------------ +// Functions called by the solver +//------------------------------ + +static int fn(sunrealtype t, N_Vector y, N_Vector ydot, void* user_data) +{ + UserData* udata = (UserData*)user_data; + sunrealtype* ydata = N_VGetArrayPointer(y); + sunrealtype* dydata = N_VGetArrayPointer(ydot); + const sunrealtype u = ydata[0]; // access solution values + const sunrealtype v = ydata[1]; + const sunrealtype w = ydata[2]; + + // fill in the RHS function + dydata[0] = udata->a - (w + ONE) * u + v * u * u; + dydata[1] = w * u - v * u * u; + dydata[2] = (udata->b - w) / udata->ep - w * u; + + // Return with success + return 0; +} + +static int Jac(sunrealtype t, N_Vector y, N_Vector fy, SUNMatrix J, + void* user_data, N_Vector tmp1, N_Vector tmp2, N_Vector tmp3) +{ + UserData* udata = (UserData*)user_data; + sunrealtype* ydata = N_VGetArrayPointer(y); + const sunrealtype u = ydata[0]; // access solution values + const sunrealtype v = ydata[1]; + const sunrealtype w = ydata[2]; + + // fill in the Jacobian + SM_ELEMENT_D(J, 0, 0) = -(w + ONE) + TWO * u * v; + SM_ELEMENT_D(J, 0, 1) = u * u; + SM_ELEMENT_D(J, 0, 2) = -u; + + SM_ELEMENT_D(J, 1, 0) = w - TWO * u * v; + SM_ELEMENT_D(J, 1, 1) = -u * u; + SM_ELEMENT_D(J, 1, 2) = u; + + SM_ELEMENT_D(J, 2, 0) = -w; + SM_ELEMENT_D(J, 2, 1) = ZERO; + SM_ELEMENT_D(J, 2, 2) = -ONE / udata->ep - u; + + // Return with success + return 0; +} + +/*------------------------------- + * Private helper functions + *-------------------------------*/ + +//------------------------------ +// Private helper functions +//------------------------------ + +static int adaptive_run(void* arkode_mem, N_Vector y, sunrealtype T0, + sunrealtype Tf, int rk_type, int order, N_Vector* yref, + UserData& udata) +{ + // Reused variables + int retval; + sunrealtype t; + sunrealtype hpart = (Tf - T0) / udata.Npart; + sunrealtype abstol = SUN_RCONST(1.e-12); + vector rtols = {SUN_RCONST(1.e-2), SUN_RCONST(1.e-4), + SUN_RCONST(1.e-6)}; + vector accum_types = {ARK_ACCUMERROR_MAX, ARK_ACCUMERROR_SUM, + ARK_ACCUMERROR_AVG}; + vector dsm(udata.Npart); + vector dsm_est(udata.Npart); + vector Nsteps(udata.Npart); + + // Loop over tolerances + cout << "\nAdaptive-step runs:\n"; + for (size_t irtol = 0; irtol < rtols.size(); irtol++) + { + // Loop over accumulation types + for (size_t iaccum = 0; iaccum < accum_types.size(); iaccum++) + { + // Loop over partition + for (int ipart = 0; ipart < udata.Npart; ipart++) + { + // Reset integrator for this run, and evolve over partition interval + t = T0 + ipart * hpart; + N_VScale(ONE, yref[ipart], y); + if (rk_type == 0) + { // DIRK + retval = ARKStepReInit(arkode_mem, NULL, fn, t, y); + } + else + { // ERK + retval = ARKStepReInit(arkode_mem, fn, NULL, t, y); + } + if (check_retval(&retval, "ARKStepReInit", 1)) return 1; + retval = ARKodeSetAccumulatedErrorType(arkode_mem, accum_types[iaccum]); + if (check_retval(&retval, "ARKodeSetAccumulatedErrorType", 1)) return 1; + retval = ARKodeResetAccumulatedError(arkode_mem); + if (check_retval(&retval, "ARKodeResetAccumulatedError", 1)) return 1; + retval = ARKodeSStolerances(arkode_mem, rtols[irtol], abstol); + if (check_retval(&retval, "ARKodeSStolerances", 1)) return 1; + retval = ARKodeSetStopTime(arkode_mem, t + hpart); + if (check_retval(&retval, "ARKodeSetStopTime", 1)) return 1; + retval = ARKodeSetMaxNumSteps(arkode_mem, 1000000); + if (check_retval(&retval, "ARKodeSetMaxNumSteps", 1)) return (1); + retval = ARKodeEvolve(arkode_mem, t + hpart, y, &t, ARK_NORMAL); + if (check_retval(&retval, "ARKodeEvolve", 1)) break; + retval = ARKodeGetAccumulatedError(arkode_mem, &(dsm_est[ipart])); + if (check_retval(&retval, "ARKodeGetAccumulatedError", 1)) break; + retval = ARKodeGetNumSteps(arkode_mem, &(Nsteps[ipart])); + if (check_retval(&retval, "ARKodeGetNumSteps", 1)) break; + + // Compute/print solution error + sunrealtype* ydata = N_VGetArrayPointer(y); + sunrealtype* yrefdata = N_VGetArrayPointer(yref[ipart + 1]); + const sunrealtype udsm = abs(ydata[0] - yrefdata[0]) / + (abstol + rtols[irtol] * abs(yrefdata[0])); + const sunrealtype vdsm = abs(ydata[1] - yrefdata[1]) / + (abstol + rtols[irtol] * abs(yrefdata[1])); + const sunrealtype wdsm = abs(ydata[2] - yrefdata[2]) / + (abstol + rtols[irtol] * abs(yrefdata[2])); + dsm[ipart] = + rtols[irtol] * + sqrt((udsm * udsm + vdsm * vdsm + wdsm * wdsm) / SUN_RCONST(3.0)); + cout << " rtol " << rtols[irtol] << " rk_type " << rk_type + << " order " << order << " acc " << accum_types[iaccum] << " t " + << t << " dsm " << dsm[ipart] << " dsm_est " << dsm_est[ipart] + << " nsteps " << Nsteps[ipart] << endl; + } + } + } + + return (0); +} + +static int fixed_run(void* arkode_mem, N_Vector y, sunrealtype T0, sunrealtype Tf, + int rk_type, int order, N_Vector* yref, UserData& udata) +{ + // Reused variables + int retval; + sunrealtype hpart = (Tf - T0) / udata.Npart; + long int nsteps2; + sunrealtype t, t2; + sunrealtype reltol = SUN_RCONST(1.e-9); + sunrealtype abstol = SUN_RCONST(1.e-12); + N_Vector y2 = N_VClone(y); + N_Vector ewt = N_VClone(y); + ; + N_Vector vtemp = N_VClone(y); + + // Set array of fixed step sizes to use, storage for corresponding errors/orders + sunrealtype hmax = (Tf - T0) / 400; + if (rk_type == 1) hmax = min(hmax, udata.ep); + vector hvals = {hmax, hmax / 4, hmax / 16, hmax / 64}; + vector accum_types = {ARK_ACCUMERROR_MAX, ARK_ACCUMERROR_SUM, + ARK_ACCUMERROR_AVG}; + vector dsm(udata.Npart); + vector dsm_est(udata.Npart); + vector Nsteps(udata.Npart); + + // Loop over step sizes + cout << "\nFixed-step runs:\n"; + for (size_t ih = 0; ih < hvals.size(); ih++) + { + // Loop over built-in accumulation types + for (size_t iaccum = 0; iaccum < accum_types.size(); iaccum++) + { + // Loop over partition + for (int ipart = 0; ipart < udata.Npart; ipart++) + { + // Reset integrator for this run, and evolve to Tf + t = T0 + ipart * hpart; + N_VScale(ONE, yref[ipart], y); + if (rk_type == 0) + { // DIRK + retval = ARKStepReInit(arkode_mem, NULL, fn, t, y); + } + else + { // ERK + retval = ARKStepReInit(arkode_mem, fn, NULL, t, y); + } + if (check_retval(&retval, "ARKStepReInit", 1)) return 1; + retval = ARKodeSetAccumulatedErrorType(arkode_mem, accum_types[iaccum]); + if (check_retval(&retval, "ARKodeSetAccumulatedErrorType", 1)) return 1; + retval = ARKodeResetAccumulatedError(arkode_mem); + if (check_retval(&retval, "ARKodeResetAccumulatedError", 1)) return 1; + retval = ARKodeSetFixedStep(arkode_mem, hvals[ih]); + if (check_retval(&retval, "ARKodeSetFixedStep", 1)) return 1; + retval = ARKodeSetMaxNumSteps(arkode_mem, 1000000); + if (check_retval(&retval, "ARKodeSetMaxNumSteps", 1)) return (1); + retval = ARKodeSetStopTime(arkode_mem, t + hpart); + if (check_retval(&retval, "ARKodeSetStopTime", 1)) return 1; + retval = ARKodeSStolerances(arkode_mem, reltol, abstol); + if (check_retval(&retval, "ARKodeSStolerances", 1)) return 1; + if (rk_type == 0) + { + retval = ARKodeSetJacEvalFrequency(arkode_mem, 1); + if (check_retval(&retval, "ARKodeSetJacEvalFrequency", 1)) return 1; + retval = ARKodeSetLSetupFrequency(arkode_mem, 1); + if (check_retval(&retval, "ARKodeSetLSetupFrequency", 1)) return 1; + retval = ARKodeSetMaxNonlinIters(arkode_mem, 20); + if (check_retval(&retval, "ARKodeSetMaxNonlinIters", 1)) return 1; + } + retval = ARKodeEvolve(arkode_mem, t + hpart, y, &t, ARK_NORMAL); + if (check_retval(&retval, "ARKodeEvolve", 1)) break; + retval = ARKodeGetAccumulatedError(arkode_mem, &(dsm_est[ipart])); + if (check_retval(&retval, "ARKodeGetAccumulatedError", 1)) break; + retval = ARKodeGetNumSteps(arkode_mem, &(Nsteps[ipart])); + if (check_retval(&retval, "ARKodeGetNumSteps", 1)) break; + + // Compute/print solution error + sunrealtype* ydata = N_VGetArrayPointer(y); + sunrealtype* yrefdata = N_VGetArrayPointer(yref[ipart + 1]); + const sunrealtype udsm = abs(ydata[0] - yrefdata[0]) / + (abstol + reltol * abs(yrefdata[0])); + const sunrealtype vdsm = abs(ydata[1] - yrefdata[1]) / + (abstol + reltol * abs(yrefdata[1])); + const sunrealtype wdsm = abs(ydata[2] - yrefdata[2]) / + (abstol + reltol * abs(yrefdata[2])); + dsm[ipart] = reltol * sqrt((udsm * udsm + vdsm * vdsm + wdsm * wdsm) / + SUN_RCONST(3.0)); + cout << " h " << hvals[ih] << " rk_type " << rk_type << " order " + << order << " acc " << accum_types[iaccum] << " t " << t + << " dsm " << dsm[ipart] << " dsm_est " << dsm_est[ipart] + << " nsteps " << Nsteps[ipart] << endl; + } + } + + // Test double-step error estimator + + // Loop over partition + for (int ipart = 0; ipart < udata.Npart; ipart++) + { + // Reset integrator for this run, and evolve over partition interval + t = t2 = T0 + ipart * hpart; + N_VScale(ONE, yref[ipart], y); + N_VScale(ONE, yref[ipart], y2); + if (rk_type == 0) + { // DIRK + retval = ARKStepReInit(arkode_mem, NULL, fn, t, y); + } + else + { // ERK + retval = ARKStepReInit(arkode_mem, fn, NULL, t, y); + } + if (check_retval(&retval, "ARKStepReInit", 1)) return 1; + retval = ARKodeSetAccumulatedErrorType(arkode_mem, ARK_ACCUMERROR_NONE); + if (check_retval(&retval, "ARKodeSetAccumulatedErrorType", 1)) return 1; + retval = ARKodeSetFixedStep(arkode_mem, hvals[ih]); + if (check_retval(&retval, "ARKodeSetFixedStep", 1)) return 1; + retval = ARKodeSetMaxNumSteps(arkode_mem, 1000000); + if (check_retval(&retval, "ARKodeSetMaxNumSteps", 1)) return (1); + retval = ARKodeSetStopTime(arkode_mem, t + hpart); + if (check_retval(&retval, "ARKodeSetStopTime", 1)) return 1; + retval = ARKodeSStolerances(arkode_mem, reltol, abstol); + if (check_retval(&retval, "ARKodeSStolerances", 1)) return 1; + if (rk_type == 0) + { + retval = ARKodeSetJacEvalFrequency(arkode_mem, 1); + if (check_retval(&retval, "ARKodeSetJacEvalFrequency", 1)) return 1; + retval = ARKodeSetLSetupFrequency(arkode_mem, 1); + if (check_retval(&retval, "ARKodeSetLSetupFrequency", 1)) return 1; + retval = ARKodeSetMaxNonlinIters(arkode_mem, 20); + if (check_retval(&retval, "ARKodeSetMaxNonlinIters", 1)) return 1; + } + retval = ARKodeEvolve(arkode_mem, t + hpart, y, &t, ARK_NORMAL); + if (check_retval(&retval, "ARKodeEvolve", 1)) break; + retval = ARKodeGetNumSteps(arkode_mem, &(Nsteps[ipart])); + if (check_retval(&retval, "ARKodeGetNumSteps", 1)) break; + + if (rk_type == 0) + { // DIRK + retval = ARKStepReInit(arkode_mem, NULL, fn, t2, y2); + } + else + { // ERK + retval = ARKStepReInit(arkode_mem, fn, NULL, t2, y2); + } + if (check_retval(&retval, "ARKStepReInit", 1)) return 1; + retval = ARKodeSetFixedStep(arkode_mem, 2.0 * hvals[ih]); + if (check_retval(&retval, "ARKodeSetFixedStep", 1)) return 1; + retval = ARKodeSetStopTime(arkode_mem, t2 + hpart); + if (check_retval(&retval, "ARKodeSetStopTime", 1)) return 1; + retval = ARKodeEvolve(arkode_mem, t2 + hpart, y2, &t2, ARK_NORMAL); + if (check_retval(&retval, "ARKodeEvolve", 1)) break; + retval = ARKodeGetNumSteps(arkode_mem, &nsteps2); + if (check_retval(&retval, "ARKodeGetNumSteps", 1)) break; + + retval = computeErrorWeights(y2, ewt, reltol, abstol, vtemp); + if (check_retval(&retval, "computeErrorWeights", 1)) break; + N_VLinearSum(ONE, y2, -ONE, y, y2); + dsm_est[ipart] = reltol * N_VWrmsNorm(y2, ewt); + Nsteps[ipart] += nsteps2; + + sunrealtype* ydata = N_VGetArrayPointer(y); + sunrealtype* yrefdata = N_VGetArrayPointer(yref[ipart + 1]); + const sunrealtype udsm = abs(ydata[0] - yrefdata[0]) / + (abstol + reltol * abs(yrefdata[0])); + const sunrealtype vdsm = abs(ydata[1] - yrefdata[1]) / + (abstol + reltol * abs(yrefdata[1])); + const sunrealtype wdsm = abs(ydata[2] - yrefdata[2]) / + (abstol + reltol * abs(yrefdata[2])); + dsm[ipart] = reltol * sqrt((udsm * udsm + vdsm * vdsm + wdsm * wdsm) / + SUN_RCONST(3.0)); + cout << " h " << hvals[ih] << " rk_type " << rk_type << " order " + << order << " acc " << 2 << " t " << t << " dsm " << dsm[ipart] + << " dsm_est " << dsm_est[ipart] << " nsteps " << Nsteps[ipart] + << endl; + } + } + + N_VDestroy(y2); + N_VDestroy(ewt); + return (0); +} + +/* Error weight calculation routine (mimics what's in ARKODE already) */ +static int computeErrorWeights(N_Vector ycur, N_Vector weight, sunrealtype rtol, + sunrealtype atol, N_Vector vtemp) +{ + N_VAbs(ycur, vtemp); + N_VScale(rtol, vtemp, vtemp); + N_VAddConst(vtemp, atol, vtemp); + N_VInv(vtemp, weight); + return (0); +} + +/* Check function return value... + opt == 0 means SUNDIALS function allocates memory so check if + returned NULL pointer + opt == 1 means SUNDIALS function returns a retval so check if + retval >= 0 + opt == 2 means function allocates memory so check if returned + NULL pointer +*/ +static int check_retval(void* returnvalue, const char* funcname, int opt) +{ + int* retval; + + // Check if SUNDIALS function returned NULL pointer - no memory allocated + if (opt == 0 && returnvalue == NULL) + { + fprintf(stderr, "\nSUNDIALS_ERROR: %s() failed - returned NULL pointer\n\n", + funcname); + return 1; + } + + // Check if retval < 0 + else if (opt == 1) + { + retval = (int*)returnvalue; + if (*retval < 0) + { + fprintf(stderr, "\nSUNDIALS_ERROR: %s() failed with retval = %d\n\n", + funcname, *retval); + return 1; + } + } + + // Check if function returned NULL pointer - no memory allocated + else if (opt == 2 && returnvalue == NULL) + { + fprintf(stderr, "\nMEMORY_ERROR: %s() failed - returned NULL pointer\n\n", + funcname); + return 1; + } + + return 0; +} + +/*---- end of file ----*/ diff --git a/test/unit_tests/arkode/CXX_serial/ark_test_accumerror_brusselator_20_-4_0.out b/test/unit_tests/arkode/CXX_serial/ark_test_accumerror_brusselator_20_-4_0.out new file mode 100644 index 0000000000..717234ba15 --- /dev/null +++ b/test/unit_tests/arkode/CXX_serial/ark_test_accumerror_brusselator_20_-4_0.out @@ -0,0 +1,329 @@ + +Accumulated error estimation test (stiff Brusselator ODE problem): + time domain: (0,10] + partition size = 20 + initial conditions: u0 = 1.2, v0 = 3.1, w0 = 3 + problem parameters: a = 1, b = 3.5, ep = 0.0004 + DIRK solver, order = 4 + +Fixed-step runs: + h 0.025 rk_type 0 order 4 acc 1 t 0.5 dsm 2.02741e-07 dsm_est 0.244873 nsteps 20 + h 0.025 rk_type 0 order 4 acc 1 t 1 dsm 4.36512e-10 dsm_est 9.15797e-10 nsteps 20 + h 0.025 rk_type 0 order 4 acc 1 t 1.5 dsm 1.47944e-09 dsm_est 1.03904e-09 nsteps 20 + h 0.025 rk_type 0 order 4 acc 1 t 2 dsm 3.07014e-09 dsm_est 7.16968e-10 nsteps 20 + h 0.025 rk_type 0 order 4 acc 1 t 2.5 dsm 2.41009e-09 dsm_est 9.26427e-10 nsteps 20 + h 0.025 rk_type 0 order 4 acc 1 t 3 dsm 2.2919e-10 dsm_est 1.68058e-09 nsteps 20 + h 0.025 rk_type 0 order 4 acc 1 t 3.5 dsm 2.10843e-11 dsm_est 1.6358e-09 nsteps 20 + h 0.025 rk_type 0 order 4 acc 1 t 4 dsm 4.85414e-11 dsm_est 8.11006e-10 nsteps 20 + h 0.025 rk_type 0 order 4 acc 1 t 4.5 dsm 1.96723e-10 dsm_est 1.90108e-10 nsteps 20 + h 0.025 rk_type 0 order 4 acc 1 t 5 dsm 8.22132e-10 dsm_est 5.32797e-10 nsteps 20 + h 0.025 rk_type 0 order 4 acc 1 t 5.5 dsm 1.54757e-09 dsm_est 9.55312e-10 nsteps 20 + h 0.025 rk_type 0 order 4 acc 1 t 6 dsm 1.4066e-09 dsm_est 5.43427e-09 nsteps 20 + h 0.025 rk_type 0 order 4 acc 1 t 6.5 dsm 1.53642e-07 dsm_est 8.50911e-07 nsteps 20 + h 0.025 rk_type 0 order 4 acc 1 t 7 dsm 4.94724e-06 dsm_est 0.000100467 nsteps 20 + h 0.025 rk_type 0 order 4 acc 1 t 7.5 dsm 4.18294e-08 dsm_est 1.0711e-05 nsteps 20 + h 0.025 rk_type 0 order 4 acc 1 t 8 dsm 1.04878e-08 dsm_est 1.1263e-07 nsteps 20 + h 0.025 rk_type 0 order 4 acc 1 t 8.5 dsm 2.79702e-09 dsm_est 2.16903e-08 nsteps 20 + h 0.025 rk_type 0 order 4 acc 1 t 9 dsm 1.60168e-09 dsm_est 1.38178e-08 nsteps 20 + h 0.025 rk_type 0 order 4 acc 1 t 9.5 dsm 1.4347e-09 dsm_est 1.88007e-08 nsteps 20 + h 0.025 rk_type 0 order 4 acc 1 t 10 dsm 5.54538e-10 dsm_est 1.51522e-08 nsteps 20 + h 0.025 rk_type 0 order 4 acc 2 t 0.5 dsm 2.02741e-07 dsm_est 0.270414 nsteps 20 + h 0.025 rk_type 0 order 4 acc 2 t 1 dsm 4.36512e-10 dsm_est 1.01676e-08 nsteps 20 + h 0.025 rk_type 0 order 4 acc 2 t 1.5 dsm 1.47944e-09 dsm_est 1.91745e-08 nsteps 20 + h 0.025 rk_type 0 order 4 acc 2 t 2 dsm 3.07014e-09 dsm_est 7.81488e-09 nsteps 20 + h 0.025 rk_type 0 order 4 acc 2 t 2.5 dsm 2.41009e-09 dsm_est 7.35801e-09 nsteps 20 + h 0.025 rk_type 0 order 4 acc 2 t 3 dsm 2.2919e-10 dsm_est 2.95688e-08 nsteps 20 + h 0.025 rk_type 0 order 4 acc 2 t 3.5 dsm 2.10843e-11 dsm_est 2.56198e-08 nsteps 20 + h 0.025 rk_type 0 order 4 acc 2 t 4 dsm 4.85414e-11 dsm_est 9.1097e-09 nsteps 20 + h 0.025 rk_type 0 order 4 acc 2 t 4.5 dsm 1.96723e-10 dsm_est 1.8883e-09 nsteps 20 + h 0.025 rk_type 0 order 4 acc 2 t 5 dsm 8.22132e-10 dsm_est 7.19339e-09 nsteps 20 + h 0.025 rk_type 0 order 4 acc 2 t 5.5 dsm 1.54757e-09 dsm_est 1.54279e-08 nsteps 20 + h 0.025 rk_type 0 order 4 acc 2 t 6 dsm 1.4066e-09 dsm_est 2.77932e-08 nsteps 20 + h 0.025 rk_type 0 order 4 acc 2 t 6.5 dsm 1.53642e-07 dsm_est 3.43927e-06 nsteps 20 + h 0.025 rk_type 0 order 4 acc 2 t 7 dsm 4.94724e-06 dsm_est 0.000536526 nsteps 20 + h 0.025 rk_type 0 order 4 acc 2 t 7.5 dsm 4.18294e-08 dsm_est 2.81303e-05 nsteps 20 + h 0.025 rk_type 0 order 4 acc 2 t 8 dsm 1.04878e-08 dsm_est 1.09073e-06 nsteps 20 + h 0.025 rk_type 0 order 4 acc 2 t 8.5 dsm 2.79702e-09 dsm_est 2.81903e-07 nsteps 20 + h 0.025 rk_type 0 order 4 acc 2 t 9 dsm 1.60168e-09 dsm_est 1.22752e-07 nsteps 20 + h 0.025 rk_type 0 order 4 acc 2 t 9.5 dsm 1.4347e-09 dsm_est 3.48997e-07 nsteps 20 + h 0.025 rk_type 0 order 4 acc 2 t 10 dsm 5.54538e-10 dsm_est 1.97881e-07 nsteps 20 + h 0.025 rk_type 0 order 4 acc 3 t 0.5 dsm 2.02741e-07 dsm_est 0.0135207 nsteps 20 + h 0.025 rk_type 0 order 4 acc 3 t 1 dsm 4.36512e-10 dsm_est 5.08381e-10 nsteps 20 + h 0.025 rk_type 0 order 4 acc 3 t 1.5 dsm 1.47944e-09 dsm_est 9.58723e-10 nsteps 20 + h 0.025 rk_type 0 order 4 acc 3 t 2 dsm 3.07014e-09 dsm_est 3.90744e-10 nsteps 20 + h 0.025 rk_type 0 order 4 acc 3 t 2.5 dsm 2.41009e-09 dsm_est 3.67901e-10 nsteps 20 + h 0.025 rk_type 0 order 4 acc 3 t 3 dsm 2.2919e-10 dsm_est 1.47844e-09 nsteps 20 + h 0.025 rk_type 0 order 4 acc 3 t 3.5 dsm 2.10843e-11 dsm_est 1.28099e-09 nsteps 20 + h 0.025 rk_type 0 order 4 acc 3 t 4 dsm 4.85414e-11 dsm_est 4.55485e-10 nsteps 20 + h 0.025 rk_type 0 order 4 acc 3 t 4.5 dsm 1.96723e-10 dsm_est 9.4415e-11 nsteps 20 + h 0.025 rk_type 0 order 4 acc 3 t 5 dsm 8.22132e-10 dsm_est 3.5967e-10 nsteps 20 + h 0.025 rk_type 0 order 4 acc 3 t 5.5 dsm 1.54757e-09 dsm_est 7.71393e-10 nsteps 20 + h 0.025 rk_type 0 order 4 acc 3 t 6 dsm 1.4066e-09 dsm_est 1.38966e-09 nsteps 20 + h 0.025 rk_type 0 order 4 acc 3 t 6.5 dsm 1.53642e-07 dsm_est 1.71964e-07 nsteps 20 + h 0.025 rk_type 0 order 4 acc 3 t 7 dsm 4.94724e-06 dsm_est 2.68263e-05 nsteps 20 + h 0.025 rk_type 0 order 4 acc 3 t 7.5 dsm 4.18294e-08 dsm_est 1.40652e-06 nsteps 20 + h 0.025 rk_type 0 order 4 acc 3 t 8 dsm 1.04878e-08 dsm_est 5.45367e-08 nsteps 20 + h 0.025 rk_type 0 order 4 acc 3 t 8.5 dsm 2.79702e-09 dsm_est 1.40952e-08 nsteps 20 + h 0.025 rk_type 0 order 4 acc 3 t 9 dsm 1.60168e-09 dsm_est 6.13761e-09 nsteps 20 + h 0.025 rk_type 0 order 4 acc 3 t 9.5 dsm 1.4347e-09 dsm_est 1.74499e-08 nsteps 20 + h 0.025 rk_type 0 order 4 acc 3 t 10 dsm 5.54538e-10 dsm_est 9.89407e-09 nsteps 20 + h 0.025 rk_type 0 order 4 acc 2 t 0.5 dsm 2.02741e-07 dsm_est 2.04151e-07 nsteps 30 + h 0.025 rk_type 0 order 4 acc 2 t 1 dsm 4.36512e-10 dsm_est 1.51075e-09 nsteps 30 + h 0.025 rk_type 0 order 4 acc 2 t 1.5 dsm 1.47944e-09 dsm_est 1.30553e-09 nsteps 30 + h 0.025 rk_type 0 order 4 acc 2 t 2 dsm 3.07014e-09 dsm_est 6.93616e-10 nsteps 30 + h 0.025 rk_type 0 order 4 acc 2 t 2.5 dsm 2.41009e-09 dsm_est 3.64938e-09 nsteps 30 + h 0.025 rk_type 0 order 4 acc 2 t 3 dsm 2.2919e-10 dsm_est 1.30625e-09 nsteps 30 + h 0.025 rk_type 0 order 4 acc 2 t 3.5 dsm 2.10843e-11 dsm_est 3.14425e-10 nsteps 30 + h 0.025 rk_type 0 order 4 acc 2 t 4 dsm 4.85414e-11 dsm_est 7.33721e-10 nsteps 30 + h 0.025 rk_type 0 order 4 acc 2 t 4.5 dsm 1.96723e-10 dsm_est 6.03307e-11 nsteps 30 + h 0.025 rk_type 0 order 4 acc 2 t 5 dsm 8.22132e-10 dsm_est 6.73954e-10 nsteps 30 + h 0.025 rk_type 0 order 4 acc 2 t 5.5 dsm 1.54757e-09 dsm_est 2.31912e-10 nsteps 30 + h 0.025 rk_type 0 order 4 acc 2 t 6 dsm 1.4066e-09 dsm_est 2.44839e-08 nsteps 30 + h 0.025 rk_type 0 order 4 acc 2 t 6.5 dsm 1.53642e-07 dsm_est 2.36231e-06 nsteps 30 + h 0.025 rk_type 0 order 4 acc 2 t 7 dsm 4.94724e-06 dsm_est 8.33486e-05 nsteps 30 + h 0.025 rk_type 0 order 4 acc 2 t 7.5 dsm 4.18294e-08 dsm_est 5.85759e-07 nsteps 30 + h 0.025 rk_type 0 order 4 acc 2 t 8 dsm 1.04878e-08 dsm_est 1.52644e-07 nsteps 30 + h 0.025 rk_type 0 order 4 acc 2 t 8.5 dsm 2.79702e-09 dsm_est 5.7594e-08 nsteps 30 + h 0.025 rk_type 0 order 4 acc 2 t 9 dsm 1.60168e-09 dsm_est 3.77187e-08 nsteps 30 + h 0.025 rk_type 0 order 4 acc 2 t 9.5 dsm 1.4347e-09 dsm_est 2.25916e-09 nsteps 30 + h 0.025 rk_type 0 order 4 acc 2 t 10 dsm 5.54538e-10 dsm_est 8.39636e-09 nsteps 30 + h 0.00625 rk_type 0 order 4 acc 1 t 0.5 dsm 2.01526e-08 dsm_est 0.12061 nsteps 80 + h 0.00625 rk_type 0 order 4 acc 1 t 1 dsm 9.02564e-12 dsm_est 3.15224e-11 nsteps 80 + h 0.00625 rk_type 0 order 4 acc 1 t 1.5 dsm 6.18719e-12 dsm_est 1.15612e-11 nsteps 80 + h 0.00625 rk_type 0 order 4 acc 1 t 2 dsm 1.21264e-11 dsm_est 3.56333e-12 nsteps 80 + h 0.00625 rk_type 0 order 4 acc 1 t 2.5 dsm 9.39437e-12 dsm_est 3.71652e-12 nsteps 80 + h 0.00625 rk_type 0 order 4 acc 1 t 3 dsm 6.39567e-12 dsm_est 6.60675e-12 nsteps 80 + h 0.00625 rk_type 0 order 4 acc 1 t 3.5 dsm 4.31321e-12 dsm_est 1.02486e-11 nsteps 80 + h 0.00625 rk_type 0 order 4 acc 1 t 4 dsm 5.26346e-12 dsm_est 6.34128e-12 nsteps 80 + h 0.00625 rk_type 0 order 4 acc 1 t 4.5 dsm 3.00982e-11 dsm_est 6.6337e-12 nsteps 80 + h 0.00625 rk_type 0 order 4 acc 1 t 5 dsm 3.35644e-12 dsm_est 3.78322e-11 nsteps 80 + h 0.00625 rk_type 0 order 4 acc 1 t 5.5 dsm 1.37915e-11 dsm_est 3.71144e-12 nsteps 80 + h 0.00625 rk_type 0 order 4 acc 1 t 6 dsm 9.91766e-11 dsm_est 2.23847e-11 nsteps 80 + h 0.00625 rk_type 0 order 4 acc 1 t 6.5 dsm 3.01672e-09 dsm_est 3.42521e-09 nsteps 80 + h 0.00625 rk_type 0 order 4 acc 1 t 7 dsm 1.77811e-08 dsm_est 4.60341e-07 nsteps 80 + h 0.00625 rk_type 0 order 4 acc 1 t 7.5 dsm 7.42418e-10 dsm_est 6.0223e-08 nsteps 80 + h 0.00625 rk_type 0 order 4 acc 1 t 8 dsm 3.89202e-10 dsm_est 4.90508e-10 nsteps 80 + h 0.00625 rk_type 0 order 4 acc 1 t 8.5 dsm 3.7018e-11 dsm_est 2.41013e-10 nsteps 80 + h 0.00625 rk_type 0 order 4 acc 1 t 9 dsm 2.94415e-11 dsm_est 5.60347e-11 nsteps 80 + h 0.00625 rk_type 0 order 4 acc 1 t 9.5 dsm 1.42778e-11 dsm_est 7.48066e-11 nsteps 80 + h 0.00625 rk_type 0 order 4 acc 1 t 10 dsm 4.93463e-12 dsm_est 6.33468e-11 nsteps 80 + h 0.00625 rk_type 0 order 4 acc 2 t 0.5 dsm 2.01526e-08 dsm_est 0.141954 nsteps 80 + h 0.00625 rk_type 0 order 4 acc 2 t 1 dsm 9.02564e-12 dsm_est 1.9256e-10 nsteps 80 + h 0.00625 rk_type 0 order 4 acc 2 t 1.5 dsm 6.18719e-12 dsm_est 3.09827e-10 nsteps 80 + h 0.00625 rk_type 0 order 4 acc 2 t 2 dsm 1.21264e-11 dsm_est 1.26799e-10 nsteps 80 + h 0.00625 rk_type 0 order 4 acc 2 t 2.5 dsm 9.39437e-12 dsm_est 1.15943e-10 nsteps 80 + h 0.00625 rk_type 0 order 4 acc 2 t 3 dsm 6.39567e-12 dsm_est 4.63554e-10 nsteps 80 + h 0.00625 rk_type 0 order 4 acc 2 t 3.5 dsm 4.31321e-12 dsm_est 4.07949e-10 nsteps 80 + h 0.00625 rk_type 0 order 4 acc 2 t 4 dsm 5.26346e-12 dsm_est 1.47561e-10 nsteps 80 + h 0.00625 rk_type 0 order 4 acc 2 t 4.5 dsm 3.00982e-11 dsm_est 3.61156e-11 nsteps 80 + h 0.00625 rk_type 0 order 4 acc 2 t 5 dsm 3.35644e-12 dsm_est 1.54366e-10 nsteps 80 + h 0.00625 rk_type 0 order 4 acc 2 t 5.5 dsm 1.37915e-11 dsm_est 2.39536e-10 nsteps 80 + h 0.00625 rk_type 0 order 4 acc 2 t 6 dsm 9.91766e-11 dsm_est 4.28866e-10 nsteps 80 + h 0.00625 rk_type 0 order 4 acc 2 t 6.5 dsm 3.01672e-09 dsm_est 5.01151e-08 nsteps 80 + h 0.00625 rk_type 0 order 4 acc 2 t 7 dsm 1.77811e-08 dsm_est 9.3156e-06 nsteps 80 + h 0.00625 rk_type 0 order 4 acc 2 t 7.5 dsm 7.42418e-10 dsm_est 5.06067e-07 nsteps 80 + h 0.00625 rk_type 0 order 4 acc 2 t 8 dsm 3.89202e-10 dsm_est 1.79275e-08 nsteps 80 + h 0.00625 rk_type 0 order 4 acc 2 t 8.5 dsm 3.7018e-11 dsm_est 4.65518e-09 nsteps 80 + h 0.00625 rk_type 0 order 4 acc 2 t 9 dsm 2.94415e-11 dsm_est 1.94773e-09 nsteps 80 + h 0.00625 rk_type 0 order 4 acc 2 t 9.5 dsm 1.42778e-11 dsm_est 5.55728e-09 nsteps 80 + h 0.00625 rk_type 0 order 4 acc 2 t 10 dsm 4.93463e-12 dsm_est 3.15451e-09 nsteps 80 + h 0.00625 rk_type 0 order 4 acc 3 t 0.5 dsm 2.01526e-08 dsm_est 0.00177442 nsteps 80 + h 0.00625 rk_type 0 order 4 acc 3 t 1 dsm 9.02564e-12 dsm_est 2.40701e-12 nsteps 80 + h 0.00625 rk_type 0 order 4 acc 3 t 1.5 dsm 6.18719e-12 dsm_est 3.87284e-12 nsteps 80 + h 0.00625 rk_type 0 order 4 acc 3 t 2 dsm 1.21264e-11 dsm_est 1.58498e-12 nsteps 80 + h 0.00625 rk_type 0 order 4 acc 3 t 2.5 dsm 9.39437e-12 dsm_est 1.44929e-12 nsteps 80 + h 0.00625 rk_type 0 order 4 acc 3 t 3 dsm 6.39567e-12 dsm_est 5.79442e-12 nsteps 80 + h 0.00625 rk_type 0 order 4 acc 3 t 3.5 dsm 4.31321e-12 dsm_est 5.09937e-12 nsteps 80 + h 0.00625 rk_type 0 order 4 acc 3 t 4 dsm 5.26346e-12 dsm_est 1.84452e-12 nsteps 80 + h 0.00625 rk_type 0 order 4 acc 3 t 4.5 dsm 3.00982e-11 dsm_est 4.51445e-13 nsteps 80 + h 0.00625 rk_type 0 order 4 acc 3 t 5 dsm 3.35644e-12 dsm_est 1.92957e-12 nsteps 80 + h 0.00625 rk_type 0 order 4 acc 3 t 5.5 dsm 1.37915e-11 dsm_est 2.9942e-12 nsteps 80 + h 0.00625 rk_type 0 order 4 acc 3 t 6 dsm 9.91766e-11 dsm_est 5.36083e-12 nsteps 80 + h 0.00625 rk_type 0 order 4 acc 3 t 6.5 dsm 3.01672e-09 dsm_est 6.26439e-10 nsteps 80 + h 0.00625 rk_type 0 order 4 acc 3 t 7 dsm 1.77811e-08 dsm_est 1.16445e-07 nsteps 80 + h 0.00625 rk_type 0 order 4 acc 3 t 7.5 dsm 7.42418e-10 dsm_est 6.32584e-09 nsteps 80 + h 0.00625 rk_type 0 order 4 acc 3 t 8 dsm 3.89202e-10 dsm_est 2.24093e-10 nsteps 80 + h 0.00625 rk_type 0 order 4 acc 3 t 8.5 dsm 3.7018e-11 dsm_est 5.81897e-11 nsteps 80 + h 0.00625 rk_type 0 order 4 acc 3 t 9 dsm 2.94415e-11 dsm_est 2.43467e-11 nsteps 80 + h 0.00625 rk_type 0 order 4 acc 3 t 9.5 dsm 1.42778e-11 dsm_est 6.94659e-11 nsteps 80 + h 0.00625 rk_type 0 order 4 acc 3 t 10 dsm 4.93463e-12 dsm_est 3.94313e-11 nsteps 80 + h 0.00625 rk_type 0 order 4 acc 2 t 0.5 dsm 2.01526e-08 dsm_est 5.96471e-08 nsteps 120 + h 0.00625 rk_type 0 order 4 acc 2 t 1 dsm 9.02564e-12 dsm_est 2.62428e-11 nsteps 120 + h 0.00625 rk_type 0 order 4 acc 2 t 1.5 dsm 6.18719e-12 dsm_est 8.82608e-11 nsteps 120 + h 0.00625 rk_type 0 order 4 acc 2 t 2 dsm 1.21264e-11 dsm_est 1.81216e-10 nsteps 120 + h 0.00625 rk_type 0 order 4 acc 2 t 2.5 dsm 9.39437e-12 dsm_est 1.39896e-10 nsteps 120 + h 0.00625 rk_type 0 order 4 acc 2 t 3 dsm 6.39567e-12 dsm_est 1.30298e-11 nsteps 120 + h 0.00625 rk_type 0 order 4 acc 2 t 3.5 dsm 4.31321e-12 dsm_est 1.17983e-12 nsteps 120 + h 0.00625 rk_type 0 order 4 acc 2 t 4 dsm 5.26346e-12 dsm_est 2.82746e-12 nsteps 120 + h 0.00625 rk_type 0 order 4 acc 2 t 4.5 dsm 3.00982e-11 dsm_est 1.13213e-11 nsteps 120 + h 0.00625 rk_type 0 order 4 acc 2 t 5 dsm 3.35644e-12 dsm_est 4.77357e-11 nsteps 120 + h 0.00625 rk_type 0 order 4 acc 2 t 5.5 dsm 1.37915e-11 dsm_est 1.78455e-10 nsteps 120 + h 0.00625 rk_type 0 order 4 acc 2 t 6 dsm 9.91766e-11 dsm_est 1.16563e-09 nsteps 120 + h 0.00625 rk_type 0 order 4 acc 2 t 6.5 dsm 3.01672e-09 dsm_est 1.01849e-08 nsteps 120 + h 0.00625 rk_type 0 order 4 acc 2 t 7 dsm 1.77811e-08 dsm_est 2.72392e-07 nsteps 120 + h 0.00625 rk_type 0 order 4 acc 2 t 7.5 dsm 7.42418e-10 dsm_est 3.28703e-09 nsteps 120 + h 0.00625 rk_type 0 order 4 acc 2 t 8 dsm 3.89202e-10 dsm_est 2.22651e-09 nsteps 120 + h 0.00625 rk_type 0 order 4 acc 2 t 8.5 dsm 3.7018e-11 dsm_est 5.88999e-10 nsteps 120 + h 0.00625 rk_type 0 order 4 acc 2 t 9 dsm 2.94415e-11 dsm_est 2.41758e-10 nsteps 120 + h 0.00625 rk_type 0 order 4 acc 2 t 9.5 dsm 1.42778e-11 dsm_est 9.06696e-11 nsteps 120 + h 0.00625 rk_type 0 order 4 acc 2 t 10 dsm 4.93463e-12 dsm_est 3.23538e-11 nsteps 120 + h 0.0015625 rk_type 0 order 4 acc 1 t 0.5 dsm 1.12995e-09 dsm_est 0.0161685 nsteps 320 + h 0.0015625 rk_type 0 order 4 acc 1 t 1 dsm 8.83314e-12 dsm_est 4.22807e-12 nsteps 320 + h 0.0015625 rk_type 0 order 4 acc 1 t 1.5 dsm 1.84069e-12 dsm_est 1.48779e-12 nsteps 320 + h 0.0015625 rk_type 0 order 4 acc 1 t 2 dsm 2.23198e-13 dsm_est 3.06e-13 nsteps 320 + h 0.0015625 rk_type 0 order 4 acc 1 t 2.5 dsm 5.57615e-13 dsm_est 3.16293e-14 nsteps 320 + h 0.0015625 rk_type 0 order 4 acc 1 t 3 dsm 6.33215e-12 dsm_est 9.28211e-14 nsteps 320 + h 0.0015625 rk_type 0 order 4 acc 1 t 3.5 dsm 4.31345e-12 dsm_est 1.06725e-12 nsteps 320 + h 0.0015625 rk_type 0 order 4 acc 1 t 4 dsm 5.25911e-12 dsm_est 7.27486e-13 nsteps 320 + h 0.0015625 rk_type 0 order 4 acc 1 t 4.5 dsm 3.00873e-11 dsm_est 8.86785e-13 nsteps 320 + h 0.0015625 rk_type 0 order 4 acc 1 t 5 dsm 1.04948e-12 dsm_est 5.07072e-12 nsteps 320 + h 0.0015625 rk_type 0 order 4 acc 1 t 5.5 dsm 6.97828e-12 dsm_est 1.75823e-13 nsteps 320 + h 0.0015625 rk_type 0 order 4 acc 1 t 6 dsm 5.98205e-11 dsm_est 1.17286e-12 nsteps 320 + h 0.0015625 rk_type 0 order 4 acc 1 t 6.5 dsm 1.87435e-11 dsm_est 1.34855e-11 nsteps 320 + h 0.0015625 rk_type 0 order 4 acc 1 t 7 dsm 6.39659e-10 dsm_est 1.86951e-09 nsteps 320 + h 0.0015625 rk_type 0 order 4 acc 1 t 7.5 dsm 1.83962e-11 dsm_est 2.58837e-10 nsteps 320 + h 0.0015625 rk_type 0 order 4 acc 1 t 8 dsm 1.77418e-10 dsm_est 3.6664e-12 nsteps 320 + h 0.0015625 rk_type 0 order 4 acc 1 t 8.5 dsm 2.78724e-12 dsm_est 2.99588e-11 nsteps 320 + h 0.0015625 rk_type 0 order 4 acc 1 t 9 dsm 2.4955e-11 dsm_est 5.0593e-13 nsteps 320 + h 0.0015625 rk_type 0 order 4 acc 1 t 9.5 dsm 1.29649e-11 dsm_est 4.22112e-12 nsteps 320 + h 0.0015625 rk_type 0 order 4 acc 1 t 10 dsm 4.44459e-12 dsm_est 2.19913e-12 nsteps 320 + h 0.0015625 rk_type 0 order 4 acc 2 t 0.5 dsm 1.12995e-09 dsm_est 0.0169353 nsteps 320 + h 0.0015625 rk_type 0 order 4 acc 2 t 1 dsm 8.83314e-12 dsm_est 6.94907e-12 nsteps 320 + h 0.0015625 rk_type 0 order 4 acc 2 t 1.5 dsm 1.84069e-12 dsm_est 6.39115e-12 nsteps 320 + h 0.0015625 rk_type 0 order 4 acc 2 t 2 dsm 2.23198e-13 dsm_est 2.81498e-12 nsteps 320 + h 0.0015625 rk_type 0 order 4 acc 2 t 2.5 dsm 5.57615e-13 dsm_est 2.25223e-12 nsteps 320 + h 0.0015625 rk_type 0 order 4 acc 2 t 3 dsm 6.33215e-12 dsm_est 7.33588e-12 nsteps 320 + h 0.0015625 rk_type 0 order 4 acc 2 t 3.5 dsm 4.31345e-12 dsm_est 7.40715e-12 nsteps 320 + h 0.0015625 rk_type 0 order 4 acc 2 t 4 dsm 5.25911e-12 dsm_est 3.01034e-12 nsteps 320 + h 0.0015625 rk_type 0 order 4 acc 2 t 4.5 dsm 3.00873e-11 dsm_est 1.41635e-12 nsteps 320 + h 0.0015625 rk_type 0 order 4 acc 2 t 5 dsm 1.04948e-12 dsm_est 7.0874e-12 nsteps 320 + h 0.0015625 rk_type 0 order 4 acc 2 t 5.5 dsm 6.97828e-12 dsm_est 3.92895e-12 nsteps 320 + h 0.0015625 rk_type 0 order 4 acc 2 t 6 dsm 5.98205e-11 dsm_est 8.03594e-12 nsteps 320 + h 0.0015625 rk_type 0 order 4 acc 2 t 6.5 dsm 1.87435e-11 dsm_est 7.78898e-10 nsteps 320 + h 0.0015625 rk_type 0 order 4 acc 2 t 7 dsm 6.39659e-10 dsm_est 1.4936e-07 nsteps 320 + h 0.0015625 rk_type 0 order 4 acc 2 t 7.5 dsm 1.83962e-11 dsm_est 8.20268e-09 nsteps 320 + h 0.0015625 rk_type 0 order 4 acc 2 t 8 dsm 1.77418e-10 dsm_est 2.85684e-10 nsteps 320 + h 0.0015625 rk_type 0 order 4 acc 2 t 8.5 dsm 2.78724e-12 dsm_est 1.0185e-10 nsteps 320 + h 0.0015625 rk_type 0 order 4 acc 2 t 9 dsm 2.4955e-11 dsm_est 3.17765e-11 nsteps 320 + h 0.0015625 rk_type 0 order 4 acc 2 t 9.5 dsm 1.29649e-11 dsm_est 9.11804e-11 nsteps 320 + h 0.0015625 rk_type 0 order 4 acc 2 t 10 dsm 4.44459e-12 dsm_est 5.14784e-11 nsteps 320 + h 0.0015625 rk_type 0 order 4 acc 3 t 0.5 dsm 1.12995e-09 dsm_est 5.29229e-05 nsteps 320 + h 0.0015625 rk_type 0 order 4 acc 3 t 1 dsm 8.83314e-12 dsm_est 2.17158e-14 nsteps 320 + h 0.0015625 rk_type 0 order 4 acc 3 t 1.5 dsm 1.84069e-12 dsm_est 1.99723e-14 nsteps 320 + h 0.0015625 rk_type 0 order 4 acc 3 t 2 dsm 2.23198e-13 dsm_est 8.79682e-15 nsteps 320 + h 0.0015625 rk_type 0 order 4 acc 3 t 2.5 dsm 5.57615e-13 dsm_est 7.03822e-15 nsteps 320 + h 0.0015625 rk_type 0 order 4 acc 3 t 3 dsm 6.33215e-12 dsm_est 2.29246e-14 nsteps 320 + h 0.0015625 rk_type 0 order 4 acc 3 t 3.5 dsm 4.31345e-12 dsm_est 2.31473e-14 nsteps 320 + h 0.0015625 rk_type 0 order 4 acc 3 t 4 dsm 5.25911e-12 dsm_est 9.40731e-15 nsteps 320 + h 0.0015625 rk_type 0 order 4 acc 3 t 4.5 dsm 3.00873e-11 dsm_est 4.42611e-15 nsteps 320 + h 0.0015625 rk_type 0 order 4 acc 3 t 5 dsm 1.04948e-12 dsm_est 2.21481e-14 nsteps 320 + h 0.0015625 rk_type 0 order 4 acc 3 t 5.5 dsm 6.97828e-12 dsm_est 1.2278e-14 nsteps 320 + h 0.0015625 rk_type 0 order 4 acc 3 t 6 dsm 5.98205e-11 dsm_est 2.51123e-14 nsteps 320 + h 0.0015625 rk_type 0 order 4 acc 3 t 6.5 dsm 1.87435e-11 dsm_est 2.43406e-12 nsteps 320 + h 0.0015625 rk_type 0 order 4 acc 3 t 7 dsm 6.39659e-10 dsm_est 4.6675e-10 nsteps 320 + h 0.0015625 rk_type 0 order 4 acc 3 t 7.5 dsm 1.83962e-11 dsm_est 2.56334e-11 nsteps 320 + h 0.0015625 rk_type 0 order 4 acc 3 t 8 dsm 1.77418e-10 dsm_est 8.92764e-13 nsteps 320 + h 0.0015625 rk_type 0 order 4 acc 3 t 8.5 dsm 2.78724e-12 dsm_est 3.18282e-13 nsteps 320 + h 0.0015625 rk_type 0 order 4 acc 3 t 9 dsm 2.4955e-11 dsm_est 9.93014e-14 nsteps 320 + h 0.0015625 rk_type 0 order 4 acc 3 t 9.5 dsm 1.29649e-11 dsm_est 2.84939e-13 nsteps 320 + h 0.0015625 rk_type 0 order 4 acc 3 t 10 dsm 4.44459e-12 dsm_est 1.6087e-13 nsteps 320 + h 0.0015625 rk_type 0 order 4 acc 2 t 0.5 dsm 1.12995e-09 dsm_est 2.29243e-09 nsteps 480 + h 0.0015625 rk_type 0 order 4 acc 2 t 1 dsm 8.83314e-12 dsm_est 1.01708e-13 nsteps 480 + h 0.0015625 rk_type 0 order 4 acc 2 t 1.5 dsm 1.84069e-12 dsm_est 3.46845e-13 nsteps 480 + h 0.0015625 rk_type 0 order 4 acc 2 t 2 dsm 2.23198e-13 dsm_est 7.13223e-13 nsteps 480 + h 0.0015625 rk_type 0 order 4 acc 2 t 2.5 dsm 5.57615e-13 dsm_est 5.5096e-13 nsteps 480 + h 0.0015625 rk_type 0 order 4 acc 2 t 3 dsm 6.33215e-12 dsm_est 5.10951e-14 nsteps 480 + h 0.0015625 rk_type 0 order 4 acc 2 t 3.5 dsm 4.31345e-12 dsm_est 4.40878e-15 nsteps 480 + h 0.0015625 rk_type 0 order 4 acc 2 t 4 dsm 5.25911e-12 dsm_est 1.13938e-14 nsteps 480 + h 0.0015625 rk_type 0 order 4 acc 2 t 4.5 dsm 3.00873e-11 dsm_est 3.76833e-14 nsteps 480 + h 0.0015625 rk_type 0 order 4 acc 2 t 5 dsm 1.04948e-12 dsm_est 1.75165e-13 nsteps 480 + h 0.0015625 rk_type 0 order 4 acc 2 t 5.5 dsm 6.97828e-12 dsm_est 6.76285e-13 nsteps 480 + h 0.0015625 rk_type 0 order 4 acc 2 t 6 dsm 5.98205e-11 dsm_est 4.58434e-12 nsteps 480 + h 0.0015625 rk_type 0 order 4 acc 2 t 6.5 dsm 1.87435e-11 dsm_est 1.80355e-10 nsteps 480 + h 0.0015625 rk_type 0 order 4 acc 2 t 7 dsm 6.39659e-10 dsm_est 7.2409e-10 nsteps 480 + h 0.0015625 rk_type 0 order 4 acc 2 t 7.5 dsm 1.83962e-11 dsm_est 3.9885e-11 nsteps 480 + h 0.0015625 rk_type 0 order 4 acc 2 t 8 dsm 1.77418e-10 dsm_est 1.97323e-11 nsteps 480 + h 0.0015625 rk_type 0 order 4 acc 2 t 8.5 dsm 2.78724e-12 dsm_est 2.15597e-12 nsteps 480 + h 0.0015625 rk_type 0 order 4 acc 2 t 9 dsm 2.4955e-11 dsm_est 9.29203e-13 nsteps 480 + h 0.0015625 rk_type 0 order 4 acc 2 t 9.5 dsm 1.29649e-11 dsm_est 3.52852e-13 nsteps 480 + h 0.0015625 rk_type 0 order 4 acc 2 t 10 dsm 4.44459e-12 dsm_est 1.2586e-13 nsteps 480 + h 0.000390625 rk_type 0 order 4 acc 1 t 0.5 dsm 4.75504e-11 dsm_est 0.000360159 nsteps 1281 + h 0.000390625 rk_type 0 order 4 acc 1 t 1 dsm 8.83253e-12 dsm_est 9.41667e-14 nsteps 1281 + h 0.000390625 rk_type 0 order 4 acc 1 t 1.5 dsm 1.8399e-12 dsm_est 3.31853e-14 nsteps 1280 + h 0.000390625 rk_type 0 order 4 acc 1 t 2 dsm 2.21232e-13 dsm_est 6.92196e-15 nsteps 1280 + h 0.000390625 rk_type 0 order 4 acc 1 t 2.5 dsm 5.57029e-13 dsm_est 7.49969e-16 nsteps 1280 + h 0.000390625 rk_type 0 order 4 acc 1 t 3 dsm 6.33194e-12 dsm_est 2.00962e-15 nsteps 1280 + h 0.000390625 rk_type 0 order 4 acc 1 t 3.5 dsm 4.31407e-12 dsm_est 2.37702e-14 nsteps 1280 + h 0.000390625 rk_type 0 order 4 acc 1 t 4 dsm 5.25853e-12 dsm_est 1.62111e-14 nsteps 1280 + h 0.000390625 rk_type 0 order 4 acc 1 t 4.5 dsm 3.00881e-11 dsm_est 1.97207e-14 nsteps 1281 + h 0.000390625 rk_type 0 order 4 acc 1 t 5 dsm 1.04964e-12 dsm_est 1.12957e-13 nsteps 1281 + h 0.000390625 rk_type 0 order 4 acc 1 t 5.5 dsm 6.97849e-12 dsm_est 3.92461e-15 nsteps 1281 + h 0.000390625 rk_type 0 order 4 acc 1 t 6 dsm 5.9817e-11 dsm_est 2.61272e-14 nsteps 1281 + h 0.000390625 rk_type 0 order 4 acc 1 t 6.5 dsm 1.43381e-11 dsm_est 2.24496e-13 nsteps 1281 + h 0.000390625 rk_type 0 order 4 acc 1 t 7 dsm 2.94602e-12 dsm_est 7.37178e-12 nsteps 1281 + h 0.000390625 rk_type 0 order 4 acc 1 t 7.5 dsm 1.82124e-11 dsm_est 1.0358e-12 nsteps 1281 + h 0.000390625 rk_type 0 order 4 acc 1 t 8 dsm 1.77421e-10 dsm_est 6.91895e-14 nsteps 1281 + h 0.000390625 rk_type 0 order 4 acc 1 t 8.5 dsm 2.81466e-12 dsm_est 6.67292e-13 nsteps 1281 + h 0.000390625 rk_type 0 order 4 acc 1 t 9 dsm 2.496e-11 dsm_est 1.06333e-14 nsteps 1281 + h 0.000390625 rk_type 0 order 4 acc 1 t 9.5 dsm 1.2967e-11 dsm_est 9.36985e-14 nsteps 1281 + h 0.000390625 rk_type 0 order 4 acc 1 t 10 dsm 4.44606e-12 dsm_est 4.86957e-14 nsteps 1281 + h 0.000390625 rk_type 0 order 4 acc 2 t 0.5 dsm 4.75504e-11 dsm_est 0.000554502 nsteps 1281 + h 0.000390625 rk_type 0 order 4 acc 2 t 1 dsm 8.83253e-12 dsm_est 2.11629e-13 nsteps 1281 + h 0.000390625 rk_type 0 order 4 acc 2 t 1.5 dsm 1.8399e-12 dsm_est 1.46902e-13 nsteps 1280 + h 0.000390625 rk_type 0 order 4 acc 2 t 2 dsm 2.21232e-13 dsm_est 8.08167e-14 nsteps 1280 + h 0.000390625 rk_type 0 order 4 acc 2 t 2.5 dsm 5.57029e-13 dsm_est 6.12168e-14 nsteps 1280 + h 0.000390625 rk_type 0 order 4 acc 2 t 3 dsm 6.33194e-12 dsm_est 1.25998e-13 nsteps 1280 + h 0.000390625 rk_type 0 order 4 acc 2 t 3.5 dsm 4.31407e-12 dsm_est 1.46827e-13 nsteps 1280 + h 0.000390625 rk_type 0 order 4 acc 2 t 4 dsm 5.25853e-12 dsm_est 8.29578e-14 nsteps 1280 + h 0.000390625 rk_type 0 order 4 acc 2 t 4.5 dsm 3.00881e-11 dsm_est 7.37135e-14 nsteps 1281 + h 0.000390625 rk_type 0 order 4 acc 2 t 5 dsm 1.04964e-12 dsm_est 2.31694e-13 nsteps 1281 + h 0.000390625 rk_type 0 order 4 acc 2 t 5.5 dsm 6.97849e-12 dsm_est 8.07729e-14 nsteps 1281 + h 0.000390625 rk_type 0 order 4 acc 2 t 6 dsm 5.9817e-11 dsm_est 1.6949e-13 nsteps 1281 + h 0.000390625 rk_type 0 order 4 acc 2 t 6.5 dsm 1.43381e-11 dsm_est 1.23339e-11 nsteps 1281 + h 0.000390625 rk_type 0 order 4 acc 2 t 7 dsm 2.94602e-12 dsm_est 2.35276e-09 nsteps 1281 + h 0.000390625 rk_type 0 order 4 acc 2 t 7.5 dsm 1.82124e-11 dsm_est 1.29354e-10 nsteps 1281 + h 0.000390625 rk_type 0 order 4 acc 2 t 8 dsm 1.77421e-10 dsm_est 4.5438e-12 nsteps 1281 + h 0.000390625 rk_type 0 order 4 acc 2 t 8.5 dsm 2.81466e-12 dsm_est 2.19649e-12 nsteps 1281 + h 0.000390625 rk_type 0 order 4 acc 2 t 9 dsm 2.496e-11 dsm_est 5.49027e-13 nsteps 1281 + h 0.000390625 rk_type 0 order 4 acc 2 t 9.5 dsm 1.2967e-11 dsm_est 1.50929e-12 nsteps 1281 + h 0.000390625 rk_type 0 order 4 acc 2 t 10 dsm 4.44606e-12 dsm_est 8.49403e-13 nsteps 1281 + h 0.000390625 rk_type 0 order 4 acc 3 t 0.5 dsm 4.75504e-11 dsm_est 4.33205e-07 nsteps 1281 + h 0.000390625 rk_type 0 order 4 acc 3 t 1 dsm 8.83253e-12 dsm_est 1.65335e-16 nsteps 1281 + h 0.000390625 rk_type 0 order 4 acc 3 t 1.5 dsm 1.8399e-12 dsm_est 1.14767e-16 nsteps 1280 + h 0.000390625 rk_type 0 order 4 acc 3 t 2 dsm 2.21232e-13 dsm_est 6.3138e-17 nsteps 1280 + h 0.000390625 rk_type 0 order 4 acc 3 t 2.5 dsm 5.57029e-13 dsm_est 4.78256e-17 nsteps 1280 + h 0.000390625 rk_type 0 order 4 acc 3 t 3 dsm 6.33194e-12 dsm_est 9.84357e-17 nsteps 1280 + h 0.000390625 rk_type 0 order 4 acc 3 t 3.5 dsm 4.31407e-12 dsm_est 1.14709e-16 nsteps 1280 + h 0.000390625 rk_type 0 order 4 acc 3 t 4 dsm 5.25853e-12 dsm_est 6.48108e-17 nsteps 1280 + h 0.000390625 rk_type 0 order 4 acc 3 t 4.5 dsm 3.00881e-11 dsm_est 5.75886e-17 nsteps 1281 + h 0.000390625 rk_type 0 order 4 acc 3 t 5 dsm 1.04964e-12 dsm_est 1.81011e-16 nsteps 1281 + h 0.000390625 rk_type 0 order 4 acc 3 t 5.5 dsm 6.97849e-12 dsm_est 6.31038e-17 nsteps 1281 + h 0.000390625 rk_type 0 order 4 acc 3 t 6 dsm 5.9817e-11 dsm_est 1.32414e-16 nsteps 1281 + h 0.000390625 rk_type 0 order 4 acc 3 t 6.5 dsm 1.43381e-11 dsm_est 9.63583e-15 nsteps 1281 + h 0.000390625 rk_type 0 order 4 acc 3 t 7 dsm 2.94602e-12 dsm_est 1.8381e-12 nsteps 1281 + h 0.000390625 rk_type 0 order 4 acc 3 t 7.5 dsm 1.82124e-11 dsm_est 1.01058e-13 nsteps 1281 + h 0.000390625 rk_type 0 order 4 acc 3 t 8 dsm 1.77421e-10 dsm_est 3.54984e-15 nsteps 1281 + h 0.000390625 rk_type 0 order 4 acc 3 t 8.5 dsm 2.81466e-12 dsm_est 1.71601e-15 nsteps 1281 + h 0.000390625 rk_type 0 order 4 acc 3 t 9 dsm 2.496e-11 dsm_est 4.28927e-16 nsteps 1281 + h 0.000390625 rk_type 0 order 4 acc 3 t 9.5 dsm 1.2967e-11 dsm_est 1.17913e-15 nsteps 1281 + h 0.000390625 rk_type 0 order 4 acc 3 t 10 dsm 4.44606e-12 dsm_est 6.63596e-16 nsteps 1281 + h 0.000390625 rk_type 0 order 4 acc 2 t 0.5 dsm 4.75504e-11 dsm_est 2.63435e-10 nsteps 1921 + h 0.000390625 rk_type 0 order 4 acc 2 t 1 dsm 8.83253e-12 dsm_est 2.03794e-15 nsteps 1922 + h 0.000390625 rk_type 0 order 4 acc 2 t 1.5 dsm 1.8399e-12 dsm_est 3.00814e-14 nsteps 1920 + h 0.000390625 rk_type 0 order 4 acc 2 t 2 dsm 2.21232e-13 dsm_est 4.15128e-14 nsteps 1920 + h 0.000390625 rk_type 0 order 4 acc 2 t 2.5 dsm 5.57029e-13 dsm_est 1.58845e-15 nsteps 1920 + h 0.000390625 rk_type 0 order 4 acc 2 t 3 dsm 6.33194e-12 dsm_est 5.52712e-16 nsteps 1920 + h 0.000390625 rk_type 0 order 4 acc 2 t 3.5 dsm 4.31407e-12 dsm_est 1.6025e-15 nsteps 1920 + h 0.000390625 rk_type 0 order 4 acc 2 t 4 dsm 5.25853e-12 dsm_est 9.59599e-16 nsteps 1920 + h 0.000390625 rk_type 0 order 4 acc 2 t 4.5 dsm 3.00881e-11 dsm_est 5.29038e-14 nsteps 1921 + h 0.000390625 rk_type 0 order 4 acc 2 t 5 dsm 1.04964e-12 dsm_est 7.31539e-14 nsteps 1921 + h 0.000390625 rk_type 0 order 4 acc 2 t 5.5 dsm 6.97849e-12 dsm_est 1.08618e-13 nsteps 1921 + h 0.000390625 rk_type 0 order 4 acc 2 t 6 dsm 5.9817e-11 dsm_est 2.24477e-13 nsteps 1921 + h 0.000390625 rk_type 0 order 4 acc 2 t 6.5 dsm 1.43381e-11 dsm_est 1.46745e-12 nsteps 1921 + h 0.000390625 rk_type 0 order 4 acc 2 t 7 dsm 2.94602e-12 dsm_est 3.70208e-11 nsteps 1921 + h 0.000390625 rk_type 0 order 4 acc 2 t 7.5 dsm 1.82124e-11 dsm_est 5.47248e-13 nsteps 1921 + h 0.000390625 rk_type 0 order 4 acc 2 t 8 dsm 1.77421e-10 dsm_est 4.99362e-13 nsteps 1921 + h 0.000390625 rk_type 0 order 4 acc 2 t 8.5 dsm 2.81466e-12 dsm_est 6.74349e-15 nsteps 1922 + h 0.000390625 rk_type 0 order 4 acc 2 t 9 dsm 2.496e-11 dsm_est 1.91764e-15 nsteps 1922 + h 0.000390625 rk_type 0 order 4 acc 2 t 9.5 dsm 1.2967e-11 dsm_est 1.53261e-15 nsteps 1922 + h 0.000390625 rk_type 0 order 4 acc 2 t 10 dsm 4.44606e-12 dsm_est 7.50123e-16 nsteps 1922 diff --git a/test/unit_tests/arkode/CXX_serial/ark_test_accumerror_brusselator_20_3_1.out b/test/unit_tests/arkode/CXX_serial/ark_test_accumerror_brusselator_20_3_1.out new file mode 100644 index 0000000000..8e2a11d1e1 --- /dev/null +++ b/test/unit_tests/arkode/CXX_serial/ark_test_accumerror_brusselator_20_3_1.out @@ -0,0 +1,189 @@ + +Accumulated error estimation test (stiff Brusselator ODE problem): + time domain: (0,10] + partition size = 20 + initial conditions: u0 = 1.2, v0 = 3.1, w0 = 3 + problem parameters: a = 1, b = 3.5, ep = 0.0004 + ERK solver, order = 3 + +Adaptive-step runs: + rtol 0.01 rk_type 1 order 3 acc 1 t 0.5 dsm 0.00199866 dsm_est 0.00993779 nsteps 492 + rtol 0.01 rk_type 1 order 3 acc 1 t 1 dsm 0.00148824 dsm_est 0.00998004 nsteps 473 + rtol 0.01 rk_type 1 order 3 acc 1 t 1.5 dsm 0.00330184 dsm_est 0.00995476 nsteps 459 + rtol 0.01 rk_type 1 order 3 acc 1 t 2 dsm 0.000346469 dsm_est 0.00994631 nsteps 450 + rtol 0.01 rk_type 1 order 3 acc 1 t 2.5 dsm 0.0103541 dsm_est 0.00997759 nsteps 430 + rtol 0.01 rk_type 1 order 3 acc 1 t 3 dsm 0.0108871 dsm_est 0.00988341 nsteps 447 + rtol 0.01 rk_type 1 order 3 acc 1 t 3.5 dsm 0.00245302 dsm_est 0.00996656 nsteps 465 + rtol 0.01 rk_type 1 order 3 acc 1 t 4 dsm 0.00613073 dsm_est 0.00995474 nsteps 464 + rtol 0.01 rk_type 1 order 3 acc 1 t 4.5 dsm 0.00368671 dsm_est 0.00994184 nsteps 464 + rtol 0.01 rk_type 1 order 3 acc 1 t 5 dsm 0.000382639 dsm_est 0.0099621 nsteps 466 + rtol 0.01 rk_type 1 order 3 acc 1 t 5.5 dsm 0.00138001 dsm_est 0.00996202 nsteps 443 + rtol 0.01 rk_type 1 order 3 acc 1 t 6 dsm 0.00204504 dsm_est 0.00995126 nsteps 463 + rtol 0.01 rk_type 1 order 3 acc 1 t 6.5 dsm 0.00544154 dsm_est 0.00991159 nsteps 465 + rtol 0.01 rk_type 1 order 3 acc 1 t 7 dsm 0.00167909 dsm_est 0.00996267 nsteps 459 + rtol 0.01 rk_type 1 order 3 acc 1 t 7.5 dsm 0.00762228 dsm_est 0.0099702 nsteps 464 + rtol 0.01 rk_type 1 order 3 acc 1 t 8 dsm 0.00815849 dsm_est 0.00996685 nsteps 463 + rtol 0.01 rk_type 1 order 3 acc 1 t 8.5 dsm 0.00479833 dsm_est 0.00996162 nsteps 463 + rtol 0.01 rk_type 1 order 3 acc 1 t 9 dsm 0.00530688 dsm_est 0.00991151 nsteps 460 + rtol 0.01 rk_type 1 order 3 acc 1 t 9.5 dsm 0.00453492 dsm_est 0.00996905 nsteps 461 + rtol 0.01 rk_type 1 order 3 acc 1 t 10 dsm 0.000530102 dsm_est 0.00998737 nsteps 461 + rtol 0.01 rk_type 1 order 3 acc 2 t 0.5 dsm 0.00199866 dsm_est 2.09808 nsteps 492 + rtol 0.01 rk_type 1 order 3 acc 2 t 1 dsm 0.00148824 dsm_est 1.89996 nsteps 473 + rtol 0.01 rk_type 1 order 3 acc 2 t 1.5 dsm 0.00330184 dsm_est 1.97327 nsteps 459 + rtol 0.01 rk_type 1 order 3 acc 2 t 2 dsm 0.000346469 dsm_est 1.9 nsteps 450 + rtol 0.01 rk_type 1 order 3 acc 2 t 2.5 dsm 0.0103541 dsm_est 1.68792 nsteps 430 + rtol 0.01 rk_type 1 order 3 acc 2 t 3 dsm 0.0108871 dsm_est 1.87188 nsteps 447 + rtol 0.01 rk_type 1 order 3 acc 2 t 3.5 dsm 0.00245302 dsm_est 1.9467 nsteps 465 + rtol 0.01 rk_type 1 order 3 acc 2 t 4 dsm 0.00613073 dsm_est 1.9405 nsteps 464 + rtol 0.01 rk_type 1 order 3 acc 2 t 4.5 dsm 0.00368671 dsm_est 1.94315 nsteps 464 + rtol 0.01 rk_type 1 order 3 acc 2 t 5 dsm 0.000382639 dsm_est 1.83475 nsteps 466 + rtol 0.01 rk_type 1 order 3 acc 2 t 5.5 dsm 0.00138001 dsm_est 1.86654 nsteps 443 + rtol 0.01 rk_type 1 order 3 acc 2 t 6 dsm 0.00204504 dsm_est 1.9419 nsteps 463 + rtol 0.01 rk_type 1 order 3 acc 2 t 6.5 dsm 0.00544154 dsm_est 1.96228 nsteps 465 + rtol 0.01 rk_type 1 order 3 acc 2 t 7 dsm 0.00167909 dsm_est 1.90643 nsteps 459 + rtol 0.01 rk_type 1 order 3 acc 2 t 7.5 dsm 0.00762228 dsm_est 1.79247 nsteps 464 + rtol 0.01 rk_type 1 order 3 acc 2 t 8 dsm 0.00815849 dsm_est 1.84371 nsteps 463 + rtol 0.01 rk_type 1 order 3 acc 2 t 8.5 dsm 0.00479833 dsm_est 1.97902 nsteps 463 + rtol 0.01 rk_type 1 order 3 acc 2 t 9 dsm 0.00530688 dsm_est 1.94856 nsteps 460 + rtol 0.01 rk_type 1 order 3 acc 2 t 9.5 dsm 0.00453492 dsm_est 1.91705 nsteps 461 + rtol 0.01 rk_type 1 order 3 acc 2 t 10 dsm 0.000530102 dsm_est 1.91042 nsteps 461 + rtol 0.01 rk_type 1 order 3 acc 3 t 0.5 dsm 0.00199866 dsm_est 0.00443873 nsteps 492 + rtol 0.01 rk_type 1 order 3 acc 3 t 1 dsm 0.00148824 dsm_est 0.00401521 nsteps 473 + rtol 0.01 rk_type 1 order 3 acc 3 t 1.5 dsm 0.00330184 dsm_est 0.00441678 nsteps 459 + rtol 0.01 rk_type 1 order 3 acc 3 t 2 dsm 0.000346469 dsm_est 0.00425191 nsteps 450 + rtol 0.01 rk_type 1 order 3 acc 3 t 2.5 dsm 0.0103541 dsm_est 0.00381705 nsteps 430 + rtol 0.01 rk_type 1 order 3 acc 3 t 3 dsm 0.0108871 dsm_est 0.0041182 nsteps 447 + rtol 0.01 rk_type 1 order 3 acc 3 t 3.5 dsm 0.00245302 dsm_est 0.00412426 nsteps 465 + rtol 0.01 rk_type 1 order 3 acc 3 t 4 dsm 0.00613073 dsm_est 0.00411939 nsteps 464 + rtol 0.01 rk_type 1 order 3 acc 3 t 4.5 dsm 0.00368671 dsm_est 0.00412003 nsteps 464 + rtol 0.01 rk_type 1 order 3 acc 3 t 5 dsm 0.000382639 dsm_est 0.00388215 nsteps 466 + rtol 0.01 rk_type 1 order 3 acc 3 t 5.5 dsm 0.00138001 dsm_est 0.00418117 nsteps 443 + rtol 0.01 rk_type 1 order 3 acc 3 t 6 dsm 0.00204504 dsm_est 0.00411411 nsteps 463 + rtol 0.01 rk_type 1 order 3 acc 3 t 6.5 dsm 0.00544154 dsm_est 0.00415099 nsteps 465 + rtol 0.01 rk_type 1 order 3 acc 3 t 7 dsm 0.00167909 dsm_est 0.00420804 nsteps 459 + rtol 0.01 rk_type 1 order 3 acc 3 t 7.5 dsm 0.00762228 dsm_est 0.00381522 nsteps 464 + rtol 0.01 rk_type 1 order 3 acc 3 t 8 dsm 0.00815849 dsm_est 0.00390452 nsteps 463 + rtol 0.01 rk_type 1 order 3 acc 3 t 8.5 dsm 0.00479833 dsm_est 0.0042077 nsteps 463 + rtol 0.01 rk_type 1 order 3 acc 3 t 9 dsm 0.00530688 dsm_est 0.00413179 nsteps 460 + rtol 0.01 rk_type 1 order 3 acc 3 t 9.5 dsm 0.00453492 dsm_est 0.00406231 nsteps 461 + rtol 0.01 rk_type 1 order 3 acc 3 t 10 dsm 0.000530102 dsm_est 0.00404373 nsteps 461 + rtol 0.0001 rk_type 1 order 3 acc 1 t 0.5 dsm 4.52215e-05 dsm_est 9.69104e-05 nsteps 501 + rtol 0.0001 rk_type 1 order 3 acc 1 t 1 dsm 1.81631e-05 dsm_est 9.49781e-05 nsteps 474 + rtol 0.0001 rk_type 1 order 3 acc 1 t 1.5 dsm 2.77186e-05 dsm_est 9.49662e-05 nsteps 474 + rtol 0.0001 rk_type 1 order 3 acc 1 t 2 dsm 1.52803e-05 dsm_est 9.4909e-05 nsteps 470 + rtol 0.0001 rk_type 1 order 3 acc 1 t 2.5 dsm 4.78098e-05 dsm_est 9.49489e-05 nsteps 464 + rtol 0.0001 rk_type 1 order 3 acc 1 t 3 dsm 2.25476e-05 dsm_est 9.47509e-05 nsteps 465 + rtol 0.0001 rk_type 1 order 3 acc 1 t 3.5 dsm 5.07755e-05 dsm_est 9.47129e-05 nsteps 474 + rtol 0.0001 rk_type 1 order 3 acc 1 t 4 dsm 2.29469e-05 dsm_est 9.49709e-05 nsteps 474 + rtol 0.0001 rk_type 1 order 3 acc 1 t 4.5 dsm 3.88359e-05 dsm_est 9.46293e-05 nsteps 470 + rtol 0.0001 rk_type 1 order 3 acc 1 t 5 dsm 1.51443e-05 dsm_est 9.49444e-05 nsteps 469 + rtol 0.0001 rk_type 1 order 3 acc 1 t 5.5 dsm 1.12906e-05 dsm_est 9.45516e-05 nsteps 470 + rtol 0.0001 rk_type 1 order 3 acc 1 t 6 dsm 2.05734e-05 dsm_est 9.49206e-05 nsteps 474 + rtol 0.0001 rk_type 1 order 3 acc 1 t 6.5 dsm 2.51686e-05 dsm_est 9.49703e-05 nsteps 481 + rtol 0.0001 rk_type 1 order 3 acc 1 t 7 dsm 6.45125e-05 dsm_est 9.93155e-05 nsteps 481 + rtol 0.0001 rk_type 1 order 3 acc 1 t 7.5 dsm 6.30239e-05 dsm_est 9.4983e-05 nsteps 475 + rtol 0.0001 rk_type 1 order 3 acc 1 t 8 dsm 2.85855e-05 dsm_est 9.44898e-05 nsteps 478 + rtol 0.0001 rk_type 1 order 3 acc 1 t 8.5 dsm 4.15619e-05 dsm_est 9.47874e-05 nsteps 480 + rtol 0.0001 rk_type 1 order 3 acc 1 t 9 dsm 9.3894e-06 dsm_est 9.91602e-05 nsteps 475 + rtol 0.0001 rk_type 1 order 3 acc 1 t 9.5 dsm 1.95141e-05 dsm_est 9.49246e-05 nsteps 482 + rtol 0.0001 rk_type 1 order 3 acc 1 t 10 dsm 2.83938e-05 dsm_est 9.5044e-05 nsteps 479 + rtol 0.0001 rk_type 1 order 3 acc 2 t 0.5 dsm 4.52215e-05 dsm_est 0.0204462 nsteps 501 + rtol 0.0001 rk_type 1 order 3 acc 2 t 1 dsm 1.81631e-05 dsm_est 0.0195291 nsteps 474 + rtol 0.0001 rk_type 1 order 3 acc 2 t 1.5 dsm 2.77186e-05 dsm_est 0.018621 nsteps 474 + rtol 0.0001 rk_type 1 order 3 acc 2 t 2 dsm 1.52803e-05 dsm_est 0.0193526 nsteps 470 + rtol 0.0001 rk_type 1 order 3 acc 2 t 2.5 dsm 4.78098e-05 dsm_est 0.0188743 nsteps 464 + rtol 0.0001 rk_type 1 order 3 acc 2 t 3 dsm 2.25476e-05 dsm_est 0.0188411 nsteps 465 + rtol 0.0001 rk_type 1 order 3 acc 2 t 3.5 dsm 5.07755e-05 dsm_est 0.0186928 nsteps 474 + rtol 0.0001 rk_type 1 order 3 acc 2 t 4 dsm 2.29469e-05 dsm_est 0.0192501 nsteps 474 + rtol 0.0001 rk_type 1 order 3 acc 2 t 4.5 dsm 3.88359e-05 dsm_est 0.0190057 nsteps 470 + rtol 0.0001 rk_type 1 order 3 acc 2 t 5 dsm 1.51443e-05 dsm_est 0.0192704 nsteps 469 + rtol 0.0001 rk_type 1 order 3 acc 2 t 5.5 dsm 1.12906e-05 dsm_est 0.0189727 nsteps 470 + rtol 0.0001 rk_type 1 order 3 acc 2 t 6 dsm 2.05734e-05 dsm_est 0.0185915 nsteps 474 + rtol 0.0001 rk_type 1 order 3 acc 2 t 6.5 dsm 2.51686e-05 dsm_est 0.0195025 nsteps 481 + rtol 0.0001 rk_type 1 order 3 acc 2 t 7 dsm 6.45125e-05 dsm_est 0.019722 nsteps 481 + rtol 0.0001 rk_type 1 order 3 acc 2 t 7.5 dsm 6.30239e-05 dsm_est 0.0180237 nsteps 475 + rtol 0.0001 rk_type 1 order 3 acc 2 t 8 dsm 2.85855e-05 dsm_est 0.019557 nsteps 478 + rtol 0.0001 rk_type 1 order 3 acc 2 t 8.5 dsm 4.15619e-05 dsm_est 0.0195763 nsteps 480 + rtol 0.0001 rk_type 1 order 3 acc 2 t 9 dsm 9.3894e-06 dsm_est 0.0195109 nsteps 475 + rtol 0.0001 rk_type 1 order 3 acc 2 t 9.5 dsm 1.95141e-05 dsm_est 0.0192328 nsteps 482 + rtol 0.0001 rk_type 1 order 3 acc 2 t 10 dsm 2.83938e-05 dsm_est 0.0195692 nsteps 479 + rtol 0.0001 rk_type 1 order 3 acc 3 t 0.5 dsm 4.52215e-05 dsm_est 4.27945e-05 nsteps 501 + rtol 0.0001 rk_type 1 order 3 acc 3 t 1 dsm 1.81631e-05 dsm_est 4.18953e-05 nsteps 474 + rtol 0.0001 rk_type 1 order 3 acc 3 t 1.5 dsm 2.77186e-05 dsm_est 4.01946e-05 nsteps 474 + rtol 0.0001 rk_type 1 order 3 acc 3 t 2 dsm 1.52803e-05 dsm_est 4.11232e-05 nsteps 470 + rtol 0.0001 rk_type 1 order 3 acc 3 t 2.5 dsm 4.78098e-05 dsm_est 4.02797e-05 nsteps 464 + rtol 0.0001 rk_type 1 order 3 acc 3 t 3 dsm 2.25476e-05 dsm_est 4.21717e-05 nsteps 465 + rtol 0.0001 rk_type 1 order 3 acc 3 t 3.5 dsm 5.07755e-05 dsm_est 4.02733e-05 nsteps 474 + rtol 0.0001 rk_type 1 order 3 acc 3 t 4 dsm 2.29469e-05 dsm_est 4.06438e-05 nsteps 474 + rtol 0.0001 rk_type 1 order 3 acc 3 t 4.5 dsm 3.88359e-05 dsm_est 4.00905e-05 nsteps 470 + rtol 0.0001 rk_type 1 order 3 acc 3 t 5 dsm 1.51443e-05 dsm_est 4.10729e-05 nsteps 469 + rtol 0.0001 rk_type 1 order 3 acc 3 t 5.5 dsm 1.12906e-05 dsm_est 4.00276e-05 nsteps 470 + rtol 0.0001 rk_type 1 order 3 acc 3 t 6 dsm 2.05734e-05 dsm_est 4.01607e-05 nsteps 474 + rtol 0.0001 rk_type 1 order 3 acc 3 t 6.5 dsm 2.51686e-05 dsm_est 4.12268e-05 nsteps 481 + rtol 0.0001 rk_type 1 order 3 acc 3 t 7 dsm 6.45125e-05 dsm_est 4.17595e-05 nsteps 481 + rtol 0.0001 rk_type 1 order 3 acc 3 t 7.5 dsm 6.30239e-05 dsm_est 3.85507e-05 nsteps 475 + rtol 0.0001 rk_type 1 order 3 acc 3 t 8 dsm 2.85855e-05 dsm_est 4.15334e-05 nsteps 478 + rtol 0.0001 rk_type 1 order 3 acc 3 t 8.5 dsm 4.15619e-05 dsm_est 4.13654e-05 nsteps 480 + rtol 0.0001 rk_type 1 order 3 acc 3 t 9 dsm 9.3894e-06 dsm_est 4.17504e-05 nsteps 475 + rtol 0.0001 rk_type 1 order 3 acc 3 t 9.5 dsm 1.95141e-05 dsm_est 4.05915e-05 nsteps 482 + rtol 0.0001 rk_type 1 order 3 acc 3 t 10 dsm 2.83938e-05 dsm_est 4.15708e-05 nsteps 479 + rtol 1e-06 rk_type 1 order 3 acc 1 t 0.5 dsm 6.49367e-08 dsm_est 9.89086e-07 nsteps 550 + rtol 1e-06 rk_type 1 order 3 acc 1 t 1 dsm 5.83524e-07 dsm_est 9.4678e-07 nsteps 488 + rtol 1e-06 rk_type 1 order 3 acc 1 t 1.5 dsm 2.01442e-08 dsm_est 9.47358e-07 nsteps 491 + rtol 1e-06 rk_type 1 order 3 acc 1 t 2 dsm 6.89174e-08 dsm_est 9.48104e-07 nsteps 485 + rtol 1e-06 rk_type 1 order 3 acc 1 t 2.5 dsm 3.25214e-07 dsm_est 9.49113e-07 nsteps 463 + rtol 1e-06 rk_type 1 order 3 acc 1 t 3 dsm 3.48745e-07 dsm_est 9.48334e-07 nsteps 481 + rtol 1e-06 rk_type 1 order 3 acc 1 t 3.5 dsm 1.27971e-06 dsm_est 9.46641e-07 nsteps 484 + rtol 1e-06 rk_type 1 order 3 acc 1 t 4 dsm 5.22124e-07 dsm_est 9.49243e-07 nsteps 485 + rtol 1e-06 rk_type 1 order 3 acc 1 t 4.5 dsm 6.25795e-07 dsm_est 9.48421e-07 nsteps 486 + rtol 1e-06 rk_type 1 order 3 acc 1 t 5 dsm 5.82624e-07 dsm_est 9.48091e-07 nsteps 487 + rtol 1e-06 rk_type 1 order 3 acc 1 t 5.5 dsm 5.29296e-07 dsm_est 9.82269e-07 nsteps 483 + rtol 1e-06 rk_type 1 order 3 acc 1 t 6 dsm 3.47222e-07 dsm_est 9.87002e-07 nsteps 484 + rtol 1e-06 rk_type 1 order 3 acc 1 t 6.5 dsm 8.05504e-07 dsm_est 9.48638e-07 nsteps 477 + rtol 1e-06 rk_type 1 order 3 acc 1 t 7 dsm 4.05624e-08 dsm_est 9.61095e-07 nsteps 487 + rtol 1e-06 rk_type 1 order 3 acc 1 t 7.5 dsm 7.28832e-08 dsm_est 9.4602e-07 nsteps 487 + rtol 1e-06 rk_type 1 order 3 acc 1 t 8 dsm 9.01356e-07 dsm_est 9.48084e-07 nsteps 485 + rtol 1e-06 rk_type 1 order 3 acc 1 t 8.5 dsm 9.82212e-07 dsm_est 9.4573e-07 nsteps 489 + rtol 1e-06 rk_type 1 order 3 acc 1 t 9 dsm 2.03978e-07 dsm_est 9.47478e-07 nsteps 468 + rtol 1e-06 rk_type 1 order 3 acc 1 t 9.5 dsm 2.77163e-07 dsm_est 9.49943e-07 nsteps 475 + rtol 1e-06 rk_type 1 order 3 acc 1 t 10 dsm 4.2482e-07 dsm_est 9.47165e-07 nsteps 476 + rtol 1e-06 rk_type 1 order 3 acc 2 t 0.5 dsm 6.49367e-08 dsm_est 0.000190015 nsteps 550 + rtol 1e-06 rk_type 1 order 3 acc 2 t 1 dsm 5.83524e-07 dsm_est 0.000191707 nsteps 488 + rtol 1e-06 rk_type 1 order 3 acc 2 t 1.5 dsm 2.01442e-08 dsm_est 0.000154747 nsteps 491 + rtol 1e-06 rk_type 1 order 3 acc 2 t 2 dsm 6.89174e-08 dsm_est 0.000191171 nsteps 485 + rtol 1e-06 rk_type 1 order 3 acc 2 t 2.5 dsm 3.25214e-07 dsm_est 0.000189145 nsteps 463 + rtol 1e-06 rk_type 1 order 3 acc 2 t 3 dsm 3.48745e-07 dsm_est 0.000193684 nsteps 481 + rtol 1e-06 rk_type 1 order 3 acc 2 t 3.5 dsm 1.27971e-06 dsm_est 0.000198922 nsteps 484 + rtol 1e-06 rk_type 1 order 3 acc 2 t 4 dsm 5.22124e-07 dsm_est 0.000197072 nsteps 485 + rtol 1e-06 rk_type 1 order 3 acc 2 t 4.5 dsm 6.25795e-07 dsm_est 0.000191436 nsteps 486 + rtol 1e-06 rk_type 1 order 3 acc 2 t 5 dsm 5.82624e-07 dsm_est 0.000196185 nsteps 487 + rtol 1e-06 rk_type 1 order 3 acc 2 t 5.5 dsm 5.29296e-07 dsm_est 0.000199124 nsteps 483 + rtol 1e-06 rk_type 1 order 3 acc 2 t 6 dsm 3.47222e-07 dsm_est 0.000199936 nsteps 484 + rtol 1e-06 rk_type 1 order 3 acc 2 t 6.5 dsm 8.05504e-07 dsm_est 0.000193196 nsteps 477 + rtol 1e-06 rk_type 1 order 3 acc 2 t 7 dsm 4.05624e-08 dsm_est 0.000198041 nsteps 487 + rtol 1e-06 rk_type 1 order 3 acc 2 t 7.5 dsm 7.28832e-08 dsm_est 0.000199497 nsteps 487 + rtol 1e-06 rk_type 1 order 3 acc 2 t 8 dsm 9.01356e-07 dsm_est 0.000197732 nsteps 485 + rtol 1e-06 rk_type 1 order 3 acc 2 t 8.5 dsm 9.82212e-07 dsm_est 0.000189126 nsteps 489 + rtol 1e-06 rk_type 1 order 3 acc 2 t 9 dsm 2.03978e-07 dsm_est 0.000189873 nsteps 468 + rtol 1e-06 rk_type 1 order 3 acc 2 t 9.5 dsm 2.77163e-07 dsm_est 0.000192779 nsteps 475 + rtol 1e-06 rk_type 1 order 3 acc 2 t 10 dsm 4.2482e-07 dsm_est 0.000186705 nsteps 476 + rtol 1e-06 rk_type 1 order 3 acc 3 t 0.5 dsm 6.49367e-08 dsm_est 3.76189e-07 nsteps 550 + rtol 1e-06 rk_type 1 order 3 acc 3 t 1 dsm 5.83524e-07 dsm_est 4.03986e-07 nsteps 488 + rtol 1e-06 rk_type 1 order 3 acc 3 t 1.5 dsm 2.01442e-08 dsm_est 3.17531e-07 nsteps 491 + rtol 1e-06 rk_type 1 order 3 acc 3 t 2 dsm 6.89174e-08 dsm_est 4.03334e-07 nsteps 485 + rtol 1e-06 rk_type 1 order 3 acc 3 t 2.5 dsm 3.25214e-07 dsm_est 4.26069e-07 nsteps 463 + rtol 1e-06 rk_type 1 order 3 acc 3 t 3 dsm 3.48745e-07 dsm_est 4.13425e-07 nsteps 481 + rtol 1e-06 rk_type 1 order 3 acc 3 t 3.5 dsm 1.27971e-06 dsm_est 4.2656e-07 nsteps 484 + rtol 1e-06 rk_type 1 order 3 acc 3 t 4 dsm 5.22124e-07 dsm_est 4.19481e-07 nsteps 485 + rtol 1e-06 rk_type 1 order 3 acc 3 t 4.5 dsm 6.25795e-07 dsm_est 4.03617e-07 nsteps 486 + rtol 1e-06 rk_type 1 order 3 acc 3 t 5 dsm 5.82624e-07 dsm_est 4.13815e-07 nsteps 487 + rtol 1e-06 rk_type 1 order 3 acc 3 t 5.5 dsm 5.29296e-07 dsm_est 4.27331e-07 nsteps 483 + rtol 1e-06 rk_type 1 order 3 acc 3 t 6 dsm 3.47222e-07 dsm_est 4.28557e-07 nsteps 484 + rtol 1e-06 rk_type 1 order 3 acc 3 t 6.5 dsm 8.05504e-07 dsm_est 4.16753e-07 nsteps 477 + rtol 1e-06 rk_type 1 order 3 acc 3 t 7 dsm 4.05624e-08 dsm_est 4.18718e-07 nsteps 487 + rtol 1e-06 rk_type 1 order 3 acc 3 t 7.5 dsm 7.28832e-08 dsm_est 4.22063e-07 nsteps 487 + rtol 1e-06 rk_type 1 order 3 acc 3 t 8 dsm 9.01356e-07 dsm_est 4.22563e-07 nsteps 485 + rtol 1e-06 rk_type 1 order 3 acc 3 t 8.5 dsm 9.82212e-07 dsm_est 3.97686e-07 nsteps 489 + rtol 1e-06 rk_type 1 order 3 acc 3 t 9 dsm 2.03978e-07 dsm_est 4.06169e-07 nsteps 468 + rtol 1e-06 rk_type 1 order 3 acc 3 t 9.5 dsm 2.77163e-07 dsm_est 4.12601e-07 nsteps 475 + rtol 1e-06 rk_type 1 order 3 acc 3 t 10 dsm 4.2482e-07 dsm_est 3.9924e-07 nsteps 476 diff --git a/test/unit_tests/arkode/CXX_serial/ark_test_accumerror_brusselator_20_5_0.out b/test/unit_tests/arkode/CXX_serial/ark_test_accumerror_brusselator_20_5_0.out new file mode 100644 index 0000000000..36b63bfbfd --- /dev/null +++ b/test/unit_tests/arkode/CXX_serial/ark_test_accumerror_brusselator_20_5_0.out @@ -0,0 +1,189 @@ + +Accumulated error estimation test (stiff Brusselator ODE problem): + time domain: (0,10] + partition size = 20 + initial conditions: u0 = 1.2, v0 = 3.1, w0 = 3 + problem parameters: a = 1, b = 3.5, ep = 0.0004 + DIRK solver, order = 5 + +Adaptive-step runs: + rtol 0.01 rk_type 0 order 5 acc 1 t 0.5 dsm 7.48644e-05 dsm_est 3.4373e-05 nsteps 9 + rtol 0.01 rk_type 0 order 5 acc 1 t 1 dsm 0.000110257 dsm_est 2.23308e-06 nsteps 5 + rtol 0.01 rk_type 0 order 5 acc 1 t 1.5 dsm 0.00132404 dsm_est 2.08137e-06 nsteps 6 + rtol 0.01 rk_type 0 order 5 acc 1 t 2 dsm 0.00110273 dsm_est 6.3665e-07 nsteps 6 + rtol 0.01 rk_type 0 order 5 acc 1 t 2.5 dsm 6.10485e-05 dsm_est 1.85399e-07 nsteps 6 + rtol 0.01 rk_type 0 order 5 acc 1 t 3 dsm 0.000275174 dsm_est 6.46876e-07 nsteps 6 + rtol 0.01 rk_type 0 order 5 acc 1 t 3.5 dsm 0.00032811 dsm_est 1.68426e-06 nsteps 6 + rtol 0.01 rk_type 0 order 5 acc 1 t 4 dsm 7.35974e-05 dsm_est 4.88814e-07 nsteps 6 + rtol 0.01 rk_type 0 order 5 acc 1 t 4.5 dsm 0.000394423 dsm_est 1.74045e-06 nsteps 6 + rtol 0.01 rk_type 0 order 5 acc 1 t 5 dsm 4.44693e-05 dsm_est 4.77027e-07 nsteps 6 + rtol 0.01 rk_type 0 order 5 acc 1 t 5.5 dsm 0.000153383 dsm_est 6.89334e-07 nsteps 5 + rtol 0.01 rk_type 0 order 5 acc 1 t 6 dsm 0.00039377 dsm_est 3.77896e-06 nsteps 6 + rtol 0.01 rk_type 0 order 5 acc 1 t 6.5 dsm 0.000506258 dsm_est 1.01998e-06 nsteps 6 + rtol 0.01 rk_type 0 order 5 acc 1 t 7 dsm 0.00148699 dsm_est 4.63864e-05 nsteps 12 + rtol 0.01 rk_type 0 order 5 acc 1 t 7.5 dsm 0.000435975 dsm_est 0.000225656 nsteps 4 + rtol 0.01 rk_type 0 order 5 acc 1 t 8 dsm 0.000824606 dsm_est 1.36787e-05 nsteps 7 + rtol 0.01 rk_type 0 order 5 acc 1 t 8.5 dsm 0.00100819 dsm_est 1.09309e-05 nsteps 6 + rtol 0.01 rk_type 0 order 5 acc 1 t 9 dsm 0.00058073 dsm_est 4.52926e-06 nsteps 6 + rtol 0.01 rk_type 0 order 5 acc 1 t 9.5 dsm 6.70214e-05 dsm_est 2.50118e-06 nsteps 6 + rtol 0.01 rk_type 0 order 5 acc 1 t 10 dsm 0.000490488 dsm_est 4.64334e-06 nsteps 6 + rtol 0.01 rk_type 0 order 5 acc 2 t 0.5 dsm 7.48644e-05 dsm_est 5.4592e-05 nsteps 9 + rtol 0.01 rk_type 0 order 5 acc 2 t 1 dsm 0.000110257 dsm_est 2.23312e-06 nsteps 5 + rtol 0.01 rk_type 0 order 5 acc 2 t 1.5 dsm 0.00132404 dsm_est 2.37777e-06 nsteps 6 + rtol 0.01 rk_type 0 order 5 acc 2 t 2 dsm 0.00110273 dsm_est 8.17396e-07 nsteps 6 + rtol 0.01 rk_type 0 order 5 acc 2 t 2.5 dsm 6.10485e-05 dsm_est 3.28054e-07 nsteps 6 + rtol 0.01 rk_type 0 order 5 acc 2 t 3 dsm 0.000275174 dsm_est 6.76339e-07 nsteps 6 + rtol 0.01 rk_type 0 order 5 acc 2 t 3.5 dsm 0.00032811 dsm_est 1.69526e-06 nsteps 6 + rtol 0.01 rk_type 0 order 5 acc 2 t 4 dsm 7.35974e-05 dsm_est 4.93897e-07 nsteps 6 + rtol 0.01 rk_type 0 order 5 acc 2 t 4.5 dsm 0.000394423 dsm_est 1.74465e-06 nsteps 6 + rtol 0.01 rk_type 0 order 5 acc 2 t 5 dsm 4.44693e-05 dsm_est 4.91596e-07 nsteps 6 + rtol 0.01 rk_type 0 order 5 acc 2 t 5.5 dsm 0.000153383 dsm_est 6.90221e-07 nsteps 5 + rtol 0.01 rk_type 0 order 5 acc 2 t 6 dsm 0.00039377 dsm_est 4.6301e-06 nsteps 6 + rtol 0.01 rk_type 0 order 5 acc 2 t 6.5 dsm 0.000506258 dsm_est 1.7875e-06 nsteps 6 + rtol 0.01 rk_type 0 order 5 acc 2 t 7 dsm 0.00148699 dsm_est 7.28369e-05 nsteps 12 + rtol 0.01 rk_type 0 order 5 acc 2 t 7.5 dsm 0.000435975 dsm_est 0.000234031 nsteps 4 + rtol 0.01 rk_type 0 order 5 acc 2 t 8 dsm 0.000824606 dsm_est 2.56036e-05 nsteps 7 + rtol 0.01 rk_type 0 order 5 acc 2 t 8.5 dsm 0.00100819 dsm_est 1.09812e-05 nsteps 6 + rtol 0.01 rk_type 0 order 5 acc 2 t 9 dsm 0.00058073 dsm_est 4.93642e-06 nsteps 6 + rtol 0.01 rk_type 0 order 5 acc 2 t 9.5 dsm 6.70214e-05 dsm_est 2.55332e-06 nsteps 6 + rtol 0.01 rk_type 0 order 5 acc 2 t 10 dsm 0.000490488 dsm_est 4.66143e-06 nsteps 6 + rtol 0.01 rk_type 0 order 5 acc 3 t 0.5 dsm 7.48644e-05 dsm_est 8.43563e-06 nsteps 9 + rtol 0.01 rk_type 0 order 5 acc 3 t 1 dsm 0.000110257 dsm_est 1.92448e-06 nsteps 5 + rtol 0.01 rk_type 0 order 5 acc 3 t 1.5 dsm 0.00132404 dsm_est 1.36392e-06 nsteps 6 + rtol 0.01 rk_type 0 order 5 acc 3 t 2 dsm 0.00110273 dsm_est 3.97765e-07 nsteps 6 + rtol 0.01 rk_type 0 order 5 acc 3 t 2.5 dsm 6.10485e-05 dsm_est 1.42453e-07 nsteps 6 + rtol 0.01 rk_type 0 order 5 acc 3 t 3 dsm 0.000275174 dsm_est 3.75126e-07 nsteps 6 + rtol 0.01 rk_type 0 order 5 acc 3 t 3.5 dsm 0.00032811 dsm_est 1.23035e-06 nsteps 6 + rtol 0.01 rk_type 0 order 5 acc 3 t 4 dsm 7.35974e-05 dsm_est 3.49622e-07 nsteps 6 + rtol 0.01 rk_type 0 order 5 acc 3 t 4.5 dsm 0.000394423 dsm_est 1.33208e-06 nsteps 6 + rtol 0.01 rk_type 0 order 5 acc 3 t 5 dsm 4.44693e-05 dsm_est 3.3167e-07 nsteps 6 + rtol 0.01 rk_type 0 order 5 acc 3 t 5.5 dsm 0.000153383 dsm_est 5.43622e-07 nsteps 5 + rtol 0.01 rk_type 0 order 5 acc 3 t 6 dsm 0.00039377 dsm_est 1.51647e-06 nsteps 6 + rtol 0.01 rk_type 0 order 5 acc 3 t 6.5 dsm 0.000506258 dsm_est 6.62913e-07 nsteps 6 + rtol 0.01 rk_type 0 order 5 acc 3 t 7 dsm 0.00148699 dsm_est 1.33552e-05 nsteps 12 + rtol 0.01 rk_type 0 order 5 acc 3 t 7.5 dsm 0.000435975 dsm_est 0.000128373 nsteps 4 + rtol 0.01 rk_type 0 order 5 acc 3 t 8 dsm 0.000824606 dsm_est 9.87403e-06 nsteps 7 + rtol 0.01 rk_type 0 order 5 acc 3 t 8.5 dsm 0.00100819 dsm_est 5.15624e-06 nsteps 6 + rtol 0.01 rk_type 0 order 5 acc 3 t 9 dsm 0.00058073 dsm_est 2.61771e-06 nsteps 6 + rtol 0.01 rk_type 0 order 5 acc 3 t 9.5 dsm 6.70214e-05 dsm_est 1.42911e-06 nsteps 6 + rtol 0.01 rk_type 0 order 5 acc 3 t 10 dsm 0.000490488 dsm_est 3.46267e-06 nsteps 6 + rtol 0.0001 rk_type 0 order 5 acc 1 t 0.5 dsm 1.9124e-05 dsm_est 4.10549e-06 nsteps 13 + rtol 0.0001 rk_type 0 order 5 acc 1 t 1 dsm 1.46639e-06 dsm_est 2.99051e-08 nsteps 3 + rtol 0.0001 rk_type 0 order 5 acc 1 t 1.5 dsm 1.49779e-06 dsm_est 2.8794e-08 nsteps 3 + rtol 0.0001 rk_type 0 order 5 acc 1 t 2 dsm 2.48711e-06 dsm_est 5.23997e-08 nsteps 3 + rtol 0.0001 rk_type 0 order 5 acc 1 t 2.5 dsm 8.68487e-07 dsm_est 8.11031e-09 nsteps 3 + rtol 0.0001 rk_type 0 order 5 acc 1 t 3 dsm 4.6854e-06 dsm_est 3.54429e-08 nsteps 4 + rtol 0.0001 rk_type 0 order 5 acc 1 t 3.5 dsm 4.86491e-06 dsm_est 1.27286e-08 nsteps 4 + rtol 0.0001 rk_type 0 order 5 acc 1 t 4 dsm 9.38226e-06 dsm_est 6.18062e-10 nsteps 3 + rtol 0.0001 rk_type 0 order 5 acc 1 t 4.5 dsm 3.64804e-06 dsm_est 5.92484e-10 nsteps 3 + rtol 0.0001 rk_type 0 order 5 acc 1 t 5 dsm 1.20837e-06 dsm_est 1.11283e-08 nsteps 3 + rtol 0.0001 rk_type 0 order 5 acc 1 t 5.5 dsm 1.96373e-05 dsm_est 1.16786e-08 nsteps 3 + rtol 0.0001 rk_type 0 order 5 acc 1 t 6 dsm 6.78601e-06 dsm_est 5.56249e-08 nsteps 4 + rtol 0.0001 rk_type 0 order 5 acc 1 t 6.5 dsm 3.28653e-05 dsm_est 5.49255e-08 nsteps 8 + rtol 0.0001 rk_type 0 order 5 acc 1 t 7 dsm 1.0851e-05 dsm_est 2.95421e-06 nsteps 17 + rtol 0.0001 rk_type 0 order 5 acc 1 t 7.5 dsm 8.11463e-06 dsm_est 7.59043e-08 nsteps 13 + rtol 0.0001 rk_type 0 order 5 acc 1 t 8 dsm 1.12113e-05 dsm_est 6.59216e-08 nsteps 7 + rtol 0.0001 rk_type 0 order 5 acc 1 t 8.5 dsm 7.59151e-06 dsm_est 8.65901e-08 nsteps 5 + rtol 0.0001 rk_type 0 order 5 acc 1 t 9 dsm 1.10466e-05 dsm_est 2.02617e-08 nsteps 4 + rtol 0.0001 rk_type 0 order 5 acc 1 t 9.5 dsm 1.12334e-05 dsm_est 1.10517e-07 nsteps 4 + rtol 0.0001 rk_type 0 order 5 acc 1 t 10 dsm 9.05222e-07 dsm_est 1.64841e-08 nsteps 4 + rtol 0.0001 rk_type 0 order 5 acc 2 t 0.5 dsm 1.9124e-05 dsm_est 5.71969e-06 nsteps 13 + rtol 0.0001 rk_type 0 order 5 acc 2 t 1 dsm 1.46639e-06 dsm_est 2.99989e-08 nsteps 3 + rtol 0.0001 rk_type 0 order 5 acc 2 t 1.5 dsm 1.49779e-06 dsm_est 2.89735e-08 nsteps 3 + rtol 0.0001 rk_type 0 order 5 acc 2 t 2 dsm 2.48711e-06 dsm_est 5.35748e-08 nsteps 3 + rtol 0.0001 rk_type 0 order 5 acc 2 t 2.5 dsm 8.68487e-07 dsm_est 1.05987e-08 nsteps 3 + rtol 0.0001 rk_type 0 order 5 acc 2 t 3 dsm 4.6854e-06 dsm_est 3.58967e-08 nsteps 4 + rtol 0.0001 rk_type 0 order 5 acc 2 t 3.5 dsm 4.86491e-06 dsm_est 1.53193e-08 nsteps 4 + rtol 0.0001 rk_type 0 order 5 acc 2 t 4 dsm 9.38226e-06 dsm_est 1.14771e-09 nsteps 3 + rtol 0.0001 rk_type 0 order 5 acc 2 t 4.5 dsm 3.64804e-06 dsm_est 8.14332e-10 nsteps 3 + rtol 0.0001 rk_type 0 order 5 acc 2 t 5 dsm 1.20837e-06 dsm_est 1.18132e-08 nsteps 3 + rtol 0.0001 rk_type 0 order 5 acc 2 t 5.5 dsm 1.96373e-05 dsm_est 1.51402e-08 nsteps 3 + rtol 0.0001 rk_type 0 order 5 acc 2 t 6 dsm 6.78601e-06 dsm_est 8.14402e-08 nsteps 4 + rtol 0.0001 rk_type 0 order 5 acc 2 t 6.5 dsm 3.28653e-05 dsm_est 1.13828e-07 nsteps 8 + rtol 0.0001 rk_type 0 order 5 acc 2 t 7 dsm 1.0851e-05 dsm_est 4.33597e-06 nsteps 17 + rtol 0.0001 rk_type 0 order 5 acc 2 t 7.5 dsm 8.11463e-06 dsm_est 2.04239e-07 nsteps 13 + rtol 0.0001 rk_type 0 order 5 acc 2 t 8 dsm 1.12113e-05 dsm_est 6.62221e-08 nsteps 7 + rtol 0.0001 rk_type 0 order 5 acc 2 t 8.5 dsm 7.59151e-06 dsm_est 8.67008e-08 nsteps 5 + rtol 0.0001 rk_type 0 order 5 acc 2 t 9 dsm 1.10466e-05 dsm_est 3.06823e-08 nsteps 4 + rtol 0.0001 rk_type 0 order 5 acc 2 t 9.5 dsm 1.12334e-05 dsm_est 1.36785e-07 nsteps 4 + rtol 0.0001 rk_type 0 order 5 acc 2 t 10 dsm 9.05222e-07 dsm_est 3.2806e-08 nsteps 4 + rtol 0.0001 rk_type 0 order 5 acc 3 t 0.5 dsm 1.9124e-05 dsm_est 8.037e-08 nsteps 13 + rtol 0.0001 rk_type 0 order 5 acc 3 t 1 dsm 1.46639e-06 dsm_est 1.96624e-08 nsteps 3 + rtol 0.0001 rk_type 0 order 5 acc 3 t 1.5 dsm 1.49779e-06 dsm_est 1.97143e-08 nsteps 3 + rtol 0.0001 rk_type 0 order 5 acc 3 t 2 dsm 2.48711e-06 dsm_est 3.32323e-08 nsteps 3 + rtol 0.0001 rk_type 0 order 5 acc 3 t 2.5 dsm 8.68487e-07 dsm_est 5.8804e-09 nsteps 3 + rtol 0.0001 rk_type 0 order 5 acc 3 t 3 dsm 4.6854e-06 dsm_est 2.06494e-08 nsteps 4 + rtol 0.0001 rk_type 0 order 5 acc 3 t 3.5 dsm 4.86491e-06 dsm_est 7.91268e-09 nsteps 4 + rtol 0.0001 rk_type 0 order 5 acc 3 t 4 dsm 9.38226e-06 dsm_est 5.58758e-10 nsteps 3 + rtol 0.0001 rk_type 0 order 5 acc 3 t 4.5 dsm 3.64804e-06 dsm_est 4.12749e-10 nsteps 3 + rtol 0.0001 rk_type 0 order 5 acc 3 t 5 dsm 1.20837e-06 dsm_est 6.31634e-09 nsteps 3 + rtol 0.0001 rk_type 0 order 5 acc 3 t 5.5 dsm 1.96373e-05 dsm_est 7.63049e-09 nsteps 3 + rtol 0.0001 rk_type 0 order 5 acc 3 t 6 dsm 6.78601e-06 dsm_est 3.45501e-08 nsteps 4 + rtol 0.0001 rk_type 0 order 5 acc 3 t 6.5 dsm 3.28653e-05 dsm_est 2.5131e-08 nsteps 8 + rtol 0.0001 rk_type 0 order 5 acc 3 t 7 dsm 1.0851e-05 dsm_est 4.68539e-07 nsteps 17 + rtol 0.0001 rk_type 0 order 5 acc 3 t 7.5 dsm 8.11463e-06 dsm_est 1.75019e-08 nsteps 13 + rtol 0.0001 rk_type 0 order 5 acc 3 t 8 dsm 1.12113e-05 dsm_est 2.06416e-08 nsteps 7 + rtol 0.0001 rk_type 0 order 5 acc 3 t 8.5 dsm 7.59151e-06 dsm_est 4.50463e-08 nsteps 5 + rtol 0.0001 rk_type 0 order 5 acc 3 t 9 dsm 1.10466e-05 dsm_est 1.18403e-08 nsteps 4 + rtol 0.0001 rk_type 0 order 5 acc 3 t 9.5 dsm 1.12334e-05 dsm_est 6.19359e-08 nsteps 4 + rtol 0.0001 rk_type 0 order 5 acc 3 t 10 dsm 9.05222e-07 dsm_est 1.24356e-08 nsteps 4 + rtol 1e-06 rk_type 0 order 5 acc 1 t 0.5 dsm 1.88136e-07 dsm_est 1.26411e-07 nsteps 20 + rtol 1e-06 rk_type 0 order 5 acc 1 t 1 dsm 3.6815e-08 dsm_est 2.79712e-09 nsteps 5 + rtol 1e-06 rk_type 0 order 5 acc 1 t 1.5 dsm 3.46973e-08 dsm_est 3.51635e-09 nsteps 7 + rtol 1e-06 rk_type 0 order 5 acc 1 t 2 dsm 2.15722e-07 dsm_est 6.11647e-09 nsteps 7 + rtol 1e-06 rk_type 0 order 5 acc 1 t 2.5 dsm 9.55646e-08 dsm_est 1.88588e-09 nsteps 7 + rtol 1e-06 rk_type 0 order 5 acc 1 t 3 dsm 1.61192e-07 dsm_est 1.2608e-08 nsteps 5 + rtol 1e-06 rk_type 0 order 5 acc 1 t 3.5 dsm 4.89781e-08 dsm_est 3.86937e-09 nsteps 5 + rtol 1e-06 rk_type 0 order 5 acc 1 t 4 dsm 2.89671e-09 dsm_est 1.89611e-10 nsteps 5 + rtol 1e-06 rk_type 0 order 5 acc 1 t 4.5 dsm 1.33856e-07 dsm_est 1.34787e-10 nsteps 4 + rtol 1e-06 rk_type 0 order 5 acc 1 t 5 dsm 1.14768e-07 dsm_est 3.89832e-09 nsteps 5 + rtol 1e-06 rk_type 0 order 5 acc 1 t 5.5 dsm 3.35877e-07 dsm_est 5.30354e-09 nsteps 7 + rtol 1e-06 rk_type 0 order 5 acc 1 t 6 dsm 3.66079e-07 dsm_est 3.68188e-09 nsteps 9 + rtol 1e-06 rk_type 0 order 5 acc 1 t 6.5 dsm 1.18284e-06 dsm_est 5.36543e-09 nsteps 13 + rtol 1e-06 rk_type 0 order 5 acc 1 t 7 dsm 6.15151e-07 dsm_est 1.3137e-07 nsteps 32 + rtol 1e-06 rk_type 0 order 5 acc 1 t 7.5 dsm 7.6586e-08 dsm_est 5.37386e-09 nsteps 17 + rtol 1e-06 rk_type 0 order 5 acc 1 t 8 dsm 4.14322e-07 dsm_est 7.83969e-10 nsteps 13 + rtol 1e-06 rk_type 0 order 5 acc 1 t 8.5 dsm 2.50606e-07 dsm_est 1.87037e-08 nsteps 9 + rtol 1e-06 rk_type 0 order 5 acc 1 t 9 dsm 1.33343e-07 dsm_est 8.70204e-09 nsteps 7 + rtol 1e-06 rk_type 0 order 5 acc 1 t 9.5 dsm 1.44237e-07 dsm_est 1.59014e-08 nsteps 6 + rtol 1e-06 rk_type 0 order 5 acc 1 t 10 dsm 1.34853e-07 dsm_est 2.74315e-08 nsteps 6 + rtol 1e-06 rk_type 0 order 5 acc 2 t 0.5 dsm 1.88136e-07 dsm_est 3.10757e-07 nsteps 20 + rtol 1e-06 rk_type 0 order 5 acc 2 t 1 dsm 3.6815e-08 dsm_est 2.85172e-09 nsteps 5 + rtol 1e-06 rk_type 0 order 5 acc 2 t 1.5 dsm 3.46973e-08 dsm_est 3.53495e-09 nsteps 7 + rtol 1e-06 rk_type 0 order 5 acc 2 t 2 dsm 2.15722e-07 dsm_est 6.21173e-09 nsteps 7 + rtol 1e-06 rk_type 0 order 5 acc 2 t 2.5 dsm 9.55646e-08 dsm_est 1.95849e-09 nsteps 7 + rtol 1e-06 rk_type 0 order 5 acc 2 t 3 dsm 1.61192e-07 dsm_est 1.42375e-08 nsteps 5 + rtol 1e-06 rk_type 0 order 5 acc 2 t 3.5 dsm 4.89781e-08 dsm_est 5.44995e-09 nsteps 5 + rtol 1e-06 rk_type 0 order 5 acc 2 t 4 dsm 2.89671e-09 dsm_est 2.05845e-10 nsteps 5 + rtol 1e-06 rk_type 0 order 5 acc 2 t 4.5 dsm 1.33856e-07 dsm_est 1.4524e-10 nsteps 4 + rtol 1e-06 rk_type 0 order 5 acc 2 t 5 dsm 1.14768e-07 dsm_est 3.97399e-09 nsteps 5 + rtol 1e-06 rk_type 0 order 5 acc 2 t 5.5 dsm 3.35877e-07 dsm_est 5.39098e-09 nsteps 7 + rtol 1e-06 rk_type 0 order 5 acc 2 t 6 dsm 3.66079e-07 dsm_est 4.54425e-09 nsteps 9 + rtol 1e-06 rk_type 0 order 5 acc 2 t 6.5 dsm 1.18284e-06 dsm_est 1.43453e-08 nsteps 13 + rtol 1e-06 rk_type 0 order 5 acc 2 t 7 dsm 6.15151e-07 dsm_est 3.71172e-07 nsteps 32 + rtol 1e-06 rk_type 0 order 5 acc 2 t 7.5 dsm 7.6586e-08 dsm_est 1.05078e-08 nsteps 17 + rtol 1e-06 rk_type 0 order 5 acc 2 t 8 dsm 4.14322e-07 dsm_est 1.80819e-09 nsteps 13 + rtol 1e-06 rk_type 0 order 5 acc 2 t 8.5 dsm 2.50606e-07 dsm_est 1.87833e-08 nsteps 9 + rtol 1e-06 rk_type 0 order 5 acc 2 t 9 dsm 1.33343e-07 dsm_est 1.22048e-08 nsteps 7 + rtol 1e-06 rk_type 0 order 5 acc 2 t 9.5 dsm 1.44237e-07 dsm_est 3.40516e-08 nsteps 6 + rtol 1e-06 rk_type 0 order 5 acc 2 t 10 dsm 1.34853e-07 dsm_est 3.35247e-08 nsteps 6 + rtol 1e-06 rk_type 0 order 5 acc 3 t 0.5 dsm 1.88136e-07 dsm_est 1.26851e-08 nsteps 20 + rtol 1e-06 rk_type 0 order 5 acc 3 t 1 dsm 3.6815e-08 dsm_est 1.6608e-09 nsteps 5 + rtol 1e-06 rk_type 0 order 5 acc 3 t 1.5 dsm 3.46973e-08 dsm_est 1.70095e-09 nsteps 7 + rtol 1e-06 rk_type 0 order 5 acc 3 t 2 dsm 2.15722e-07 dsm_est 2.55077e-09 nsteps 7 + rtol 1e-06 rk_type 0 order 5 acc 3 t 2.5 dsm 9.55646e-08 dsm_est 8.55183e-10 nsteps 7 + rtol 1e-06 rk_type 0 order 5 acc 3 t 3 dsm 1.61192e-07 dsm_est 6.55528e-09 nsteps 5 + rtol 1e-06 rk_type 0 order 5 acc 3 t 3.5 dsm 4.89781e-08 dsm_est 2.24419e-09 nsteps 5 + rtol 1e-06 rk_type 0 order 5 acc 3 t 4 dsm 2.89671e-09 dsm_est 1.14512e-10 nsteps 5 + rtol 1e-06 rk_type 0 order 5 acc 3 t 4.5 dsm 1.33856e-07 dsm_est 9.42445e-11 nsteps 4 + rtol 1e-06 rk_type 0 order 5 acc 3 t 5 dsm 1.14768e-07 dsm_est 2.14148e-09 nsteps 5 + rtol 1e-06 rk_type 0 order 5 acc 3 t 5.5 dsm 3.35877e-07 dsm_est 2.26456e-09 nsteps 7 + rtol 1e-06 rk_type 0 order 5 acc 3 t 6 dsm 3.66079e-07 dsm_est 1.25374e-09 nsteps 9 + rtol 1e-06 rk_type 0 order 5 acc 3 t 6.5 dsm 1.18284e-06 dsm_est 2.39129e-09 nsteps 13 + rtol 1e-06 rk_type 0 order 5 acc 3 t 7 dsm 6.15151e-07 dsm_est 2.56642e-08 nsteps 32 + rtol 1e-06 rk_type 0 order 5 acc 3 t 7.5 dsm 7.6586e-08 dsm_est 1.02588e-09 nsteps 17 + rtol 1e-06 rk_type 0 order 5 acc 3 t 8 dsm 4.14322e-07 dsm_est 2.56944e-10 nsteps 13 + rtol 1e-06 rk_type 0 order 5 acc 3 t 8.5 dsm 2.50606e-07 dsm_est 7.50375e-09 nsteps 9 + rtol 1e-06 rk_type 0 order 5 acc 3 t 9 dsm 1.33343e-07 dsm_est 3.79527e-09 nsteps 7 + rtol 1e-06 rk_type 0 order 5 acc 3 t 9.5 dsm 1.44237e-07 dsm_est 1.06042e-08 nsteps 6 + rtol 1e-06 rk_type 0 order 5 acc 3 t 10 dsm 1.34853e-07 dsm_est 1.51614e-08 nsteps 6 diff --git a/test/unit_tests/arkode/CXX_serial/ark_test_accumerror_kpr.cpp b/test/unit_tests/arkode/CXX_serial/ark_test_accumerror_kpr.cpp new file mode 100644 index 0000000000..4a7cd7535e --- /dev/null +++ b/test/unit_tests/arkode/CXX_serial/ark_test_accumerror_kpr.cpp @@ -0,0 +1,725 @@ +/* ---------------------------------------------------------------- + * Programmer(s): Daniel R. Reynolds @ SMU + * ---------------------------------------------------------------- + * SUNDIALS Copyright Start + * Copyright (c) 2002-2024, Lawrence Livermore National Security + * and Southern Methodist University. + * All rights reserved. + * + * See the top-level LICENSE and NOTICE files for details. + * + * SPDX-License-Identifier: BSD-3-Clause + * SUNDIALS Copyright End + * ---------------------------------------------------------------- + * Routine to test the accumulated temporal error estimation + * approaches from ARKStep and ERKStep. Uses a nonlinear + * Kvaerno-Prothero-Robinson ODE test problem with analytical + * solution, + * + * [u]' = [ G e ] [(u^2-p-1)/(2u)] + [ p'(t)/(2u) ] + * [v] [ e -1 ] [(v^2-q-2)/(2v)] [ q'(t)/(2v) ] + * + * where p(t) = cos(t), and q(t) = cos(omega*t*(1+exp(-(t-2)^2))). + * + * This problem has analytical solution given by + * u(t) = sqrt(2+p(t)), v(t) = sqrt(2+q(t)). + * We use the parameters: e = 0.1 and G = -10 [default] + * + * The stiffness of the problem is essentially determined + * by G, for |G| > 50 it is "stiff" and ideally suited to an + * implicit method. + * + * Coupling between the two components is determined by e, with + * coupling strength proportional to |e|. + * + * The "fast" variable, v, oscillates at a frequency "omega" times + * faster than u. + * + * We partition the full time integration interval, 0 < t < 5, into + * Npart pieces, and run the accumulation test over each. + * + * We use either the ARKStep/DIRK/Newton/Dense solver (0) or + * ERKStep (1). Either defaults to using a 4th-order method. + * + * By default, all runs use temporal adaptivity; however, if the + * requested 'ord' command-line input is negative, we run with + * order |ord|, using fixed step sizes. + * + * The program should be run with arguments in the following order: + * $ a.out Npart ord method G e omega + * Not all arguments are required, but these must be omitted from + * end-to-beginning, i.e. any one of + * $ a.out Npart ord method G e + * $ a.out Npart ord method G + * $ a.out Npart ord method + * $ a.out Npart ord + * $ a.out Npart + * $ a.out + * are acceptable. We require: + * * method = {0, 1} + * * G < 0.0 + * * omega > 0.0 + * * Npart > 0 + * + * For either temporally adaptive (ord >= 0) or fixed-step (ord < 0) + * runs, we test a variety of tolerances/step sizes, and compare + * the true error at the end of each partition against the + * integrator-reported accumulated error estimate. + * ----------------------------------------------------------------*/ + +// Header files +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#if defined(SUNDIALS_EXTENDED_PRECISION) +#define GSYM "Lg" +#define ESYM "Le" +#define FSYM "Lf" +#else +#define GSYM "g" +#define ESYM "e" +#define FSYM "f" +#endif + +#define ZERO SUN_RCONST(0.0) +#define ONE SUN_RCONST(1.0) +#define TWO SUN_RCONST(2.0) + +using namespace std; + +// User data structure +struct UserData +{ + sunrealtype G; + sunrealtype e; + sunrealtype omega; + int Npart; +}; + +// User-supplied functions called by the solver +static int fn(sunrealtype t, N_Vector y, N_Vector ydot, void* user_data); +static int Jn(sunrealtype t, N_Vector y, N_Vector fy, SUNMatrix J, + void* user_data, N_Vector tmp1, N_Vector tmp2, N_Vector tmp3); + +// Private utility functions +static int adaptive_run(void* arkode_mem, N_Vector y, sunrealtype T0, + sunrealtype Tf, int rk_type, int order, UserData& udata); +static int fixed_run(void* arkode_mem, N_Vector y, sunrealtype T0, + sunrealtype Tf, int rk_type, int order, UserData& udata); +static sunrealtype p(sunrealtype t); +static sunrealtype q(sunrealtype t, UserData& udata); +static sunrealtype pdot(sunrealtype t); +static sunrealtype qdot(sunrealtype t, UserData& udata); +static sunrealtype utrue(sunrealtype t); +static sunrealtype vtrue(sunrealtype t, UserData& udata); +static int Ytrue(sunrealtype t, N_Vector y, UserData& udata); +static int computeErrorWeights(N_Vector ycur, N_Vector weight, sunrealtype rtol, + sunrealtype atol, N_Vector vtemp); +static int check_retval(void* returnvalue, const char* funcname, int opt); + +// Main Program +int main(int argc, char* argv[]) +{ + // general problem parameters + sunrealtype T0 = SUN_RCONST(0.0); // initial time + sunrealtype Tf = SUN_RCONST(5.0); // final time + sunindextype NEQ = 2; // number of dependent vars. + int rk_type = 1; // type of RK method [DIRK=0, ERK=1] + int order = 4; // order of accuracy for RK method + sunbooleantype adaptive = SUNTRUE; // adaptive vs fixed-step run + + // general problem variables + int retval; // reusable error-checking flag + N_Vector y = NULL; // empty vector for the computed solution + void* arkode_mem = NULL; // empty ARKODE memory structure + SUNMatrix A = NULL; // empty system matrix + SUNLinearSolver LS = NULL; // empty system linear solver object + UserData udata; // user-data structure + udata.G = SUN_RCONST(-10.0); // stiffness parameter + udata.e = SUN_RCONST(0.1); // coupling strength + udata.omega = SUN_RCONST(5.0); // time scale ratio + udata.Npart = 20; // partition size + + // + // Initialization + // + + // Retrieve the command-line options: Npart ord method G e omega + if (argc > 1) udata.Npart = atoi(argv[1]); + if (argc > 2) order = atoi(argv[2]); + if (argc > 3) rk_type = atoi(argv[3]); + if (argc > 4) udata.G = SUNStrToReal(argv[4]); + if (argc > 5) udata.e = SUNStrToReal(argv[5]); + if (argc > 6) udata.omega = SUNStrToReal(argv[6]); + + // Check arguments for validity + // 0 <= rk_type <= 1 + // G < 0.0 + // omega > 0.0 + // Npart > 0 + if ((rk_type < 0) || (rk_type > 1)) + { + cerr << "ERROR: RK type be an integer in {0,1} \n"; + return (-1); + } + if (udata.G >= ZERO) + { + cerr << "ERROR: G must be a negative real number\n"; + return (-1); + } + if (udata.omega <= ZERO) + { + cerr << "ERROR: omega must be a positive real number\n"; + return (-1); + } + if (udata.Npart < 1) + { + cerr << "ERROR: Npart must be a positive integer\n"; + return (-1); + } + + // Handle adaptive run vs order-of-convergence run + if (order < 0) + { + adaptive = SUNFALSE; + order = abs(order); + } + if (order == 0) order = 4; + + // Initial problem output (and set implicit solver tolerances as needed) + cout << "\nAccumulated error estimation test (Nonlinear " + "Kvaerno-Prothero-Robinson problem):\n"; + cout << " time domain: (" << T0 << "," << Tf << "]\n"; + cout << " partition size = " << udata.Npart << endl; + cout << " G = " << udata.G << endl; + cout << " e = " << udata.e << endl; + cout << " omega = " << udata.omega << endl; + if (rk_type == 0) { cout << " DIRK solver, order = " << order << endl; } + else if (rk_type == 1) + { + cout << " ERK solver, order = " << order << endl; + } + + // + // Problem Setup + // + + // Create SUNDIALS context + sundials::Context ctx; + + // Create and initialize serial vector for the solution + y = N_VNew_Serial(NEQ, ctx); + if (check_retval((void*)y, "N_VNew_Serial", 0)) return 1; + retval = Ytrue(T0, y, udata); + if (check_retval(&retval, "Ytrue", 1)) return 1; + + // Initialize ARKStep or ERKStep. + if (rk_type == 0) + { // DIRK method + + arkode_mem = ARKStepCreate(NULL, fn, T0, y, ctx); + if (check_retval((void*)arkode_mem, "ARKStepCreate", 0)) return 1; + + // Initialize/attach linear solvers (if required) + A = SUNDenseMatrix(NEQ, NEQ, ctx); + if (check_retval((void*)A, "SUNDenseMatrix", 0)) return 1; + LS = SUNLinSol_Dense(y, A, ctx); + if (check_retval((void*)LS, "SUNLinSol_Dense", 0)) return 1; + retval = ARKodeSetLinearSolver(arkode_mem, LS, A); + if (check_retval(&retval, "ARKodeSetLinearSolver", 1)) return (1); + retval = ARKodeSetJacFn(arkode_mem, Jn); + if (check_retval(&retval, "ARKodeSetJacFn", 1)) return 1; + + // Set desired solver order + retval = ARKodeSetOrder(arkode_mem, order); + if (check_retval(&retval, "ARKodeSetOrder", 1)) return 1; + + // Set the user data pointer + retval = ARKodeSetUserData(arkode_mem, (void*)&udata); + if (check_retval(&retval, "ARKodeSetUserData", 1)) return 1; + } + else + { // ERK method + + arkode_mem = ERKStepCreate(fn, T0, y, ctx); + if (check_retval((void*)arkode_mem, "ERKStepCreate", 0)) return 1; + + // Set maximum stepsize for ERK run + retval = ARKodeSetMaxStep(arkode_mem, ONE / abs(udata.G)); + if (check_retval(&retval, "ARKodeSetMaxStep", 1)) return (1); + + // Set desired solver order + retval = ARKodeSetOrder(arkode_mem, order); + if (check_retval(&retval, "ARKodeSetOrder", 1)) return 1; + + // Set the user data pointer + retval = ARKodeSetUserData(arkode_mem, (void*)&udata); + if (check_retval(&retval, "ARKodeSetUserData", 1)) return 1; + } + + // Integrate ODE, based on run type + if (adaptive) + { + retval = adaptive_run(arkode_mem, y, T0, Tf, rk_type, order, udata); + if (check_retval(&retval, "adaptive_run", 1)) return 1; + } + else + { + retval = fixed_run(arkode_mem, y, T0, Tf, rk_type, order, udata); + if (check_retval(&retval, "fixed_run", 1)) return 1; + } + + // Clean up and return + ARKodeFree(&arkode_mem); + if (LS != NULL) SUNLinSolFree(LS); // free system linear solver + if (A != NULL) SUNMatDestroy(A); // free system matrix + N_VDestroy(y); // Free y vector + return 0; +} + +//------------------------------ +// Functions called by the solver +//------------------------------ + +static int fn(sunrealtype t, N_Vector y, N_Vector ydot, void* user_data) +{ + UserData* udata = (UserData*)user_data; + sunrealtype* ydata = N_VGetArrayPointer(y); + sunrealtype* dydata = N_VGetArrayPointer(ydot); + const sunrealtype u = ydata[0]; + const sunrealtype v = ydata[1]; + sunrealtype tmp1, tmp2; + + // fill in the RHS function: + // [G e]*[(-2+u^2-p(t))/(2*u)] + [pdot(t)/(2u)] + // [e -1] [(-2+v^2-s(t))/(2*v)] [qdot(t)/(2v)] + tmp1 = (-TWO + u * u - p(t)) / (TWO * u); + tmp2 = (-TWO + v * v - q(t, *udata)) / (TWO * v); + dydata[0] = udata->G * tmp1 + udata->e * tmp2 + pdot(t) / (TWO * u); + dydata[1] = udata->e * tmp1 - tmp2 + qdot(t, *udata) / (TWO * v); + + // Return with success + return 0; +} + +static int Jn(sunrealtype t, N_Vector y, N_Vector fy, SUNMatrix J, + void* user_data, N_Vector tmp1, N_Vector tmp2, N_Vector tmp3) +{ + UserData* udata = (UserData*)user_data; + sunrealtype* ydata = N_VGetArrayPointer(y); + const sunrealtype u = ydata[0]; + const sunrealtype v = ydata[1]; + sunrealtype t11, t22; + + // fill in the Jacobian: + // [G e]*[1-(u^2-p(t)-2)/(2*u^2), 0] + [-r'(t)/(2*u^2), 0] + // [e -1] [0, 1-(v^2-s(t)-2)/(2*v^2)] [0, -s'(t)/(2*v^2)] + t11 = ONE - (u * u - p(t) - TWO) / (TWO * u * u); + t22 = ONE - (v * v - q(t, *udata) - TWO) / (TWO * v * v); + SM_ELEMENT_D(J, 0, 0) = udata->G * t11 - pdot(t) / (TWO * u * u); + SM_ELEMENT_D(J, 0, 1) = udata->e * t22; + SM_ELEMENT_D(J, 1, 0) = udata->e * t11; + SM_ELEMENT_D(J, 1, 1) = -t22 - qdot(t, *udata) / (TWO * v * v); + + // Return with success + return 0; +} + +//------------------------------ +// Private helper functions +//------------------------------ + +static int adaptive_run(void* arkode_mem, N_Vector y, sunrealtype T0, + sunrealtype Tf, int rk_type, int order, UserData& udata) +{ + // Reused variables + int retval; + sunrealtype t; + sunrealtype hpart = (Tf - T0) / udata.Npart; + sunrealtype abstol = SUN_RCONST(1.e-12); + vector rtols = {SUN_RCONST(1.e-2), SUN_RCONST(1.e-4), + SUN_RCONST(1.e-6)}; + vector accum_types = {ARK_ACCUMERROR_MAX, ARK_ACCUMERROR_SUM, + ARK_ACCUMERROR_AVG}; + vector dsm(udata.Npart); + vector dsm_est(udata.Npart); + vector Nsteps(udata.Npart); + sunrealtype* ydata = N_VGetArrayPointer(y); + + // Loop over tolerances + cout << "\nAdaptive-step runs:\n"; + for (size_t irtol = 0; irtol < rtols.size(); irtol++) + { + // Loop over accumulation types + for (size_t iaccum = 0; iaccum < accum_types.size(); iaccum++) + { + // Loop over partition + for (int ipart = 0; ipart < udata.Npart; ipart++) + { + // Reset integrator for this run, and evolve over partition interval + t = T0 + ipart * hpart; + retval = Ytrue(t, y, udata); + if (check_retval(&retval, "Ytrue", 1)) return 1; + if (rk_type == 0) + { // DIRK + retval = ARKStepReInit(arkode_mem, NULL, fn, t, y); + if (check_retval(&retval, "ARKStepReInit", 1)) return 1; + retval = ARKodeSetAccumulatedErrorType(arkode_mem, accum_types[iaccum]); + if (check_retval(&retval, "ARKodeSetAccumulatedErrorType", 1)) + return 1; + retval = ARKodeResetAccumulatedError(arkode_mem); + if (check_retval(&retval, "ARKodeResetAccumulatedError", 1)) return 1; + retval = ARKodeSStolerances(arkode_mem, rtols[irtol], abstol); + if (check_retval(&retval, "ARKodeSStolerances", 1)) return 1; + retval = ARKodeSetStopTime(arkode_mem, t + hpart); + if (check_retval(&retval, "ARKodeSetStopTime", 1)) return 1; + retval = ARKodeSetMaxNumSteps(arkode_mem, 1000000); + if (check_retval(&retval, "ARKodeSetMaxNumSteps", 1)) return (1); + retval = ARKodeEvolve(arkode_mem, t + hpart, y, &t, ARK_NORMAL); + if (check_retval(&retval, "ARKodeEvolve", 1)) break; + retval = ARKodeGetAccumulatedError(arkode_mem, &(dsm_est[ipart])); + if (check_retval(&retval, "ARKodeGetAccumulatedError", 1)) break; + retval = ARKodeGetNumSteps(arkode_mem, &(Nsteps[ipart])); + if (check_retval(&retval, "ARKodeGetNumSteps", 1)) break; + } + else + { // ERK + retval = ERKStepReInit(arkode_mem, fn, t, y); + if (check_retval(&retval, "ERKStepReInit", 1)) return 1; + retval = ARKodeSetAccumulatedErrorType(arkode_mem, accum_types[iaccum]); + if (check_retval(&retval, "ARKodeSetAccumulatedErrorType", 1)) + return 1; + retval = ARKodeResetAccumulatedError(arkode_mem); + if (check_retval(&retval, "ARKodeResetAccumulatedError", 1)) return 1; + retval = ARKodeSStolerances(arkode_mem, rtols[irtol], abstol); + if (check_retval(&retval, "ARKodeSStolerances", 1)) return 1; + retval = ARKodeSetStopTime(arkode_mem, t + hpart); + if (check_retval(&retval, "ARKodeSetStopTime", 1)) return 1; + retval = ARKodeSetMaxNumSteps(arkode_mem, 1000000); + if (check_retval(&retval, "ARKodeSetMaxNumSteps", 1)) return (1); + retval = ARKodeEvolve(arkode_mem, t + hpart, y, &t, ARK_NORMAL); + if (check_retval(&retval, "ARKodeEvolve", 1)) break; + retval = ARKodeGetAccumulatedError(arkode_mem, &(dsm_est[ipart])); + if (check_retval(&retval, "ARKodeGetAccumulatedError", 1)) break; + retval = ARKodeGetNumSteps(arkode_mem, &(Nsteps[ipart])); + if (check_retval(&retval, "ARKodeGetNumSteps", 1)) break; + } + + // Compute/print solution error + sunrealtype udsm = abs(ydata[0] - utrue(t)) / + (abstol + rtols[irtol] * abs(utrue(t))); + sunrealtype vdsm = abs(ydata[1] - vtrue(t, udata)) / + (abstol + rtols[irtol] * abs(vtrue(t, udata))); + dsm[ipart] = rtols[irtol] * sqrt(0.5 * (udsm * udsm + vdsm * vdsm)); + cout << " rtol " << rtols[irtol] << " rk_type " << rk_type + << " order " << order << " acc " << accum_types[iaccum] << " t " + << t << " dsm " << dsm[ipart] << " dsm_est " << dsm_est[ipart] + << " nsteps " << Nsteps[ipart] << endl; + } + } + } + + return (0); +} + +static int fixed_run(void* arkode_mem, N_Vector y, sunrealtype T0, + sunrealtype Tf, int rk_type, int order, UserData& udata) +{ + // local variables + int retval; + sunrealtype hpart = (Tf - T0) / udata.Npart; + long int nsteps2; + sunrealtype t, t2; + sunrealtype reltol = SUN_RCONST(1.e-9); + sunrealtype abstol = SUN_RCONST(1.e-12); + N_Vector y2 = N_VClone(y); + N_Vector ewt = N_VClone(y); + N_Vector vtemp = N_VClone(y); + + // Set array of fixed step sizes to use, storage for corresponding errors/orders + sunrealtype hmax = (Tf - T0) / 1000; + if (rk_type == 1) hmax = min(hmax, ONE / abs(udata.G)); + vector hvals = {hmax, hmax / 4, hmax / 16, hmax / 64}; + vector accum_types = {ARK_ACCUMERROR_MAX, ARK_ACCUMERROR_SUM, + ARK_ACCUMERROR_AVG}; + vector dsm(udata.Npart); + vector dsm_est(udata.Npart); + vector Nsteps(udata.Npart); + sunrealtype* ydata = N_VGetArrayPointer(y); + + // Loop over step sizes + cout << "\nFixed-step runs:\n"; + for (size_t ih = 0; ih < hvals.size(); ih++) + { + // Loop over built-in accumulation types + for (size_t iaccum = 0; iaccum < accum_types.size(); iaccum++) + { + // Loop over partition + for (int ipart = 0; ipart < udata.Npart; ipart++) + { + // Reset integrator for this run, and evolve over partition interval + t = T0 + ipart * hpart; + retval = Ytrue(t, y, udata); + if (check_retval(&retval, "Ytrue", 1)) return 1; + if (rk_type == 0) + { // DIRK + retval = ARKStepReInit(arkode_mem, NULL, fn, t, y); + if (check_retval(&retval, "ARKStepReInit", 1)) return 1; + retval = ARKodeSetAccumulatedErrorType(arkode_mem, accum_types[iaccum]); + if (check_retval(&retval, "ARKodeSetAccumulatedErrorType", 1)) + return 1; + retval = ARKodeResetAccumulatedError(arkode_mem); + if (check_retval(&retval, "ARKodeResetAccumulatedError", 1)) return 1; + retval = ARKodeSetFixedStep(arkode_mem, hvals[ih]); + if (check_retval(&retval, "ARKodeSetFixedStep", 1)) return 1; + retval = ARKodeSetMaxNumSteps(arkode_mem, 1000000); + if (check_retval(&retval, "ARKodeSetMaxNumSteps", 1)) return (1); + retval = ARKodeSetStopTime(arkode_mem, t + hpart); + if (check_retval(&retval, "ARKodeSetStopTime", 1)) return 1; + retval = ARKodeSStolerances(arkode_mem, reltol, abstol); + if (check_retval(&retval, "ARKodeSStolerances", 1)) return 1; + retval = ARKodeSetJacEvalFrequency(arkode_mem, 1); + if (check_retval(&retval, "ARKodeSetJacEvalFrequency", 1)) return 1; + retval = ARKodeSetLSetupFrequency(arkode_mem, 1); + if (check_retval(&retval, "ARKodeSetLSetupFrequency", 1)) return 1; + retval = ARKodeSetMaxNonlinIters(arkode_mem, 20); + if (check_retval(&retval, "ARKodeSetMaxNonlinIters", 1)) return 1; + retval = ARKodeEvolve(arkode_mem, t + hpart, y, &t, ARK_NORMAL); + if (check_retval(&retval, "ARKodeEvolve", 1)) break; + retval = ARKodeGetAccumulatedError(arkode_mem, &(dsm_est[ipart])); + if (check_retval(&retval, "ARKodeGetAccumulatedError", 1)) break; + retval = ARKodeGetNumSteps(arkode_mem, &(Nsteps[ipart])); + if (check_retval(&retval, "ARKodeGetNumSteps", 1)) break; + } + else + { // ERK + retval = ERKStepReInit(arkode_mem, fn, t, y); + if (check_retval(&retval, "ERKStepReInit", 1)) return 1; + retval = ARKodeSetAccumulatedErrorType(arkode_mem, accum_types[iaccum]); + if (check_retval(&retval, "ARKodeSetAccumulatedErrorType", 1)) + return 1; + retval = ARKodeResetAccumulatedError(arkode_mem); + if (check_retval(&retval, "ARKodeResetAccumulatedError", 1)) return 1; + retval = ARKodeSetFixedStep(arkode_mem, hvals[ih]); + if (check_retval(&retval, "ARKodeSetFixedStep", 1)) return 1; + retval = ARKodeSetMaxNumSteps(arkode_mem, 1000000); + if (check_retval(&retval, "ARKodeSetMaxNumSteps", 1)) return (1); + retval = ARKodeSStolerances(arkode_mem, reltol, abstol); + if (check_retval(&retval, "ARKodeSStolerances", 1)) return 1; + retval = ARKodeSetStopTime(arkode_mem, t + hpart); + if (check_retval(&retval, "ARKodeSetStopTime", 1)) return 1; + retval = ARKodeEvolve(arkode_mem, t + hpart, y, &t, ARK_NORMAL); + if (check_retval(&retval, "ARKodeEvolve", 1)) break; + retval = ARKodeGetAccumulatedError(arkode_mem, &(dsm_est[ipart])); + if (check_retval(&retval, "ARKodeGetAccumulatedError", 1)) break; + retval = ARKodeGetNumSteps(arkode_mem, &(Nsteps[ipart])); + if (check_retval(&retval, "ARKodeGetNumSteps", 1)) break; + } + + // Compute/print solution error + sunrealtype udsm = abs(ydata[0] - utrue(t)) / + (abstol + reltol * abs(utrue(t))); + sunrealtype vdsm = abs(ydata[1] - vtrue(t, udata)) / + (abstol + reltol * abs(vtrue(t, udata))); + dsm[ipart] = reltol * sqrt(0.5 * (udsm * udsm + vdsm * vdsm)); + cout << " h " << hvals[ih] << " rk_type " << rk_type << " order " + << order << " acc " << accum_types[iaccum] << " t " << t + << " dsm " << dsm[ipart] << " dsm_est " << dsm_est[ipart] + << " nsteps " << Nsteps[ipart] << endl; + } + } + + // Test double-step error estimator + + // Loop over partition + for (int ipart = 0; ipart < udata.Npart; ipart++) + { + // Reset integrator for this run, and evolve over partition interval + t = t2 = T0 + ipart * hpart; + retval = Ytrue(t, y, udata); + if (check_retval(&retval, "Ytrue", 1)) return 1; + retval = Ytrue(t2, y2, udata); + if (check_retval(&retval, "Ytrue", 1)) return 1; + if (rk_type == 0) + { // DIRK + retval = ARKStepReInit(arkode_mem, NULL, fn, t, y); + if (check_retval(&retval, "ARKStepReInit", 1)) return 1; + retval = ARKodeSetAccumulatedErrorType(arkode_mem, ARK_ACCUMERROR_NONE); + if (check_retval(&retval, "ARKodeSetAccumulatedErrorType", 1)) return 1; + retval = ARKodeSetFixedStep(arkode_mem, hvals[ih]); + if (check_retval(&retval, "ARKodeSetFixedStep", 1)) return 1; + retval = ARKodeSetMaxNumSteps(arkode_mem, 1000000); + if (check_retval(&retval, "ARKodeSetMaxNumSteps", 1)) return (1); + retval = ARKodeSetStopTime(arkode_mem, t + hpart); + if (check_retval(&retval, "ARKodeSetStopTime", 1)) return 1; + retval = ARKodeSStolerances(arkode_mem, reltol, abstol); + if (check_retval(&retval, "ARKodeSStolerances", 1)) return 1; + retval = ARKodeSetJacEvalFrequency(arkode_mem, 1); + if (check_retval(&retval, "ARKodeSetJacEvalFrequency", 1)) return 1; + retval = ARKodeSetLSetupFrequency(arkode_mem, 1); + if (check_retval(&retval, "ARKodeSetLSetupFrequency", 1)) return 1; + retval = ARKodeSetMaxNonlinIters(arkode_mem, 20); + if (check_retval(&retval, "ARKodeSetMaxNonlinIters", 1)) return 1; + retval = ARKodeEvolve(arkode_mem, t + hpart, y, &t, ARK_NORMAL); + if (check_retval(&retval, "ARKodeEvolve", 1)) break; + retval = ARKodeGetNumSteps(arkode_mem, &(Nsteps[ipart])); + if (check_retval(&retval, "ARKodeGetNumSteps", 1)) break; + + retval = ARKStepReInit(arkode_mem, NULL, fn, t2, y2); + if (check_retval(&retval, "ARKStepReInit", 1)) return 1; + retval = ARKodeSetFixedStep(arkode_mem, 2.0 * hvals[ih]); + if (check_retval(&retval, "ARKodeSetFixedStep", 1)) return 1; + retval = ARKodeSetStopTime(arkode_mem, t2 + hpart); + if (check_retval(&retval, "ARKodeSetStopTime", 1)) return 1; + retval = ARKodeEvolve(arkode_mem, t2 + hpart, y2, &t2, ARK_NORMAL); + if (check_retval(&retval, "ARKodeEvolve", 1)) break; + retval = ARKodeGetNumSteps(arkode_mem, &nsteps2); + if (check_retval(&retval, "ARKodeGetNumSteps", 1)) break; + } + else + { // ERK + retval = ERKStepReInit(arkode_mem, fn, t, y); + if (check_retval(&retval, "ERKStepReInit", 1)) return 1; + retval = ARKodeSetAccumulatedErrorType(arkode_mem, ARK_ACCUMERROR_NONE); + if (check_retval(&retval, "ARKodeSetAccumulatedErrorType", 1)) return 1; + retval = ARKodeSetFixedStep(arkode_mem, hvals[ih]); + if (check_retval(&retval, "ARKodeSetFixedStep", 1)) return 1; + retval = ARKodeSetMaxNumSteps(arkode_mem, 1000000); + if (check_retval(&retval, "ARKodeSetMaxNumSteps", 1)) return (1); + retval = ARKodeSetStopTime(arkode_mem, t + hpart); + if (check_retval(&retval, "ARKodeSetStopTime", 1)) return 1; + retval = ARKodeSStolerances(arkode_mem, reltol, abstol); + if (check_retval(&retval, "ARKodeSStolerances", 1)) return 1; + retval = ARKodeEvolve(arkode_mem, t + hpart, y, &t, ARK_NORMAL); + if (check_retval(&retval, "ARKodeEvolve", 1)) break; + retval = ARKodeGetNumSteps(arkode_mem, &(Nsteps[ipart])); + if (check_retval(&retval, "ARKodeGetNumSteps", 1)) break; + + retval = ERKStepReInit(arkode_mem, fn, t2, y2); + if (check_retval(&retval, "ERKStepReInit", 1)) return 1; + retval = ARKodeSetFixedStep(arkode_mem, 2.0 * hvals[ih]); + if (check_retval(&retval, "ARKodeSetFixedStep", 1)) return 1; + retval = ARKodeSetStopTime(arkode_mem, t2 + hpart); + if (check_retval(&retval, "ARKodeSetStopTime", 1)) return 1; + retval = ARKodeEvolve(arkode_mem, t2 + hpart, y2, &t2, ARK_NORMAL); + if (check_retval(&retval, "ARKodeEvolve", 1)) break; + retval = ARKodeGetNumSteps(arkode_mem, &nsteps2); + if (check_retval(&retval, "ARKodeGetNumSteps", 1)) break; + } + retval = computeErrorWeights(y2, ewt, reltol, abstol, vtemp); + if (check_retval(&retval, "computeErrorWeights", 1)) break; + N_VLinearSum(ONE, y2, -ONE, y, y2); + dsm_est[ipart] = reltol * N_VWrmsNorm(y2, ewt); + Nsteps[ipart] += nsteps2; + sunrealtype udsm = abs(ydata[0] - utrue(t)) / + (abstol + reltol * abs(utrue(t))); + sunrealtype vdsm = abs(ydata[1] - vtrue(t, udata)) / + (abstol + reltol * abs(vtrue(t, udata))); + dsm[ipart] = reltol * sqrt(0.5 * (udsm * udsm + vdsm * vdsm)); + cout << " h " << hvals[ih] << " rk_type " << rk_type << " order " + << order << " acc " << 2 << " t " << t << " dsm " << dsm[ipart] + << " dsm_est " << dsm_est[ipart] << " nsteps " << Nsteps[ipart] + << endl; + } + } + + N_VDestroy(y2); + N_VDestroy(ewt); + return (0); +} + +static sunrealtype p(sunrealtype t) { return (cos(t)); } + +static sunrealtype q(sunrealtype t, UserData& udata) +{ + return (cos(udata.omega * t * (ONE + exp(-(t - 2) * (t - 2))))); +} + +static sunrealtype pdot(sunrealtype t) { return (-sin(t)); } + +static sunrealtype qdot(sunrealtype t, UserData& udata) +{ + return (-sin(udata.omega * t * (ONE + exp(-(t - 2) * (t - 2)))) * udata.omega * + (ONE + exp(-(t - 2) * (t - 2)) - + t * 2 * (t - 2) * (exp(-(t - 2) * (t - 2))))); +} + +static sunrealtype utrue(sunrealtype t) { return (SUNRsqrt(TWO + p(t))); } + +static sunrealtype vtrue(sunrealtype t, UserData& udata) +{ + return (SUNRsqrt(TWO + q(t, udata))); +} + +static int Ytrue(sunrealtype t, N_Vector y, UserData& udata) +{ + sunrealtype* ydata = N_VGetArrayPointer(y); + ydata[0] = utrue(t); + ydata[1] = vtrue(t, udata); + return (0); +} + +static int computeErrorWeights(N_Vector ycur, N_Vector weight, sunrealtype rtol, + sunrealtype atol, N_Vector vtemp) +{ + N_VAbs(ycur, vtemp); + N_VScale(rtol, vtemp, vtemp); + N_VAddConst(vtemp, atol, vtemp); + N_VInv(vtemp, weight); + return (0); +} + +/* Check function return value... + opt == 0 means SUNDIALS function allocates memory so check if + returned NULL pointer + opt == 1 means SUNDIALS function returns a retval so check if + retval < 0 + opt == 2 means function allocates memory so check if returned + NULL pointer +*/ +static int check_retval(void* returnvalue, const char* funcname, int opt) +{ + int* retval; + + // Check if SUNDIALS function returned NULL pointer - no memory allocated + if (opt == 0 && returnvalue == NULL) + { + fprintf(stderr, "\nSUNDIALS_ERROR: %s() failed - returned NULL pointer\n\n", + funcname); + return 1; + } + + // Check if retval < 0 + else if (opt == 1) + { + retval = (int*)returnvalue; + if (*retval < 0) + { + fprintf(stderr, "\nSUNDIALS_ERROR: %s() failed with retval = %d\n\n", + funcname, *retval); + return 1; + } + } + + // Check if function returned NULL pointer - no memory allocated + else if (opt == 2 && returnvalue == NULL) + { + fprintf(stderr, "\nMEMORY_ERROR: %s() failed - returned NULL pointer\n\n", + funcname); + return 1; + } + + return 0; +} + +//---- end of file ---- diff --git a/test/unit_tests/arkode/CXX_serial/ark_test_accumerror_kpr_20_-4_1.out b/test/unit_tests/arkode/CXX_serial/ark_test_accumerror_kpr_20_-4_1.out new file mode 100644 index 0000000000..0ddc51a414 --- /dev/null +++ b/test/unit_tests/arkode/CXX_serial/ark_test_accumerror_kpr_20_-4_1.out @@ -0,0 +1,330 @@ + +Accumulated error estimation test (Nonlinear Kvaerno-Prothero-Robinson problem): + time domain: (0,5] + partition size = 20 + G = -10 + e = 0.1 + omega = 5 + ERK solver, order = 4 + +Fixed-step runs: + h 0.005 rk_type 1 order 4 acc 1 t 0.25 dsm 5.99625e-11 dsm_est 2.97934e-09 nsteps 50 + h 0.005 rk_type 1 order 4 acc 1 t 0.5 dsm 1.42974e-10 dsm_est 1.09464e-08 nsteps 50 + h 0.005 rk_type 1 order 4 acc 1 t 0.75 dsm 2.42719e-10 dsm_est 4.48851e-08 nsteps 50 + h 0.005 rk_type 1 order 4 acc 1 t 1 dsm 6.83162e-10 dsm_est 2.52438e-08 nsteps 50 + h 0.005 rk_type 1 order 4 acc 1 t 1.25 dsm 3.14281e-09 dsm_est 6.51615e-07 nsteps 50 + h 0.005 rk_type 1 order 4 acc 1 t 1.5 dsm 4.52762e-09 dsm_est 3.9027e-07 nsteps 50 + h 0.005 rk_type 1 order 4 acc 1 t 1.75 dsm 4.7305e-10 dsm_est 1.03348e-06 nsteps 50 + h 0.005 rk_type 1 order 4 acc 1 t 2 dsm 1.22724e-09 dsm_est 2.15168e-07 nsteps 50 + h 0.005 rk_type 1 order 4 acc 1 t 2.25 dsm 2.1725e-10 dsm_est 4.54458e-08 nsteps 50 + h 0.005 rk_type 1 order 4 acc 1 t 2.5 dsm 1.44845e-10 dsm_est 1.64155e-08 nsteps 50 + h 0.005 rk_type 1 order 4 acc 1 t 2.75 dsm 1.45894e-10 dsm_est 1.12159e-08 nsteps 50 + h 0.005 rk_type 1 order 4 acc 1 t 3 dsm 2.11123e-10 dsm_est 1.10902e-08 nsteps 50 + h 0.005 rk_type 1 order 4 acc 1 t 3.25 dsm 2.34671e-10 dsm_est 3.64366e-09 nsteps 50 + h 0.005 rk_type 1 order 4 acc 1 t 3.5 dsm 1.99557e-10 dsm_est 7.94986e-10 nsteps 50 + h 0.005 rk_type 1 order 4 acc 1 t 3.75 dsm 1.51624e-10 dsm_est 7.64317e-10 nsteps 50 + h 0.005 rk_type 1 order 4 acc 1 t 4 dsm 9.7978e-11 dsm_est 1.84333e-09 nsteps 50 + h 0.005 rk_type 1 order 4 acc 1 t 4.25 dsm 3.36113e-11 dsm_est 3.03774e-09 nsteps 50 + h 0.005 rk_type 1 order 4 acc 1 t 4.5 dsm 7.15711e-11 dsm_est 1.1807e-08 nsteps 50 + h 0.005 rk_type 1 order 4 acc 1 t 4.75 dsm 3.79788e-11 dsm_est 3.66885e-09 nsteps 50 + h 0.005 rk_type 1 order 4 acc 1 t 5 dsm 4.13058e-11 dsm_est 1.68612e-09 nsteps 50 + h 0.005 rk_type 1 order 4 acc 2 t 0.25 dsm 5.99625e-11 dsm_est 6.92498e-08 nsteps 50 + h 0.005 rk_type 1 order 4 acc 2 t 0.5 dsm 1.42974e-10 dsm_est 3.44716e-07 nsteps 50 + h 0.005 rk_type 1 order 4 acc 2 t 0.75 dsm 2.42719e-10 dsm_est 1.11167e-06 nsteps 50 + h 0.005 rk_type 1 order 4 acc 2 t 1 dsm 6.83162e-10 dsm_est 3.96873e-07 nsteps 50 + h 0.005 rk_type 1 order 4 acc 2 t 1.25 dsm 3.14281e-09 dsm_est 9.51778e-06 nsteps 50 + h 0.005 rk_type 1 order 4 acc 2 t 1.5 dsm 4.52762e-09 dsm_est 4.8884e-06 nsteps 50 + h 0.005 rk_type 1 order 4 acc 2 t 1.75 dsm 4.7305e-10 dsm_est 1.58084e-05 nsteps 50 + h 0.005 rk_type 1 order 4 acc 2 t 2 dsm 1.22724e-09 dsm_est 3.22447e-06 nsteps 50 + h 0.005 rk_type 1 order 4 acc 2 t 2.25 dsm 2.1725e-10 dsm_est 1.37158e-06 nsteps 50 + h 0.005 rk_type 1 order 4 acc 2 t 2.5 dsm 1.44845e-10 dsm_est 5.71622e-07 nsteps 50 + h 0.005 rk_type 1 order 4 acc 2 t 2.75 dsm 1.45894e-10 dsm_est 2.89412e-07 nsteps 50 + h 0.005 rk_type 1 order 4 acc 2 t 3 dsm 2.11123e-10 dsm_est 2.24322e-07 nsteps 50 + h 0.005 rk_type 1 order 4 acc 2 t 3.25 dsm 2.34671e-10 dsm_est 1.10202e-07 nsteps 50 + h 0.005 rk_type 1 order 4 acc 2 t 3.5 dsm 1.99557e-10 dsm_est 2.70653e-08 nsteps 50 + h 0.005 rk_type 1 order 4 acc 2 t 3.75 dsm 1.51624e-10 dsm_est 2.01726e-08 nsteps 50 + h 0.005 rk_type 1 order 4 acc 2 t 4 dsm 9.7978e-11 dsm_est 4.76316e-08 nsteps 50 + h 0.005 rk_type 1 order 4 acc 2 t 4.25 dsm 3.36113e-11 dsm_est 1.20904e-07 nsteps 50 + h 0.005 rk_type 1 order 4 acc 2 t 4.5 dsm 7.15711e-11 dsm_est 3.7071e-07 nsteps 50 + h 0.005 rk_type 1 order 4 acc 2 t 4.75 dsm 3.79788e-11 dsm_est 8.7779e-08 nsteps 50 + h 0.005 rk_type 1 order 4 acc 2 t 5 dsm 4.13058e-11 dsm_est 6.13145e-08 nsteps 50 + h 0.005 rk_type 1 order 4 acc 3 t 0.25 dsm 5.99625e-11 dsm_est 1.385e-09 nsteps 50 + h 0.005 rk_type 1 order 4 acc 3 t 0.5 dsm 1.42974e-10 dsm_est 6.89431e-09 nsteps 50 + h 0.005 rk_type 1 order 4 acc 3 t 0.75 dsm 2.42719e-10 dsm_est 2.22335e-08 nsteps 50 + h 0.005 rk_type 1 order 4 acc 3 t 1 dsm 6.83162e-10 dsm_est 7.93747e-09 nsteps 50 + h 0.005 rk_type 1 order 4 acc 3 t 1.25 dsm 3.14281e-09 dsm_est 1.90356e-07 nsteps 50 + h 0.005 rk_type 1 order 4 acc 3 t 1.5 dsm 4.52762e-09 dsm_est 9.7768e-08 nsteps 50 + h 0.005 rk_type 1 order 4 acc 3 t 1.75 dsm 4.7305e-10 dsm_est 3.16168e-07 nsteps 50 + h 0.005 rk_type 1 order 4 acc 3 t 2 dsm 1.22724e-09 dsm_est 6.44894e-08 nsteps 50 + h 0.005 rk_type 1 order 4 acc 3 t 2.25 dsm 2.1725e-10 dsm_est 2.74317e-08 nsteps 50 + h 0.005 rk_type 1 order 4 acc 3 t 2.5 dsm 1.44845e-10 dsm_est 1.14324e-08 nsteps 50 + h 0.005 rk_type 1 order 4 acc 3 t 2.75 dsm 1.45894e-10 dsm_est 5.78824e-09 nsteps 50 + h 0.005 rk_type 1 order 4 acc 3 t 3 dsm 2.11123e-10 dsm_est 4.48643e-09 nsteps 50 + h 0.005 rk_type 1 order 4 acc 3 t 3.25 dsm 2.34671e-10 dsm_est 2.20404e-09 nsteps 50 + h 0.005 rk_type 1 order 4 acc 3 t 3.5 dsm 1.99557e-10 dsm_est 5.41306e-10 nsteps 50 + h 0.005 rk_type 1 order 4 acc 3 t 3.75 dsm 1.51624e-10 dsm_est 4.03452e-10 nsteps 50 + h 0.005 rk_type 1 order 4 acc 3 t 4 dsm 9.7978e-11 dsm_est 9.52633e-10 nsteps 50 + h 0.005 rk_type 1 order 4 acc 3 t 4.25 dsm 3.36113e-11 dsm_est 2.41808e-09 nsteps 50 + h 0.005 rk_type 1 order 4 acc 3 t 4.5 dsm 7.15711e-11 dsm_est 7.4142e-09 nsteps 50 + h 0.005 rk_type 1 order 4 acc 3 t 4.75 dsm 3.79788e-11 dsm_est 1.75558e-09 nsteps 50 + h 0.005 rk_type 1 order 4 acc 3 t 5 dsm 4.13058e-11 dsm_est 1.22629e-09 nsteps 50 + h 0.005 rk_type 1 order 4 acc 2 t 0.25 dsm 5.99625e-11 dsm_est 9.19534e-10 nsteps 75 + h 0.005 rk_type 1 order 4 acc 2 t 0.5 dsm 1.42974e-10 dsm_est 2.10629e-09 nsteps 75 + h 0.005 rk_type 1 order 4 acc 2 t 0.75 dsm 2.42719e-10 dsm_est 3.82746e-09 nsteps 75 + h 0.005 rk_type 1 order 4 acc 2 t 1 dsm 6.83162e-10 dsm_est 1.03061e-08 nsteps 75 + h 0.005 rk_type 1 order 4 acc 2 t 1.25 dsm 3.14281e-09 dsm_est 4.33257e-08 nsteps 75 + h 0.005 rk_type 1 order 4 acc 2 t 1.5 dsm 4.52762e-09 dsm_est 6.98227e-08 nsteps 75 + h 0.005 rk_type 1 order 4 acc 2 t 1.75 dsm 4.7305e-10 dsm_est 3.66571e-09 nsteps 75 + h 0.005 rk_type 1 order 4 acc 2 t 2 dsm 1.22724e-09 dsm_est 1.87356e-08 nsteps 75 + h 0.005 rk_type 1 order 4 acc 2 t 2.25 dsm 2.1725e-10 dsm_est 3.03702e-09 nsteps 75 + h 0.005 rk_type 1 order 4 acc 2 t 2.5 dsm 1.44845e-10 dsm_est 2.22121e-09 nsteps 75 + h 0.005 rk_type 1 order 4 acc 2 t 2.75 dsm 1.45894e-10 dsm_est 2.22678e-09 nsteps 75 + h 0.005 rk_type 1 order 4 acc 2 t 3 dsm 2.11123e-10 dsm_est 3.23991e-09 nsteps 75 + h 0.005 rk_type 1 order 4 acc 2 t 3.25 dsm 2.34671e-10 dsm_est 3.61593e-09 nsteps 75 + h 0.005 rk_type 1 order 4 acc 2 t 3.5 dsm 1.99557e-10 dsm_est 3.07907e-09 nsteps 75 + h 0.005 rk_type 1 order 4 acc 2 t 3.75 dsm 1.51624e-10 dsm_est 2.34121e-09 nsteps 75 + h 0.005 rk_type 1 order 4 acc 2 t 4 dsm 9.7978e-11 dsm_est 1.51474e-09 nsteps 75 + h 0.005 rk_type 1 order 4 acc 2 t 4.25 dsm 3.36113e-11 dsm_est 5.09945e-10 nsteps 75 + h 0.005 rk_type 1 order 4 acc 2 t 4.5 dsm 7.15711e-11 dsm_est 1.10419e-09 nsteps 75 + h 0.005 rk_type 1 order 4 acc 2 t 4.75 dsm 3.79788e-11 dsm_est 5.88316e-10 nsteps 75 + h 0.005 rk_type 1 order 4 acc 2 t 5 dsm 4.13058e-11 dsm_est 6.25891e-10 nsteps 75 + h 0.00125 rk_type 1 order 4 acc 1 t 0.25 dsm 2.30499e-13 dsm_est 1.18706e-11 nsteps 200 + h 0.00125 rk_type 1 order 4 acc 1 t 0.5 dsm 5.68219e-13 dsm_est 4.29143e-11 nsteps 200 + h 0.00125 rk_type 1 order 4 acc 1 t 0.75 dsm 9.09327e-13 dsm_est 1.75788e-10 nsteps 200 + h 0.00125 rk_type 1 order 4 acc 1 t 1 dsm 2.66412e-12 dsm_est 1.00941e-10 nsteps 200 + h 0.00125 rk_type 1 order 4 acc 1 t 1.25 dsm 1.30178e-11 dsm_est 2.55862e-09 nsteps 200 + h 0.00125 rk_type 1 order 4 acc 1 t 1.5 dsm 1.73534e-11 dsm_est 1.64905e-09 nsteps 200 + h 0.00125 rk_type 1 order 4 acc 1 t 1.75 dsm 3.44384e-12 dsm_est 4.05424e-09 nsteps 200 + h 0.00125 rk_type 1 order 4 acc 1 t 2 dsm 4.73982e-12 dsm_est 8.44242e-10 nsteps 200 + h 0.00125 rk_type 1 order 4 acc 1 t 2.25 dsm 8.24836e-13 dsm_est 1.78198e-10 nsteps 200 + h 0.00125 rk_type 1 order 4 acc 1 t 2.5 dsm 5.58183e-13 dsm_est 6.41367e-11 nsteps 200 + h 0.00125 rk_type 1 order 4 acc 1 t 2.75 dsm 5.66294e-13 dsm_est 4.38146e-11 nsteps 200 + h 0.00125 rk_type 1 order 4 acc 1 t 3 dsm 8.06614e-13 dsm_est 4.34752e-11 nsteps 200 + h 0.00125 rk_type 1 order 4 acc 1 t 3.25 dsm 8.98387e-13 dsm_est 1.416e-11 nsteps 200 + h 0.00125 rk_type 1 order 4 acc 1 t 3.5 dsm 7.63217e-13 dsm_est 3.10184e-12 nsteps 200 + h 0.00125 rk_type 1 order 4 acc 1 t 3.75 dsm 5.78309e-13 dsm_est 2.99367e-12 nsteps 200 + h 0.00125 rk_type 1 order 4 acc 1 t 4 dsm 3.75531e-13 dsm_est 7.27428e-12 nsteps 200 + h 0.00125 rk_type 1 order 4 acc 1 t 4.25 dsm 1.33194e-13 dsm_est 1.19044e-11 nsteps 200 + h 0.00125 rk_type 1 order 4 acc 1 t 4.5 dsm 2.44986e-13 dsm_est 4.62152e-11 nsteps 200 + h 0.00125 rk_type 1 order 4 acc 1 t 4.75 dsm 1.41286e-13 dsm_est 1.51237e-11 nsteps 200 + h 0.00125 rk_type 1 order 4 acc 1 t 5 dsm 1.73009e-13 dsm_est 6.57848e-12 nsteps 200 + h 0.00125 rk_type 1 order 4 acc 2 t 0.25 dsm 2.30499e-13 dsm_est 1.08204e-09 nsteps 200 + h 0.00125 rk_type 1 order 4 acc 2 t 0.5 dsm 5.68219e-13 dsm_est 5.40888e-09 nsteps 200 + h 0.00125 rk_type 1 order 4 acc 2 t 0.75 dsm 9.09327e-13 dsm_est 1.7413e-08 nsteps 200 + h 0.00125 rk_type 1 order 4 acc 2 t 1 dsm 2.66412e-12 dsm_est 6.10198e-09 nsteps 200 + h 0.00125 rk_type 1 order 4 acc 2 t 1.25 dsm 1.30178e-11 dsm_est 1.49252e-07 nsteps 200 + h 0.00125 rk_type 1 order 4 acc 2 t 1.5 dsm 1.73534e-11 dsm_est 7.5991e-08 nsteps 200 + h 0.00125 rk_type 1 order 4 acc 2 t 1.75 dsm 3.44384e-12 dsm_est 2.47716e-07 nsteps 200 + h 0.00125 rk_type 1 order 4 acc 2 t 2 dsm 4.73982e-12 dsm_est 4.99807e-08 nsteps 200 + h 0.00125 rk_type 1 order 4 acc 2 t 2.25 dsm 8.24836e-13 dsm_est 2.14752e-08 nsteps 200 + h 0.00125 rk_type 1 order 4 acc 2 t 2.5 dsm 5.58183e-13 dsm_est 8.93029e-09 nsteps 200 + h 0.00125 rk_type 1 order 4 acc 2 t 2.75 dsm 5.66294e-13 dsm_est 4.52416e-09 nsteps 200 + h 0.00125 rk_type 1 order 4 acc 2 t 3 dsm 8.06614e-13 dsm_est 3.502e-09 nsteps 200 + h 0.00125 rk_type 1 order 4 acc 2 t 3.25 dsm 8.98387e-13 dsm_est 1.71624e-09 nsteps 200 + h 0.00125 rk_type 1 order 4 acc 2 t 3.5 dsm 7.63217e-13 dsm_est 4.19654e-10 nsteps 200 + h 0.00125 rk_type 1 order 4 acc 2 t 3.75 dsm 5.78309e-13 dsm_est 3.14069e-10 nsteps 200 + h 0.00125 rk_type 1 order 4 acc 2 t 4 dsm 3.75531e-13 dsm_est 7.43405e-10 nsteps 200 + h 0.00125 rk_type 1 order 4 acc 2 t 4.25 dsm 1.33194e-13 dsm_est 1.89465e-09 nsteps 200 + h 0.00125 rk_type 1 order 4 acc 2 t 4.5 dsm 2.44986e-13 dsm_est 5.80293e-09 nsteps 200 + h 0.00125 rk_type 1 order 4 acc 2 t 4.75 dsm 1.41286e-13 dsm_est 1.36602e-09 nsteps 200 + h 0.00125 rk_type 1 order 4 acc 2 t 5 dsm 1.73009e-13 dsm_est 9.5065e-10 nsteps 200 + h 0.00125 rk_type 1 order 4 acc 3 t 0.25 dsm 2.30499e-13 dsm_est 5.41022e-12 nsteps 200 + h 0.00125 rk_type 1 order 4 acc 3 t 0.5 dsm 5.68219e-13 dsm_est 2.70444e-11 nsteps 200 + h 0.00125 rk_type 1 order 4 acc 3 t 0.75 dsm 9.09327e-13 dsm_est 8.70648e-11 nsteps 200 + h 0.00125 rk_type 1 order 4 acc 3 t 1 dsm 2.66412e-12 dsm_est 3.05099e-11 nsteps 200 + h 0.00125 rk_type 1 order 4 acc 3 t 1.25 dsm 1.30178e-11 dsm_est 7.46262e-10 nsteps 200 + h 0.00125 rk_type 1 order 4 acc 3 t 1.5 dsm 1.73534e-11 dsm_est 3.79955e-10 nsteps 200 + h 0.00125 rk_type 1 order 4 acc 3 t 1.75 dsm 3.44384e-12 dsm_est 1.23858e-09 nsteps 200 + h 0.00125 rk_type 1 order 4 acc 3 t 2 dsm 4.73982e-12 dsm_est 2.49903e-10 nsteps 200 + h 0.00125 rk_type 1 order 4 acc 3 t 2.25 dsm 8.24836e-13 dsm_est 1.07376e-10 nsteps 200 + h 0.00125 rk_type 1 order 4 acc 3 t 2.5 dsm 5.58183e-13 dsm_est 4.46515e-11 nsteps 200 + h 0.00125 rk_type 1 order 4 acc 3 t 2.75 dsm 5.66294e-13 dsm_est 2.26208e-11 nsteps 200 + h 0.00125 rk_type 1 order 4 acc 3 t 3 dsm 8.06614e-13 dsm_est 1.751e-11 nsteps 200 + h 0.00125 rk_type 1 order 4 acc 3 t 3.25 dsm 8.98387e-13 dsm_est 8.58119e-12 nsteps 200 + h 0.00125 rk_type 1 order 4 acc 3 t 3.5 dsm 7.63217e-13 dsm_est 2.09827e-12 nsteps 200 + h 0.00125 rk_type 1 order 4 acc 3 t 3.75 dsm 5.78309e-13 dsm_est 1.57035e-12 nsteps 200 + h 0.00125 rk_type 1 order 4 acc 3 t 4 dsm 3.75531e-13 dsm_est 3.71703e-12 nsteps 200 + h 0.00125 rk_type 1 order 4 acc 3 t 4.25 dsm 1.33194e-13 dsm_est 9.47327e-12 nsteps 200 + h 0.00125 rk_type 1 order 4 acc 3 t 4.5 dsm 2.44986e-13 dsm_est 2.90146e-11 nsteps 200 + h 0.00125 rk_type 1 order 4 acc 3 t 4.75 dsm 1.41286e-13 dsm_est 6.83008e-12 nsteps 200 + h 0.00125 rk_type 1 order 4 acc 3 t 5 dsm 1.73009e-13 dsm_est 4.75325e-12 nsteps 200 + h 0.00125 rk_type 1 order 4 acc 2 t 0.25 dsm 2.30499e-13 dsm_est 3.47846e-12 nsteps 300 + h 0.00125 rk_type 1 order 4 acc 2 t 0.5 dsm 5.68219e-13 dsm_est 8.44621e-12 nsteps 300 + h 0.00125 rk_type 1 order 4 acc 2 t 0.75 dsm 9.09327e-13 dsm_est 1.38911e-11 nsteps 300 + h 0.00125 rk_type 1 order 4 acc 2 t 1 dsm 2.66412e-12 dsm_est 3.99292e-11 nsteps 300 + h 0.00125 rk_type 1 order 4 acc 2 t 1.25 dsm 1.30178e-11 dsm_est 1.91091e-10 nsteps 300 + h 0.00125 rk_type 1 order 4 acc 2 t 1.5 dsm 1.73534e-11 dsm_est 2.61959e-10 nsteps 300 + h 0.00125 rk_type 1 order 4 acc 2 t 1.75 dsm 3.44384e-12 dsm_est 4.28383e-11 nsteps 300 + h 0.00125 rk_type 1 order 4 acc 2 t 2 dsm 4.73982e-12 dsm_est 7.1306e-11 nsteps 300 + h 0.00125 rk_type 1 order 4 acc 2 t 2.25 dsm 8.24836e-13 dsm_est 1.31816e-11 nsteps 300 + h 0.00125 rk_type 1 order 4 acc 2 t 2.5 dsm 5.58183e-13 dsm_est 8.4007e-12 nsteps 300 + h 0.00125 rk_type 1 order 4 acc 2 t 2.75 dsm 5.66294e-13 dsm_est 8.47988e-12 nsteps 300 + h 0.00125 rk_type 1 order 4 acc 2 t 3 dsm 8.06614e-13 dsm_est 1.22473e-11 nsteps 300 + h 0.00125 rk_type 1 order 4 acc 2 t 3.25 dsm 8.98387e-13 dsm_est 1.35837e-11 nsteps 300 + h 0.00125 rk_type 1 order 4 acc 2 t 3.5 dsm 7.63217e-13 dsm_est 1.15437e-11 nsteps 300 + h 0.00125 rk_type 1 order 4 acc 2 t 3.75 dsm 5.78309e-13 dsm_est 8.76917e-12 nsteps 300 + h 0.00125 rk_type 1 order 4 acc 2 t 4 dsm 3.75531e-13 dsm_est 5.66133e-12 nsteps 300 + h 0.00125 rk_type 1 order 4 acc 2 t 4.25 dsm 1.33194e-13 dsm_est 1.9304e-12 nsteps 300 + h 0.00125 rk_type 1 order 4 acc 2 t 4.5 dsm 2.44986e-13 dsm_est 4.1717e-12 nsteps 300 + h 0.00125 rk_type 1 order 4 acc 2 t 4.75 dsm 1.41286e-13 dsm_est 2.17896e-12 nsteps 300 + h 0.00125 rk_type 1 order 4 acc 2 t 5 dsm 1.73009e-13 dsm_est 2.38734e-12 nsteps 300 + h 0.0003125 rk_type 1 order 4 acc 1 t 0.25 dsm 9.97977e-16 dsm_est 4.66004e-14 nsteps 800 + h 0.0003125 rk_type 1 order 4 acc 1 t 0.5 dsm 7.34738e-15 dsm_est 1.67783e-13 nsteps 800 + h 0.0003125 rk_type 1 order 4 acc 1 t 0.75 dsm 1.89479e-14 dsm_est 6.87079e-13 nsteps 800 + h 0.0003125 rk_type 1 order 4 acc 1 t 1 dsm 6.41345e-15 dsm_est 3.96662e-13 nsteps 800 + h 0.0003125 rk_type 1 order 4 acc 1 t 1.25 dsm 1.49538e-13 dsm_est 1.00006e-11 nsteps 801 + h 0.0003125 rk_type 1 order 4 acc 1 t 1.5 dsm 1.0257e-13 dsm_est 6.56125e-12 nsteps 801 + h 0.0003125 rk_type 1 order 4 acc 1 t 1.75 dsm 4.74681e-14 dsm_est 1.58483e-11 nsteps 801 + h 0.0003125 rk_type 1 order 4 acc 1 t 2 dsm 3.28771e-14 dsm_est 3.30065e-12 nsteps 801 + h 0.0003125 rk_type 1 order 4 acc 1 t 2.25 dsm 2.08777e-13 dsm_est 6.96642e-13 nsteps 800 + h 0.0003125 rk_type 1 order 4 acc 1 t 2.5 dsm 1.03256e-14 dsm_est 2.50524e-13 nsteps 800 + h 0.0003125 rk_type 1 order 4 acc 1 t 2.75 dsm 1.44079e-14 dsm_est 1.71146e-13 nsteps 800 + h 0.0003125 rk_type 1 order 4 acc 1 t 3 dsm 6.86653e-14 dsm_est 1.69952e-13 nsteps 800 + h 0.0003125 rk_type 1 order 4 acc 1 t 3.25 dsm 4.56716e-14 dsm_est 5.52408e-14 nsteps 800 + h 0.0003125 rk_type 1 order 4 acc 1 t 3.5 dsm 1.14798e-14 dsm_est 1.21147e-14 nsteps 800 + h 0.0003125 rk_type 1 order 4 acc 1 t 3.75 dsm 1.10427e-14 dsm_est 1.17036e-14 nsteps 800 + h 0.0003125 rk_type 1 order 4 acc 1 t 4 dsm 5.31806e-14 dsm_est 2.84886e-14 nsteps 800 + h 0.0003125 rk_type 1 order 4 acc 1 t 4.25 dsm 2.08119e-13 dsm_est 4.65384e-14 nsteps 801 + h 0.0003125 rk_type 1 order 4 acc 1 t 4.5 dsm 1.57233e-14 dsm_est 1.80608e-13 nsteps 801 + h 0.0003125 rk_type 1 order 4 acc 1 t 4.75 dsm 1.39902e-13 dsm_est 5.98529e-14 nsteps 801 + h 0.0003125 rk_type 1 order 4 acc 1 t 5 dsm 7.63042e-14 dsm_est 2.56897e-14 nsteps 801 + h 0.0003125 rk_type 1 order 4 acc 2 t 0.25 dsm 9.97977e-16 dsm_est 1.6907e-11 nsteps 800 + h 0.0003125 rk_type 1 order 4 acc 2 t 0.5 dsm 7.34738e-15 dsm_est 8.45809e-11 nsteps 800 + h 0.0003125 rk_type 1 order 4 acc 2 t 0.75 dsm 1.89479e-14 dsm_est 2.72242e-10 nsteps 800 + h 0.0003125 rk_type 1 order 4 acc 2 t 1 dsm 6.41345e-15 dsm_est 9.49565e-11 nsteps 800 + h 0.0003125 rk_type 1 order 4 acc 2 t 1.25 dsm 1.49538e-13 dsm_est 2.33397e-09 nsteps 801 + h 0.0003125 rk_type 1 order 4 acc 2 t 1.5 dsm 1.0257e-13 dsm_est 1.18555e-09 nsteps 801 + h 0.0003125 rk_type 1 order 4 acc 2 t 1.75 dsm 4.74681e-14 dsm_est 3.87341e-09 nsteps 801 + h 0.0003125 rk_type 1 order 4 acc 2 t 2 dsm 3.28771e-14 dsm_est 7.79395e-10 nsteps 801 + h 0.0003125 rk_type 1 order 4 acc 2 t 2.25 dsm 2.08777e-13 dsm_est 3.3572e-10 nsteps 800 + h 0.0003125 rk_type 1 order 4 acc 2 t 2.5 dsm 1.03256e-14 dsm_est 1.39527e-10 nsteps 800 + h 0.0003125 rk_type 1 order 4 acc 2 t 2.75 dsm 1.44079e-14 dsm_est 7.06925e-11 nsteps 800 + h 0.0003125 rk_type 1 order 4 acc 2 t 3 dsm 6.86653e-14 dsm_est 5.47055e-11 nsteps 800 + h 0.0003125 rk_type 1 order 4 acc 2 t 3.25 dsm 4.56716e-14 dsm_est 2.67951e-11 nsteps 800 + h 0.0003125 rk_type 1 order 4 acc 2 t 3.5 dsm 1.14798e-14 dsm_est 6.54805e-12 nsteps 800 + h 0.0003125 rk_type 1 order 4 acc 2 t 3.75 dsm 1.10427e-14 dsm_est 4.9065e-12 nsteps 800 + h 0.0003125 rk_type 1 order 4 acc 2 t 4 dsm 5.31806e-14 dsm_est 1.16127e-11 nsteps 800 + h 0.0003125 rk_type 1 order 4 acc 2 t 4.25 dsm 2.08119e-13 dsm_est 2.96268e-11 nsteps 801 + h 0.0003125 rk_type 1 order 4 acc 2 t 4.5 dsm 1.57233e-14 dsm_est 9.07089e-11 nsteps 801 + h 0.0003125 rk_type 1 order 4 acc 2 t 4.75 dsm 1.39902e-13 dsm_est 2.13237e-11 nsteps 801 + h 0.0003125 rk_type 1 order 4 acc 2 t 5 dsm 7.63042e-14 dsm_est 1.48242e-11 nsteps 801 + h 0.0003125 rk_type 1 order 4 acc 3 t 0.25 dsm 9.97977e-16 dsm_est 2.11337e-14 nsteps 800 + h 0.0003125 rk_type 1 order 4 acc 3 t 0.5 dsm 7.34738e-15 dsm_est 1.05726e-13 nsteps 800 + h 0.0003125 rk_type 1 order 4 acc 3 t 0.75 dsm 1.89479e-14 dsm_est 3.40303e-13 nsteps 800 + h 0.0003125 rk_type 1 order 4 acc 3 t 1 dsm 6.41345e-15 dsm_est 1.18696e-13 nsteps 800 + h 0.0003125 rk_type 1 order 4 acc 3 t 1.25 dsm 1.49538e-13 dsm_est 2.91746e-12 nsteps 801 + h 0.0003125 rk_type 1 order 4 acc 3 t 1.5 dsm 1.0257e-13 dsm_est 1.48193e-12 nsteps 801 + h 0.0003125 rk_type 1 order 4 acc 3 t 1.75 dsm 4.74681e-14 dsm_est 4.84176e-12 nsteps 801 + h 0.0003125 rk_type 1 order 4 acc 3 t 2 dsm 3.28771e-14 dsm_est 9.74244e-13 nsteps 801 + h 0.0003125 rk_type 1 order 4 acc 3 t 2.25 dsm 2.08777e-13 dsm_est 4.1965e-13 nsteps 800 + h 0.0003125 rk_type 1 order 4 acc 3 t 2.5 dsm 1.03256e-14 dsm_est 1.74409e-13 nsteps 800 + h 0.0003125 rk_type 1 order 4 acc 3 t 2.75 dsm 1.44079e-14 dsm_est 8.83656e-14 nsteps 800 + h 0.0003125 rk_type 1 order 4 acc 3 t 3 dsm 6.86653e-14 dsm_est 6.83819e-14 nsteps 800 + h 0.0003125 rk_type 1 order 4 acc 3 t 3.25 dsm 4.56716e-14 dsm_est 3.34939e-14 nsteps 800 + h 0.0003125 rk_type 1 order 4 acc 3 t 3.5 dsm 1.14798e-14 dsm_est 8.18506e-15 nsteps 800 + h 0.0003125 rk_type 1 order 4 acc 3 t 3.75 dsm 1.10427e-14 dsm_est 6.13312e-15 nsteps 800 + h 0.0003125 rk_type 1 order 4 acc 3 t 4 dsm 5.31806e-14 dsm_est 1.45159e-14 nsteps 800 + h 0.0003125 rk_type 1 order 4 acc 3 t 4.25 dsm 2.08119e-13 dsm_est 3.70335e-14 nsteps 801 + h 0.0003125 rk_type 1 order 4 acc 3 t 4.5 dsm 1.57233e-14 dsm_est 1.13386e-13 nsteps 801 + h 0.0003125 rk_type 1 order 4 acc 3 t 4.75 dsm 1.39902e-13 dsm_est 2.66546e-14 nsteps 801 + h 0.0003125 rk_type 1 order 4 acc 3 t 5 dsm 7.63042e-14 dsm_est 1.85303e-14 nsteps 801 + h 0.0003125 rk_type 1 order 4 acc 2 t 0.25 dsm 9.97977e-16 dsm_est 1.35296e-14 nsteps 1200 + h 0.0003125 rk_type 1 order 4 acc 2 t 0.5 dsm 7.34738e-15 dsm_est 3.14131e-14 nsteps 1200 + h 0.0003125 rk_type 1 order 4 acc 2 t 0.75 dsm 1.89479e-14 dsm_est 6.96153e-14 nsteps 1200 + h 0.0003125 rk_type 1 order 4 acc 2 t 1 dsm 6.41345e-15 dsm_est 1.77682e-13 nsteps 1200 + h 0.0003125 rk_type 1 order 4 acc 2 t 1.25 dsm 1.49538e-13 dsm_est 5.92376e-13 nsteps 1201 + h 0.0003125 rk_type 1 order 4 acc 2 t 1.5 dsm 1.0257e-13 dsm_est 9.50139e-13 nsteps 1201 + h 0.0003125 rk_type 1 order 4 acc 2 t 1.75 dsm 4.74681e-14 dsm_est 1.5963e-13 nsteps 1201 + h 0.0003125 rk_type 1 order 4 acc 2 t 2 dsm 3.28771e-14 dsm_est 2.52198e-13 nsteps 1201 + h 0.0003125 rk_type 1 order 4 acc 2 t 2.25 dsm 2.08777e-13 dsm_est 3.31346e-13 nsteps 1200 + h 0.0003125 rk_type 1 order 4 acc 2 t 2.5 dsm 1.03256e-14 dsm_est 3.26259e-14 nsteps 1200 + h 0.0003125 rk_type 1 order 4 acc 2 t 2.75 dsm 1.44079e-14 dsm_est 3.69706e-14 nsteps 1200 + h 0.0003125 rk_type 1 order 4 acc 2 t 3 dsm 6.86653e-14 dsm_est 8.29842e-14 nsteps 1200 + h 0.0003125 rk_type 1 order 4 acc 2 t 3.25 dsm 4.56716e-14 dsm_est 7.57076e-14 nsteps 1200 + h 0.0003125 rk_type 1 order 4 acc 2 t 3.5 dsm 1.14798e-14 dsm_est 4.72639e-14 nsteps 1200 + h 0.0003125 rk_type 1 order 4 acc 2 t 3.75 dsm 1.10427e-14 dsm_est 3.43678e-14 nsteps 1200 + h 0.0003125 rk_type 1 order 4 acc 2 t 4 dsm 5.31806e-14 dsm_est 4.43107e-14 nsteps 1200 + h 0.0003125 rk_type 1 order 4 acc 2 t 4.25 dsm 2.08119e-13 dsm_est 3.19466e-13 nsteps 1201 + h 0.0003125 rk_type 1 order 4 acc 2 t 4.5 dsm 1.57233e-14 dsm_est 3.54399e-14 nsteps 1201 + h 0.0003125 rk_type 1 order 4 acc 2 t 4.75 dsm 1.39902e-13 dsm_est 2.1045e-13 nsteps 1201 + h 0.0003125 rk_type 1 order 4 acc 2 t 5 dsm 7.63042e-14 dsm_est 1.1047e-13 nsteps 1201 + h 7.8125e-05 rk_type 1 order 4 acc 1 t 0.25 dsm 1.20076e-14 dsm_est 1.82253e-16 nsteps 3200 + h 7.8125e-05 rk_type 1 order 4 acc 1 t 0.5 dsm 6.92895e-14 dsm_est 6.55669e-16 nsteps 3201 + h 7.8125e-05 rk_type 1 order 4 acc 1 t 0.75 dsm 7.1887e-14 dsm_est 2.68471e-15 nsteps 3200 + h 7.8125e-05 rk_type 1 order 4 acc 1 t 1 dsm 5.29714e-14 dsm_est 1.55185e-15 nsteps 3200 + h 7.8125e-05 rk_type 1 order 4 acc 1 t 1.25 dsm 4.54758e-13 dsm_est 3.90711e-14 nsteps 3201 + h 7.8125e-05 rk_type 1 order 4 acc 1 t 1.5 dsm 1.61784e-13 dsm_est 2.57413e-14 nsteps 3201 + h 7.8125e-05 rk_type 1 order 4 acc 1 t 1.75 dsm 1.4649e-13 dsm_est 6.1914e-14 nsteps 3201 + h 7.8125e-05 rk_type 1 order 4 acc 1 t 2 dsm 6.85301e-14 dsm_est 1.28969e-14 nsteps 3201 + h 7.8125e-05 rk_type 1 order 4 acc 1 t 2.25 dsm 3.74507e-13 dsm_est 2.72291e-15 nsteps 3201 + h 7.8125e-05 rk_type 1 order 4 acc 1 t 2.5 dsm 1.92671e-14 dsm_est 9.81217e-16 nsteps 3201 + h 7.8125e-05 rk_type 1 order 4 acc 1 t 2.75 dsm 1.93516e-14 dsm_est 6.71729e-16 nsteps 3201 + h 7.8125e-05 rk_type 1 order 4 acc 1 t 3 dsm 1.23711e-13 dsm_est 6.65622e-16 nsteps 3201 + h 7.8125e-05 rk_type 1 order 4 acc 1 t 3.25 dsm 8.16997e-14 dsm_est 2.16207e-16 nsteps 3201 + h 7.8125e-05 rk_type 1 order 4 acc 1 t 3.5 dsm 1.95956e-14 dsm_est 4.74185e-17 nsteps 3201 + h 7.8125e-05 rk_type 1 order 4 acc 1 t 3.75 dsm 2.16401e-14 dsm_est 4.58122e-17 nsteps 3201 + h 7.8125e-05 rk_type 1 order 4 acc 1 t 4 dsm 9.37664e-14 dsm_est 1.11469e-16 nsteps 3201 + h 7.8125e-05 rk_type 1 order 4 acc 1 t 4.25 dsm 2.10442e-13 dsm_est 1.82276e-16 nsteps 3201 + h 7.8125e-05 rk_type 1 order 4 acc 1 t 4.5 dsm 1.64627e-14 dsm_est 7.11037e-16 nsteps 3201 + h 7.8125e-05 rk_type 1 order 4 acc 1 t 4.75 dsm 1.39177e-13 dsm_est 2.35957e-16 nsteps 3201 + h 7.8125e-05 rk_type 1 order 4 acc 1 t 5 dsm 7.51104e-14 dsm_est 1.00425e-16 nsteps 3201 + h 7.8125e-05 rk_type 1 order 4 acc 2 t 0.25 dsm 1.20076e-14 dsm_est 2.64165e-13 nsteps 3200 + h 7.8125e-05 rk_type 1 order 4 acc 2 t 0.5 dsm 6.92895e-14 dsm_est 1.32181e-12 nsteps 3201 + h 7.8125e-05 rk_type 1 order 4 acc 2 t 0.75 dsm 7.1887e-14 dsm_est 4.25372e-12 nsteps 3200 + h 7.8125e-05 rk_type 1 order 4 acc 2 t 1 dsm 5.29714e-14 dsm_est 1.48185e-12 nsteps 3200 + h 7.8125e-05 rk_type 1 order 4 acc 2 t 1.25 dsm 4.54758e-13 dsm_est 3.64743e-11 nsteps 3201 + h 7.8125e-05 rk_type 1 order 4 acc 2 t 1.5 dsm 1.61784e-13 dsm_est 1.85159e-11 nsteps 3201 + h 7.8125e-05 rk_type 1 order 4 acc 2 t 1.75 dsm 1.4649e-13 dsm_est 6.05314e-11 nsteps 3201 + h 7.8125e-05 rk_type 1 order 4 acc 2 t 2 dsm 6.85301e-14 dsm_est 1.2171e-11 nsteps 3201 + h 7.8125e-05 rk_type 1 order 4 acc 2 t 2.25 dsm 3.74507e-13 dsm_est 5.24549e-12 nsteps 3201 + h 7.8125e-05 rk_type 1 order 4 acc 2 t 2.5 dsm 1.92671e-14 dsm_est 2.18076e-12 nsteps 3201 + h 7.8125e-05 rk_type 1 order 4 acc 2 t 2.75 dsm 1.93516e-14 dsm_est 1.10503e-12 nsteps 3201 + h 7.8125e-05 rk_type 1 order 4 acc 2 t 3 dsm 1.23711e-13 dsm_est 8.55102e-13 nsteps 3201 + h 7.8125e-05 rk_type 1 order 4 acc 2 t 3.25 dsm 8.16997e-14 dsm_est 4.18589e-13 nsteps 3201 + h 7.8125e-05 rk_type 1 order 4 acc 2 t 3.5 dsm 1.95956e-14 dsm_est 1.02298e-13 nsteps 3201 + h 7.8125e-05 rk_type 1 order 4 acc 2 t 3.75 dsm 2.16401e-14 dsm_est 7.6628e-14 nsteps 3201 + h 7.8125e-05 rk_type 1 order 4 acc 2 t 4 dsm 9.37664e-14 dsm_est 1.81659e-13 nsteps 3201 + h 7.8125e-05 rk_type 1 order 4 acc 2 t 4.25 dsm 2.10442e-13 dsm_est 4.62687e-13 nsteps 3201 + h 7.8125e-05 rk_type 1 order 4 acc 2 t 4.5 dsm 1.64627e-14 dsm_est 1.42144e-12 nsteps 3201 + h 7.8125e-05 rk_type 1 order 4 acc 2 t 4.75 dsm 1.39177e-13 dsm_est 3.32669e-13 nsteps 3201 + h 7.8125e-05 rk_type 1 order 4 acc 2 t 5 dsm 7.51104e-14 dsm_est 2.32583e-13 nsteps 3201 + h 7.8125e-05 rk_type 1 order 4 acc 3 t 0.25 dsm 1.20076e-14 dsm_est 8.25514e-17 nsteps 3200 + h 7.8125e-05 rk_type 1 order 4 acc 3 t 0.5 dsm 6.92895e-14 dsm_est 4.13064e-16 nsteps 3201 + h 7.8125e-05 rk_type 1 order 4 acc 3 t 0.75 dsm 7.1887e-14 dsm_est 1.32929e-15 nsteps 3200 + h 7.8125e-05 rk_type 1 order 4 acc 3 t 1 dsm 5.29714e-14 dsm_est 4.63079e-16 nsteps 3200 + h 7.8125e-05 rk_type 1 order 4 acc 3 t 1.25 dsm 4.54758e-13 dsm_est 1.13982e-14 nsteps 3201 + h 7.8125e-05 rk_type 1 order 4 acc 3 t 1.5 dsm 1.61784e-13 dsm_est 5.78623e-15 nsteps 3201 + h 7.8125e-05 rk_type 1 order 4 acc 3 t 1.75 dsm 1.4649e-13 dsm_est 1.89161e-14 nsteps 3201 + h 7.8125e-05 rk_type 1 order 4 acc 3 t 2 dsm 6.85301e-14 dsm_est 3.80343e-15 nsteps 3201 + h 7.8125e-05 rk_type 1 order 4 acc 3 t 2.25 dsm 3.74507e-13 dsm_est 1.63922e-15 nsteps 3201 + h 7.8125e-05 rk_type 1 order 4 acc 3 t 2.5 dsm 1.92671e-14 dsm_est 6.81488e-16 nsteps 3201 + h 7.8125e-05 rk_type 1 order 4 acc 3 t 2.75 dsm 1.93516e-14 dsm_est 3.45321e-16 nsteps 3201 + h 7.8125e-05 rk_type 1 order 4 acc 3 t 3 dsm 1.23711e-13 dsm_est 2.67219e-16 nsteps 3201 + h 7.8125e-05 rk_type 1 order 4 acc 3 t 3.25 dsm 8.16997e-14 dsm_est 1.30809e-16 nsteps 3201 + h 7.8125e-05 rk_type 1 order 4 acc 3 t 3.5 dsm 1.95956e-14 dsm_est 3.19683e-17 nsteps 3201 + h 7.8125e-05 rk_type 1 order 4 acc 3 t 3.75 dsm 2.16401e-14 dsm_est 2.39462e-17 nsteps 3201 + h 7.8125e-05 rk_type 1 order 4 acc 3 t 4 dsm 9.37664e-14 dsm_est 5.67685e-17 nsteps 3201 + h 7.8125e-05 rk_type 1 order 4 acc 3 t 4.25 dsm 2.10442e-13 dsm_est 1.4459e-16 nsteps 3201 + h 7.8125e-05 rk_type 1 order 4 acc 3 t 4.5 dsm 1.64627e-14 dsm_est 4.44199e-16 nsteps 3201 + h 7.8125e-05 rk_type 1 order 4 acc 3 t 4.75 dsm 1.39177e-13 dsm_est 1.03959e-16 nsteps 3201 + h 7.8125e-05 rk_type 1 order 4 acc 3 t 5 dsm 7.51104e-14 dsm_est 7.26822e-17 nsteps 3201 + h 7.8125e-05 rk_type 1 order 4 acc 2 t 0.25 dsm 1.20076e-14 dsm_est 9.70841e-15 nsteps 4800 + h 7.8125e-05 rk_type 1 order 4 acc 2 t 0.5 dsm 6.92895e-14 dsm_est 1.22494e-13 nsteps 4801 + h 7.8125e-05 rk_type 1 order 4 acc 2 t 0.75 dsm 7.1887e-14 dsm_est 1.01008e-13 nsteps 4801 + h 7.8125e-05 rk_type 1 order 4 acc 2 t 1 dsm 5.29714e-14 dsm_est 7.31368e-14 nsteps 4801 + h 7.8125e-05 rk_type 1 order 4 acc 2 t 1.25 dsm 4.54758e-13 dsm_est 7.05734e-13 nsteps 4801 + h 7.8125e-05 rk_type 1 order 4 acc 2 t 1.5 dsm 1.61784e-13 dsm_est 2.49851e-13 nsteps 4801 + h 7.8125e-05 rk_type 1 order 4 acc 2 t 1.75 dsm 1.4649e-13 dsm_est 2.2764e-13 nsteps 4801 + h 7.8125e-05 rk_type 1 order 4 acc 2 t 2 dsm 6.85301e-14 dsm_est 1.06912e-13 nsteps 4801 + h 7.8125e-05 rk_type 1 order 4 acc 2 t 2.25 dsm 3.74507e-13 dsm_est 1.85903e-15 nsteps 4802 + h 7.8125e-05 rk_type 1 order 4 acc 2 t 2.5 dsm 1.92671e-14 dsm_est 4.28748e-15 nsteps 4802 + h 7.8125e-05 rk_type 1 order 4 acc 2 t 2.75 dsm 1.93516e-14 dsm_est 3.17803e-15 nsteps 4802 + h 7.8125e-05 rk_type 1 order 4 acc 2 t 3 dsm 1.23711e-13 dsm_est 2.14064e-15 nsteps 4802 + h 7.8125e-05 rk_type 1 order 4 acc 2 t 3.25 dsm 8.16997e-14 dsm_est 9.8125e-16 nsteps 4802 + h 7.8125e-05 rk_type 1 order 4 acc 2 t 3.5 dsm 1.95956e-14 dsm_est 1.42241e-15 nsteps 4802 + h 7.8125e-05 rk_type 1 order 4 acc 2 t 3.75 dsm 2.16401e-14 dsm_est 9.52702e-16 nsteps 4802 + h 7.8125e-05 rk_type 1 order 4 acc 2 t 4 dsm 9.37664e-14 dsm_est 1.67292e-15 nsteps 4802 + h 7.8125e-05 rk_type 1 order 4 acc 2 t 4.25 dsm 2.10442e-13 dsm_est 5.74872e-16 nsteps 4802 + h 7.8125e-05 rk_type 1 order 4 acc 2 t 4.5 dsm 1.64627e-14 dsm_est 2.39534e-15 nsteps 4802 + h 7.8125e-05 rk_type 1 order 4 acc 2 t 4.75 dsm 1.39177e-13 dsm_est 1.10424e-15 nsteps 4802 + h 7.8125e-05 rk_type 1 order 4 acc 2 t 5 dsm 7.51104e-14 dsm_est 1.21712e-15 nsteps 4802 diff --git a/test/unit_tests/arkode/CXX_serial/ark_test_accumerror_kpr_20_2_0.out b/test/unit_tests/arkode/CXX_serial/ark_test_accumerror_kpr_20_2_0.out new file mode 100644 index 0000000000..8809b5e0a0 --- /dev/null +++ b/test/unit_tests/arkode/CXX_serial/ark_test_accumerror_kpr_20_2_0.out @@ -0,0 +1,190 @@ + +Accumulated error estimation test (Nonlinear Kvaerno-Prothero-Robinson problem): + time domain: (0,5] + partition size = 20 + G = -10 + e = 0.1 + omega = 5 + DIRK solver, order = 2 + +Adaptive-step runs: + rtol 0.01 rk_type 0 order 2 acc 1 t 0.25 dsm 5.77245e-05 dsm_est 0.00686971 nsteps 9 + rtol 0.01 rk_type 0 order 2 acc 1 t 0.5 dsm 0.00372257 dsm_est 0.00877859 nsteps 8 + rtol 0.01 rk_type 0 order 2 acc 1 t 0.75 dsm 0.000232425 dsm_est 0.0066976 nsteps 13 + rtol 0.01 rk_type 0 order 2 acc 1 t 1 dsm 0.00327055 dsm_est 0.00759421 nsteps 9 + rtol 0.01 rk_type 0 order 2 acc 1 t 1.25 dsm 0.00363058 dsm_est 0.00633487 nsteps 16 + rtol 0.01 rk_type 0 order 2 acc 1 t 1.5 dsm 0.00267076 dsm_est 0.00679482 nsteps 12 + rtol 0.01 rk_type 0 order 2 acc 1 t 1.75 dsm 0.00971976 dsm_est 0.00698823 nsteps 16 + rtol 0.01 rk_type 0 order 2 acc 1 t 2 dsm 0.000918207 dsm_est 0.00684032 nsteps 14 + rtol 0.01 rk_type 0 order 2 acc 1 t 2.25 dsm 0.0016944 dsm_est 0.00722321 nsteps 10 + rtol 0.01 rk_type 0 order 2 acc 1 t 2.5 dsm 0.0056199 dsm_est 0.00390805 nsteps 7 + rtol 0.01 rk_type 0 order 2 acc 1 t 2.75 dsm 0.00855479 dsm_est 0.00899318 nsteps 6 + rtol 0.01 rk_type 0 order 2 acc 1 t 3 dsm 0.0023308 dsm_est 0.00881185 nsteps 7 + rtol 0.01 rk_type 0 order 2 acc 1 t 3.25 dsm 0.000539467 dsm_est 0.00351937 nsteps 8 + rtol 0.01 rk_type 0 order 2 acc 1 t 3.5 dsm 0.000312605 dsm_est 0.00446438 nsteps 6 + rtol 0.01 rk_type 0 order 2 acc 1 t 3.75 dsm 0.00144605 dsm_est 0.00759178 nsteps 4 + rtol 0.01 rk_type 0 order 2 acc 1 t 4 dsm 0.00023147 dsm_est 0.0031488 nsteps 7 + rtol 0.01 rk_type 0 order 2 acc 1 t 4.25 dsm 0.00806953 dsm_est 0.00741572 nsteps 4 + rtol 0.01 rk_type 0 order 2 acc 1 t 4.5 dsm 0.000322019 dsm_est 0.00679423 nsteps 11 + rtol 0.01 rk_type 0 order 2 acc 1 t 4.75 dsm 0.00405487 dsm_est 0.00313156 nsteps 7 + rtol 0.01 rk_type 0 order 2 acc 1 t 5 dsm 0.000699178 dsm_est 0.0036148 nsteps 8 + rtol 0.01 rk_type 0 order 2 acc 2 t 0.25 dsm 5.77245e-05 dsm_est 0.0164981 nsteps 9 + rtol 0.01 rk_type 0 order 2 acc 2 t 0.5 dsm 0.00372257 dsm_est 0.0210208 nsteps 8 + rtol 0.01 rk_type 0 order 2 acc 2 t 0.75 dsm 0.000232425 dsm_est 0.0308702 nsteps 13 + rtol 0.01 rk_type 0 order 2 acc 2 t 1 dsm 0.00327055 dsm_est 0.0340018 nsteps 9 + rtol 0.01 rk_type 0 order 2 acc 2 t 1.25 dsm 0.00363058 dsm_est 0.045914 nsteps 16 + rtol 0.01 rk_type 0 order 2 acc 2 t 1.5 dsm 0.00267076 dsm_est 0.0507535 nsteps 12 + rtol 0.01 rk_type 0 order 2 acc 2 t 1.75 dsm 0.00971976 dsm_est 0.05629 nsteps 16 + rtol 0.01 rk_type 0 order 2 acc 2 t 2 dsm 0.000918207 dsm_est 0.0375381 nsteps 14 + rtol 0.01 rk_type 0 order 2 acc 2 t 2.25 dsm 0.0016944 dsm_est 0.031166 nsteps 10 + rtol 0.01 rk_type 0 order 2 acc 2 t 2.5 dsm 0.0056199 dsm_est 0.00967058 nsteps 7 + rtol 0.01 rk_type 0 order 2 acc 2 t 2.75 dsm 0.00855479 dsm_est 0.0140582 nsteps 6 + rtol 0.01 rk_type 0 order 2 acc 2 t 3 dsm 0.0023308 dsm_est 0.014547 nsteps 7 + rtol 0.01 rk_type 0 order 2 acc 2 t 3.25 dsm 0.000539467 dsm_est 0.0111796 nsteps 8 + rtol 0.01 rk_type 0 order 2 acc 2 t 3.5 dsm 0.000312605 dsm_est 0.00770553 nsteps 6 + rtol 0.01 rk_type 0 order 2 acc 2 t 3.75 dsm 0.00144605 dsm_est 0.00972643 nsteps 4 + rtol 0.01 rk_type 0 order 2 acc 2 t 4 dsm 0.00023147 dsm_est 0.00981914 nsteps 7 + rtol 0.01 rk_type 0 order 2 acc 2 t 4.25 dsm 0.00806953 dsm_est 0.0118304 nsteps 4 + rtol 0.01 rk_type 0 order 2 acc 2 t 4.5 dsm 0.000322019 dsm_est 0.0262973 nsteps 11 + rtol 0.01 rk_type 0 order 2 acc 2 t 4.75 dsm 0.00405487 dsm_est 0.00626689 nsteps 7 + rtol 0.01 rk_type 0 order 2 acc 2 t 5 dsm 0.000699178 dsm_est 0.0128716 nsteps 8 + rtol 0.01 rk_type 0 order 2 acc 3 t 0.25 dsm 5.77245e-05 dsm_est 0.00353036 nsteps 9 + rtol 0.01 rk_type 0 order 2 acc 3 t 0.5 dsm 0.00372257 dsm_est 0.00558255 nsteps 8 + rtol 0.01 rk_type 0 order 2 acc 3 t 0.75 dsm 0.000232425 dsm_est 0.00326237 nsteps 13 + rtol 0.01 rk_type 0 order 2 acc 3 t 1 dsm 0.00327055 dsm_est 0.00560468 nsteps 9 + rtol 0.01 rk_type 0 order 2 acc 3 t 1.25 dsm 0.00363058 dsm_est 0.00326167 nsteps 16 + rtol 0.01 rk_type 0 order 2 acc 3 t 1.5 dsm 0.00267076 dsm_est 0.00448671 nsteps 12 + rtol 0.01 rk_type 0 order 2 acc 3 t 1.75 dsm 0.00971976 dsm_est 0.00430156 nsteps 16 + rtol 0.01 rk_type 0 order 2 acc 3 t 2 dsm 0.000918207 dsm_est 0.00360429 nsteps 14 + rtol 0.01 rk_type 0 order 2 acc 3 t 2.25 dsm 0.0016944 dsm_est 0.00427241 nsteps 10 + rtol 0.01 rk_type 0 order 2 acc 3 t 2.5 dsm 0.0056199 dsm_est 0.0029018 nsteps 7 + rtol 0.01 rk_type 0 order 2 acc 3 t 2.75 dsm 0.00855479 dsm_est 0.00614645 nsteps 6 + rtol 0.01 rk_type 0 order 2 acc 3 t 3 dsm 0.0023308 dsm_est 0.00499894 nsteps 7 + rtol 0.01 rk_type 0 order 2 acc 3 t 3.25 dsm 0.000539467 dsm_est 0.00271774 nsteps 8 + rtol 0.01 rk_type 0 order 2 acc 3 t 3.5 dsm 0.000312605 dsm_est 0.0029728 nsteps 6 + rtol 0.01 rk_type 0 order 2 acc 3 t 3.75 dsm 0.00144605 dsm_est 0.00565195 nsteps 4 + rtol 0.01 rk_type 0 order 2 acc 3 t 4 dsm 0.00023147 dsm_est 0.00239782 nsteps 7 + rtol 0.01 rk_type 0 order 2 acc 3 t 4.25 dsm 0.00806953 dsm_est 0.00616552 nsteps 4 + rtol 0.01 rk_type 0 order 2 acc 3 t 4.5 dsm 0.000322019 dsm_est 0.00389097 nsteps 11 + rtol 0.01 rk_type 0 order 2 acc 3 t 4.75 dsm 0.00405487 dsm_est 0.00155112 nsteps 7 + rtol 0.01 rk_type 0 order 2 acc 3 t 5 dsm 0.000699178 dsm_est 0.00252209 nsteps 8 + rtol 0.0001 rk_type 0 order 2 acc 1 t 0.25 dsm 7.46709e-07 dsm_est 7.18663e-05 nsteps 49 + rtol 0.0001 rk_type 0 order 2 acc 1 t 0.5 dsm 6.50352e-05 dsm_est 7.49302e-05 nsteps 42 + rtol 0.0001 rk_type 0 order 2 acc 1 t 0.75 dsm 4.48379e-06 dsm_est 7.39118e-05 nsteps 84 + rtol 0.0001 rk_type 0 order 2 acc 1 t 1 dsm 3.76158e-05 dsm_est 7.93376e-05 nsteps 61 + rtol 0.0001 rk_type 0 order 2 acc 1 t 1.25 dsm 6.82164e-05 dsm_est 9.03489e-05 nsteps 110 + rtol 0.0001 rk_type 0 order 2 acc 1 t 1.5 dsm 3.68171e-05 dsm_est 8.51313e-05 nsteps 109 + rtol 0.0001 rk_type 0 order 2 acc 1 t 1.75 dsm 2.35133e-05 dsm_est 8.17961e-05 nsteps 136 + rtol 0.0001 rk_type 0 order 2 acc 1 t 2 dsm 1.61655e-05 dsm_est 6.74799e-05 nsteps 91 + rtol 0.0001 rk_type 0 order 2 acc 1 t 2.25 dsm 6.22229e-05 dsm_est 8.55795e-05 nsteps 65 + rtol 0.0001 rk_type 0 order 2 acc 1 t 2.5 dsm 4.95459e-05 dsm_est 9.95948e-05 nsteps 38 + rtol 0.0001 rk_type 0 order 2 acc 1 t 2.75 dsm 4.09894e-05 dsm_est 7.97659e-05 nsteps 35 + rtol 0.0001 rk_type 0 order 2 acc 1 t 3 dsm 3.51226e-05 dsm_est 9.83341e-05 nsteps 41 + rtol 0.0001 rk_type 0 order 2 acc 1 t 3.25 dsm 9.918e-06 dsm_est 7.80442e-05 nsteps 34 + rtol 0.0001 rk_type 0 order 2 acc 1 t 3.5 dsm 6.68205e-06 dsm_est 6.93297e-05 nsteps 29 + rtol 0.0001 rk_type 0 order 2 acc 1 t 3.75 dsm 1.12533e-05 dsm_est 7.07769e-05 nsteps 22 + rtol 0.0001 rk_type 0 order 2 acc 1 t 4 dsm 4.18856e-06 dsm_est 7.35665e-05 nsteps 31 + rtol 0.0001 rk_type 0 order 2 acc 1 t 4.25 dsm 5.65033e-05 dsm_est 9.50758e-05 nsteps 27 + rtol 0.0001 rk_type 0 order 2 acc 1 t 4.5 dsm 8.06381e-06 dsm_est 7.57142e-05 nsteps 60 + rtol 0.0001 rk_type 0 order 2 acc 1 t 4.75 dsm 3.08146e-05 dsm_est 7.53944e-05 nsteps 36 + rtol 0.0001 rk_type 0 order 2 acc 1 t 5 dsm 1.43844e-05 dsm_est 7.56604e-05 nsteps 37 + rtol 0.0001 rk_type 0 order 2 acc 2 t 0.25 dsm 7.46709e-07 dsm_est 0.00190862 nsteps 49 + rtol 0.0001 rk_type 0 order 2 acc 2 t 0.5 dsm 6.50352e-05 dsm_est 0.00204717 nsteps 42 + rtol 0.0001 rk_type 0 order 2 acc 2 t 0.75 dsm 4.48379e-06 dsm_est 0.00379996 nsteps 84 + rtol 0.0001 rk_type 0 order 2 acc 2 t 1 dsm 3.76158e-05 dsm_est 0.00364205 nsteps 61 + rtol 0.0001 rk_type 0 order 2 acc 2 t 1.25 dsm 6.82164e-05 dsm_est 0.00560546 nsteps 110 + rtol 0.0001 rk_type 0 order 2 acc 2 t 1.5 dsm 3.68171e-05 dsm_est 0.00560365 nsteps 109 + rtol 0.0001 rk_type 0 order 2 acc 2 t 1.75 dsm 2.35133e-05 dsm_est 0.00647595 nsteps 136 + rtol 0.0001 rk_type 0 order 2 acc 2 t 2 dsm 1.61655e-05 dsm_est 0.00463485 nsteps 91 + rtol 0.0001 rk_type 0 order 2 acc 2 t 2.25 dsm 6.22229e-05 dsm_est 0.00349003 nsteps 65 + rtol 0.0001 rk_type 0 order 2 acc 2 t 2.5 dsm 4.95459e-05 dsm_est 0.00168906 nsteps 38 + rtol 0.0001 rk_type 0 order 2 acc 2 t 2.75 dsm 4.09894e-05 dsm_est 0.00204891 nsteps 35 + rtol 0.0001 rk_type 0 order 2 acc 2 t 3 dsm 3.51226e-05 dsm_est 0.00157108 nsteps 41 + rtol 0.0001 rk_type 0 order 2 acc 2 t 3.25 dsm 9.918e-06 dsm_est 0.00168635 nsteps 34 + rtol 0.0001 rk_type 0 order 2 acc 2 t 3.5 dsm 6.68205e-06 dsm_est 0.00104605 nsteps 29 + rtol 0.0001 rk_type 0 order 2 acc 2 t 3.75 dsm 1.12533e-05 dsm_est 0.00113201 nsteps 22 + rtol 0.0001 rk_type 0 order 2 acc 2 t 4 dsm 4.18856e-06 dsm_est 0.00148082 nsteps 31 + rtol 0.0001 rk_type 0 order 2 acc 2 t 4.25 dsm 5.65033e-05 dsm_est 0.0013283 nsteps 27 + rtol 0.0001 rk_type 0 order 2 acc 2 t 4.5 dsm 8.06381e-06 dsm_est 0.00333997 nsteps 60 + rtol 0.0001 rk_type 0 order 2 acc 2 t 4.75 dsm 3.08146e-05 dsm_est 0.00136969 nsteps 36 + rtol 0.0001 rk_type 0 order 2 acc 2 t 5 dsm 1.43844e-05 dsm_est 0.00206727 nsteps 37 + rtol 0.0001 rk_type 0 order 2 acc 3 t 0.25 dsm 7.46709e-07 dsm_est 3.95038e-05 nsteps 49 + rtol 0.0001 rk_type 0 order 2 acc 3 t 0.5 dsm 6.50352e-05 dsm_est 4.6374e-05 nsteps 42 + rtol 0.0001 rk_type 0 order 2 acc 3 t 0.75 dsm 4.48379e-06 dsm_est 4.43011e-05 nsteps 84 + rtol 0.0001 rk_type 0 order 2 acc 3 t 1 dsm 3.76158e-05 dsm_est 5.97518e-05 nsteps 61 + rtol 0.0001 rk_type 0 order 2 acc 3 t 1.25 dsm 6.82164e-05 dsm_est 4.87769e-05 nsteps 110 + rtol 0.0001 rk_type 0 order 2 acc 3 t 1.5 dsm 3.68171e-05 dsm_est 5.35469e-05 nsteps 109 + rtol 0.0001 rk_type 0 order 2 acc 3 t 1.75 dsm 2.35133e-05 dsm_est 4.62728e-05 nsteps 136 + rtol 0.0001 rk_type 0 order 2 acc 3 t 2 dsm 1.61655e-05 dsm_est 5.09881e-05 nsteps 91 + rtol 0.0001 rk_type 0 order 2 acc 3 t 2.25 dsm 6.22229e-05 dsm_est 5.36889e-05 nsteps 65 + rtol 0.0001 rk_type 0 order 2 acc 3 t 2.5 dsm 4.95459e-05 dsm_est 5.23304e-05 nsteps 38 + rtol 0.0001 rk_type 0 order 2 acc 3 t 2.75 dsm 4.09894e-05 dsm_est 5.62503e-05 nsteps 35 + rtol 0.0001 rk_type 0 order 2 acc 3 t 3 dsm 3.51226e-05 dsm_est 4.33776e-05 nsteps 41 + rtol 0.0001 rk_type 0 order 2 acc 3 t 3.25 dsm 9.918e-06 dsm_est 5.1345e-05 nsteps 34 + rtol 0.0001 rk_type 0 order 2 acc 3 t 3.5 dsm 6.68205e-06 dsm_est 3.84131e-05 nsteps 29 + rtol 0.0001 rk_type 0 order 2 acc 3 t 3.75 dsm 1.12533e-05 dsm_est 5.1961e-05 nsteps 22 + rtol 0.0001 rk_type 0 order 2 acc 3 t 4 dsm 4.18856e-06 dsm_est 4.8569e-05 nsteps 31 + rtol 0.0001 rk_type 0 order 2 acc 3 t 4.25 dsm 5.65033e-05 dsm_est 4.99955e-05 nsteps 27 + rtol 0.0001 rk_type 0 order 2 acc 3 t 4.5 dsm 8.06381e-06 dsm_est 5.6039e-05 nsteps 60 + rtol 0.0001 rk_type 0 order 2 acc 3 t 4.75 dsm 3.08146e-05 dsm_est 3.95264e-05 nsteps 36 + rtol 0.0001 rk_type 0 order 2 acc 3 t 5 dsm 1.43844e-05 dsm_est 5.62992e-05 nsteps 37 + rtol 1e-06 rk_type 0 order 2 acc 1 t 0.25 dsm 5.66725e-09 dsm_est 7.18787e-07 nsteps 488 + rtol 1e-06 rk_type 0 order 2 acc 1 t 0.5 dsm 9.92276e-07 dsm_est 8.1602e-07 nsteps 403 + rtol 1e-06 rk_type 0 order 2 acc 1 t 0.75 dsm 8.0717e-08 dsm_est 7.2088e-07 nsteps 823 + rtol 1e-06 rk_type 0 order 2 acc 1 t 1 dsm 5.67858e-07 dsm_est 9.90249e-07 nsteps 596 + rtol 1e-06 rk_type 0 order 2 acc 1 t 1.25 dsm 1.03484e-06 dsm_est 7.69939e-07 nsteps 1091 + rtol 1e-06 rk_type 0 order 2 acc 1 t 1.5 dsm 5.45182e-07 dsm_est 9.21351e-07 nsteps 1080 + rtol 1e-06 rk_type 0 order 2 acc 1 t 1.75 dsm 3.61096e-07 dsm_est 8.11495e-07 nsteps 1337 + rtol 1e-06 rk_type 0 order 2 acc 1 t 2 dsm 2.2003e-07 dsm_est 6.89881e-07 nsteps 898 + rtol 1e-06 rk_type 0 order 2 acc 1 t 2.25 dsm 9.38782e-07 dsm_est 7.22168e-07 nsteps 635 + rtol 1e-06 rk_type 0 order 2 acc 1 t 2.5 dsm 5.20042e-07 dsm_est 7.8752e-07 nsteps 372 + rtol 1e-06 rk_type 0 order 2 acc 1 t 2.75 dsm 4.66825e-07 dsm_est 7.09276e-07 nsteps 354 + rtol 1e-06 rk_type 0 order 2 acc 1 t 3 dsm 3.30086e-07 dsm_est 7.18289e-07 nsteps 409 + rtol 1e-06 rk_type 0 order 2 acc 1 t 3.25 dsm 1.19548e-07 dsm_est 7.25689e-07 nsteps 320 + rtol 1e-06 rk_type 0 order 2 acc 1 t 3.5 dsm 4.13474e-08 dsm_est 7.16259e-07 nsteps 288 + rtol 1e-06 rk_type 0 order 2 acc 1 t 3.75 dsm 1.02293e-07 dsm_est 7.17021e-07 nsteps 225 + rtol 1e-06 rk_type 0 order 2 acc 1 t 4 dsm 3.98477e-08 dsm_est 7.20467e-07 nsteps 304 + rtol 1e-06 rk_type 0 order 2 acc 1 t 4.25 dsm 7.93335e-07 dsm_est 7.48243e-07 nsteps 268 + rtol 1e-06 rk_type 0 order 2 acc 1 t 4.5 dsm 7.4366e-08 dsm_est 7.22713e-07 nsteps 597 + rtol 1e-06 rk_type 0 order 2 acc 1 t 4.75 dsm 5.08713e-07 dsm_est 8.6505e-07 nsteps 347 + rtol 1e-06 rk_type 0 order 2 acc 1 t 5 dsm 1.42752e-07 dsm_est 7.22893e-07 nsteps 366 + rtol 1e-06 rk_type 0 order 2 acc 2 t 0.25 dsm 5.66725e-09 dsm_est 0.000191192 nsteps 488 + rtol 1e-06 rk_type 0 order 2 acc 2 t 0.5 dsm 9.92276e-07 dsm_est 0.000207431 nsteps 403 + rtol 1e-06 rk_type 0 order 2 acc 2 t 0.75 dsm 8.0717e-08 dsm_est 0.00038834 nsteps 823 + rtol 1e-06 rk_type 0 order 2 acc 2 t 1 dsm 5.67858e-07 dsm_est 0.000365552 nsteps 596 + rtol 1e-06 rk_type 0 order 2 acc 2 t 1.25 dsm 1.03484e-06 dsm_est 0.000558232 nsteps 1091 + rtol 1e-06 rk_type 0 order 2 acc 2 t 1.5 dsm 5.45182e-07 dsm_est 0.000561123 nsteps 1080 + rtol 1e-06 rk_type 0 order 2 acc 2 t 1.75 dsm 3.61096e-07 dsm_est 0.000646341 nsteps 1337 + rtol 1e-06 rk_type 0 order 2 acc 2 t 2 dsm 2.2003e-07 dsm_est 0.000468686 nsteps 898 + rtol 1e-06 rk_type 0 order 2 acc 2 t 2.25 dsm 9.38782e-07 dsm_est 0.00034842 nsteps 635 + rtol 1e-06 rk_type 0 order 2 acc 2 t 2.5 dsm 5.20042e-07 dsm_est 0.000167351 nsteps 372 + rtol 1e-06 rk_type 0 order 2 acc 2 t 2.75 dsm 4.66825e-07 dsm_est 0.000203788 nsteps 354 + rtol 1e-06 rk_type 0 order 2 acc 2 t 3 dsm 3.30086e-07 dsm_est 0.000158918 nsteps 409 + rtol 1e-06 rk_type 0 order 2 acc 2 t 3.25 dsm 1.19548e-07 dsm_est 0.000177948 nsteps 320 + rtol 1e-06 rk_type 0 order 2 acc 2 t 3.5 dsm 4.13474e-08 dsm_est 0.0001041 nsteps 288 + rtol 1e-06 rk_type 0 order 2 acc 2 t 3.75 dsm 1.02293e-07 dsm_est 0.000113361 nsteps 225 + rtol 1e-06 rk_type 0 order 2 acc 2 t 4 dsm 3.98477e-08 dsm_est 0.000151291 nsteps 304 + rtol 1e-06 rk_type 0 order 2 acc 2 t 4.25 dsm 7.93335e-07 dsm_est 0.000130015 nsteps 268 + rtol 1e-06 rk_type 0 order 2 acc 2 t 4.5 dsm 7.4366e-08 dsm_est 0.000335997 nsteps 597 + rtol 1e-06 rk_type 0 order 2 acc 2 t 4.75 dsm 5.08713e-07 dsm_est 0.000143029 nsteps 347 + rtol 1e-06 rk_type 0 order 2 acc 2 t 5 dsm 1.42752e-07 dsm_est 0.000210843 nsteps 366 + rtol 1e-06 rk_type 0 order 2 acc 3 t 0.25 dsm 5.66725e-09 dsm_est 3.9261e-07 nsteps 488 + rtol 1e-06 rk_type 0 order 2 acc 3 t 0.5 dsm 9.92276e-07 dsm_est 5.09315e-07 nsteps 403 + rtol 1e-06 rk_type 0 order 2 acc 3 t 0.75 dsm 8.0717e-08 dsm_est 4.63477e-07 nsteps 823 + rtol 1e-06 rk_type 0 order 2 acc 3 t 1 dsm 5.67858e-07 dsm_est 6.16216e-07 nsteps 596 + rtol 1e-06 rk_type 0 order 2 acc 3 t 1.25 dsm 1.03484e-06 dsm_est 4.92364e-07 nsteps 1091 + rtol 1e-06 rk_type 0 order 2 acc 3 t 1.5 dsm 5.45182e-07 dsm_est 5.41053e-07 nsteps 1080 + rtol 1e-06 rk_type 0 order 2 acc 3 t 1.75 dsm 3.61096e-07 dsm_est 4.72477e-07 nsteps 1337 + rtol 1e-06 rk_type 0 order 2 acc 3 t 2 dsm 2.2003e-07 dsm_est 5.24929e-07 nsteps 898 + rtol 1e-06 rk_type 0 order 2 acc 3 t 2.25 dsm 9.38782e-07 dsm_est 5.42556e-07 nsteps 635 + rtol 1e-06 rk_type 0 order 2 acc 3 t 2.5 dsm 5.20042e-07 dsm_est 4.96892e-07 nsteps 372 + rtol 1e-06 rk_type 0 order 2 acc 3 t 2.75 dsm 4.66825e-07 dsm_est 5.60217e-07 nsteps 354 + rtol 1e-06 rk_type 0 order 2 acc 3 t 3 dsm 3.30086e-07 dsm_est 4.24795e-07 nsteps 409 + rtol 1e-06 rk_type 0 order 2 acc 3 t 3.25 dsm 1.19548e-07 dsm_est 5.56477e-07 nsteps 320 + rtol 1e-06 rk_type 0 order 2 acc 3 t 3.5 dsm 4.13474e-08 dsm_est 3.67781e-07 nsteps 288 + rtol 1e-06 rk_type 0 order 2 acc 3 t 3.75 dsm 1.02293e-07 dsm_est 5.03214e-07 nsteps 225 + rtol 1e-06 rk_type 0 order 2 acc 3 t 4 dsm 3.98477e-08 dsm_est 4.99206e-07 nsteps 304 + rtol 1e-06 rk_type 0 order 2 acc 3 t 4.25 dsm 7.93335e-07 dsm_est 4.93361e-07 nsteps 268 + rtol 1e-06 rk_type 0 order 2 acc 3 t 4.5 dsm 7.4366e-08 dsm_est 5.62432e-07 nsteps 597 + rtol 1e-06 rk_type 0 order 2 acc 3 t 4.75 dsm 5.08713e-07 dsm_est 4.57462e-07 nsteps 347 + rtol 1e-06 rk_type 0 order 2 acc 3 t 5 dsm 1.42752e-07 dsm_est 5.75749e-07 nsteps 366 diff --git a/test/unit_tests/arkode/CXX_serial/ark_test_accumerror_kpr_20_3_1.out b/test/unit_tests/arkode/CXX_serial/ark_test_accumerror_kpr_20_3_1.out new file mode 100644 index 0000000000..9c8d250c22 --- /dev/null +++ b/test/unit_tests/arkode/CXX_serial/ark_test_accumerror_kpr_20_3_1.out @@ -0,0 +1,190 @@ + +Accumulated error estimation test (Nonlinear Kvaerno-Prothero-Robinson problem): + time domain: (0,5] + partition size = 20 + G = -10 + e = 0.1 + omega = 5 + ERK solver, order = 3 + +Adaptive-step runs: + rtol 0.01 rk_type 1 order 3 acc 1 t 0.25 dsm 6.04149e-05 dsm_est 0.000128901 nsteps 5 + rtol 0.01 rk_type 1 order 3 acc 1 t 0.5 dsm 0.000268262 dsm_est 0.00122853 nsteps 5 + rtol 0.01 rk_type 1 order 3 acc 1 t 0.75 dsm 0.000162426 dsm_est 0.00195582 nsteps 5 + rtol 0.01 rk_type 1 order 3 acc 1 t 1 dsm 0.00010345 dsm_est 0.0018572 nsteps 5 + rtol 0.01 rk_type 1 order 3 acc 1 t 1.25 dsm 0.00145293 dsm_est 0.00223784 nsteps 7 + rtol 0.01 rk_type 1 order 3 acc 1 t 1.5 dsm 0.000475504 dsm_est 0.00220612 nsteps 6 + rtol 0.01 rk_type 1 order 3 acc 1 t 1.75 dsm 0.000953909 dsm_est 0.00848961 nsteps 5 + rtol 0.01 rk_type 1 order 3 acc 1 t 2 dsm 0.00190469 dsm_est 0.00438086 nsteps 6 + rtol 0.01 rk_type 1 order 3 acc 1 t 2.25 dsm 0.00091692 dsm_est 0.00242184 nsteps 5 + rtol 0.01 rk_type 1 order 3 acc 1 t 2.5 dsm 0.000303064 dsm_est 0.00155453 nsteps 5 + rtol 0.01 rk_type 1 order 3 acc 1 t 2.75 dsm 8.75302e-05 dsm_est 0.000628795 nsteps 5 + rtol 0.01 rk_type 1 order 3 acc 1 t 3 dsm 0.000106108 dsm_est 0.000628042 nsteps 5 + rtol 0.01 rk_type 1 order 3 acc 1 t 3.25 dsm 0.000146676 dsm_est 0.000206402 nsteps 5 + rtol 0.01 rk_type 1 order 3 acc 1 t 3.5 dsm 0.000132279 dsm_est 0.000121892 nsteps 5 + rtol 0.01 rk_type 1 order 3 acc 1 t 3.75 dsm 0.000106549 dsm_est 7.66243e-05 nsteps 5 + rtol 0.01 rk_type 1 order 3 acc 1 t 4 dsm 7.68783e-05 dsm_est 6.29323e-05 nsteps 5 + rtol 0.01 rk_type 1 order 3 acc 1 t 4.25 dsm 9.2941e-05 dsm_est 0.000487848 nsteps 5 + rtol 0.01 rk_type 1 order 3 acc 1 t 4.5 dsm 1.84821e-05 dsm_est 0.000635863 nsteps 5 + rtol 0.01 rk_type 1 order 3 acc 1 t 4.75 dsm 6.25225e-05 dsm_est 0.000713957 nsteps 5 + rtol 0.01 rk_type 1 order 3 acc 1 t 5 dsm 1.27772e-05 dsm_est 0.000232819 nsteps 5 + rtol 0.01 rk_type 1 order 3 acc 2 t 0.25 dsm 6.04149e-05 dsm_est 0.000142481 nsteps 5 + rtol 0.01 rk_type 1 order 3 acc 2 t 0.5 dsm 0.000268262 dsm_est 0.0017944 nsteps 5 + rtol 0.01 rk_type 1 order 3 acc 2 t 0.75 dsm 0.000162426 dsm_est 0.00306316 nsteps 5 + rtol 0.01 rk_type 1 order 3 acc 2 t 1 dsm 0.00010345 dsm_est 0.00295527 nsteps 5 + rtol 0.01 rk_type 1 order 3 acc 2 t 1.25 dsm 0.00145293 dsm_est 0.00455884 nsteps 7 + rtol 0.01 rk_type 1 order 3 acc 2 t 1.5 dsm 0.000475504 dsm_est 0.00371453 nsteps 6 + rtol 0.01 rk_type 1 order 3 acc 2 t 1.75 dsm 0.000953909 dsm_est 0.0112601 nsteps 5 + rtol 0.01 rk_type 1 order 3 acc 2 t 2 dsm 0.00190469 dsm_est 0.00636832 nsteps 6 + rtol 0.01 rk_type 1 order 3 acc 2 t 2.25 dsm 0.00091692 dsm_est 0.00259729 nsteps 5 + rtol 0.01 rk_type 1 order 3 acc 2 t 2.5 dsm 0.000303064 dsm_est 0.00186612 nsteps 5 + rtol 0.01 rk_type 1 order 3 acc 2 t 2.75 dsm 8.75302e-05 dsm_est 0.00125767 nsteps 5 + rtol 0.01 rk_type 1 order 3 acc 2 t 3 dsm 0.000106108 dsm_est 0.00108028 nsteps 5 + rtol 0.01 rk_type 1 order 3 acc 2 t 3.25 dsm 0.000146676 dsm_est 0.000287211 nsteps 5 + rtol 0.01 rk_type 1 order 3 acc 2 t 3.5 dsm 0.000132279 dsm_est 0.000198803 nsteps 5 + rtol 0.01 rk_type 1 order 3 acc 2 t 3.75 dsm 0.000106549 dsm_est 0.000127557 nsteps 5 + rtol 0.01 rk_type 1 order 3 acc 2 t 4 dsm 7.68783e-05 dsm_est 9.87869e-05 nsteps 5 + rtol 0.01 rk_type 1 order 3 acc 2 t 4.25 dsm 9.2941e-05 dsm_est 0.000739077 nsteps 5 + rtol 0.01 rk_type 1 order 3 acc 2 t 4.5 dsm 1.84821e-05 dsm_est 0.000782096 nsteps 5 + rtol 0.01 rk_type 1 order 3 acc 2 t 4.75 dsm 6.25225e-05 dsm_est 0.00123861 nsteps 5 + rtol 0.01 rk_type 1 order 3 acc 2 t 5 dsm 1.27772e-05 dsm_est 0.000335449 nsteps 5 + rtol 0.01 rk_type 1 order 3 acc 3 t 0.25 dsm 6.04149e-05 dsm_est 5.47626e-05 nsteps 5 + rtol 0.01 rk_type 1 order 3 acc 3 t 0.5 dsm 0.000268262 dsm_est 0.000688366 nsteps 5 + rtol 0.01 rk_type 1 order 3 acc 3 t 0.75 dsm 0.000162426 dsm_est 0.00119286 nsteps 5 + rtol 0.01 rk_type 1 order 3 acc 3 t 1 dsm 0.00010345 dsm_est 0.00117728 nsteps 5 + rtol 0.01 rk_type 1 order 3 acc 3 t 1.25 dsm 0.00145293 dsm_est 0.00131716 nsteps 7 + rtol 0.01 rk_type 1 order 3 acc 3 t 1.5 dsm 0.000475504 dsm_est 0.00085833 nsteps 6 + rtol 0.01 rk_type 1 order 3 acc 3 t 1.75 dsm 0.000953909 dsm_est 0.0042376 nsteps 5 + rtol 0.01 rk_type 1 order 3 acc 3 t 2 dsm 0.00190469 dsm_est 0.00253135 nsteps 6 + rtol 0.01 rk_type 1 order 3 acc 3 t 2.25 dsm 0.00091692 dsm_est 0.00101199 nsteps 5 + rtol 0.01 rk_type 1 order 3 acc 3 t 2.5 dsm 0.000303064 dsm_est 0.000742258 nsteps 5 + rtol 0.01 rk_type 1 order 3 acc 3 t 2.75 dsm 8.75302e-05 dsm_est 0.000500525 nsteps 5 + rtol 0.01 rk_type 1 order 3 acc 3 t 3 dsm 0.000106108 dsm_est 0.000425438 nsteps 5 + rtol 0.01 rk_type 1 order 3 acc 3 t 3.25 dsm 0.000146676 dsm_est 0.000113454 nsteps 5 + rtol 0.01 rk_type 1 order 3 acc 3 t 3.5 dsm 0.000132279 dsm_est 7.91918e-05 nsteps 5 + rtol 0.01 rk_type 1 order 3 acc 3 t 3.75 dsm 0.000106549 dsm_est 5.03981e-05 nsteps 5 + rtol 0.01 rk_type 1 order 3 acc 3 t 4 dsm 7.68783e-05 dsm_est 3.86745e-05 nsteps 5 + rtol 0.01 rk_type 1 order 3 acc 3 t 4.25 dsm 9.2941e-05 dsm_est 0.00028618 nsteps 5 + rtol 0.01 rk_type 1 order 3 acc 3 t 4.5 dsm 1.84821e-05 dsm_est 0.000303327 nsteps 5 + rtol 0.01 rk_type 1 order 3 acc 3 t 4.75 dsm 6.25225e-05 dsm_est 0.000490051 nsteps 5 + rtol 0.01 rk_type 1 order 3 acc 3 t 5 dsm 1.27772e-05 dsm_est 0.000133564 nsteps 5 + rtol 0.0001 rk_type 1 order 3 acc 1 t 0.25 dsm 2.72131e-05 dsm_est 1.82775e-05 nsteps 6 + rtol 0.0001 rk_type 1 order 3 acc 1 t 0.5 dsm 1.24325e-05 dsm_est 7.57337e-05 nsteps 10 + rtol 0.0001 rk_type 1 order 3 acc 1 t 0.75 dsm 3.04294e-06 dsm_est 5.32249e-05 nsteps 11 + rtol 0.0001 rk_type 1 order 3 acc 1 t 1 dsm 5.56473e-06 dsm_est 4.83864e-05 nsteps 10 + rtol 0.0001 rk_type 1 order 3 acc 1 t 1.25 dsm 2.64925e-05 dsm_est 9.09824e-05 nsteps 14 + rtol 0.0001 rk_type 1 order 3 acc 1 t 1.5 dsm 3.99013e-05 dsm_est 6.618e-05 nsteps 17 + rtol 0.0001 rk_type 1 order 3 acc 1 t 1.75 dsm 6.46566e-06 dsm_est 9.0814e-05 nsteps 20 + rtol 0.0001 rk_type 1 order 3 acc 1 t 2 dsm 2.27591e-05 dsm_est 4.33739e-05 nsteps 14 + rtol 0.0001 rk_type 1 order 3 acc 1 t 2.25 dsm 2.35987e-05 dsm_est 6.01739e-05 nsteps 12 + rtol 0.0001 rk_type 1 order 3 acc 1 t 2.5 dsm 1.9839e-05 dsm_est 5.21299e-05 nsteps 10 + rtol 0.0001 rk_type 1 order 3 acc 1 t 2.75 dsm 4.82543e-06 dsm_est 7.16519e-05 nsteps 9 + rtol 0.0001 rk_type 1 order 3 acc 1 t 3 dsm 1.42111e-05 dsm_est 8.44199e-05 nsteps 9 + rtol 0.0001 rk_type 1 order 3 acc 1 t 3.25 dsm 8.99237e-05 dsm_est 5.93926e-05 nsteps 6 + rtol 0.0001 rk_type 1 order 3 acc 1 t 3.5 dsm 7.05943e-05 dsm_est 2.57508e-05 nsteps 6 + rtol 0.0001 rk_type 1 order 3 acc 1 t 3.75 dsm 0.00011745 dsm_est 7.78236e-05 nsteps 5 + rtol 0.0001 rk_type 1 order 3 acc 1 t 4 dsm 8.6392e-05 dsm_est 6.06003e-05 nsteps 5 + rtol 0.0001 rk_type 1 order 3 acc 1 t 4.25 dsm 1.06282e-05 dsm_est 9.64146e-05 nsteps 8 + rtol 0.0001 rk_type 1 order 3 acc 1 t 4.5 dsm 3.00465e-06 dsm_est 6.91731e-05 nsteps 9 + rtol 0.0001 rk_type 1 order 3 acc 1 t 4.75 dsm 2.24177e-06 dsm_est 6.08731e-05 nsteps 9 + rtol 0.0001 rk_type 1 order 3 acc 1 t 5 dsm 4.61559e-06 dsm_est 3.8972e-05 nsteps 7 + rtol 0.0001 rk_type 1 order 3 acc 2 t 0.25 dsm 2.72131e-05 dsm_est 4.924e-05 nsteps 6 + rtol 0.0001 rk_type 1 order 3 acc 2 t 0.5 dsm 1.24325e-05 dsm_est 0.000277893 nsteps 10 + rtol 0.0001 rk_type 1 order 3 acc 2 t 0.75 dsm 3.04294e-06 dsm_est 0.000266101 nsteps 11 + rtol 0.0001 rk_type 1 order 3 acc 2 t 1 dsm 5.56473e-06 dsm_est 0.00021078 nsteps 10 + rtol 0.0001 rk_type 1 order 3 acc 2 t 1.25 dsm 2.64925e-05 dsm_est 0.000612671 nsteps 14 + rtol 0.0001 rk_type 1 order 3 acc 2 t 1.5 dsm 3.99013e-05 dsm_est 0.000376163 nsteps 17 + rtol 0.0001 rk_type 1 order 3 acc 2 t 1.75 dsm 6.46566e-06 dsm_est 0.000664655 nsteps 20 + rtol 0.0001 rk_type 1 order 3 acc 2 t 2 dsm 2.27591e-05 dsm_est 0.000263341 nsteps 14 + rtol 0.0001 rk_type 1 order 3 acc 2 t 2.25 dsm 2.35987e-05 dsm_est 0.000218874 nsteps 12 + rtol 0.0001 rk_type 1 order 3 acc 2 t 2.5 dsm 1.9839e-05 dsm_est 0.000144657 nsteps 10 + rtol 0.0001 rk_type 1 order 3 acc 2 t 2.75 dsm 4.82543e-06 dsm_est 0.000184366 nsteps 9 + rtol 0.0001 rk_type 1 order 3 acc 2 t 3 dsm 1.42111e-05 dsm_est 0.000233128 nsteps 9 + rtol 0.0001 rk_type 1 order 3 acc 2 t 3.25 dsm 8.99237e-05 dsm_est 9.1606e-05 nsteps 6 + rtol 0.0001 rk_type 1 order 3 acc 2 t 3.5 dsm 7.05943e-05 dsm_est 6.46269e-05 nsteps 6 + rtol 0.0001 rk_type 1 order 3 acc 2 t 3.75 dsm 0.00011745 dsm_est 0.000129769 nsteps 5 + rtol 0.0001 rk_type 1 order 3 acc 2 t 4 dsm 8.6392e-05 dsm_est 0.000108688 nsteps 5 + rtol 0.0001 rk_type 1 order 3 acc 2 t 4.25 dsm 1.06282e-05 dsm_est 0.000207268 nsteps 8 + rtol 0.0001 rk_type 1 order 3 acc 2 t 4.5 dsm 3.00465e-06 dsm_est 0.00017063 nsteps 9 + rtol 0.0001 rk_type 1 order 3 acc 2 t 4.75 dsm 2.24177e-06 dsm_est 0.000176806 nsteps 9 + rtol 0.0001 rk_type 1 order 3 acc 2 t 5 dsm 4.61559e-06 dsm_est 8.40566e-05 nsteps 7 + rtol 0.0001 rk_type 1 order 3 acc 3 t 0.25 dsm 2.72131e-05 dsm_est 1.26444e-05 nsteps 6 + rtol 0.0001 rk_type 1 order 3 acc 3 t 0.5 dsm 1.24325e-05 dsm_est 3.83049e-05 nsteps 10 + rtol 0.0001 rk_type 1 order 3 acc 3 t 0.75 dsm 3.04294e-06 dsm_est 3.06274e-05 nsteps 11 + rtol 0.0001 rk_type 1 order 3 acc 3 t 1 dsm 5.56473e-06 dsm_est 2.34303e-05 nsteps 10 + rtol 0.0001 rk_type 1 order 3 acc 3 t 1.25 dsm 2.64925e-05 dsm_est 4.97711e-05 nsteps 14 + rtol 0.0001 rk_type 1 order 3 acc 3 t 1.5 dsm 3.99013e-05 dsm_est 2.68233e-05 nsteps 17 + rtol 0.0001 rk_type 1 order 3 acc 3 t 1.75 dsm 6.46566e-06 dsm_est 4.0356e-05 nsteps 20 + rtol 0.0001 rk_type 1 order 3 acc 3 t 2 dsm 2.27591e-05 dsm_est 2.34866e-05 nsteps 14 + rtol 0.0001 rk_type 1 order 3 acc 3 t 2.25 dsm 2.35987e-05 dsm_est 2.21042e-05 nsteps 12 + rtol 0.0001 rk_type 1 order 3 acc 3 t 2.5 dsm 1.9839e-05 dsm_est 1.76794e-05 nsteps 10 + rtol 0.0001 rk_type 1 order 3 acc 3 t 2.75 dsm 4.82543e-06 dsm_est 2.9381e-05 nsteps 9 + rtol 0.0001 rk_type 1 order 3 acc 3 t 3 dsm 1.42111e-05 dsm_est 4.44933e-05 nsteps 9 + rtol 0.0001 rk_type 1 order 3 acc 3 t 3.25 dsm 8.99237e-05 dsm_est 2.62142e-05 nsteps 6 + rtol 0.0001 rk_type 1 order 3 acc 3 t 3.5 dsm 7.05943e-05 dsm_est 1.71657e-05 nsteps 6 + rtol 0.0001 rk_type 1 order 3 acc 3 t 3.75 dsm 0.00011745 dsm_est 5.1548e-05 nsteps 5 + rtol 0.0001 rk_type 1 order 3 acc 3 t 4 dsm 8.6392e-05 dsm_est 4.3218e-05 nsteps 5 + rtol 0.0001 rk_type 1 order 3 acc 3 t 4.25 dsm 1.06282e-05 dsm_est 4.16064e-05 nsteps 8 + rtol 0.0001 rk_type 1 order 3 acc 3 t 4.5 dsm 3.00465e-06 dsm_est 3.06597e-05 nsteps 9 + rtol 0.0001 rk_type 1 order 3 acc 3 t 4.75 dsm 2.24177e-06 dsm_est 2.78662e-05 nsteps 9 + rtol 0.0001 rk_type 1 order 3 acc 3 t 5 dsm 4.61559e-06 dsm_est 2.06734e-05 nsteps 7 + rtol 1e-06 rk_type 1 order 3 acc 1 t 0.25 dsm 4.12033e-07 dsm_est 8.83529e-07 nsteps 17 + rtol 1e-06 rk_type 1 order 3 acc 1 t 0.5 dsm 2.46326e-07 dsm_est 8.87311e-07 nsteps 31 + rtol 1e-06 rk_type 1 order 3 acc 1 t 0.75 dsm 3.64026e-08 dsm_est 8.31388e-07 nsteps 39 + rtol 1e-06 rk_type 1 order 3 acc 1 t 1 dsm 2.25687e-07 dsm_est 5.06051e-07 nsteps 45 + rtol 1e-06 rk_type 1 order 3 acc 1 t 1.25 dsm 5.93423e-07 dsm_est 9.4211e-07 nsteps 53 + rtol 1e-06 rk_type 1 order 3 acc 1 t 1.5 dsm 6.11123e-07 dsm_est 7.4438e-07 nsteps 68 + rtol 1e-06 rk_type 1 order 3 acc 1 t 1.75 dsm 1.11041e-07 dsm_est 8.66272e-07 nsteps 76 + rtol 1e-06 rk_type 1 order 3 acc 1 t 2 dsm 4.68945e-07 dsm_est 8.0627e-07 nsteps 49 + rtol 1e-06 rk_type 1 order 3 acc 1 t 2.25 dsm 2.82077e-07 dsm_est 7.6683e-07 nsteps 46 + rtol 1e-06 rk_type 1 order 3 acc 1 t 2.5 dsm 3.42754e-07 dsm_est 6.52319e-07 nsteps 37 + rtol 1e-06 rk_type 1 order 3 acc 1 t 2.75 dsm 8.76441e-08 dsm_est 7.34826e-07 nsteps 30 + rtol 1e-06 rk_type 1 order 3 acc 1 t 3 dsm 9.61476e-08 dsm_est 8.15376e-07 nsteps 29 + rtol 1e-06 rk_type 1 order 3 acc 1 t 3.25 dsm 1.10578e-06 dsm_est 8.36809e-07 nsteps 19 + rtol 1e-06 rk_type 1 order 3 acc 1 t 3.5 dsm 8.13041e-07 dsm_est 6.57651e-07 nsteps 19 + rtol 1e-06 rk_type 1 order 3 acc 1 t 3.75 dsm 8.63105e-07 dsm_est 6.37719e-07 nsteps 15 + rtol 1e-06 rk_type 1 order 3 acc 1 t 4 dsm 6.24598e-07 dsm_est 6.02239e-07 nsteps 17 + rtol 1e-06 rk_type 1 order 3 acc 1 t 4.25 dsm 1.79535e-07 dsm_est 8.62348e-07 nsteps 24 + rtol 1e-06 rk_type 1 order 3 acc 1 t 4.5 dsm 4.23449e-08 dsm_est 8.85746e-07 nsteps 29 + rtol 1e-06 rk_type 1 order 3 acc 1 t 4.75 dsm 1.70945e-08 dsm_est 6.68877e-07 nsteps 35 + rtol 1e-06 rk_type 1 order 3 acc 1 t 5 dsm 4.21376e-08 dsm_est 6.1895e-07 nsteps 23 + rtol 1e-06 rk_type 1 order 3 acc 2 t 0.25 dsm 4.12033e-07 dsm_est 5.39389e-06 nsteps 17 + rtol 1e-06 rk_type 1 order 3 acc 2 t 0.5 dsm 2.46326e-07 dsm_est 1.9237e-05 nsteps 31 + rtol 1e-06 rk_type 1 order 3 acc 2 t 0.75 dsm 3.64026e-08 dsm_est 1.83009e-05 nsteps 39 + rtol 1e-06 rk_type 1 order 3 acc 2 t 1 dsm 2.25687e-07 dsm_est 9.58735e-06 nsteps 45 + rtol 1e-06 rk_type 1 order 3 acc 2 t 1.25 dsm 5.93423e-07 dsm_est 3.20094e-05 nsteps 53 + rtol 1e-06 rk_type 1 order 3 acc 2 t 1.5 dsm 6.11123e-07 dsm_est 1.91705e-05 nsteps 68 + rtol 1e-06 rk_type 1 order 3 acc 2 t 1.75 dsm 1.11041e-07 dsm_est 3.76134e-05 nsteps 76 + rtol 1e-06 rk_type 1 order 3 acc 2 t 2 dsm 4.68945e-07 dsm_est 1.77029e-05 nsteps 49 + rtol 1e-06 rk_type 1 order 3 acc 2 t 2.25 dsm 2.82077e-07 dsm_est 1.41512e-05 nsteps 46 + rtol 1e-06 rk_type 1 order 3 acc 2 t 2.5 dsm 3.42754e-07 dsm_est 8.81414e-06 nsteps 37 + rtol 1e-06 rk_type 1 order 3 acc 2 t 2.75 dsm 8.76441e-08 dsm_est 1.05628e-05 nsteps 30 + rtol 1e-06 rk_type 1 order 3 acc 2 t 3 dsm 9.61476e-08 dsm_est 1.02396e-05 nsteps 29 + rtol 1e-06 rk_type 1 order 3 acc 2 t 3.25 dsm 1.10578e-06 dsm_est 5.86128e-06 nsteps 19 + rtol 1e-06 rk_type 1 order 3 acc 2 t 3.5 dsm 8.13041e-07 dsm_est 4.13828e-06 nsteps 19 + rtol 1e-06 rk_type 1 order 3 acc 2 t 3.75 dsm 8.63105e-07 dsm_est 4.96105e-06 nsteps 15 + rtol 1e-06 rk_type 1 order 3 acc 2 t 4 dsm 6.24598e-07 dsm_est 3.42283e-06 nsteps 17 + rtol 1e-06 rk_type 1 order 3 acc 2 t 4.25 dsm 1.79535e-07 dsm_est 1.35763e-05 nsteps 24 + rtol 1e-06 rk_type 1 order 3 acc 2 t 4.5 dsm 4.23449e-08 dsm_est 9.97609e-06 nsteps 29 + rtol 1e-06 rk_type 1 order 3 acc 2 t 4.75 dsm 1.70945e-08 dsm_est 8.39064e-06 nsteps 35 + rtol 1e-06 rk_type 1 order 3 acc 2 t 5 dsm 4.21376e-08 dsm_est 4.92976e-06 nsteps 23 + rtol 1e-06 rk_type 1 order 3 acc 3 t 0.25 dsm 4.12033e-07 dsm_est 3.51639e-07 nsteps 17 + rtol 1e-06 rk_type 1 order 3 acc 3 t 0.5 dsm 2.46326e-07 dsm_est 6.81523e-07 nsteps 31 + rtol 1e-06 rk_type 1 order 3 acc 3 t 0.75 dsm 3.64026e-08 dsm_est 5.27456e-07 nsteps 39 + rtol 1e-06 rk_type 1 order 3 acc 3 t 1 dsm 2.25687e-07 dsm_est 2.33885e-07 nsteps 45 + rtol 1e-06 rk_type 1 order 3 acc 3 t 1.25 dsm 5.93423e-07 dsm_est 6.2587e-07 nsteps 53 + rtol 1e-06 rk_type 1 order 3 acc 3 t 1.5 dsm 6.11123e-07 dsm_est 3.04709e-07 nsteps 68 + rtol 1e-06 rk_type 1 order 3 acc 3 t 1.75 dsm 1.11041e-07 dsm_est 5.31606e-07 nsteps 76 + rtol 1e-06 rk_type 1 order 3 acc 3 t 2 dsm 4.68945e-07 dsm_est 4.08204e-07 nsteps 49 + rtol 1e-06 rk_type 1 order 3 acc 3 t 2.25 dsm 2.82077e-07 dsm_est 3.48802e-07 nsteps 46 + rtol 1e-06 rk_type 1 order 3 acc 3 t 2.5 dsm 3.42754e-07 dsm_est 2.65247e-07 nsteps 37 + rtol 1e-06 rk_type 1 order 3 acc 3 t 2.75 dsm 8.76441e-08 dsm_est 3.82534e-07 nsteps 30 + rtol 1e-06 rk_type 1 order 3 acc 3 t 3 dsm 9.61476e-08 dsm_est 3.90658e-07 nsteps 29 + rtol 1e-06 rk_type 1 order 3 acc 3 t 3.25 dsm 1.10578e-06 dsm_est 3.96373e-07 nsteps 19 + rtol 1e-06 rk_type 1 order 3 acc 3 t 3.5 dsm 8.13041e-07 dsm_est 2.65458e-07 nsteps 19 + rtol 1e-06 rk_type 1 order 3 acc 3 t 3.75 dsm 8.63105e-07 dsm_est 4.14868e-07 nsteps 15 + rtol 1e-06 rk_type 1 order 3 acc 3 t 4 dsm 6.24598e-07 dsm_est 2.48565e-07 nsteps 17 + rtol 1e-06 rk_type 1 order 3 acc 3 t 4.25 dsm 1.79535e-07 dsm_est 6.40873e-07 nsteps 24 + rtol 1e-06 rk_type 1 order 3 acc 3 t 4.5 dsm 4.23449e-08 dsm_est 4.08016e-07 nsteps 29 + rtol 1e-06 rk_type 1 order 3 acc 3 t 4.75 dsm 1.70945e-08 dsm_est 2.72362e-07 nsteps 35 + rtol 1e-06 rk_type 1 order 3 acc 3 t 5 dsm 4.21376e-08 dsm_est 2.53485e-07 nsteps 23 diff --git a/test/unit_tests/arkode/CXX_serial/ark_test_analytic_sys_mri.cpp b/test/unit_tests/arkode/CXX_serial/ark_test_analytic_sys_mri.cpp index c56ac4292d..163881fa4a 100644 --- a/test/unit_tests/arkode/CXX_serial/ark_test_analytic_sys_mri.cpp +++ b/test/unit_tests/arkode/CXX_serial/ark_test_analytic_sys_mri.cpp @@ -129,8 +129,8 @@ int main(int argc, char* argv[]) if (check_flag((void*)inner_mem, "ARKStepCreate", 0)) { return 1; } MRIStepInnerStepper inner_stepper = NULL; - flag = ARKStepCreateMRIStepInnerStepper(inner_mem, &inner_stepper); - if (check_flag(&flag, "ARKStepCreateMRIStepInnerStepper", 1)) { return 1; } + flag = ARKodeCreateMRIStepInnerStepper(inner_mem, &inner_stepper); + if (check_flag(&flag, "ARKodeCreateMRIStepInnerStepper", 1)) { return 1; } mristep_mem = MRIStepCreate(NULL, f, T0, y, inner_stepper, sunctx); if (check_flag((void*)mristep_mem, "MRIStepCreate", 0)) { return 1; } diff --git a/test/unit_tests/arkode/CXX_serial/ark_test_brusselator_mriadapt.cpp b/test/unit_tests/arkode/CXX_serial/ark_test_brusselator_mriadapt.cpp new file mode 100644 index 0000000000..1169aabc17 --- /dev/null +++ b/test/unit_tests/arkode/CXX_serial/ark_test_brusselator_mriadapt.cpp @@ -0,0 +1,1388 @@ +/* ---------------------------------------------------------------- + * Programmer(s): Daniel R. Reynolds @ SMU + * ---------------------------------------------------------------- + * SUNDIALS Copyright Start + * Copyright (c) 2002-2024, Lawrence Livermore National Security + * and Southern Methodist University. + * All rights reserved. + * + * See the top-level LICENSE and NOTICE files for details. + * + * SPDX-License-Identifier: BSD-3-Clause + * SUNDIALS Copyright End + * ---------------------------------------------------------------- + * Multirate stiff Brusselator ODE test problem: + * du/dt = a - (w+1)*u + v*u^2 + * dv/dt = w*u - v*u^2 + * dw/dt = (b-w)/ep - w*u + * for t in the interval [0.0, 10.0], with initial conditions + * u0=1.2, v0=3.1, w0=3, and parameters a=1, b=3.5. + * + * Problem stiffness is determined by ep, wherein if the dynamical + * time step is given by H and the explicit time step size is given + * by h, then H/h = 1/(100 ep), i.e., the stability-limited step + * takes over at values of ep < 1e-2. + * + * This program allows a single problem-defining input parameter: + * ep: stiffness factor [default = 1/2500] + * + * We perform a multirate splitting of this problem as + * f^s(t,u,v,w) = [a - (w+1)*u + v*u^2] + * [ w*u - v*u^2 ] + * [ -w*u ] + * f^f(t,u,v,w) = [ 0 ] + * [ 0 ] + * [(b-w)/ep] + * For methods that support ImEx treatment of the slow time scale, we + * further split the slow operator f^s into + * f^I(t,u,v,w) = [-(w+1)*u] + * [ w*u ] + * [ -w*u ] + * f^E(t,u,v,w) = [a + v*u^2] + * [ -v*u^2 ] + * [ 0 ] + * + * Additional input options may be used to select between various + * solver options: + * - slow fixed/initial step size: hs [default = 0.01] + * - fast fixed/initial step size: hf [default = 0.0001] + * - set initial adaptive step size as hs/hf above: set_h0 [default 0] + * - relative solution tolerance: rtol [default = 1e-4] + * - absolute solution tolerance: atol [default = 1e-11] + * - slow stepsize safety factor: safety [default = 0.96] + * - relative solution tolerance for fast integrator: fast_rtol [default = 1e-4] + * - use p (0) vs q (1) for slow adaptivity: slow_pq [default = 0] + * - use p (0) vs q (1) for fast adaptivity: fast_pq [default = 0] + * - "slow" MRI method: mri_method [default = ARKODE_MRI_GARK_ERK45a] + * - "fast" ERKStep method order: fast_order [default 4] + * To put all physics at the slow scale, use "0", otherwise + * specify a valid explicit method order. + * - "slow" MRI temporal adaptivity controller: scontrol [default = 6] + * 0: no controller [fixed time steps] + * 5: I controller (as part of MRI-HTOL) + * 6: I controller (alone) + * 7: PI controller (as part of MRI-HTOL) + * 8: PI controller (alone) + * 9: PID controller (as part of MRI-HTOL) + * 10: PID controller (alone) + * 11: ExpGus controller (as part of MRI-HTOL) + * 12: ExpGus controller (alone) + * 13: ImpGus controller (as part of MRI-HTOL) + * 14: ImpGus controller (alone) + * 15: ImExGus controller (as part of MRI-HTOL) + * 16: ImExGus controller (alone) + * - "fast" ERKStep temporal adaptivity controller: fcontrol [default = 1] + * Note that this will only be used for 5 <= scontrol <= 16. + * 0: no controller [fixed time steps] + * 1: I controller + * 2: PI controller + * 3: PID controller + * 4: ExpGus controller + * 5: ImpGus controller + * 6: ImExGus controller + * - "fast" ERKStep accumulated error type: faccum [default = 0] + * Note that this will only be used for multirate scontrol options + * -1: no accumulation + * 0: maximum accumulation + * 1: additive accumulation + * 2: average accumulation + * - controller parameters: (k1s, k2s, k3s, k1f, k2f, k3f, + * bias, htol_relch, htol_minfac, htol_maxfac) + * slow single-rate controllers: use k1s through k3s, as appropriate. + * fast single-rate controllers: use k1f through k3f, as appropriate. + * MRIHTol controllers: use htol_relch, htol_minfac, htol_maxfac. + * all controllers (fast and slow) use bias. + * ** if any one of a relevant set are "-1" then the defaults are used + * + * Outputs and solution error values are printed at equal intervals + * of 0.5 and run statistics are printed at the end. + * ----------------------------------------------------------------*/ + +// Header files +#include // prototypes for ERKStep fcts., consts +#include // prototypes for MRIStep fcts., consts +#include +#include +#include +#include +#include +#include // serial N_Vector type, fcts., macros +#include +#include +#include +#include +#include +#include // dense linear solver +#include // dense matrix type, fcts., macros +#include "../../utilities/test_utilities.hpp" // common utility functions + +#if defined(SUNDIALS_EXTENDED_PRECISION) +#define ESYM "Le" +#define FSYM "Lf" +#else +#define ESYM "e" +#define FSYM "f" +#endif + +#define ZERO SUN_RCONST(0.0) +#define ONE SUN_RCONST(1.0) +#define TWO SUN_RCONST(2.0) + +// Problem options +struct Options +{ + // Problem parameters + sunrealtype a = SUN_RCONST(1.0); + sunrealtype b = SUN_RCONST(3.5); + sunrealtype ep = SUN_RCONST(0.0004); + + // Step sizes and tolerances + int set_h0 = 0; + sunrealtype hs = SUN_RCONST(1.0e-2); + sunrealtype hf = SUN_RCONST(1.0e-4); + sunrealtype rtol = SUN_RCONST(1.0e-4); + sunrealtype atol = SUN_RCONST(1.0e-11); + sunrealtype fast_rtol = SUN_RCONST(1.0e-4); + + // Method selection + std::string mri_method = "ARKODE_MRI_GARK_ERK45a"; + int fast_order = 4; + int scontrol = 6; + int fcontrol = 1; + int faccum = 0; + int slow_pq = 0; + int fast_pq = 0; + + // controller parameters + sunrealtype k1s = SUN_RCONST(-1.0); + sunrealtype k2s = SUN_RCONST(-1.0); + sunrealtype k3s = SUN_RCONST(-1.0); + sunrealtype k1f = SUN_RCONST(-1.0); + sunrealtype k2f = SUN_RCONST(-1.0); + sunrealtype k3f = SUN_RCONST(-1.0); + sunrealtype bias = SUN_RCONST(-1.0); + sunrealtype htol_relch = SUN_RCONST(-1.0); + sunrealtype htol_minfac = SUN_RCONST(-1.0); + sunrealtype htol_maxfac = SUN_RCONST(-1.0); + sunrealtype slow_safety = SUN_RCONST(-1.0); +}; + +// User-supplied functions called by the solver +static int fse(sunrealtype t, N_Vector y, N_Vector ydot, void* user_data); +static int fsi(sunrealtype t, N_Vector y, N_Vector ydot, void* user_data); +static int fs(sunrealtype t, N_Vector y, N_Vector ydot, void* user_data); +static int ff(sunrealtype t, N_Vector y, N_Vector ydot, void* user_data); +static int fn(sunrealtype t, N_Vector y, N_Vector ydot, void* user_data); +static int f0(sunrealtype t, N_Vector y, N_Vector ydot, void* user_data); +static int Js(sunrealtype t, N_Vector y, N_Vector fy, SUNMatrix J, + void* user_data, N_Vector tmp1, N_Vector tmp2, N_Vector tmp3); +static int Jsi(sunrealtype t, N_Vector y, N_Vector fy, SUNMatrix J, + void* user_data, N_Vector tmp1, N_Vector tmp2, N_Vector tmp3); +static int Jn(sunrealtype t, N_Vector y, N_Vector fy, SUNMatrix J, + void* user_data, N_Vector tmp1, N_Vector tmp2, N_Vector tmp3); + +// Utility functions +static void InputHelp(); +static int ReadInputs(std::vector& args, Options& opts, + SUNContext ctx); +static void PrintSlowAdaptivity(Options opts); +static void PrintFastAdaptivity(Options opts); + +// Main Program +int main(int argc, char* argv[]) +{ + // SUNDIALS context objects + sundials::Context sunctx; // main solver + sundials::Context refctx; // reference solver + + // Read input options + Options opts; + std::vector args(argv + 1, argv + argc); + int flag = ReadInputs(args, opts, sunctx); + if (check_flag(flag, "ReadInputs")) return 1; + + // General problem parameters + sunrealtype T0 = SUN_RCONST(0.0); // initial time + sunrealtype Tf = SUN_RCONST(10.0); // final time + sunindextype NEQ = 3; // number of dependent vars. + int Nt = 20; // number of output times + + // Initial problem output + // While traversing these, set various function pointers, table constants, and method orders. + ARKRhsFn f_f, f_se, f_si; + ARKLsJacFn J_s; + int retval; + sunbooleantype slowimplicit, slowimex; + slowimplicit = slowimex = SUNFALSE; + f_si = NULL; + J_s = NULL; + f_f = (opts.fast_order == 0) ? f0 : ff; + f_se = (opts.fast_order == 0) ? fn : fs; + if ((opts.mri_method == "ARKODE_MRI_GARK_IRK21a") || + (opts.mri_method == "ARKODE_MRI_GARK_ESDIRK34a") || + (opts.mri_method == "ARKODE_MRI_GARK_ESDIRK46a")) + { + slowimplicit = SUNTRUE; + f_se = NULL; + f_si = (opts.fast_order == 0) ? fn : fs; + J_s = (opts.fast_order == 0) ? Jn : Js; + } + if ((opts.mri_method == "ARKODE_IMEX_MRI_SR21") || + (opts.mri_method == "ARKODE_IMEX_MRI_SR32") || + (opts.mri_method == "ARKODE_IMEX_MRI_SR43")) + { + slowimex = SUNTRUE; + slowimplicit = SUNTRUE; + f_se = (opts.fast_order == 0) ? f0 : fse; + f_si = (opts.fast_order == 0) ? fn : fsi; + J_s = (opts.fast_order == 0) ? Jn : Jsi; + } + std::cout << "\nAdaptive multirate stiff Brusselator test problem:\n"; + std::cout << " time domain: (" << T0 << "," << Tf << "]\n"; + std::cout << " ep = " << opts.ep << std::endl; + std::cout << "\n Slow integrator: " << opts.mri_method; + if (slowimex) { std::cout << " (ImEx)" << std::endl; } + else if (slowimplicit) { std::cout << " (implicit)" << std::endl; } + else { std::cout << " (explicit)" << std::endl; } + PrintSlowAdaptivity(opts); + if (opts.fast_order == 0) { std::cout << "\n Fast integrator disabled"; } + else { std::cout << "\n Fast order " << opts.fast_order << std::endl; } + PrintFastAdaptivity(opts); + + // If SUNLogger is enabled, manually disable it for the reference solver + SUNLogger logger = NULL; + retval = SUNLogger_Create(SUN_COMM_NULL, 0, &logger); + retval = SUNContext_SetLogger(refctx, logger); + retval = SUNLogger_SetErrorFilename(logger, "/dev/null"); + retval = SUNLogger_SetWarningFilename(logger, "/dev/null"); + retval = SUNLogger_SetInfoFilename(logger, "/dev/null"); + retval = SUNLogger_SetDebugFilename(logger, "/dev/null"); + + // Create and initialize serial vectors for the solution and reference + N_Vector y = N_VNew_Serial(NEQ, sunctx); + if (check_ptr((void*)y, "N_VNew_Serial")) return 1; + N_Vector yref = N_VNew_Serial(NEQ, refctx); + if (check_ptr((void*)yref, "N_VNew_Serial")) return 1; + + // Set initial conditions + sunrealtype* ydata = N_VGetArrayPointer(y); + sunrealtype* yrefdata = N_VGetArrayPointer(yref); + ydata[0] = SUN_RCONST(1.2); + ydata[1] = SUN_RCONST(3.1); + ydata[2] = SUN_RCONST(3.0); + N_VScale(ONE, y, yref); + + // Create and configure reference solver object + void* arkode_ref = ERKStepCreate(fn, T0, yref, refctx); + if (check_ptr((void*)arkode_ref, "ERKStepCreate")) return 1; + retval = ARKodeSetUserData(arkode_ref, (void*)&opts); + if (check_flag(retval, "ARKodeSetUserData")) return 1; + retval = ARKodeSetOrder(arkode_ref, 5); + if (check_flag(retval, "ARKodeSetOrder")) return 1; + retval = ARKodeSStolerances(arkode_ref, SUN_RCONST(1.e-10), SUN_RCONST(1.e-12)); + if (check_flag(retval, "ARKodeSStolerances")) return 1; + retval = ARKodeSetMaxNumSteps(arkode_ref, 10000000); + if (check_flag(retval, "ARKodeSetMaxNumSteps")) return (1); + + // Create and configure fast controller object + SUNAdaptController fcontrol = NULL; + switch (opts.fcontrol) + { + case (1): + fcontrol = SUNAdaptController_I(sunctx); + if (check_ptr((void*)fcontrol, "SUNAdaptController_I")) return 1; + if (opts.k1f > -1) + { + retval = SUNAdaptController_SetParams_I(fcontrol, opts.k1f); + if (check_flag(retval, "SUNAdaptController_SetParams_I")) return 1; + } + break; + case (2): + fcontrol = SUNAdaptController_PI(sunctx); + if (check_ptr((void*)fcontrol, "SUNAdaptController_PI")) return 1; + if (std::min(opts.k1f, opts.k2f) > -1) + { + retval = SUNAdaptController_SetParams_PI(fcontrol, opts.k1f, opts.k2f); + if (check_flag(retval, "SUNAdaptController_SetParams_PI")) return 1; + } + break; + case (3): + fcontrol = SUNAdaptController_PID(sunctx); + if (check_ptr((void*)fcontrol, "SUNAdaptController_PID")) return 1; + if (std::min(opts.k1f, std::min(opts.k2f, opts.k3f)) > -1) + { + retval = SUNAdaptController_SetParams_PID(fcontrol, opts.k1f, opts.k2f, + opts.k3f); + if (check_flag(retval, "SUNAdaptController_SetParams_PID")) return 1; + } + break; + case (4): + fcontrol = SUNAdaptController_ExpGus(sunctx); + if (check_ptr((void*)fcontrol, "SUNAdaptController_ExpGus")) return 1; + if (std::min(opts.k1f, opts.k2f) > -1) + { + retval = SUNAdaptController_SetParams_ExpGus(fcontrol, opts.k1f, opts.k2f); + if (check_flag(retval, "SUNAdaptController_SetParams_ExpGus")) return 1; + } + break; + case (5): + fcontrol = SUNAdaptController_ImpGus(sunctx); + if (check_ptr((void*)fcontrol, "SUNAdaptController_ImpGus")) return 1; + if (std::min(opts.k1f, opts.k2f) > -1) + { + retval = SUNAdaptController_SetParams_ImpGus(fcontrol, opts.k1f, opts.k2f); + if (check_flag(retval, "SUNAdaptController_SetParams_ImpGus")) return 1; + } + break; + case (6): + fcontrol = SUNAdaptController_ImExGus(sunctx); + if (check_ptr((void*)fcontrol, "SUNAdaptController_ImExGus")) return 1; + break; + } + if ((opts.bias > -1) && (opts.fcontrol > 0)) + { + retval = SUNAdaptController_SetErrorBias(fcontrol, opts.bias); + if (check_flag(retval, "SUNAdaptController_SetErrorBias")) return 1; + } + + // Create ERKStep (fast) integrator + void* inner_arkode_mem = NULL; // ARKode memory structure + inner_arkode_mem = ERKStepCreate(f_f, T0, y, sunctx); + if (check_ptr((void*)inner_arkode_mem, "ERKStepCreate")) return 1; + retval = ARKodeSetOrder(inner_arkode_mem, opts.fast_order); + if (check_flag(retval, "ARKodeSetOrder")) return 1; + retval = ARKodeSStolerances(inner_arkode_mem, opts.fast_rtol, opts.atol); + if (check_flag(retval, "ARKodeSStolerances")) return 1; + if (opts.fcontrol != 0) + { + retval = ARKodeSetAdaptController(inner_arkode_mem, fcontrol); + if (check_flag(retval, "ARKodeSetAdaptController")) return 1; + if (opts.set_h0 != 0) + { + retval = ARKodeSetInitStep(inner_arkode_mem, opts.hf); + if (check_flag(retval, "ARKodeSetInitStep")) return 1; + } + retval = ARKodeSetAdaptivityAdjustment(inner_arkode_mem, opts.fast_pq - 1); + if (check_flag(retval, "ARKodeSetAdaptivityAdjustment")) return 1; + } + else + { + retval = ARKodeSetFixedStep(inner_arkode_mem, opts.hf); + if (check_flag(retval, "ARKodeSetFixedStep")) return 1; + } + ARKAccumError acc_type = ARK_ACCUMERROR_NONE; + if (opts.faccum == 0) { acc_type = ARK_ACCUMERROR_MAX; } + if (opts.faccum == 1) { acc_type = ARK_ACCUMERROR_SUM; } + if (opts.faccum == 2) { acc_type = ARK_ACCUMERROR_AVG; } + retval = ARKodeSetAccumulatedErrorType(inner_arkode_mem, acc_type); + if (check_flag(retval, "ARKodeSetAccumulatedErrorType")) return 1; + retval = ARKodeSetMaxNumSteps(inner_arkode_mem, 1000000); + if (check_flag(retval, "ARKodeSetMaxNumSteps")) return 1; + retval = ARKodeSetUserData(inner_arkode_mem, (void*)&opts); + if (check_flag(retval, "ARKodeSetUserData")) return 1; + + // Create inner stepper + MRIStepInnerStepper inner_stepper = NULL; // inner stepper + retval = ARKodeCreateMRIStepInnerStepper(inner_arkode_mem, &inner_stepper); + if (check_flag(retval, "ARKodeCreateMRIStepInnerStepper")) return 1; + + // Create slow controller object, and select orders of accuracy as relevant + SUNAdaptController scontrol = NULL; + SUNAdaptController scontrol_H = NULL; + SUNAdaptController scontrol_Tol = NULL; + switch (opts.scontrol) + { + case (5): + scontrol_H = SUNAdaptController_I(sunctx); + if (check_ptr((void*)scontrol_H, "SUNAdaptController_I (slow H)")) return 1; + scontrol_Tol = SUNAdaptController_I(sunctx); + if (check_ptr((void*)scontrol_Tol, "SUNAdaptController_I (slow Tol)")) + return 1; + if (opts.k1s > -1) + { + retval = SUNAdaptController_SetParams_I(scontrol_H, opts.k1s); + if (check_flag(retval, "SUNAdaptController_SetParams_I")) return 1; + retval = SUNAdaptController_SetParams_I(scontrol_Tol, opts.k1s); + if (check_flag(retval, "SUNAdaptController_SetParams_I")) return 1; + } + scontrol = SUNAdaptController_MRIHTol(scontrol_H, scontrol_Tol, sunctx); + if (check_ptr((void*)scontrol, "SUNAdaptController_MRIHTol")) return 1; + if (std::min(opts.htol_relch, std::min(opts.htol_minfac, opts.htol_maxfac)) > + -1) + { + retval = SUNAdaptController_SetParams_MRIHTol(scontrol, opts.htol_relch, + opts.htol_minfac, + opts.htol_maxfac); + if (check_flag(retval, "SUNAdaptController_SetParams_MRIHTol")) return 1; + } + break; + case (6): + scontrol = SUNAdaptController_I(sunctx); + if (check_ptr((void*)scontrol, "SUNAdaptControllerI (slow)")) return 1; + if (opts.k1s > -1) + { + retval = SUNAdaptController_SetParams_I(scontrol, opts.k1s); + if (check_flag(retval, "SUNAdaptController_SetParams_I")) return 1; + } + break; + case (7): + scontrol_H = SUNAdaptController_PI(sunctx); + if (check_ptr((void*)scontrol_H, "SUNAdaptController_PI (slow H)")) + return 1; + scontrol_Tol = SUNAdaptController_PI(sunctx); + if (check_ptr((void*)scontrol_Tol, "SUNAdaptController_PI (slow Tol)")) + return 1; + if (std::min(opts.k1s, opts.k2s) > -1) + { + retval = SUNAdaptController_SetParams_PI(scontrol_H, opts.k1s, opts.k2s); + if (check_flag(retval, "SUNAdaptController_SetParams_PI")) return 1; + retval = SUNAdaptController_SetParams_PI(scontrol_Tol, opts.k1s, opts.k2s); + if (check_flag(retval, "SUNAdaptController_SetParams_PI")) return 1; + } + scontrol = SUNAdaptController_MRIHTol(scontrol_H, scontrol_Tol, sunctx); + if (check_ptr((void*)scontrol, "SUNAdaptController_MRIHTol")) return 1; + if (std::min(opts.htol_relch, std::min(opts.htol_minfac, opts.htol_maxfac)) > + -1) + { + retval = SUNAdaptController_SetParams_MRIHTol(scontrol, opts.htol_relch, + opts.htol_minfac, + opts.htol_maxfac); + if (check_flag(retval, "SUNAdaptController_SetParams_MRIHTol")) return 1; + } + break; + case (8): + scontrol = SUNAdaptController_PI(sunctx); + if (check_ptr((void*)scontrol, "SUNAdaptController_PI (slow)")) return 1; + if (std::min(opts.k1s, opts.k2s) > -1) + { + retval = SUNAdaptController_SetParams_PI(scontrol, opts.k1s, opts.k2s); + if (check_flag(retval, "SUNAdaptController_SetParams_PI")) return 1; + } + break; + case (9): + scontrol_H = SUNAdaptController_PID(sunctx); + if (check_ptr((void*)scontrol_H, "SUNAdaptController_PID (slow H)")) + return 1; + scontrol_Tol = SUNAdaptController_PID(sunctx); + if (check_ptr((void*)scontrol_Tol, "SUNAdaptController_PID (slow Tol)")) + return 1; + if (std::min(opts.k1s, std::min(opts.k2s, opts.k3s)) > -1) + { + retval = SUNAdaptController_SetParams_PID(scontrol_H, opts.k1s, opts.k2s, + opts.k3s); + if (check_flag(retval, "SUNAdaptController_SetParams_PID")) return 1; + retval = SUNAdaptController_SetParams_PID(scontrol_Tol, opts.k1s, + opts.k2s, opts.k3s); + if (check_flag(retval, "SUNAdaptController_SetParams_PID")) return 1; + } + scontrol = SUNAdaptController_MRIHTol(scontrol_H, scontrol_Tol, sunctx); + if (check_ptr((void*)scontrol, "SUNAdaptController_MRIHTol")) return 1; + if (std::min(opts.htol_relch, std::min(opts.htol_minfac, opts.htol_maxfac)) > + -1) + { + retval = SUNAdaptController_SetParams_MRIHTol(scontrol, opts.htol_relch, + opts.htol_minfac, + opts.htol_maxfac); + if (check_flag(retval, "SUNAdaptController_SetParams_MRIHTol")) return 1; + } + break; + case (10): + scontrol = SUNAdaptController_PID(sunctx); + if (check_ptr((void*)scontrol, "SUNAdaptController_PID (slow)")) return 1; + if (std::min(opts.k1s, std::min(opts.k2s, opts.k3s)) > -1) + { + retval = SUNAdaptController_SetParams_PID(scontrol, opts.k1s, opts.k2s, + opts.k3s); + if (check_flag(retval, "SUNAdaptController_SetParams_PID")) return 1; + } + break; + case (11): + scontrol_H = SUNAdaptController_ExpGus(sunctx); + if (check_ptr((void*)scontrol_H, "SUNAdaptController_ExpGus (slow H)")) + return 1; + scontrol_Tol = SUNAdaptController_ExpGus(sunctx); + if (check_ptr((void*)scontrol_Tol, "SUNAdaptController_ExpGus (slow Tol)")) + return 1; + if (std::min(opts.k1s, opts.k2s) > -1) + { + retval = SUNAdaptController_SetParams_ExpGus(scontrol_H, opts.k1s, + opts.k2s); + if (check_flag(retval, "SUNAdaptController_SetParams_ExpGus")) return 1; + retval = SUNAdaptController_SetParams_ExpGus(scontrol_Tol, opts.k1s, + opts.k2s); + if (check_flag(retval, "SUNAdaptController_SetParams_ExpGus")) return 1; + } + scontrol = SUNAdaptController_MRIHTol(scontrol_H, scontrol_Tol, sunctx); + if (check_ptr((void*)scontrol, "SUNAdaptController_MRIHTol")) return 1; + if (std::min(opts.htol_relch, std::min(opts.htol_minfac, opts.htol_maxfac)) > + -1) + { + retval = SUNAdaptController_SetParams_MRIHTol(scontrol, opts.htol_relch, + opts.htol_minfac, + opts.htol_maxfac); + if (check_flag(retval, "SUNAdaptController_SetParams_MRIHTol")) return 1; + } + break; + case (12): + scontrol = SUNAdaptController_ExpGus(sunctx); + if (check_ptr((void*)scontrol, "SUNAdaptController_ExpGus (slow)")) + return 1; + if (std::min(opts.k1s, opts.k2s) > -1) + { + retval = SUNAdaptController_SetParams_ExpGus(scontrol, opts.k1s, opts.k2s); + if (check_flag(retval, "SUNAdaptController_SetParams_ExpGus")) return 1; + } + break; + case (13): + scontrol_H = SUNAdaptController_ImpGus(sunctx); + if (check_ptr((void*)scontrol_H, "SUNAdaptController_ImpGus (slow H)")) + return 1; + scontrol_Tol = SUNAdaptController_ImpGus(sunctx); + if (check_ptr((void*)scontrol_Tol, "SUNAdaptController_ImpGus (slow Tol)")) + return 1; + if (std::min(opts.k1s, opts.k2s) > -1) + { + retval = SUNAdaptController_SetParams_ImpGus(scontrol_H, opts.k1s, + opts.k2s); + if (check_flag(retval, "SUNAdaptController_SetParams_ImpGus")) return 1; + retval = SUNAdaptController_SetParams_ImpGus(scontrol_Tol, opts.k1s, + opts.k2s); + if (check_flag(retval, "SUNAdaptController_SetParams_ImpGus")) return 1; + } + scontrol = SUNAdaptController_MRIHTol(scontrol_H, scontrol_Tol, sunctx); + if (check_ptr((void*)scontrol, "SUNAdaptController_MRIHTol")) return 1; + if (std::min(opts.htol_relch, std::min(opts.htol_minfac, opts.htol_maxfac)) > + -1) + { + retval = SUNAdaptController_SetParams_MRIHTol(scontrol, opts.htol_relch, + opts.htol_minfac, + opts.htol_maxfac); + if (check_flag(retval, "SUNAdaptController_SetParams_MRIHTol")) return 1; + } + break; + case (14): + scontrol = SUNAdaptController_ImpGus(sunctx); + if (check_ptr((void*)scontrol, "SUNAdaptController_ImpGus (slow)")) + return 1; + if (std::min(opts.k1s, opts.k2s) > -1) + { + retval = SUNAdaptController_SetParams_ImpGus(scontrol, opts.k1s, opts.k2s); + if (check_flag(retval, "SUNAdaptController_SetParams_ImpGus")) return 1; + } + break; + case (15): + scontrol_H = SUNAdaptController_ImExGus(sunctx); + if (check_ptr((void*)scontrol_H, "SUNAdaptController_ImExGus (slow H)")) + return 1; + scontrol_Tol = SUNAdaptController_ImExGus(sunctx); + if (check_ptr((void*)scontrol_Tol, "SUNAdaptController_ImExGus (slow Tol)")) + return 1; + scontrol = SUNAdaptController_MRIHTol(scontrol_H, scontrol_Tol, sunctx); + if (check_ptr((void*)scontrol, "SUNAdaptController_MRIHTol")) return 1; + if (std::min(opts.htol_relch, std::min(opts.htol_minfac, opts.htol_maxfac)) > + -1) + { + retval = SUNAdaptController_SetParams_MRIHTol(scontrol, opts.htol_relch, + opts.htol_minfac, + opts.htol_maxfac); + if (check_flag(retval, "SUNAdaptController_SetParams_MRIHTol")) return 1; + } + break; + case (16): + scontrol = SUNAdaptController_ImExGus(sunctx); + if (check_ptr((void*)scontrol, "SUNAdaptController_ImExGus (slow)")) + return 1; + break; + } + if ((opts.bias > -1) && (opts.scontrol > 0)) + { + retval = SUNAdaptController_SetErrorBias(scontrol, opts.bias); + if (check_flag(retval, "SUNAdaptController_SetErrorBias")) return 1; + } + + // Create MRI (slow) integrator + void* arkode_mem = NULL; // ARKode memory structure + arkode_mem = MRIStepCreate(f_se, f_si, T0, y, inner_stepper, sunctx); + if (check_ptr((void*)arkode_mem, "MRIStepCreate")) return 1; + MRIStepCoupling C = MRIStepCoupling_LoadTableByName((opts.mri_method).c_str()); + if (check_ptr((void*)C, "MRIStepCoupling_LoadTableByName")) return 1; + retval = MRIStepSetCoupling(arkode_mem, C); + if (check_flag(retval, "MRIStepSetCoupling")) return 1; + SUNMatrix As = NULL; // matrix for slow solver + SUNLinearSolver LSs = NULL; // slow linear solver object + if (slowimplicit) + { + As = SUNDenseMatrix(NEQ, NEQ, sunctx); + if (check_ptr((void*)As, "SUNDenseMatrix")) return 1; + LSs = SUNLinSol_Dense(y, As, sunctx); + if (check_ptr((void*)LSs, "SUNLinSol_Dense")) return 1; + retval = ARKodeSetLinearSolver(arkode_mem, LSs, As); + if (check_flag(retval, "ARKodeSetLinearSolver")) return 1; + retval = ARKodeSetJacFn(arkode_mem, J_s); + if (check_flag(retval, "ARKodeSetJacFn")) return 1; + } + retval = ARKodeSStolerances(arkode_mem, opts.rtol, opts.atol); + if (check_flag(retval, "ARKodeSStolerances")) return 1; + retval = ARKodeSetMaxNumSteps(arkode_mem, 100000); + if (check_flag(retval, "ARKodeSetMaxNumSteps")) return 1; + retval = ARKodeSetUserData(arkode_mem, (void*)&opts); + if (check_flag(retval, "ARKodeSetUserData")) return 1; + if (opts.scontrol != 0) + { + retval = ARKodeSetAdaptController(arkode_mem, scontrol); + if (check_flag(retval, "ARKodeSetAdaptController")) return 1; + if (opts.set_h0 != 0) + { + retval = ARKodeSetInitStep(arkode_mem, opts.hs); + if (check_flag(retval, "ARKodeSetInitStep")) return 1; + } + if (opts.slow_pq == 1) + { + retval = ARKodeSetAdaptivityAdjustment(arkode_mem, 0); + if (check_flag(retval, "ARKodeSetAdaptivityAdjustment")) return 1; + } + if (opts.slow_safety > -1) + { + retval = ARKodeSetSafetyFactor(arkode_mem, opts.slow_safety); + if (check_flag(retval, "ARKodeSetSafetyFactor")) return 1; + } + } + else + { + retval = ARKodeSetFixedStep(arkode_mem, opts.hs); + if (check_flag(retval, "ARKodeSetFixedStep")) return 1; + } + + // + // Integrate ODE + // + + // Main time-stepping loop: calls ARKodeEvolve to perform the + // integration, then prints results. Stops when the final time + // has been reached + sunrealtype t = T0; + sunrealtype t2 = T0; + sunrealtype dTout = (Tf - T0) / Nt; + sunrealtype tout = T0 + dTout; + sunrealtype u, v, w, uerr, verr, werr, uerrtot, verrtot, werrtot, errtot; + sunrealtype accuracy; + uerr = verr = werr = uerrtot = verrtot = werrtot = errtot = accuracy = ZERO; + printf(" t u v w uerr verr " + "werr\n"); + printf(" " + "---------------------------------------------------------------------" + "----\n"); + printf(" %10.6" FSYM " %10.6" FSYM " %10.6" FSYM " %10.6" FSYM " %.1" ESYM + " %.1" ESYM " %.1" ESYM "\n", + t, ydata[0], ydata[1], ydata[2], uerr, verr, werr); + while (Tf - t > SUN_RCONST(1.0e-8)) + { + // reset reference solver so that it begins with identical state + retval = ARKodeReset(arkode_ref, t, y); + + // evolve solution in one-step mode + retval = ARKodeSetStopTime(arkode_mem, tout); + if (check_flag(retval, "ARKodeSetStopTime")) return 1; + retval = ARKodeEvolve(arkode_mem, tout, y, &t, ARK_ONE_STEP); + if (retval < 0) + { + printf("ARKodeEvolve error (%i)\n", retval); + return 1; + } + + // evolve reference solver to same time in "normal" mode + retval = ARKodeSetStopTime(arkode_ref, t); + if (check_flag(retval, "ARKodeSetStopTime")) return 1; + retval = ARKodeEvolve(arkode_ref, t, yref, &t2, ARK_NORMAL); + if (retval < 0) + { + printf("ARKodeEvolve reference solution error (%i)\n", retval); + return 1; + } + + // access/print solution and error + u = ydata[0]; + v = ydata[1]; + w = ydata[2]; + uerr = std::abs(yrefdata[0] - u); + verr = std::abs(yrefdata[1] - v); + werr = std::abs(yrefdata[2] - w); + uerrtot += uerr * uerr; + verrtot += verr * verr; + werrtot += werr * werr; + errtot += uerr * uerr + verr * verr + werr * werr; + accuracy = std::max(accuracy, + uerr / std::abs(opts.atol + opts.rtol * yrefdata[0])); + accuracy = std::max(accuracy, + verr / std::abs(opts.atol + opts.rtol * yrefdata[1])); + accuracy = std::max(accuracy, + werr / std::abs(opts.atol + opts.rtol * yrefdata[2])); + + // Periodically output current results to screen + if (t >= tout) + { + tout += dTout; + tout = (tout > Tf) ? Tf : tout; + printf(" %10.6" FSYM " %10.6" FSYM " %10.6" FSYM " %10.6" FSYM + " %.1" ESYM " %.1" ESYM " %.1" ESYM "\n", + t, u, v, w, uerr, verr, werr); + } + } + printf(" " + "---------------------------------------------------------------------" + "----\n"); + + // + // Finalize + // + + // Get some slow integrator statistics + long int nsts, natts, netfs, nfse, nfsi; + retval = ARKodeGetNumSteps(arkode_mem, &nsts); + check_flag(retval, "ARKodeGetNumSteps"); + retval = ARKodeGetNumStepAttempts(arkode_mem, &natts); + check_flag(retval, "ARKodeGetNumStepAttempts"); + retval = ARKodeGetNumErrTestFails(arkode_mem, &netfs); + check_flag(retval, "ARKodeGetNumErrTestFails"); + retval = ARKodeGetNumRhsEvals(arkode_mem, 0, &nfse); + check_flag(retval, "ARKodeGetNumRhsEvals"); + retval = ARKodeGetNumRhsEvals(arkode_mem, 1, &nfsi); + check_flag(retval, "ARKodeGetNumRhsEvals"); + + // Get some fast integrator statistics + long int nstf, nattf, netff, nff; + retval = ARKodeGetNumSteps(inner_arkode_mem, &nstf); + check_flag(retval, "ARKodeGetNumSteps"); + retval = ARKodeGetNumStepAttempts(inner_arkode_mem, &nattf); + check_flag(retval, "ARKodeGetNumStepAttempts"); + retval = ARKodeGetNumErrTestFails(inner_arkode_mem, &netff); + check_flag(retval, "ARKodeGetNumErrTestFails"); + retval = ARKodeGetNumRhsEvals(inner_arkode_mem, 0, &nff); + check_flag(retval, "ARKodeGetNumRhsEvals"); + + // Print some final statistics + uerrtot = std::sqrt(uerrtot / (sunrealtype)nsts); + verrtot = std::sqrt(verrtot / (sunrealtype)nsts); + werrtot = std::sqrt(werrtot / (sunrealtype)nsts); + errtot = std::sqrt(errtot / SUN_RCONST(3.0) / (sunrealtype)nsts); + std::cout << "\nFinal Solver Statistics:\n"; + std::cout << " Slow steps = " << nsts << " (attempts = " << natts + << ", fails = " << netfs << ")\n"; + std::cout << " Fast steps = " << nstf << " (attempts = " << nattf + << ", fails = " << netff << ")\n"; + std::cout << " u error = " << uerrtot << ", v error = " << verrtot + << ", w error = " << werrtot << ", total error = " << errtot + << std::endl; + std::cout << " Relative accuracy = " << accuracy << std::endl; + std::cout << " Total RHS evals: Fse = " << nfse << ", Fsi = " << nfsi + << ", Ff = " << nff << std::endl; + + // Get/print slow integrator decoupled implicit solver statistics + if (slowimplicit) + { + long int nnis, nncs, njes; + retval = ARKodeGetNonlinSolvStats(arkode_mem, &nnis, &nncs); + check_flag(retval, "ARKodeGetNonlinSolvStats"); + retval = ARKodeGetNumJacEvals(arkode_mem, &njes); + check_flag(retval, "ARKodeGetNumJacEvals"); + std::cout << " Slow Newton iters = " << nnis << std::endl; + std::cout << " Slow Newton conv fails = " << nncs << std::endl; + std::cout << " Slow Jacobian evals = " << njes << std::endl; + } + + // Clean up and return + N_VDestroy(y); + MRIStepCoupling_Free(C); + if (As) { SUNMatDestroy(As); } + if (LSs) { SUNLinSolFree(LSs); } + if (scontrol) { SUNAdaptController_Destroy(scontrol); } + if (scontrol_H) { SUNAdaptController_Destroy(scontrol_H); } + if (scontrol_Tol) { SUNAdaptController_Destroy(scontrol_Tol); } + if (fcontrol) { SUNAdaptController_Destroy(fcontrol); } + ARKodeFree(&inner_arkode_mem); // Free fast integrator memory + MRIStepInnerStepper_Free(&inner_stepper); // Free inner stepper structure + ARKodeFree(&arkode_mem); // Free slow integrator memory + ARKodeFree(&arkode_ref); // Free reference solver memory + SUNLogger_Destroy(&logger); // Free logger + + return 0; +} + +// ------------------------------ +// Functions called by the solver +// ----------------------------- + +// ff routine to compute the fast portion of the ODE RHS. +static int ff(sunrealtype t, N_Vector y, N_Vector ydot, void* user_data) +{ + Options* opts = (Options*)user_data; + sunrealtype* ydata = N_VGetArrayPointer(y); + sunrealtype* dydata = N_VGetArrayPointer(ydot); + const sunrealtype w = ydata[2]; + + // fill in the RHS function: + dydata[0] = ZERO; + dydata[1] = ZERO; + dydata[2] = (opts->b - w) / opts->ep; + + // Return with success + return 0; +} + +// fs routine to compute the slow portion of the ODE RHS. +static int fs(sunrealtype t, N_Vector y, N_Vector ydot, void* user_data) +{ + Options* opts = (Options*)user_data; + sunrealtype* ydata = N_VGetArrayPointer(y); + sunrealtype* dydata = N_VGetArrayPointer(ydot); + const sunrealtype u = ydata[0]; + const sunrealtype v = ydata[1]; + const sunrealtype w = ydata[2]; + + // fill in the RHS function: + dydata[0] = opts->a - (w + ONE) * u + v * u * u; + dydata[1] = w * u - v * u * u; + dydata[2] = -w * u; + + // Return with success + return 0; +} + +// fse routine to compute the slow portion of the ODE RHS. +static int fse(sunrealtype t, N_Vector y, N_Vector ydot, void* user_data) +{ + Options* opts = (Options*)user_data; + sunrealtype* ydata = N_VGetArrayPointer(y); + sunrealtype* dydata = N_VGetArrayPointer(ydot); + const sunrealtype u = ydata[0]; + const sunrealtype v = ydata[1]; + + // fill in the RHS function: + dydata[0] = opts->a + v * u * u; + dydata[1] = -v * u * u; + dydata[2] = ZERO; + + // Return with success + return 0; +} + +// fsi routine to compute the slow portion of the ODE RHS.(currently same as fse) +static int fsi(sunrealtype t, N_Vector y, N_Vector ydot, void* user_data) +{ + sunrealtype* ydata = N_VGetArrayPointer(y); + sunrealtype* dydata = N_VGetArrayPointer(ydot); + const sunrealtype u = ydata[0]; + const sunrealtype w = ydata[2]; + + // fill in the RHS function: + dydata[0] = -(w + ONE) * u; + dydata[1] = w * u; + dydata[2] = -w * u; + + // Return with success + return 0; +} + +static int fn(sunrealtype t, N_Vector y, N_Vector ydot, void* user_data) +{ + Options* opts = (Options*)user_data; + sunrealtype* ydata = N_VGetArrayPointer(y); + sunrealtype* dydata = N_VGetArrayPointer(ydot); + const sunrealtype u = ydata[0]; + const sunrealtype v = ydata[1]; + const sunrealtype w = ydata[2]; + + // fill in the RHS function: + dydata[0] = opts->a - (w + ONE) * u + v * u * u; + dydata[1] = w * u - v * u * u; + dydata[2] = (opts->b - w) / opts->ep - w * u; + + // Return with success + return 0; +} + +static int f0(sunrealtype t, N_Vector y, N_Vector ydot, void* user_data) +{ + N_VConst(ZERO, ydot); + return (0); +} + +static int Js(sunrealtype t, N_Vector y, N_Vector fy, SUNMatrix J, + void* user_data, N_Vector tmp1, N_Vector tmp2, N_Vector tmp3) +{ + sunrealtype* ydata = N_VGetArrayPointer(y); + const sunrealtype u = ydata[0]; + const sunrealtype v = ydata[1]; + const sunrealtype w = ydata[2]; + + // fill in the Jacobian: + SM_ELEMENT_D(J, 0, 0) = -(w + ONE) + TWO * u * v; + SM_ELEMENT_D(J, 0, 1) = u * u; + SM_ELEMENT_D(J, 0, 2) = -u; + + SM_ELEMENT_D(J, 1, 0) = w - TWO * u * v; + SM_ELEMENT_D(J, 1, 1) = -u * u; + SM_ELEMENT_D(J, 1, 2) = u; + + SM_ELEMENT_D(J, 2, 0) = -w; + SM_ELEMENT_D(J, 2, 1) = ZERO; + SM_ELEMENT_D(J, 2, 2) = -u; + + // Return with success + return 0; +} + +static int Jsi(sunrealtype t, N_Vector y, N_Vector fy, SUNMatrix J, + void* user_data, N_Vector tmp1, N_Vector tmp2, N_Vector tmp3) +{ + sunrealtype* ydata = N_VGetArrayPointer(y); + const sunrealtype u = ydata[0]; + const sunrealtype w = ydata[2]; + + // fill in the Jacobian: + SM_ELEMENT_D(J, 0, 0) = -(w + ONE); + SM_ELEMENT_D(J, 0, 1) = ZERO; + SM_ELEMENT_D(J, 0, 2) = -u; + + SM_ELEMENT_D(J, 1, 0) = w; + SM_ELEMENT_D(J, 1, 1) = ZERO; + SM_ELEMENT_D(J, 1, 2) = u; + + SM_ELEMENT_D(J, 2, 0) = -w; + SM_ELEMENT_D(J, 2, 1) = ZERO; + SM_ELEMENT_D(J, 2, 2) = -u; + + // Return with success + return 0; +} + +static int Jn(sunrealtype t, N_Vector y, N_Vector fy, SUNMatrix J, + void* user_data, N_Vector tmp1, N_Vector tmp2, N_Vector tmp3) +{ + Options* opts = (Options*)user_data; + sunrealtype* ydata = N_VGetArrayPointer(y); + const sunrealtype u = ydata[0]; + const sunrealtype v = ydata[1]; + const sunrealtype w = ydata[2]; + + // fill in the Jacobian: + SM_ELEMENT_D(J, 0, 0) = -(w + ONE) + TWO * u * v; + SM_ELEMENT_D(J, 0, 1) = u * u; + SM_ELEMENT_D(J, 0, 2) = -u; + + SM_ELEMENT_D(J, 1, 0) = w - TWO * u * v; + SM_ELEMENT_D(J, 1, 1) = -u * u; + SM_ELEMENT_D(J, 1, 2) = u; + + SM_ELEMENT_D(J, 2, 0) = -w; + SM_ELEMENT_D(J, 2, 1) = ZERO; + SM_ELEMENT_D(J, 2, 2) = -ONE / opts->ep - u; + + // Return with success + return 0; +} + +// ------------------------------ +// Private helper functions +// ----------------------------- + +// ----------------------------------------------------------------------------- +// Utility functions +// ----------------------------------------------------------------------------- + +// Print command line options +void InputHelp() +{ + std::cout << std::endl; + std::cout << "Command line options:" << std::endl; + std::cout << " --help : print options and exit\n"; + std::cout << " --ep : stiffness factor\n"; + std::cout << " --hs : slow (fixed/initial) step size\n"; + std::cout << " --hf : fast (fixed/initial) step size\n"; + std::cout + << " --set_h0 : use hs/hf above to set the initial step size\n"; + std::cout << " --rtol : relative solution tolerance\n"; + std::cout << " --atol : absolute solution tolerance\n"; + std::cout + << " --fast_rtol : relative solution tolerance for fast method\n"; + std::cout << " --mri_method : MRI method name (valid ARKODE_MRITableID)\n"; + std::cout << " --fast_order : fast RK method order\n"; + std::cout << " --scontrol : slow time step controller, int in [0,16] " + "(see source)\n"; + std::cout << " --fcontrol : fast time step controller, int in [0,6] " + "(see source)\n"; + std::cout << " --faccum : fast error accumulation type {-1,0,1,2}\n"; + std::cout << " --slow_pq : use p (0) vs q (1) for slow adaptivity\n"; + std::cout << " --fast_pq : use p (0) vs q (1) for fast adaptivity\n"; + std::cout << " --k1s, --k2s, ..., -k6s : slow controller parameters\n"; + std::cout << " --k1f, --k2f, -k3f : fast controller parameters\n"; + std::cout << " --bias : slow and fast controller bias factors\n"; + std::cout << " --safety : slow time step safety factor\n"; + std::cout + << " --htol_relch : HTol controller maximum relative tolerance change\n"; + std::cout + << " --htol_minfac : HTol controller minimum relative tolerance factor\n"; + std::cout + << " --htol_maxfac : HTol controller maximum relative tolerance factor\n"; +} + +// Read input options +int ReadInputs(std::vector& args, Options& opts, SUNContext ctx) +{ + if (find(args.begin(), args.end(), "--help") != args.end()) + { + InputHelp(); + return 1; + } + + // Problem options + find_arg(args, "--ep", opts.ep); + find_arg(args, "--hs", opts.hs); + find_arg(args, "--hf", opts.hf); + find_arg(args, "--set_h0", opts.set_h0); + find_arg(args, "--rtol", opts.rtol); + find_arg(args, "--atol", opts.atol); + find_arg(args, "--fast_rtol", opts.fast_rtol); + find_arg(args, "--mri_method", opts.mri_method); + find_arg(args, "--fast_order", opts.fast_order); + find_arg(args, "--scontrol", opts.scontrol); + find_arg(args, "--fcontrol", opts.fcontrol); + find_arg(args, "--faccum", opts.faccum); + find_arg(args, "--slow_pq", opts.slow_pq); + find_arg(args, "--fast_pq", opts.fast_pq); + find_arg(args, "--k1s", opts.k1s); + find_arg(args, "--k2s", opts.k2s); + find_arg(args, "--k3s", opts.k3s); + find_arg(args, "--k1f", opts.k1f); + find_arg(args, "--k2f", opts.k2f); + find_arg(args, "--k3f", opts.k3f); + find_arg(args, "--bias", opts.bias); + find_arg(args, "--safety", opts.slow_safety); + find_arg(args, "--htol_relch", opts.htol_relch); + find_arg(args, "--htol_minfac", opts.htol_minfac); + find_arg(args, "--htol_maxfac", opts.htol_maxfac); + + // Check inputs for validity + // 0 < rtol < 1 + if ((opts.rtol < ZERO) || (opts.rtol > ONE)) + { + std::cerr << "ERROR: rtol must be in (0,1), (" << opts.rtol << " input)\n"; + return -1; + } + // 0 < atol < 1 + if ((opts.atol < ZERO) || (opts.atol > ONE)) + { + std::cerr << "ERROR: atol must be in (0,1), (" << opts.atol << " input)\n"; + return -1; + } + // 0 < fast_rtol < 1 + if ((opts.fast_rtol < ZERO) || (opts.fast_rtol > ONE)) + { + std::cerr << "ERROR: fast_rtol must be in (0,1), (" << opts.fast_rtol + << " input)\n"; + return -1; + } + // slow_pq in {0,1} + if ((opts.slow_pq < 0) || (opts.slow_pq > 1)) + { + std::cerr << "ERROR: slow_pq must be in {0,1}, (" << opts.slow_pq + << " input)\n"; + return -1; + } + // fast_pq in {0,1} + if ((opts.fast_pq < 0) || (opts.fast_pq > 1)) + { + std::cerr << "ERROR: fast_pq must be in {0,1}, (" << opts.fast_pq + << " input)\n"; + return -1; + } + // scontrol in [0,16] + if ((opts.scontrol < 0) || (opts.scontrol > 16)) + { + std::cerr << "ERROR: scontrol must be in [0,16], (" << opts.scontrol + << " input)\n"; + return -1; + } + // fcontrol in [0,6] + if ((opts.fcontrol < 0) || (opts.fcontrol > 6)) + { + std::cerr << "ERROR: fcontrol must be in [0,6], (" << opts.fcontrol + << " input)\n"; + return -1; + } + // hs > 0 if scontrol == 0 + if ((opts.hs <= 0) && (opts.scontrol == 0)) + { + std::cerr << "ERROR: positive hs required with scontrol = 0, (" << opts.hs + << " input)\n"; + return -1; + } + // hf > 0 if fcontrol == 0 + if ((opts.hf <= 0) && (opts.fcontrol == 0)) + { + std::cerr << "ERROR: positive hf required with fcontrol = 0, (" << opts.hf + << " input)\n"; + return -1; + } + // ep > 0.0 + if (opts.ep <= ZERO) + { + std::cerr << "ERROR: ep must be a positive real number, (" << opts.ep + << " input)\n"; + return -1; + } + + return 0; +} + +static void PrintSlowAdaptivity(Options opts) +{ + switch (opts.scontrol) + { + case (0): + std::cout << " fixed steps, hs = " << opts.hs << std::endl; + std::cout << " rtol = " << opts.rtol << ", atol = " << opts.atol << "\n"; + break; + case (5): + std::cout + << " MRI-HTOL controller (using I for H) based on order of MRI " + << ((opts.slow_pq == 1) ? "method\n" : "embedding\n"); + std::cout << " rtol = " << opts.rtol << ", atol = " << opts.atol << "\n"; + std::cout << " fast error accumulation strategy = " << opts.faccum << "\n"; + if (opts.k1s > -1) + { + std::cout << " slow controller parameter: " << opts.k1s << "\n"; + } + if (std::min(opts.htol_relch, std::min(opts.htol_minfac, opts.htol_maxfac)) > + -1) + { + std::cout << " HTol controller parameters: " << opts.htol_relch << " " + << opts.htol_minfac << " " << opts.htol_maxfac << "\n"; + } + break; + case (6): + std::cout << " Decoupled I controller for slow time scale, based on " + "order of MRI " + << ((opts.slow_pq == 1) ? "method\n" : "embedding\n"); + std::cout << " rtol = " << opts.rtol << ", atol = " << opts.atol << "\n"; + if (opts.k1s > -1) + { + std::cout << " slow controller parameter: " << opts.k1s << "\n"; + } + break; + case (7): + std::cout + << " MRI-HTOL controller (using PI for H) based on order of MRI " + << ((opts.slow_pq == 1) ? "method\n" : "embedding\n"); + std::cout << " rtol = " << opts.rtol << ", atol = " << opts.atol << "\n"; + std::cout << " fast error accumulation strategy = " << opts.faccum << "\n"; + if (std::min(opts.k1s, opts.k2s) > -1) + { + std::cout << " slow controller parameters: " << opts.k1s << " " + << opts.k2s << "\n"; + } + if (std::min(opts.htol_relch, std::min(opts.htol_minfac, opts.htol_maxfac)) > + -1) + { + std::cout << " HTol controller parameters: " << opts.htol_relch << " " + << opts.htol_minfac << " " << opts.htol_maxfac << "\n"; + } + break; + case (8): + std::cout << " Decoupled PI controller for slow time scale, based on " + "order of MRI " + << ((opts.slow_pq == 1) ? "method\n" : "embedding\n"); + std::cout << " rtol = " << opts.rtol << ", atol = " << opts.atol << "\n"; + if (std::min(opts.k1s, opts.k2s) > -1) + { + std::cout << " slow controller parameters: " << opts.k1s << " " + << opts.k2s << "\n"; + } + break; + case (9): + std::cout + << " MRI-HTOL controller (using PID for H) based on order of MRI " + << ((opts.slow_pq == 1) ? "method\n" : "embedding\n"); + std::cout << " rtol = " << opts.rtol << ", atol = " << opts.atol << "\n"; + std::cout << " fast error accumulation strategy = " << opts.faccum << "\n"; + if (std::min(opts.k1s, std::min(opts.k2s, opts.k3s)) > -1) + { + std::cout << " slow controller parameters: " << opts.k1s << " " + << opts.k2s << " " << opts.k3s << "\n"; + } + if (std::min(opts.htol_relch, std::min(opts.htol_minfac, opts.htol_maxfac)) > + -1) + { + std::cout << " HTol controller parameters: " << opts.htol_relch << " " + << opts.htol_minfac << " " << opts.htol_maxfac << "\n"; + } + break; + case (10): + std::cout << " Decoupled PID controller for slow time scale, based on " + "order of MRI " + << ((opts.slow_pq == 1) ? "method\n" : "embedding\n"); + std::cout << " rtol = " << opts.rtol << ", atol = " << opts.atol << "\n"; + if (std::min(opts.k1s, std::min(opts.k2s, opts.k3s)) > -1) + { + std::cout << " slow controller parameters: " << opts.k1s << " " + << opts.k2s << " " << opts.k3s << "\n"; + } + break; + case (11): + std::cout + << " MRI-HTOL controller (using ExpGus for H) based on order of MRI " + << ((opts.slow_pq == 1) ? "method\n" : "embedding\n"); + std::cout << " rtol = " << opts.rtol << ", atol = " << opts.atol << "\n"; + std::cout << " fast error accumulation strategy = " << opts.faccum << "\n"; + if (std::min(opts.k1s, opts.k2s) > -1) + { + std::cout << " slow controller parameters: " << opts.k1s << " " + << opts.k2s << "\n"; + } + if (std::min(opts.htol_relch, std::min(opts.htol_minfac, opts.htol_maxfac)) > + -1) + { + std::cout << " HTol controller parameters: " << opts.htol_relch << " " + << opts.htol_minfac << " " << opts.htol_maxfac << "\n"; + } + break; + case (12): + std::cout << " Decoupled ExpGus controller for slow time scale, based " + "on order of MRI " + << ((opts.slow_pq == 1) ? "method\n" : "embedding\n"); + std::cout << " rtol = " << opts.rtol << ", atol = " << opts.atol << "\n"; + if (std::min(opts.k1s, opts.k2s) > -1) + { + std::cout << " slow controller parameters: " << opts.k1s << " " + << opts.k2s << "\n"; + } + break; + case (13): + std::cout + << " MRI-HTOL controller (using ImpGus for H) based on order of MRI " + << ((opts.slow_pq == 1) ? "method\n" : "embedding\n"); + std::cout << " rtol = " << opts.rtol << ", atol = " << opts.atol << "\n"; + std::cout << " fast error accumulation strategy = " << opts.faccum << "\n"; + if (std::min(opts.k1s, opts.k2s) > -1) + { + std::cout << " slow controller parameters: " << opts.k1s << " " + << opts.k2s << "\n"; + } + if (std::min(opts.htol_relch, std::min(opts.htol_minfac, opts.htol_maxfac)) > + -1) + { + std::cout << " HTol controller parameters: " << opts.htol_relch << " " + << opts.htol_minfac << " " << opts.htol_maxfac << "\n"; + } + break; + case (14): + std::cout << " Decoupled ImpGus controller for slow time scale, based " + "on order of MRI " + << ((opts.slow_pq == 1) ? "method\n" : "embedding\n"); + std::cout << " rtol = " << opts.rtol << ", atol = " << opts.atol << "\n"; + if (std::min(opts.k1s, opts.k2s) > -1) + { + std::cout << " slow controller parameters: " << opts.k1s << " " + << opts.k2s << "\n"; + } + break; + case (15): + std::cout + << " MRI-HTOL controller (using ImExGus for H) based on order of MRI " + << ((opts.slow_pq == 1) ? "method\n" : "embedding\n"); + std::cout << " rtol = " << opts.rtol << ", atol = " << opts.atol << "\n"; + std::cout << " fast error accumulation strategy = " << opts.faccum << "\n"; + break; + case (16): + std::cout << " Decoupled ImExGus controller for slow time scale, based " + "on order of MRI " + << ((opts.slow_pq == 1) ? "method\n" : "embedding\n"); + std::cout << " rtol = " << opts.rtol << ", atol = " << opts.atol << "\n"; + break; + } + if (opts.bias > -1) + { + std::cout << " controller bias factor: " << opts.bias << "\n"; + } + if (opts.slow_safety > -1) + { + std::cout << " slow step safety factor: " << opts.slow_safety << "\n"; + } +} + +static void PrintFastAdaptivity(Options opts) +{ + switch (opts.fcontrol) + { + case (0): + std::cout << " fixed steps, hf = " << opts.hf << std::endl; + std::cout << " fast_rtol = " << opts.fast_rtol + << ", atol = " << opts.atol << "\n"; + break; + case (1): + std::cout << " I controller for fast time scale, based on order of RK " + << ((opts.fast_pq == 1) ? "method\n" : "embedding\n"); + std::cout << " fast_rtol = " << opts.fast_rtol + << ", atol = " << opts.atol << "\n"; + if (opts.k1f > -1) + { + std::cout << " fast controller parameter: " << opts.k1f << "\n"; + } + break; + case (2): + std::cout << " PI controller for fast time scale, based on order of RK " + << ((opts.fast_pq == 1) ? "method\n" : "embedding\n"); + std::cout << " fast_rtol = " << opts.fast_rtol + << ", atol = " << opts.atol << "\n"; + if (std::min(opts.k1f, opts.k2f) > -1) + { + std::cout << " fast controller parameters: " << opts.k1f << " " + << opts.k2f << "\n"; + } + break; + case (3): + std::cout << " PID controller for fast time scale, based on order of RK " + << ((opts.fast_pq == 1) ? "method\n" : "embedding\n"); + std::cout << " fast_rtol = " << opts.fast_rtol + << ", atol = " << opts.atol << "\n"; + if (std::min(opts.k1f, std::min(opts.k2f, opts.k3f)) > -1) + { + std::cout << " fast controller parameters: " << opts.k1f << " " + << opts.k2f << " " << opts.k3f << "\n"; + } + break; + case (4): + std::cout + << " ExpGus controller for fast time scale, based on order of RK " + << ((opts.fast_pq == 1) ? "method\n" : "embedding\n"); + std::cout << " fast_rtol = " << opts.fast_rtol + << ", atol = " << opts.atol << "\n"; + if (std::min(opts.k1f, opts.k2f) > -1) + { + std::cout << " fast controller parameters: " << opts.k1f << " " + << opts.k2f << "\n"; + } + break; + case (5): + std::cout + << " ImpGus controller for fast time scale, based on order of RK " + << ((opts.fast_pq == 1) ? "method\n" : "embedding\n"); + std::cout << " fast_rtol = " << opts.fast_rtol + << ", atol = " << opts.atol << "\n"; + if (std::min(opts.k1f, opts.k2f) > -1) + { + std::cout << " fast controller parameters: " << opts.k1f << " " + << opts.k2f << "\n"; + } + break; + case (6): + std::cout + << " ImExGus controller for fast time scale, based on order of RK " + << ((opts.fast_pq == 1) ? "method\n" : "embedding\n"); + std::cout << " fast_rtol = " << opts.fast_rtol + << ", atol = " << opts.atol << "\n"; + break; + } +} + +//---- end of file ----// diff --git a/test/unit_tests/arkode/CXX_serial/ark_test_brusselator_mriadapt_--rtol_0.000004_--scontrol_0.out b/test/unit_tests/arkode/CXX_serial/ark_test_brusselator_mriadapt_--rtol_0.000004_--scontrol_0.out new file mode 100644 index 0000000000..760c6d2b1d --- /dev/null +++ b/test/unit_tests/arkode/CXX_serial/ark_test_brusselator_mriadapt_--rtol_0.000004_--scontrol_0.out @@ -0,0 +1,43 @@ + +Adaptive multirate stiff Brusselator test problem: + time domain: (0,10] + ep = 0.0004 + + Slow integrator: ARKODE_MRI_GARK_ERK45a (explicit) + fixed steps, hs = 0.01 + rtol = 4e-06, atol = 1e-11 + + Fast order 4 + I controller for fast time scale, based on order of RK embedding + fast_rtol = 0.0001, atol = 1e-11 + t u v w uerr verr werr + ------------------------------------------------------------------------- + 0.000000 1.200000 3.100000 3.000000 0.0e+00 0.0e+00 0.0e+00 + 0.500000 1.200613 2.996066 3.498311 1.2e-07 1.2e-07 8.6e-06 + 1.000000 1.107158 3.008131 3.498438 1.2e-07 1.2e-07 1.3e-05 + 1.500000 0.917798 3.188082 3.498698 1.0e-07 1.0e-07 1.7e-05 + 2.000000 0.691486 3.512327 3.499015 7.6e-08 7.6e-08 1.7e-05 + 2.500000 0.510160 3.896431 3.499274 5.5e-08 5.5e-08 1.2e-05 + 3.000000 0.410222 4.269502 3.499416 4.6e-08 4.6e-08 9.6e-06 + 3.500000 0.372044 4.614020 3.499469 3.0e-08 3.0e-08 9.8e-06 + 4.000000 0.367587 4.934562 3.499478 5.3e-08 5.3e-08 7.9e-06 + 4.500000 0.382205 5.233154 3.499474 3.2e-08 3.2e-08 9.1e-06 + 5.000000 0.412956 5.504352 3.499431 4.1e-08 4.1e-08 8.5e-06 + 5.500000 0.467990 5.730486 3.499356 5.5e-08 5.5e-08 1.1e-05 + 6.000000 0.585318 5.854262 3.499196 6.5e-08 6.6e-08 1.5e-05 + 6.500000 1.060808 5.503433 3.498555 5.4e-07 5.5e-07 3.8e-05 + 7.000000 4.794999 0.734608 3.493240 3.6e-06 3.6e-06 5.8e-05 + 7.500000 3.037708 1.057903 3.495704 2.0e-06 2.0e-06 4.7e-05 + 8.000000 1.833974 1.562357 3.497406 7.7e-07 7.8e-07 2.7e-05 + 8.500000 1.008519 2.191334 3.498570 2.5e-07 2.5e-07 1.8e-05 + 9.000000 0.534097 2.794912 3.499237 6.6e-08 6.7e-08 1.5e-05 + 9.500000 0.352784 3.263320 3.499486 4.3e-08 4.3e-08 2.0e-05 + 10.000000 0.305955 3.648439 3.499562 2.5e-08 2.5e-08 9.8e-06 + ------------------------------------------------------------------------- + +Final Solver Statistics: + Slow steps = 1000 (attempts = 1000, fails = 0) + Fast steps = 11777 (attempts = 16708, fails = 4931) + u error = 1.83324e-06, v error = 1.63119e-06, w error = 5.54867e-05, total error = 3.20666e-05 + Relative accuracy = 83.5081 + Total RHS evals: Fse = 5000, Fsi = 0, Ff = 79611 diff --git a/test/unit_tests/arkode/CXX_serial/ark_test_dahlquist_mri.cpp b/test/unit_tests/arkode/CXX_serial/ark_test_dahlquist_mri.cpp index 966d5425fb..4134c124bd 100644 --- a/test/unit_tests/arkode/CXX_serial/ark_test_dahlquist_mri.cpp +++ b/test/unit_tests/arkode/CXX_serial/ark_test_dahlquist_mri.cpp @@ -155,6 +155,10 @@ int main(int argc, char* argv[]) numfails += run_tests(MRISTEP_IMEX, prob_opts, prob_data, sunctx); + numfails += run_tests(MRISTEP_MERK, prob_opts, prob_data, sunctx); + + numfails += run_tests(MRISTEP_SR, prob_opts, prob_data, sunctx); + if (numfails) { std::cout << "\n\nFailed " << numfails << " tests!\n"; } else { std::cout << "\n\nAll tests passed!\n"; } @@ -185,7 +189,7 @@ int run_tests(MRISTEP_METHOD_TYPE type, ProblemOptions& prob_opts, SUNMatrix A = nullptr; SUNLinearSolver LS = nullptr; - if (type == MRISTEP_IMPLICIT || type == MRISTEP_IMEX) + if (type == MRISTEP_IMPLICIT || type == MRISTEP_IMEX || type == MRISTEP_SR) { // Initialize dense matrix data structures and solvers A = SUNDenseMatrix(1, 1, sunctx); @@ -229,8 +233,8 @@ int run_tests(MRISTEP_METHOD_TYPE type, ProblemOptions& prob_opts, // Wrap ARKStep integrator as fast integrator object MRIStepInnerStepper inner_stepper = nullptr; - flag = ARKStepCreateMRIStepInnerStepper(arkstep_mem, &inner_stepper); - if (check_flag(&flag, "ARKStepCreateMRIStepInnerStepper", 1)) { return 1; } + flag = ARKodeCreateMRIStepInnerStepper(arkstep_mem, &inner_stepper); + if (check_flag(&flag, "ARKodeCreateMRIStepInnerStepper", 1)) { return 1; } // ---------------------- // Create slow integrator @@ -239,7 +243,7 @@ int run_tests(MRISTEP_METHOD_TYPE type, ProblemOptions& prob_opts, // Create slow integrator based on MRI type void* mristep_mem = nullptr; - if (type == MRISTEP_EXPLICIT) + if ((type == MRISTEP_EXPLICIT) || (type == MRISTEP_MERK)) { mristep_mem = MRIStepCreate(fe, nullptr, prob_opts.t0, y, inner_stepper, sunctx); @@ -249,7 +253,7 @@ int run_tests(MRISTEP_METHOD_TYPE type, ProblemOptions& prob_opts, mristep_mem = MRIStepCreate(nullptr, fi, prob_opts.t0, y, inner_stepper, sunctx); } - else if (type == MRISTEP_IMEX) + else if ((type == MRISTEP_IMEX) || (type == MRISTEP_SR)) { mristep_mem = MRIStepCreate(fe, fi, prob_opts.t0, y, inner_stepper, sunctx); } @@ -268,7 +272,7 @@ int run_tests(MRISTEP_METHOD_TYPE type, ProblemOptions& prob_opts, flag = ARKodeSetFixedStep(mristep_mem, prob_opts.hs); if (check_flag(&flag, "ARKodeSetFixedStep", 1)) { return 1; } - if (type == MRISTEP_IMPLICIT || type == MRISTEP_IMEX) + if (type == MRISTEP_IMPLICIT || type == MRISTEP_IMEX || type == MRISTEP_SR) { // Attach linear solver flag = ARKodeSetLinearSolver(mristep_mem, LS, A); @@ -295,9 +299,9 @@ int run_tests(MRISTEP_METHOD_TYPE type, ProblemOptions& prob_opts, if (check_flag(&flag, "ARKStepSetInterpolantType", 1)) { return 1; } } - // ------------------------------------ - // Evolve with various IMEX MRI methods - // ------------------------------------ + // ------------------------------- + // Evolve with various MRI methods + // ------------------------------- // Methods to test paired with whether they are stiffly accurate std::map methods; @@ -317,6 +321,17 @@ int run_tests(MRISTEP_METHOD_TYPE type, ProblemOptions& prob_opts, {"ARKODE_MRI_GARK_RALSTON3", false}, {"ARKODE_MRI_GARK_ERK45a", false}}); } + else if (type == MRISTEP_MERK) + { + std::cout << "\n=================\n"; + std::cout << "Test MERK methods\n"; + std::cout << "=================\n"; + + methods.insert({{"ARKODE_MERK21", true}, + {"ARKODE_MERK32", true}, + {"ARKODE_MERK43", true}, + {"ARKODE_MERK54", true}}); + } else if (type == MRISTEP_IMPLICIT) { std::cout << "\n=========================\n"; @@ -342,10 +357,21 @@ int run_tests(MRISTEP_METHOD_TYPE type, ProblemOptions& prob_opts, {"ARKODE_IMEX_MRI_GARK3b", false}, {"ARKODE_IMEX_MRI_GARK4", false}}); } + else if (type == MRISTEP_SR) + { + std::cout << "\n========================\n"; + std::cout << "Test IMEX MRI SR methods\n"; + std::cout << "========================\n"; + + methods.insert({{"ARKODE_IMEX_MRI_SR21", true}, + {"ARKODE_IMEX_MRI_SR32", true}, + {"ARKODE_IMEX_MRI_SR43", true}}); + } else { return 1; } for (const auto& pair : methods) { + int methodfails = 0; std::string id = pair.first; bool stiffly_accurate = pair.second; std::cout << "\nTesting method " << id << "\n"; @@ -408,7 +434,7 @@ int run_tests(MRISTEP_METHOD_TYPE type, ProblemOptions& prob_opts, flag = ARKodeGetNumRhsEvals(mristep_mem, 1, &mri_nfsi); if (check_flag(&flag, "ARKodeGetNumRhsEvals", 1)) { return 1; } - if (type == MRISTEP_IMPLICIT || type == MRISTEP_IMEX) + if (type == MRISTEP_IMPLICIT || type == MRISTEP_IMEX || type == MRISTEP_SR) { flag = ARKodeGetNumNonlinSolvIters(mristep_mem, &mri_nni); if (check_flag(&flag, "ARKodeGetNumNonlinSolvIters", 1)) { return 1; } @@ -427,11 +453,8 @@ int run_tests(MRISTEP_METHOD_TYPE type, ProblemOptions& prob_opts, } sunrealtype pow = prob_data.lambda_f; - if (type == MRISTEP_EXPLICIT || type == MRISTEP_IMEX) - { - pow += prob_data.lambda_e; - } - if (type == MRISTEP_IMPLICIT || type == MRISTEP_IMEX) + if (type != MRISTEP_IMPLICIT) { pow += prob_data.lambda_e; } + if (type == MRISTEP_IMPLICIT || type == MRISTEP_IMEX || type == MRISTEP_SR) { pow += prob_data.lambda_i; } @@ -449,7 +472,7 @@ int run_tests(MRISTEP_METHOD_TYPE type, ProblemOptions& prob_opts, std::cout << " Fe evals = " << mri_nfse << "\n"; std::cout << " Fi evals = " << mri_nfsi << "\n"; - if (type == MRISTEP_IMPLICIT || type == MRISTEP_IMEX) + if (type == MRISTEP_IMPLICIT || type == MRISTEP_IMEX || type == MRISTEP_SR) { std::cout << " NLS iters = " << mri_nni << "\n"; std::cout << " NLS fails = " << mri_ncfn << "\n"; @@ -467,31 +490,29 @@ int run_tests(MRISTEP_METHOD_TYPE type, ProblemOptions& prob_opts, int nstages_evaluated = nstages_stored; if (stiffly_accurate) nstages_evaluated--; long int fe_evals = 0; - if (type == MRISTEP_EXPLICIT || type == MRISTEP_IMEX) - { - fe_evals = mri_nst * nstages_evaluated; - } + if (type != MRISTEP_IMPLICIT) { fe_evals = mri_nst * nstages_evaluated; } if (mri_nfse != fe_evals) { - numfails++; + methodfails++; std::cout << "Fe RHS evals: " << mri_nfse << " vs " << fe_evals << "\n"; } long int fi_evals = 0; - if (type == MRISTEP_IMPLICIT || type == MRISTEP_IMEX) + if (type == MRISTEP_IMPLICIT || type == MRISTEP_IMEX || type == MRISTEP_SR) { fi_evals = mri_nst * nstages_evaluated + mri_nni; } if (mri_nfsi != fi_evals) { - numfails++; + methodfails++; std::cout << "Fi RHS evals: " << mri_nfsi << " vs " << fi_evals << "\n"; } - if (numfails) { std::cout << "Failed " << numfails << " tests\n"; } + if (methodfails) { std::cout << "Failed " << methodfails << " tests\n"; } else { std::cout << "All checks passed\n"; } + numfails += methodfails; // ------------------- // Setup for next test @@ -508,7 +529,7 @@ int run_tests(MRISTEP_METHOD_TYPE type, ProblemOptions& prob_opts, if (check_flag(&flag, "ARKStepReInit", 1)) { return 1; } // Re-initialize slow integrator based on MRI type - if (type == MRISTEP_EXPLICIT) + if ((type == MRISTEP_EXPLICIT) || (type == MRISTEP_MERK)) { flag = MRIStepReInit(mristep_mem, fe, nullptr, prob_opts.t0, y); } @@ -516,7 +537,7 @@ int run_tests(MRISTEP_METHOD_TYPE type, ProblemOptions& prob_opts, { flag = MRIStepReInit(mristep_mem, nullptr, fi, prob_opts.t0, y); } - else if (type == MRISTEP_IMEX) + else if (type == MRISTEP_IMEX || type == MRISTEP_SR) { flag = MRIStepReInit(mristep_mem, fe, fi, prob_opts.t0, y); } @@ -528,7 +549,7 @@ int run_tests(MRISTEP_METHOD_TYPE type, ProblemOptions& prob_opts, MRIStepInnerStepper_Free(&inner_stepper); ARKodeFree(&mristep_mem); ARKodeFree(&arkstep_mem); - if (type == MRISTEP_IMPLICIT || type == MRISTEP_IMEX) + if (type == MRISTEP_IMPLICIT || type == MRISTEP_IMEX || type == MRISTEP_SR) { SUNLinSolFree(LS); SUNMatDestroy(A); diff --git a/test/unit_tests/arkode/CXX_serial/ark_test_dahlquist_mri_-1.out b/test/unit_tests/arkode/CXX_serial/ark_test_dahlquist_mri_-1.out index 9f09d86912..dedbba4239 100644 --- a/test/unit_tests/arkode/CXX_serial/ark_test_dahlquist_mri_-1.out +++ b/test/unit_tests/arkode/CXX_serial/ark_test_dahlquist_mri_-1.out @@ -14,6 +14,7 @@ Test explicit MRI methods ========================= Testing method ARKODE_MIS_KW3 + type = explicit MRI nmat = 1 stages = 4 method order (q) = 3 @@ -24,6 +25,7 @@ Testing method ARKODE_MIS_KW3 0.3333333333333333 0 0 0 -0.5208333333333333 0.9375 0 0 0.3541666666666666 -0.6375 0.5333333333333333 0 + 0 0 0 0 Stored stages = 3 @@ -40,15 +42,17 @@ Comparing Solver Statistics: All checks passed Testing method ARKODE_MRI_GARK_ERK22a + type = explicit MRI nmat = 1 stages = 3 method order (q) = 2 - embedding order (p) = 0 + embedding order (p) = 1 c = 0 0.5 1 W[0] = 0 0 0 0.5 0 0 -0.5 1 0 + 0.5 0 0 Stored stages = 2 @@ -65,15 +69,17 @@ Comparing Solver Statistics: All checks passed Testing method ARKODE_MRI_GARK_ERK22b + type = explicit MRI nmat = 1 stages = 3 method order (q) = 2 - embedding order (p) = 0 + embedding order (p) = 1 c = 0 1 1 W[0] = 0 0 0 1 0 0 -0.5 0.5 0 + 0 0 0 Stored stages = 2 @@ -90,22 +96,25 @@ Comparing Solver Statistics: All checks passed Testing method ARKODE_MRI_GARK_ERK33a + type = explicit MRI nmat = 2 stages = 4 method order (q) = 3 - embedding order (p) = 0 + embedding order (p) = 2 c = 0 0.3333333333333333 0.6666666666666666 1 W[0] = 0 0 0 0 0.3333333333333333 0 0 0 -0.3333333333333333 0.6666666666666666 0 0 0 -0.6666666666666666 1 0 + 0.08333333333333333 -0.3333333333333333 0.5833333333333334 0 W[1] = 0 0 0 0 0 0 0 0 0 0 0 0 0.5 0 -0.5 0 + 0 0 0 0 Stored stages = 3 @@ -122,10 +131,11 @@ Comparing Solver Statistics: All checks passed Testing method ARKODE_MRI_GARK_ERK45a + type = explicit MRI nmat = 2 stages = 6 method order (q) = 4 - embedding order (p) = 0 + embedding order (p) = 3 c = 0 0.2 0.4 0.6 0.8 1 W[0] = 0 0 0 0 0 0 @@ -134,6 +144,7 @@ Testing method ARKODE_MRI_GARK_ERK45a -0.5121234603937985 1.955496920787597 -1.243373460393798 0 0 0 -0.1068927211587161 -4.656693056981116 3.994968532757531 0.9686172453823019 0 0 0.911960843690752 -0.1837327083772207 -1.193926866090864 -2.611983006811319 3.277681737588653 0 + -1.858584369075205 2.224667606006969 -0.5244469581796045 -0.09396291472257937 0.45232663597042 0 W[1] = 0 0 0 0 0 0 @@ -142,6 +153,7 @@ Testing method ARKODE_MRI_GARK_ERK45a -0.0382530792124029 0.6952561584248058 -0.6570030792124029 0 0 0 1.87616694642529 3.003768197383342 -3 -1.879935143808632 0 0 -2.423803191489362 2 1 5 -5.576196808510638 0 + 3.304787234042553 -3.304787234042553 0 0 0 0 Stored stages = 5 @@ -158,6 +170,7 @@ Comparing Solver Statistics: All checks passed Testing method ARKODE_MRI_GARK_FORWARD_EULER + type = explicit MRI nmat = 1 stages = 2 method order (q) = 1 @@ -166,6 +179,7 @@ Testing method ARKODE_MRI_GARK_FORWARD_EULER W[0] = 0 0 1 0 + 0 0 Stored stages = 1 @@ -182,15 +196,17 @@ Comparing Solver Statistics: All checks passed Testing method ARKODE_MRI_GARK_RALSTON2 + type = explicit MRI nmat = 1 stages = 3 method order (q) = 2 - embedding order (p) = 0 + embedding order (p) = 1 c = 0 0.6666666666666666 1 W[0] = 0 0 0 0.6666666666666666 0 0 -0.4166666666666666 0.75 0 + 0.3333333333333334 0 0 Stored stages = 2 @@ -207,22 +223,25 @@ Comparing Solver Statistics: All checks passed Testing method ARKODE_MRI_GARK_RALSTON3 + type = explicit MRI nmat = 2 stages = 4 method order (q) = 3 - embedding order (p) = 0 + embedding order (p) = 2 c = 0 0.5 0.75 1 W[0] = 0 0 0 0 0.5 0 0 0 -2.75 3 0 0 1.305555555555556 -0.1666666666666667 -0.8888888888888888 0 + 0.025 0.175 0.05 0 W[1] = 0 0 0 0 0 0 0 0 4.5 -4.5 0 0 -2.166666666666667 -0.5 2.666666666666667 0 + 0 0 0 0 Stored stages = 3 @@ -243,6 +262,7 @@ Test implicit MRI methods ========================= Testing method ARKODE_MRI_GARK_BACKWARD_EULER + type = implicit MRI nmat = 1 stages = 3 method order (q) = 1 @@ -252,6 +272,7 @@ Testing method ARKODE_MRI_GARK_BACKWARD_EULER 0 0 0 1 0 0 -1 0 1 + 0 0 0 Stored stages = 2 @@ -273,19 +294,22 @@ Comparing Solver Statistics: All checks passed Testing method ARKODE_MRI_GARK_ESDIRK34a + type = implicit MRI nmat = 1 - stages = 7 + stages = 8 method order (q) = 3 - embedding order (p) = 0 - c = 0 0.3333333333333333 0.3333333333333333 0.6666666666666666 0.6666666666666666 1 1 + embedding order (p) = 2 + c = 0 0.3333333333333333 0.3333333333333333 0.6666666666666666 0.6666666666666666 1 1 1 G[0] = - 0 0 0 0 0 0 0 - 0.3333333333333333 0 0 0 0 0 0 - -0.435866521508459 0 0.435866521508459 0 0 0 0 - -0.3045790611944505 0 0.6379123945277838 0 0 0 0 - 0.2116913105640267 0 -0.6475578320724856 0 0.435866521508459 0 0 - 0.4454209388055495 0 0.8813784805616198 0 -0.993466086033836 0 0 - -0.435866521508459 0 0 0 0 0 0.435866521508459 + 0 0 0 0 0 0 0 0 + 0.3333333333333333 0 0 0 0 0 0 0 + -0.435866521508459 0 0.435866521508459 0 0 0 0 0 + -0.3045790611944505 0 0.6379123945277838 0 0 0 0 0 + 0.2116913105640267 0 -0.6475578320724856 0 0.435866521508459 0 0 0 + 0.4454209388055495 0 0.8813784805616198 0 -0.993466086033836 0 0 0 + -0.435866521508459 0 0 0 0 0 0.435866521508459 0 + 0 0 0 0 0 0 0 0 + 0.2453831999117524 0 0.4204215033044045 0 -1.576992606344066 0 0.9111879031279093 0 Stored stages = 4 @@ -307,36 +331,41 @@ Comparing Solver Statistics: All checks passed Testing method ARKODE_MRI_GARK_ESDIRK46a + type = implicit MRI nmat = 2 - stages = 11 + stages = 12 method order (q) = 4 - embedding order (p) = 0 - c = 0 0.2 0.2 0.4 0.4 0.6 0.6 0.8 0.8 1 1 + embedding order (p) = 3 + c = 0 0.2 0.2 0.4 0.4 0.6 0.6 0.8 0.8 1 1 1 G[0] = - 0 0 0 0 0 0 0 0 0 0 0 - 0.2 0 0 0 0 0 0 0 0 0 0 - -0.25 0 0.25 0 0 0 0 0 0 0 0 - 0.9179311933794375 0 -0.7179311933794374 0 0 0 0 0 0 0 0 - 2.643172353961828 0 -2.893172353961828 0 0.25 0 0 0 0 0 0 - 0.501564151341775 0 0.06834736723773695 0 -0.369911518579512 0 0 0 0 0 0 - 4.342116951031425 0 0.03897604588394062 0 -4.631092996915365 0 0.25 0 0 0 0 - -1.690014953911908 0 0.7232372452056922 0 1.84784916447243 0 -0.681071455766214 0 0 0 0 - 3.315267994849762 0 1.086235127654301 0 -1.202424037428737 0 -3.449079085075326 0 0.25 0 0 - -1.563558636602688 0 1.020883954835773 0 2.489384426659126 0 -0.1865282766779755 0 -1.560181468214235 0 0 - 0.19 0 -0.2433333333333333 0 0.4233333333333333 0 0.4233333333333333 0 -1.043333333333333 0 0.25 + 0 0 0 0 0 0 0 0 0 0 0 0 + 0.2 0 0 0 0 0 0 0 0 0 0 0 + -0.25 0 0.25 0 0 0 0 0 0 0 0 0 + 0.9179311933794375 0 -0.7179311933794374 0 0 0 0 0 0 0 0 0 + 2.643172353961828 0 -2.893172353961828 0 0.25 0 0 0 0 0 0 0 + 0.501564151341775 0 0.06834736723773695 0 -0.369911518579512 0 0 0 0 0 0 0 + 4.342116951031425 0 0.03897604588394062 0 -4.631092996915365 0 0.25 0 0 0 0 0 + -1.690014953911908 0 0.7232372452056922 0 1.84784916447243 0 -0.681071455766214 0 0 0 0 0 + 3.315267994849762 0 1.086235127654301 0 -1.202424037428737 0 -3.449079085075326 0 0.25 0 0 0 + -1.563558636602688 0 1.020883954835773 0 2.489384426659126 0 -0.1865282766779755 0 -1.560181468214235 0 0 0 + 0.19 0 -0.2433333333333333 0 0.4233333333333333 0 0.4233333333333333 0 -1.043333333333333 0 0.25 0 + 0 0 0 0 0 0 0 0 0 0 0 0 + -0.25 0 0.6355065879145843 0 -0.2777146751476601 0 -0.4798955020445252 0 0.5009086778736938 0 -0.1288050885960927 0 G[1] = - 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 - -1.735862386758875 0 1.735862386758875 0 0 0 0 0 0 0 0 - -5.82844997108155 0 5.82844997108155 0 0 0 0 0 0 0 0 - -0.4610230395256553 0 -0.9787999976333687 0 1.439823037159024 0 0 0 0 0 0 - -7.403989721900906 0 0.06115468960863698 0 7.342835032292269 0 0 0 0 0 0 - 2.099785727661873 0 -1.585581271787903 0 -2.976347367406398 0 2.462142911532428 0 0 0 0 - -5.523652150637583 0 -1.829811152193671 0 1.834216697306453 0 5.519246605524801 0 0 0 0 - 2.020233434143436 0 -2.384427012786476 0 -4.40813747576723 0 0.1519681179818014 0 4.62036293642847 0 0 - 0.12 0 -0.09666666666666666 0 0.2366666666666667 0 0.2366666666666667 0 -0.4966666666666666 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 + -1.735862386758875 0 1.735862386758875 0 0 0 0 0 0 0 0 0 + -5.82844997108155 0 5.82844997108155 0 0 0 0 0 0 0 0 0 + -0.4610230395256553 0 -0.9787999976333687 0 1.439823037159024 0 0 0 0 0 0 0 + -7.403989721900906 0 0.06115468960863698 0 7.342835032292269 0 0 0 0 0 0 0 + 2.099785727661873 0 -1.585581271787903 0 -2.976347367406398 0 2.462142911532428 0 0 0 0 0 + -5.523652150637583 0 -1.829811152193671 0 1.834216697306453 0 5.519246605524801 0 0 0 0 0 + 2.020233434143436 0 -2.384427012786476 0 -4.40813747576723 0 0.1519681179818014 0 4.62036293642847 0 0 0 + 0.12 0 -0.09666666666666666 0 0.2366666666666667 0 0.2366666666666667 0 -0.4966666666666666 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 Stored stages = 6 @@ -358,6 +387,7 @@ Comparing Solver Statistics: All checks passed Testing method ARKODE_MRI_GARK_IMPLICIT_MIDPOINT + type = implicit MRI nmat = 1 stages = 4 method order (q) = 2 @@ -368,6 +398,7 @@ Testing method ARKODE_MRI_GARK_IMPLICIT_MIDPOINT 0.5 0 0 0 -0.5 0 0.5 0 0 0 0.5 0 + 0 0 0 0 Stored stages = 2 @@ -389,15 +420,18 @@ Comparing Solver Statistics: All checks passed Testing method ARKODE_MRI_GARK_IRK21a + type = implicit MRI nmat = 1 - stages = 3 + stages = 4 method order (q) = 2 - embedding order (p) = 0 - c = 0 1 1 + embedding order (p) = 1 + c = 0 1 1 1 G[0] = - 0 0 0 - 1 0 0 - -0.5 0 0.5 + 0 0 0 0 + 1 0 0 0 + -0.5 0 0.5 0 + 0 0 0 0 + -0.5 0 0.5 0 Stored stages = 2 @@ -423,6 +457,7 @@ Test IMEX MRI methods ===================== Testing method ARKODE_IMEX_MRI_GARK3a + type = ImEx MRI nmat = 1 stages = 8 method order (q) = 3 @@ -437,6 +472,7 @@ Testing method ARKODE_IMEX_MRI_GARK3a -0.4271371821005074 0 0.1562747733103381 0 0.5529291480359398 0 0 0 0 0 0 0 0 0 0 0 0.1058582960718796 0 0.6555675011400702 0 -1.197292318720409 0 0.435866521508459 0 + 0 0 0 0 0 0 0 0 G[0] = 0 0 0 0 0 0 0 0 @@ -447,6 +483,7 @@ Testing method ARKODE_IMEX_MRI_GARK3a 0.435866521508459 0 0.9264299099302395 0 -1.080229692192928 0 0 0 -0.435866521508459 0 0 0 0 0 0.435866521508459 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 Stored stages = 4 @@ -468,6 +505,7 @@ Comparing Solver Statistics: All checks passed Testing method ARKODE_IMEX_MRI_GARK3b + type = ImEx MRI nmat = 1 stages = 8 method order (q) = 3 @@ -482,6 +520,7 @@ Testing method ARKODE_IMEX_MRI_GARK3b 0.1195213959425454 0 -1.843725226689662 0 2.006270569992887 0 0 0 -0.5466585780430528 0 2 0 -1.453341421956947 0 0 0 0.1058582960718796 0 0.6555675011400702 0 -1.197292318720409 0 0.435866521508459 0 + 0 0 0 0 0 0 0 0 G[0] = 0 0 0 0 0 0 0 0 @@ -492,6 +531,7 @@ Testing method ARKODE_IMEX_MRI_GARK3b 0.1123373143006048 0 1.051807513648115 0 -0.8820780887029493 0 0 0 -0.1123373143006048 0 -0.1253776037178755 0 -0.1981516034899788 0 0.435866521508459 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 Stored stages = 4 @@ -513,6 +553,7 @@ Comparing Solver Statistics: All checks passed Testing method ARKODE_IMEX_MRI_GARK4 + type = ImEx MRI nmat = 2 stages = 12 method order (q) = 4 @@ -531,6 +572,7 @@ Testing method ARKODE_IMEX_MRI_GARK4 -2.424429547752048 0 2.430325019757162 0 1.905479301151525 0 -1.231139266635725 0 -0.5552355065209142 0 0 0 -0.01044135044479749 0 0.07260303614655074 0 -0.1288275951677261 0 0.1129355350093824 0 -0.04626962554340952 0 0 0 -0.8108522787762101 0 0.2560073199220492 0 0.8068294072697528 0 -0.4557148228721824 0 -0.04626962554340952 0 0.25 0 + 0 0 0 0 0 0 0 0 0 0 0 0 W[1] = 0 0 0 0 0 0 0 0 0 0 0 0 @@ -545,6 +587,7 @@ Testing method ARKODE_IMEX_MRI_GARK4 -1.110471013041828 0 0 0 0 0 0 0 1.110471013041828 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 G[0] = 0 0 0 0 0 0 0 0 0 0 0 0 @@ -559,6 +602,7 @@ Testing method ARKODE_IMEX_MRI_GARK4 3.337028151688726 0 1.547057811385124 0 -4.12988801314935 0 0.9260375565964145 0 -1.555235506520914 0 0 0 -0.8212936292210076 0 0.3286103560686 0 0.6780018121020267 0 -0.3427792878628 0 -0.09253925108681904 0 0.25 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 G[1] = 0 0 0 0 0 0 0 0 0 0 0 0 @@ -573,6 +617,7 @@ Testing method ARKODE_IMEX_MRI_GARK4 -2.610471013041828 0 0 0 0 0 0 0 2.610471013041828 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 Stored stages = 6 @@ -594,6 +639,7 @@ Comparing Solver Statistics: All checks passed Testing method ARKODE_IMEX_MRI_GARK_EULER + type = ImEx MRI nmat = 1 stages = 3 method order (q) = 1 @@ -603,11 +649,13 @@ Testing method ARKODE_IMEX_MRI_GARK_EULER 0 0 0 1 0 0 0 0 0 + 0 0 0 G[0] = 0 0 0 1 0 0 -1 0 1 + 0 0 0 Stored stages = 2 @@ -629,6 +677,7 @@ Comparing Solver Statistics: All checks passed Testing method ARKODE_IMEX_MRI_GARK_MIDPOINT + type = ImEx MRI nmat = 1 stages = 4 method order (q) = 2 @@ -639,12 +688,14 @@ Testing method ARKODE_IMEX_MRI_GARK_MIDPOINT 0.5 0 0 0 0 0 0 0 -0.5 0 1 0 + 0 0 0 0 G[0] = 0 0 0 0 0.5 0 0 0 -0.5 0 0.5 0 0 0 0.5 0 + 0 0 0 0 Stored stages = 2 @@ -666,6 +717,7 @@ Comparing Solver Statistics: All checks passed Testing method ARKODE_IMEX_MRI_GARK_TRAPEZOIDAL + type = ImEx MRI nmat = 1 stages = 4 method order (q) = 2 @@ -676,12 +728,14 @@ Testing method ARKODE_IMEX_MRI_GARK_TRAPEZOIDAL 1 0 0 0 0 0 0 0 -0.5 0 0.5 0 + 0 0 0 0 G[0] = 0 0 0 0 1 0 0 0 -0.5 0 0.5 0 0 0 0 0 + 0 0 0 0 Stored stages = 2 @@ -702,5 +756,391 @@ MRIStep Statistics: Comparing Solver Statistics: All checks passed +================= +Test MERK methods +================= + +Testing method ARKODE_MERK21 + type = MERK + nmat = 2 + stages = 3 + method order (q) = 2 + embedding order (p) = 1 + c = 0 0.5 1 + W[0] = + 0 0 0 + 1 0 0 + 1 0 0 + 1 0 0 + + W[1] = + 0 0 0 + 0 0 0 + -2 2 0 + 0 0 0 + + ngroup = 2 + group[0] = 1 3 + group[1] = 2 + Stored stages = 3 + +MRIStep Statistics: + Time = 0.01 + y(t) = 0.980199 + y_n = 0.980199 + Error = -4.12939e-07 + Steps = 1 + Fe evals = 2 + Fi evals = 0 + +Comparing Solver Statistics: +All checks passed + +Testing method ARKODE_MERK32 + type = MERK + nmat = 2 + stages = 4 + method order (q) = 3 + embedding order (p) = 2 + c = 0 0.5 0.6666666666666666 1 + W[0] = + 0 0 0 0 + 1 0 0 0 + 1 0 0 0 + 1 0 0 0 + 1 0 0 0 + + W[1] = + 0 0 0 0 + 0 0 0 0 + -2 2 0 0 + -1.5 0 1.5 0 + -2 2 0 0 + + ngroup = 3 + group[0] = 1 + group[1] = 2 4 + group[2] = 3 + Stored stages = 4 + +MRIStep Statistics: + Time = 0.01 + y(t) = 0.980199 + y_n = 0.980199 + Error = 4.5532e-10 + Steps = 1 + Fe evals = 3 + Fi evals = 0 + +Comparing Solver Statistics: +All checks passed + +Testing method ARKODE_MERK43 + type = MERK + nmat = 3 + stages = 7 + method order (q) = 4 + embedding order (p) = 3 + c = 0 0.5 0.5 0.3333333333333333 0.8333333333333334 0.3333333333333333 1 + W[0] = + 0 0 0 0 0 0 0 + 1 0 0 0 0 0 0 + 1 0 0 0 0 0 0 + 1 0 0 0 0 0 0 + 1 0 0 0 0 0 0 + 1 0 0 0 0 0 0 + 1 0 0 0 0 0 0 + 1 0 0 0 0 0 0 + + W[1] = + 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 + -2 2 0 0 0 0 0 + -2 2 0 0 0 0 0 + -4.999999999999998 0 -4 8.999999999999998 0 0 0 + -4.999999999999998 0 -4 8.999999999999998 0 0 0 + -4.200000000000001 0 0 0 -0.7999999999999999 5.000000000000001 0 + -4.999999999999998 0 -4 8.999999999999998 0 0 0 + + W[2] = + 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 + 5.999999999999998 0 12 -18 0 0 0 + 5.999999999999998 0 12 -18 0 0 0 + 3.6 0 0 0 2.4 -6 0 + 5.999999999999998 0 12 -18 0 0 0 + + ngroup = 4 + group[0] = 1 + group[1] = 3 2 + group[2] = 5 4 7 + group[3] = 6 + Stored stages = 7 + +MRIStep Statistics: + Time = 0.01 + y(t) = 0.980199 + y_n = 0.980199 + Error = -4.19176e-12 + Steps = 1 + Fe evals = 6 + Fi evals = 0 + +Comparing Solver Statistics: +All checks passed + +Testing method ARKODE_MERK54 + type = MERK + nmat = 4 + stages = 11 + method order (q) = 5 + embedding order (p) = 4 + c = 0 0.5 0.5 0.3333333333333333 0.5 0.3333333333333333 0.25 0.7 0.5 0.6666666666666666 1 + W[0] = + 0 0 0 0 0 0 0 0 0 0 0 + 1 0 0 0 0 0 0 0 0 0 0 + 1 0 0 0 0 0 0 0 0 0 0 + 1 0 0 0 0 0 0 0 0 0 0 + 1 0 0 0 0 0 0 0 0 0 0 + 1 0 0 0 0 0 0 0 0 0 0 + 1 0 0 0 0 0 0 0 0 0 0 + 1 0 0 0 0 0 0 0 0 0 0 + 1 0 0 0 0 0 0 0 0 0 0 + 1 0 0 0 0 0 0 0 0 0 0 + 1 0 0 0 0 0 0 0 0 0 0 + 1 0 0 0 0 0 0 0 0 0 0 + + W[1] = + 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 + -2 2 0 0 0 0 0 0 0 0 0 + -2 2 0 0 0 0 0 0 0 0 0 + -4.999999999999998 0 -4 8.999999999999998 0 0 0 0 0 0 0 + -4.999999999999998 0 -4 8.999999999999998 0 0 0 0 0 0 0 + -4.999999999999998 0 -4 8.999999999999998 0 0 0 0 0 0 0 + -9.000000000000007 0 0 0 4 -27 32.00000000000001 0 0 0 0 + -9.000000000000007 0 0 0 4 -27 32.00000000000001 0 0 0 0 + -9.000000000000007 0 0 0 4 -27 32.00000000000001 0 0 0 0 + -4.928571428571431 0 0 0 0 0 0 71.42857142857147 28.00000000000001 -94.50000000000004 0 + -9.000000000000007 0 0 0 4 -27 32.00000000000001 0 0 0 0 + + W[2] = + 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 + 5.999999999999998 0 12 -18 0 0 0 0 0 0 0 + 5.999999999999998 0 12 -18 0 0 0 0 0 0 0 + 5.999999999999998 0 12 -18 0 0 0 0 0 0 0 + 26 0 0 0 -27.99999999999999 162 -160 0 0 0 0 + 26 0 0 0 -27.99999999999999 162 -160 0 0 0 0 + 26 0 0 0 -27.99999999999999 162 -160 0 0 0 0 + 7.999999999999943 0 0 0 0 0 0 -250.0000000000001 -82.00000000000004 324.0000000000002 0 + 26 0 0 0 -27.99999999999999 162 -160 0 0 0 0 + + W[3] = + 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 + -24.00000000000006 0 0 0 47.99999999999999 -216 192.0000000000001 0 0 0 0 + -24.00000000000006 0 0 0 47.99999999999999 -216 192.0000000000001 0 0 0 0 + -24.00000000000006 0 0 0 47.99999999999999 -216 192.0000000000001 0 0 0 0 + -4.285714285714278 0 0 0 0 0 0 214.2857142857144 60.00000000000002 -270.0000000000001 0 + -24.00000000000006 0 0 0 47.99999999999999 -216 192.0000000000001 0 0 0 0 + + ngroup = 5 + group[0] = 1 + group[1] = 3 2 + group[2] = 6 5 4 + group[3] = 8 9 7 11 + group[4] = 10 + Stored stages = 11 + +MRIStep Statistics: + Time = 0.01 + y(t) = 0.980199 + y_n = 0.980199 + Error = -3.58946e-12 + Steps = 1 + Fe evals = 10 + Fi evals = 0 + +Comparing Solver Statistics: +All checks passed + +======================== +Test IMEX MRI SR methods +======================== + +Testing method ARKODE_IMEX_MRI_SR21 + type = MRISR + nmat = 1 + stages = 4 + method order (q) = 2 + embedding order (p) = 1 + c = 0 0.6 0.2666666666666667 1 + W[0] = + 0 0 0 0 + 0.6 0 0 0 + 0.08484848484848485 0.1818181818181818 0 0 + -0.2407407407407407 0.5074074074074074 0.7333333333333333 0 + -0.25 0.5 0.75 0 + + G[0] = + 0 0 0 0 + -0.4782608695652174 0.4782608695652174 0 0 + -0.1277806419583357 -0.3504802276068817 0.4782608695652174 0 + 0.1281737365715925 -0.9496349237862043 0.3432003176493945 0.4782608695652174 + -2.583333333333333 -0.1666666666666667 2.75 0 + + Stored stages = 4 + +MRIStep Statistics: + Time = 0.01 + y(t) = 0.970446 + y_n = 0.970445 + Error = 6.56922e-07 + Steps = 1 + Fe evals = 3 + Fi evals = 6 + NLS iters = 3 + NLS fails = 0 + LS setups = 1 + LS Fi evals = 0 + Ji evals = 1 + +Comparing Solver Statistics: +All checks passed + +Testing method ARKODE_IMEX_MRI_SR32 + type = MRISR + nmat = 2 + stages = 5 + method order (q) = 3 + embedding order (p) = 2 + c = 0 0.6764705882352942 0.8 1.133333333333333 1 + W[0] = + 0 0 0 0 0 + 0.6764705882352942 0 0 0 0 + 1.014285714285714 -0.2142857142857143 0 0 0 + 0.1073593073593074 0.5714285714285714 0.4545454545454545 0 0 + 0.8641357630008525 0.08623188405797101 0.34375 -0.2941176470588235 0 + 1.020324985968944 -1.483870967741935 1.970588235294118 -0.5070422535211268 0 + + W[1] = + 0 0 0 0 0 + 0 0 0 0 0 + -0.2264473168820995 0.2264473168820995 0 0 0 + -1.741503979463316 8.210746794478919 -6.469242815015602 0 0 + -1.295451217034184 2.560595940177763 -2.104988533033297 0.8398438098897179 0 + -1.638681583030989 6.083126027475434 -5.777777777777778 1.333333333333333 0 + + G[0] = + 0 0 0 0 0 + -0.5714285714285714 0.5714285714285714 0 0 0 + -0.8655695979919582 0.2941410265633868 0.5714285714285714 0 0 + 1.211752194844657 -2.237726220818683 0.4545454545454545 0.5714285714285714 0 + 0.02135581474837214 -0.07308298152405064 -0.2010145240388127 -0.3186868806140802 0.5714285714285714 + -0.04323671497584541 0.05514147688060732 0.07142857142857142 -0.08333333333333333 0 + + G[1] = + 0 0 0 0 0 + 0 0 0 0 0 + 0 0 0 0 0 + 0 0 0 0 0 + 0 0 0 0 0 + 0 0 0 0 0 + + Stored stages = 5 + +MRIStep Statistics: + Time = 0.01 + y(t) = 0.970446 + y_n = 0.970446 + Error = -3.76499e-09 + Steps = 1 + Fe evals = 4 + Fi evals = 8 + NLS iters = 4 + NLS fails = 0 + LS setups = 1 + LS Fi evals = 0 + Ji evals = 1 + +Comparing Solver Statistics: +All checks passed + +Testing method ARKODE_IMEX_MRI_SR43 + type = MRISR + nmat = 2 + stages = 7 + method order (q) = 4 + embedding order (p) = 3 + c = 0 0.25 0.75 0.55 0.5 1 1 + W[0] = + 0 0 0 0 0 0 0 + 0.25 0 0 0 0 0 0 + 1.125 -0.375 0 0 0 0 0 + 0.07991452991452991 0.7777777777777778 -0.3076923076923077 0 0 0 0 + 0.3878787878787879 0.1666666666666667 -0.6 0.5454545454545454 0 0 0 + 3.307624927156177 -0.2222222222222222 -0.3636363636363636 -0.1666666666666667 -1.555099674630925 0 0 + 0 0.6363636363636364 -8.344696969696969 13.66792929292929 -7.083333333333333 2.123737373737374 0 + 0.0025 4.083333333333333 7.166666666666667 -0.7 -7.083333333333333 -2.469166666666667 0 + + W[1] = + 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 + -2.75 2.75 0 0 0 0 0 + -0.4198290598290598 -0.4088888888888889 0.8287179487179487 0 0 0 0 + -0.9169340463458111 0.6549019607843137 1.463235294117647 -1.20120320855615 0 0 0 + -6.615249854312355 7.027777777777778 -0.5227272727272727 25.33333333333333 -25.22313398407148 0 0 + 0 0.8106060606060606 14.64772727272727 -11.71085858585859 0 -3.747474747474747 0 + -0.005 -5.708333333333333 -14.6875 15.4625 0 4.938333333333333 0 + + G[0] = + 0 0 0 0 0 0 0 + -0.25 0.25 0 0 0 0 0 + 0.25 -0.5 0.25 0 0 0 0 + 0.13 -0.2333333333333333 -0.1466666666666667 0.25 0 0 0 + 0.07058823529411765 -0.2213235294117647 -0.1819852941176471 0.08272058823529412 0.25 0 0 + 0 -2.25 -0.3958333333333333 -4.6875 7.083333333333333 0.25 0 + 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 + + G[1] = + 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 + + Stored stages = 7 + +MRIStep Statistics: + Time = 0.01 + y(t) = 0.970446 + y_n = 0.970446 + Error = -6.94172e-11 + Steps = 1 + Fe evals = 6 + Fi evals = 11 + NLS iters = 5 + NLS fails = 0 + LS setups = 1 + LS Fi evals = 0 + Ji evals = 1 + +Comparing Solver Statistics: +All checks passed + All tests passed! diff --git a/test/unit_tests/arkode/CXX_serial/ark_test_dahlquist_mri_0.out b/test/unit_tests/arkode/CXX_serial/ark_test_dahlquist_mri_0.out index 4591cb3cd3..b4d2dc4117 100644 --- a/test/unit_tests/arkode/CXX_serial/ark_test_dahlquist_mri_0.out +++ b/test/unit_tests/arkode/CXX_serial/ark_test_dahlquist_mri_0.out @@ -14,6 +14,7 @@ Test explicit MRI methods ========================= Testing method ARKODE_MIS_KW3 + type = explicit MRI nmat = 1 stages = 4 method order (q) = 3 @@ -24,6 +25,7 @@ Testing method ARKODE_MIS_KW3 0.3333333333333333 0 0 0 -0.5208333333333333 0.9375 0 0 0.3541666666666666 -0.6375 0.5333333333333333 0 + 0 0 0 0 Stored stages = 3 @@ -40,15 +42,17 @@ Comparing Solver Statistics: All checks passed Testing method ARKODE_MRI_GARK_ERK22a + type = explicit MRI nmat = 1 stages = 3 method order (q) = 2 - embedding order (p) = 0 + embedding order (p) = 1 c = 0 0.5 1 W[0] = 0 0 0 0.5 0 0 -0.5 1 0 + 0.5 0 0 Stored stages = 2 @@ -65,15 +69,17 @@ Comparing Solver Statistics: All checks passed Testing method ARKODE_MRI_GARK_ERK22b + type = explicit MRI nmat = 1 stages = 3 method order (q) = 2 - embedding order (p) = 0 + embedding order (p) = 1 c = 0 1 1 W[0] = 0 0 0 1 0 0 -0.5 0.5 0 + 0 0 0 Stored stages = 2 @@ -90,22 +96,25 @@ Comparing Solver Statistics: All checks passed Testing method ARKODE_MRI_GARK_ERK33a + type = explicit MRI nmat = 2 stages = 4 method order (q) = 3 - embedding order (p) = 0 + embedding order (p) = 2 c = 0 0.3333333333333333 0.6666666666666666 1 W[0] = 0 0 0 0 0.3333333333333333 0 0 0 -0.3333333333333333 0.6666666666666666 0 0 0 -0.6666666666666666 1 0 + 0.08333333333333333 -0.3333333333333333 0.5833333333333334 0 W[1] = 0 0 0 0 0 0 0 0 0 0 0 0 0.5 0 -0.5 0 + 0 0 0 0 Stored stages = 3 @@ -122,10 +131,11 @@ Comparing Solver Statistics: All checks passed Testing method ARKODE_MRI_GARK_ERK45a + type = explicit MRI nmat = 2 stages = 6 method order (q) = 4 - embedding order (p) = 0 + embedding order (p) = 3 c = 0 0.2 0.4 0.6 0.8 1 W[0] = 0 0 0 0 0 0 @@ -134,6 +144,7 @@ Testing method ARKODE_MRI_GARK_ERK45a -0.5121234603937985 1.955496920787597 -1.243373460393798 0 0 0 -0.1068927211587161 -4.656693056981116 3.994968532757531 0.9686172453823019 0 0 0.911960843690752 -0.1837327083772207 -1.193926866090864 -2.611983006811319 3.277681737588653 0 + -1.858584369075205 2.224667606006969 -0.5244469581796045 -0.09396291472257937 0.45232663597042 0 W[1] = 0 0 0 0 0 0 @@ -142,6 +153,7 @@ Testing method ARKODE_MRI_GARK_ERK45a -0.0382530792124029 0.6952561584248058 -0.6570030792124029 0 0 0 1.87616694642529 3.003768197383342 -3 -1.879935143808632 0 0 -2.423803191489362 2 1 5 -5.576196808510638 0 + 3.304787234042553 -3.304787234042553 0 0 0 0 Stored stages = 5 @@ -158,6 +170,7 @@ Comparing Solver Statistics: All checks passed Testing method ARKODE_MRI_GARK_FORWARD_EULER + type = explicit MRI nmat = 1 stages = 2 method order (q) = 1 @@ -166,6 +179,7 @@ Testing method ARKODE_MRI_GARK_FORWARD_EULER W[0] = 0 0 1 0 + 0 0 Stored stages = 1 @@ -182,15 +196,17 @@ Comparing Solver Statistics: All checks passed Testing method ARKODE_MRI_GARK_RALSTON2 + type = explicit MRI nmat = 1 stages = 3 method order (q) = 2 - embedding order (p) = 0 + embedding order (p) = 1 c = 0 0.6666666666666666 1 W[0] = 0 0 0 0.6666666666666666 0 0 -0.4166666666666666 0.75 0 + 0.3333333333333334 0 0 Stored stages = 2 @@ -207,22 +223,25 @@ Comparing Solver Statistics: All checks passed Testing method ARKODE_MRI_GARK_RALSTON3 + type = explicit MRI nmat = 2 stages = 4 method order (q) = 3 - embedding order (p) = 0 + embedding order (p) = 2 c = 0 0.5 0.75 1 W[0] = 0 0 0 0 0.5 0 0 0 -2.75 3 0 0 1.305555555555556 -0.1666666666666667 -0.8888888888888888 0 + 0.025 0.175 0.05 0 W[1] = 0 0 0 0 0 0 0 0 4.5 -4.5 0 0 -2.166666666666667 -0.5 2.666666666666667 0 + 0 0 0 0 Stored stages = 3 @@ -243,6 +262,7 @@ Test implicit MRI methods ========================= Testing method ARKODE_MRI_GARK_BACKWARD_EULER + type = implicit MRI nmat = 1 stages = 3 method order (q) = 1 @@ -252,6 +272,7 @@ Testing method ARKODE_MRI_GARK_BACKWARD_EULER 0 0 0 1 0 0 -1 0 1 + 0 0 0 Stored stages = 2 @@ -273,19 +294,22 @@ Comparing Solver Statistics: All checks passed Testing method ARKODE_MRI_GARK_ESDIRK34a + type = implicit MRI nmat = 1 - stages = 7 + stages = 8 method order (q) = 3 - embedding order (p) = 0 - c = 0 0.3333333333333333 0.3333333333333333 0.6666666666666666 0.6666666666666666 1 1 + embedding order (p) = 2 + c = 0 0.3333333333333333 0.3333333333333333 0.6666666666666666 0.6666666666666666 1 1 1 G[0] = - 0 0 0 0 0 0 0 - 0.3333333333333333 0 0 0 0 0 0 - -0.435866521508459 0 0.435866521508459 0 0 0 0 - -0.3045790611944505 0 0.6379123945277838 0 0 0 0 - 0.2116913105640267 0 -0.6475578320724856 0 0.435866521508459 0 0 - 0.4454209388055495 0 0.8813784805616198 0 -0.993466086033836 0 0 - -0.435866521508459 0 0 0 0 0 0.435866521508459 + 0 0 0 0 0 0 0 0 + 0.3333333333333333 0 0 0 0 0 0 0 + -0.435866521508459 0 0.435866521508459 0 0 0 0 0 + -0.3045790611944505 0 0.6379123945277838 0 0 0 0 0 + 0.2116913105640267 0 -0.6475578320724856 0 0.435866521508459 0 0 0 + 0.4454209388055495 0 0.8813784805616198 0 -0.993466086033836 0 0 0 + -0.435866521508459 0 0 0 0 0 0.435866521508459 0 + 0 0 0 0 0 0 0 0 + 0.2453831999117524 0 0.4204215033044045 0 -1.576992606344066 0 0.9111879031279093 0 Stored stages = 4 @@ -307,36 +331,41 @@ Comparing Solver Statistics: All checks passed Testing method ARKODE_MRI_GARK_ESDIRK46a + type = implicit MRI nmat = 2 - stages = 11 + stages = 12 method order (q) = 4 - embedding order (p) = 0 - c = 0 0.2 0.2 0.4 0.4 0.6 0.6 0.8 0.8 1 1 + embedding order (p) = 3 + c = 0 0.2 0.2 0.4 0.4 0.6 0.6 0.8 0.8 1 1 1 G[0] = - 0 0 0 0 0 0 0 0 0 0 0 - 0.2 0 0 0 0 0 0 0 0 0 0 - -0.25 0 0.25 0 0 0 0 0 0 0 0 - 0.9179311933794375 0 -0.7179311933794374 0 0 0 0 0 0 0 0 - 2.643172353961828 0 -2.893172353961828 0 0.25 0 0 0 0 0 0 - 0.501564151341775 0 0.06834736723773695 0 -0.369911518579512 0 0 0 0 0 0 - 4.342116951031425 0 0.03897604588394062 0 -4.631092996915365 0 0.25 0 0 0 0 - -1.690014953911908 0 0.7232372452056922 0 1.84784916447243 0 -0.681071455766214 0 0 0 0 - 3.315267994849762 0 1.086235127654301 0 -1.202424037428737 0 -3.449079085075326 0 0.25 0 0 - -1.563558636602688 0 1.020883954835773 0 2.489384426659126 0 -0.1865282766779755 0 -1.560181468214235 0 0 - 0.19 0 -0.2433333333333333 0 0.4233333333333333 0 0.4233333333333333 0 -1.043333333333333 0 0.25 + 0 0 0 0 0 0 0 0 0 0 0 0 + 0.2 0 0 0 0 0 0 0 0 0 0 0 + -0.25 0 0.25 0 0 0 0 0 0 0 0 0 + 0.9179311933794375 0 -0.7179311933794374 0 0 0 0 0 0 0 0 0 + 2.643172353961828 0 -2.893172353961828 0 0.25 0 0 0 0 0 0 0 + 0.501564151341775 0 0.06834736723773695 0 -0.369911518579512 0 0 0 0 0 0 0 + 4.342116951031425 0 0.03897604588394062 0 -4.631092996915365 0 0.25 0 0 0 0 0 + -1.690014953911908 0 0.7232372452056922 0 1.84784916447243 0 -0.681071455766214 0 0 0 0 0 + 3.315267994849762 0 1.086235127654301 0 -1.202424037428737 0 -3.449079085075326 0 0.25 0 0 0 + -1.563558636602688 0 1.020883954835773 0 2.489384426659126 0 -0.1865282766779755 0 -1.560181468214235 0 0 0 + 0.19 0 -0.2433333333333333 0 0.4233333333333333 0 0.4233333333333333 0 -1.043333333333333 0 0.25 0 + 0 0 0 0 0 0 0 0 0 0 0 0 + -0.25 0 0.6355065879145843 0 -0.2777146751476601 0 -0.4798955020445252 0 0.5009086778736938 0 -0.1288050885960927 0 G[1] = - 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 - -1.735862386758875 0 1.735862386758875 0 0 0 0 0 0 0 0 - -5.82844997108155 0 5.82844997108155 0 0 0 0 0 0 0 0 - -0.4610230395256553 0 -0.9787999976333687 0 1.439823037159024 0 0 0 0 0 0 - -7.403989721900906 0 0.06115468960863698 0 7.342835032292269 0 0 0 0 0 0 - 2.099785727661873 0 -1.585581271787903 0 -2.976347367406398 0 2.462142911532428 0 0 0 0 - -5.523652150637583 0 -1.829811152193671 0 1.834216697306453 0 5.519246605524801 0 0 0 0 - 2.020233434143436 0 -2.384427012786476 0 -4.40813747576723 0 0.1519681179818014 0 4.62036293642847 0 0 - 0.12 0 -0.09666666666666666 0 0.2366666666666667 0 0.2366666666666667 0 -0.4966666666666666 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 + -1.735862386758875 0 1.735862386758875 0 0 0 0 0 0 0 0 0 + -5.82844997108155 0 5.82844997108155 0 0 0 0 0 0 0 0 0 + -0.4610230395256553 0 -0.9787999976333687 0 1.439823037159024 0 0 0 0 0 0 0 + -7.403989721900906 0 0.06115468960863698 0 7.342835032292269 0 0 0 0 0 0 0 + 2.099785727661873 0 -1.585581271787903 0 -2.976347367406398 0 2.462142911532428 0 0 0 0 0 + -5.523652150637583 0 -1.829811152193671 0 1.834216697306453 0 5.519246605524801 0 0 0 0 0 + 2.020233434143436 0 -2.384427012786476 0 -4.40813747576723 0 0.1519681179818014 0 4.62036293642847 0 0 0 + 0.12 0 -0.09666666666666666 0 0.2366666666666667 0 0.2366666666666667 0 -0.4966666666666666 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 Stored stages = 6 @@ -358,6 +387,7 @@ Comparing Solver Statistics: All checks passed Testing method ARKODE_MRI_GARK_IMPLICIT_MIDPOINT + type = implicit MRI nmat = 1 stages = 4 method order (q) = 2 @@ -368,6 +398,7 @@ Testing method ARKODE_MRI_GARK_IMPLICIT_MIDPOINT 0.5 0 0 0 -0.5 0 0.5 0 0 0 0.5 0 + 0 0 0 0 Stored stages = 2 @@ -389,15 +420,18 @@ Comparing Solver Statistics: All checks passed Testing method ARKODE_MRI_GARK_IRK21a + type = implicit MRI nmat = 1 - stages = 3 + stages = 4 method order (q) = 2 - embedding order (p) = 0 - c = 0 1 1 + embedding order (p) = 1 + c = 0 1 1 1 G[0] = - 0 0 0 - 1 0 0 - -0.5 0 0.5 + 0 0 0 0 + 1 0 0 0 + -0.5 0 0.5 0 + 0 0 0 0 + -0.5 0 0.5 0 Stored stages = 2 @@ -423,6 +457,7 @@ Test IMEX MRI methods ===================== Testing method ARKODE_IMEX_MRI_GARK3a + type = ImEx MRI nmat = 1 stages = 8 method order (q) = 3 @@ -437,6 +472,7 @@ Testing method ARKODE_IMEX_MRI_GARK3a -0.4271371821005074 0 0.1562747733103381 0 0.5529291480359398 0 0 0 0 0 0 0 0 0 0 0 0.1058582960718796 0 0.6555675011400702 0 -1.197292318720409 0 0.435866521508459 0 + 0 0 0 0 0 0 0 0 G[0] = 0 0 0 0 0 0 0 0 @@ -447,6 +483,7 @@ Testing method ARKODE_IMEX_MRI_GARK3a 0.435866521508459 0 0.9264299099302395 0 -1.080229692192928 0 0 0 -0.435866521508459 0 0 0 0 0 0.435866521508459 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 Stored stages = 4 @@ -468,6 +505,7 @@ Comparing Solver Statistics: All checks passed Testing method ARKODE_IMEX_MRI_GARK3b + type = ImEx MRI nmat = 1 stages = 8 method order (q) = 3 @@ -482,6 +520,7 @@ Testing method ARKODE_IMEX_MRI_GARK3b 0.1195213959425454 0 -1.843725226689662 0 2.006270569992887 0 0 0 -0.5466585780430528 0 2 0 -1.453341421956947 0 0 0 0.1058582960718796 0 0.6555675011400702 0 -1.197292318720409 0 0.435866521508459 0 + 0 0 0 0 0 0 0 0 G[0] = 0 0 0 0 0 0 0 0 @@ -492,6 +531,7 @@ Testing method ARKODE_IMEX_MRI_GARK3b 0.1123373143006048 0 1.051807513648115 0 -0.8820780887029493 0 0 0 -0.1123373143006048 0 -0.1253776037178755 0 -0.1981516034899788 0 0.435866521508459 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 Stored stages = 4 @@ -513,6 +553,7 @@ Comparing Solver Statistics: All checks passed Testing method ARKODE_IMEX_MRI_GARK4 + type = ImEx MRI nmat = 2 stages = 12 method order (q) = 4 @@ -531,6 +572,7 @@ Testing method ARKODE_IMEX_MRI_GARK4 -2.424429547752048 0 2.430325019757162 0 1.905479301151525 0 -1.231139266635725 0 -0.5552355065209142 0 0 0 -0.01044135044479749 0 0.07260303614655074 0 -0.1288275951677261 0 0.1129355350093824 0 -0.04626962554340952 0 0 0 -0.8108522787762101 0 0.2560073199220492 0 0.8068294072697528 0 -0.4557148228721824 0 -0.04626962554340952 0 0.25 0 + 0 0 0 0 0 0 0 0 0 0 0 0 W[1] = 0 0 0 0 0 0 0 0 0 0 0 0 @@ -545,6 +587,7 @@ Testing method ARKODE_IMEX_MRI_GARK4 -1.110471013041828 0 0 0 0 0 0 0 1.110471013041828 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 G[0] = 0 0 0 0 0 0 0 0 0 0 0 0 @@ -559,6 +602,7 @@ Testing method ARKODE_IMEX_MRI_GARK4 3.337028151688726 0 1.547057811385124 0 -4.12988801314935 0 0.9260375565964145 0 -1.555235506520914 0 0 0 -0.8212936292210076 0 0.3286103560686 0 0.6780018121020267 0 -0.3427792878628 0 -0.09253925108681904 0 0.25 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 G[1] = 0 0 0 0 0 0 0 0 0 0 0 0 @@ -573,6 +617,7 @@ Testing method ARKODE_IMEX_MRI_GARK4 -2.610471013041828 0 0 0 0 0 0 0 2.610471013041828 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 Stored stages = 6 @@ -594,6 +639,7 @@ Comparing Solver Statistics: All checks passed Testing method ARKODE_IMEX_MRI_GARK_EULER + type = ImEx MRI nmat = 1 stages = 3 method order (q) = 1 @@ -603,11 +649,13 @@ Testing method ARKODE_IMEX_MRI_GARK_EULER 0 0 0 1 0 0 0 0 0 + 0 0 0 G[0] = 0 0 0 1 0 0 -1 0 1 + 0 0 0 Stored stages = 2 @@ -629,6 +677,7 @@ Comparing Solver Statistics: All checks passed Testing method ARKODE_IMEX_MRI_GARK_MIDPOINT + type = ImEx MRI nmat = 1 stages = 4 method order (q) = 2 @@ -639,12 +688,14 @@ Testing method ARKODE_IMEX_MRI_GARK_MIDPOINT 0.5 0 0 0 0 0 0 0 -0.5 0 1 0 + 0 0 0 0 G[0] = 0 0 0 0 0.5 0 0 0 -0.5 0 0.5 0 0 0 0.5 0 + 0 0 0 0 Stored stages = 2 @@ -666,6 +717,7 @@ Comparing Solver Statistics: All checks passed Testing method ARKODE_IMEX_MRI_GARK_TRAPEZOIDAL + type = ImEx MRI nmat = 1 stages = 4 method order (q) = 2 @@ -676,12 +728,14 @@ Testing method ARKODE_IMEX_MRI_GARK_TRAPEZOIDAL 1 0 0 0 0 0 0 0 -0.5 0 0.5 0 + 0 0 0 0 G[0] = 0 0 0 0 1 0 0 0 -0.5 0 0.5 0 0 0 0 0 + 0 0 0 0 Stored stages = 2 @@ -702,5 +756,391 @@ MRIStep Statistics: Comparing Solver Statistics: All checks passed +================= +Test MERK methods +================= + +Testing method ARKODE_MERK21 + type = MERK + nmat = 2 + stages = 3 + method order (q) = 2 + embedding order (p) = 1 + c = 0 0.5 1 + W[0] = + 0 0 0 + 1 0 0 + 1 0 0 + 1 0 0 + + W[1] = + 0 0 0 + 0 0 0 + -2 2 0 + 0 0 0 + + ngroup = 2 + group[0] = 1 3 + group[1] = 2 + Stored stages = 3 + +MRIStep Statistics: + Time = 0.01 + y(t) = 0.980199 + y_n = 0.980199 + Error = -4.12939e-07 + Steps = 1 + Fe evals = 2 + Fi evals = 0 + +Comparing Solver Statistics: +All checks passed + +Testing method ARKODE_MERK32 + type = MERK + nmat = 2 + stages = 4 + method order (q) = 3 + embedding order (p) = 2 + c = 0 0.5 0.6666666666666666 1 + W[0] = + 0 0 0 0 + 1 0 0 0 + 1 0 0 0 + 1 0 0 0 + 1 0 0 0 + + W[1] = + 0 0 0 0 + 0 0 0 0 + -2 2 0 0 + -1.5 0 1.5 0 + -2 2 0 0 + + ngroup = 3 + group[0] = 1 + group[1] = 2 4 + group[2] = 3 + Stored stages = 4 + +MRIStep Statistics: + Time = 0.01 + y(t) = 0.980199 + y_n = 0.980199 + Error = 4.5532e-10 + Steps = 1 + Fe evals = 3 + Fi evals = 0 + +Comparing Solver Statistics: +All checks passed + +Testing method ARKODE_MERK43 + type = MERK + nmat = 3 + stages = 7 + method order (q) = 4 + embedding order (p) = 3 + c = 0 0.5 0.5 0.3333333333333333 0.8333333333333334 0.3333333333333333 1 + W[0] = + 0 0 0 0 0 0 0 + 1 0 0 0 0 0 0 + 1 0 0 0 0 0 0 + 1 0 0 0 0 0 0 + 1 0 0 0 0 0 0 + 1 0 0 0 0 0 0 + 1 0 0 0 0 0 0 + 1 0 0 0 0 0 0 + + W[1] = + 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 + -2 2 0 0 0 0 0 + -2 2 0 0 0 0 0 + -4.999999999999998 0 -4 8.999999999999998 0 0 0 + -4.999999999999998 0 -4 8.999999999999998 0 0 0 + -4.200000000000001 0 0 0 -0.7999999999999999 5.000000000000001 0 + -4.999999999999998 0 -4 8.999999999999998 0 0 0 + + W[2] = + 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 + 5.999999999999998 0 12 -18 0 0 0 + 5.999999999999998 0 12 -18 0 0 0 + 3.6 0 0 0 2.4 -6 0 + 5.999999999999998 0 12 -18 0 0 0 + + ngroup = 4 + group[0] = 1 + group[1] = 3 2 + group[2] = 5 4 7 + group[3] = 6 + Stored stages = 7 + +MRIStep Statistics: + Time = 0.01 + y(t) = 0.980199 + y_n = 0.980199 + Error = -4.19176e-12 + Steps = 1 + Fe evals = 6 + Fi evals = 0 + +Comparing Solver Statistics: +All checks passed + +Testing method ARKODE_MERK54 + type = MERK + nmat = 4 + stages = 11 + method order (q) = 5 + embedding order (p) = 4 + c = 0 0.5 0.5 0.3333333333333333 0.5 0.3333333333333333 0.25 0.7 0.5 0.6666666666666666 1 + W[0] = + 0 0 0 0 0 0 0 0 0 0 0 + 1 0 0 0 0 0 0 0 0 0 0 + 1 0 0 0 0 0 0 0 0 0 0 + 1 0 0 0 0 0 0 0 0 0 0 + 1 0 0 0 0 0 0 0 0 0 0 + 1 0 0 0 0 0 0 0 0 0 0 + 1 0 0 0 0 0 0 0 0 0 0 + 1 0 0 0 0 0 0 0 0 0 0 + 1 0 0 0 0 0 0 0 0 0 0 + 1 0 0 0 0 0 0 0 0 0 0 + 1 0 0 0 0 0 0 0 0 0 0 + 1 0 0 0 0 0 0 0 0 0 0 + + W[1] = + 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 + -2 2 0 0 0 0 0 0 0 0 0 + -2 2 0 0 0 0 0 0 0 0 0 + -4.999999999999998 0 -4 8.999999999999998 0 0 0 0 0 0 0 + -4.999999999999998 0 -4 8.999999999999998 0 0 0 0 0 0 0 + -4.999999999999998 0 -4 8.999999999999998 0 0 0 0 0 0 0 + -9.000000000000007 0 0 0 4 -27 32.00000000000001 0 0 0 0 + -9.000000000000007 0 0 0 4 -27 32.00000000000001 0 0 0 0 + -9.000000000000007 0 0 0 4 -27 32.00000000000001 0 0 0 0 + -4.928571428571431 0 0 0 0 0 0 71.42857142857147 28.00000000000001 -94.50000000000004 0 + -9.000000000000007 0 0 0 4 -27 32.00000000000001 0 0 0 0 + + W[2] = + 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 + 5.999999999999998 0 12 -18 0 0 0 0 0 0 0 + 5.999999999999998 0 12 -18 0 0 0 0 0 0 0 + 5.999999999999998 0 12 -18 0 0 0 0 0 0 0 + 26 0 0 0 -27.99999999999999 162 -160 0 0 0 0 + 26 0 0 0 -27.99999999999999 162 -160 0 0 0 0 + 26 0 0 0 -27.99999999999999 162 -160 0 0 0 0 + 7.999999999999943 0 0 0 0 0 0 -250.0000000000001 -82.00000000000004 324.0000000000002 0 + 26 0 0 0 -27.99999999999999 162 -160 0 0 0 0 + + W[3] = + 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 + -24.00000000000006 0 0 0 47.99999999999999 -216 192.0000000000001 0 0 0 0 + -24.00000000000006 0 0 0 47.99999999999999 -216 192.0000000000001 0 0 0 0 + -24.00000000000006 0 0 0 47.99999999999999 -216 192.0000000000001 0 0 0 0 + -4.285714285714278 0 0 0 0 0 0 214.2857142857144 60.00000000000002 -270.0000000000001 0 + -24.00000000000006 0 0 0 47.99999999999999 -216 192.0000000000001 0 0 0 0 + + ngroup = 5 + group[0] = 1 + group[1] = 3 2 + group[2] = 6 5 4 + group[3] = 8 9 7 11 + group[4] = 10 + Stored stages = 11 + +MRIStep Statistics: + Time = 0.01 + y(t) = 0.980199 + y_n = 0.980199 + Error = -3.58946e-12 + Steps = 1 + Fe evals = 10 + Fi evals = 0 + +Comparing Solver Statistics: +All checks passed + +======================== +Test IMEX MRI SR methods +======================== + +Testing method ARKODE_IMEX_MRI_SR21 + type = MRISR + nmat = 1 + stages = 4 + method order (q) = 2 + embedding order (p) = 1 + c = 0 0.6 0.2666666666666667 1 + W[0] = + 0 0 0 0 + 0.6 0 0 0 + 0.08484848484848485 0.1818181818181818 0 0 + -0.2407407407407407 0.5074074074074074 0.7333333333333333 0 + -0.25 0.5 0.75 0 + + G[0] = + 0 0 0 0 + -0.4782608695652174 0.4782608695652174 0 0 + -0.1277806419583357 -0.3504802276068817 0.4782608695652174 0 + 0.1281737365715925 -0.9496349237862043 0.3432003176493945 0.4782608695652174 + -2.583333333333333 -0.1666666666666667 2.75 0 + + Stored stages = 4 + +MRIStep Statistics: + Time = 0.01 + y(t) = 0.970446 + y_n = 0.970445 + Error = 6.56922e-07 + Steps = 1 + Fe evals = 3 + Fi evals = 6 + NLS iters = 3 + NLS fails = 0 + LS setups = 1 + LS Fi evals = 0 + Ji evals = 1 + +Comparing Solver Statistics: +All checks passed + +Testing method ARKODE_IMEX_MRI_SR32 + type = MRISR + nmat = 2 + stages = 5 + method order (q) = 3 + embedding order (p) = 2 + c = 0 0.6764705882352942 0.8 1.133333333333333 1 + W[0] = + 0 0 0 0 0 + 0.6764705882352942 0 0 0 0 + 1.014285714285714 -0.2142857142857143 0 0 0 + 0.1073593073593074 0.5714285714285714 0.4545454545454545 0 0 + 0.8641357630008525 0.08623188405797101 0.34375 -0.2941176470588235 0 + 1.020324985968944 -1.483870967741935 1.970588235294118 -0.5070422535211268 0 + + W[1] = + 0 0 0 0 0 + 0 0 0 0 0 + -0.2264473168820995 0.2264473168820995 0 0 0 + -1.741503979463316 8.210746794478919 -6.469242815015602 0 0 + -1.295451217034184 2.560595940177763 -2.104988533033297 0.8398438098897179 0 + -1.638681583030989 6.083126027475434 -5.777777777777778 1.333333333333333 0 + + G[0] = + 0 0 0 0 0 + -0.5714285714285714 0.5714285714285714 0 0 0 + -0.8655695979919582 0.2941410265633868 0.5714285714285714 0 0 + 1.211752194844657 -2.237726220818683 0.4545454545454545 0.5714285714285714 0 + 0.02135581474837214 -0.07308298152405064 -0.2010145240388127 -0.3186868806140802 0.5714285714285714 + -0.04323671497584541 0.05514147688060732 0.07142857142857142 -0.08333333333333333 0 + + G[1] = + 0 0 0 0 0 + 0 0 0 0 0 + 0 0 0 0 0 + 0 0 0 0 0 + 0 0 0 0 0 + 0 0 0 0 0 + + Stored stages = 5 + +MRIStep Statistics: + Time = 0.01 + y(t) = 0.970446 + y_n = 0.970446 + Error = -3.76499e-09 + Steps = 1 + Fe evals = 4 + Fi evals = 8 + NLS iters = 4 + NLS fails = 0 + LS setups = 1 + LS Fi evals = 0 + Ji evals = 1 + +Comparing Solver Statistics: +All checks passed + +Testing method ARKODE_IMEX_MRI_SR43 + type = MRISR + nmat = 2 + stages = 7 + method order (q) = 4 + embedding order (p) = 3 + c = 0 0.25 0.75 0.55 0.5 1 1 + W[0] = + 0 0 0 0 0 0 0 + 0.25 0 0 0 0 0 0 + 1.125 -0.375 0 0 0 0 0 + 0.07991452991452991 0.7777777777777778 -0.3076923076923077 0 0 0 0 + 0.3878787878787879 0.1666666666666667 -0.6 0.5454545454545454 0 0 0 + 3.307624927156177 -0.2222222222222222 -0.3636363636363636 -0.1666666666666667 -1.555099674630925 0 0 + 0 0.6363636363636364 -8.344696969696969 13.66792929292929 -7.083333333333333 2.123737373737374 0 + 0.0025 4.083333333333333 7.166666666666667 -0.7 -7.083333333333333 -2.469166666666667 0 + + W[1] = + 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 + -2.75 2.75 0 0 0 0 0 + -0.4198290598290598 -0.4088888888888889 0.8287179487179487 0 0 0 0 + -0.9169340463458111 0.6549019607843137 1.463235294117647 -1.20120320855615 0 0 0 + -6.615249854312355 7.027777777777778 -0.5227272727272727 25.33333333333333 -25.22313398407148 0 0 + 0 0.8106060606060606 14.64772727272727 -11.71085858585859 0 -3.747474747474747 0 + -0.005 -5.708333333333333 -14.6875 15.4625 0 4.938333333333333 0 + + G[0] = + 0 0 0 0 0 0 0 + -0.25 0.25 0 0 0 0 0 + 0.25 -0.5 0.25 0 0 0 0 + 0.13 -0.2333333333333333 -0.1466666666666667 0.25 0 0 0 + 0.07058823529411765 -0.2213235294117647 -0.1819852941176471 0.08272058823529412 0.25 0 0 + 0 -2.25 -0.3958333333333333 -4.6875 7.083333333333333 0.25 0 + 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 + + G[1] = + 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 + + Stored stages = 7 + +MRIStep Statistics: + Time = 0.01 + y(t) = 0.970446 + y_n = 0.970446 + Error = -6.94172e-11 + Steps = 1 + Fe evals = 6 + Fi evals = 11 + NLS iters = 5 + NLS fails = 0 + LS setups = 1 + LS Fi evals = 0 + Ji evals = 1 + +Comparing Solver Statistics: +All checks passed + All tests passed! diff --git a/test/unit_tests/arkode/CXX_serial/ark_test_dahlquist_mri_1.out b/test/unit_tests/arkode/CXX_serial/ark_test_dahlquist_mri_1.out index 5311a51fcd..9f48d829f2 100644 --- a/test/unit_tests/arkode/CXX_serial/ark_test_dahlquist_mri_1.out +++ b/test/unit_tests/arkode/CXX_serial/ark_test_dahlquist_mri_1.out @@ -14,6 +14,7 @@ Test explicit MRI methods ========================= Testing method ARKODE_MIS_KW3 + type = explicit MRI nmat = 1 stages = 4 method order (q) = 3 @@ -24,6 +25,7 @@ Testing method ARKODE_MIS_KW3 0.3333333333333333 0 0 0 -0.5208333333333333 0.9375 0 0 0.3541666666666666 -0.6375 0.5333333333333333 0 + 0 0 0 0 Stored stages = 3 @@ -40,15 +42,17 @@ Comparing Solver Statistics: All checks passed Testing method ARKODE_MRI_GARK_ERK22a + type = explicit MRI nmat = 1 stages = 3 method order (q) = 2 - embedding order (p) = 0 + embedding order (p) = 1 c = 0 0.5 1 W[0] = 0 0 0 0.5 0 0 -0.5 1 0 + 0.5 0 0 Stored stages = 2 @@ -65,15 +69,17 @@ Comparing Solver Statistics: All checks passed Testing method ARKODE_MRI_GARK_ERK22b + type = explicit MRI nmat = 1 stages = 3 method order (q) = 2 - embedding order (p) = 0 + embedding order (p) = 1 c = 0 1 1 W[0] = 0 0 0 1 0 0 -0.5 0.5 0 + 0 0 0 Stored stages = 2 @@ -90,22 +96,25 @@ Comparing Solver Statistics: All checks passed Testing method ARKODE_MRI_GARK_ERK33a + type = explicit MRI nmat = 2 stages = 4 method order (q) = 3 - embedding order (p) = 0 + embedding order (p) = 2 c = 0 0.3333333333333333 0.6666666666666666 1 W[0] = 0 0 0 0 0.3333333333333333 0 0 0 -0.3333333333333333 0.6666666666666666 0 0 0 -0.6666666666666666 1 0 + 0.08333333333333333 -0.3333333333333333 0.5833333333333334 0 W[1] = 0 0 0 0 0 0 0 0 0 0 0 0 0.5 0 -0.5 0 + 0 0 0 0 Stored stages = 3 @@ -122,10 +131,11 @@ Comparing Solver Statistics: All checks passed Testing method ARKODE_MRI_GARK_ERK45a + type = explicit MRI nmat = 2 stages = 6 method order (q) = 4 - embedding order (p) = 0 + embedding order (p) = 3 c = 0 0.2 0.4 0.6 0.8 1 W[0] = 0 0 0 0 0 0 @@ -134,6 +144,7 @@ Testing method ARKODE_MRI_GARK_ERK45a -0.5121234603937985 1.955496920787597 -1.243373460393798 0 0 0 -0.1068927211587161 -4.656693056981116 3.994968532757531 0.9686172453823019 0 0 0.911960843690752 -0.1837327083772207 -1.193926866090864 -2.611983006811319 3.277681737588653 0 + -1.858584369075205 2.224667606006969 -0.5244469581796045 -0.09396291472257937 0.45232663597042 0 W[1] = 0 0 0 0 0 0 @@ -142,6 +153,7 @@ Testing method ARKODE_MRI_GARK_ERK45a -0.0382530792124029 0.6952561584248058 -0.6570030792124029 0 0 0 1.87616694642529 3.003768197383342 -3 -1.879935143808632 0 0 -2.423803191489362 2 1 5 -5.576196808510638 0 + 3.304787234042553 -3.304787234042553 0 0 0 0 Stored stages = 5 @@ -158,6 +170,7 @@ Comparing Solver Statistics: All checks passed Testing method ARKODE_MRI_GARK_FORWARD_EULER + type = explicit MRI nmat = 1 stages = 2 method order (q) = 1 @@ -166,6 +179,7 @@ Testing method ARKODE_MRI_GARK_FORWARD_EULER W[0] = 0 0 1 0 + 0 0 Stored stages = 1 @@ -182,15 +196,17 @@ Comparing Solver Statistics: All checks passed Testing method ARKODE_MRI_GARK_RALSTON2 + type = explicit MRI nmat = 1 stages = 3 method order (q) = 2 - embedding order (p) = 0 + embedding order (p) = 1 c = 0 0.6666666666666666 1 W[0] = 0 0 0 0.6666666666666666 0 0 -0.4166666666666666 0.75 0 + 0.3333333333333334 0 0 Stored stages = 2 @@ -207,22 +223,25 @@ Comparing Solver Statistics: All checks passed Testing method ARKODE_MRI_GARK_RALSTON3 + type = explicit MRI nmat = 2 stages = 4 method order (q) = 3 - embedding order (p) = 0 + embedding order (p) = 2 c = 0 0.5 0.75 1 W[0] = 0 0 0 0 0.5 0 0 0 -2.75 3 0 0 1.305555555555556 -0.1666666666666667 -0.8888888888888888 0 + 0.025 0.175 0.05 0 W[1] = 0 0 0 0 0 0 0 0 4.5 -4.5 0 0 -2.166666666666667 -0.5 2.666666666666667 0 + 0 0 0 0 Stored stages = 3 @@ -243,6 +262,7 @@ Test implicit MRI methods ========================= Testing method ARKODE_MRI_GARK_BACKWARD_EULER + type = implicit MRI nmat = 1 stages = 3 method order (q) = 1 @@ -252,6 +272,7 @@ Testing method ARKODE_MRI_GARK_BACKWARD_EULER 0 0 0 1 0 0 -1 0 1 + 0 0 0 Stored stages = 2 @@ -273,19 +294,22 @@ Comparing Solver Statistics: All checks passed Testing method ARKODE_MRI_GARK_ESDIRK34a + type = implicit MRI nmat = 1 - stages = 7 + stages = 8 method order (q) = 3 - embedding order (p) = 0 - c = 0 0.3333333333333333 0.3333333333333333 0.6666666666666666 0.6666666666666666 1 1 + embedding order (p) = 2 + c = 0 0.3333333333333333 0.3333333333333333 0.6666666666666666 0.6666666666666666 1 1 1 G[0] = - 0 0 0 0 0 0 0 - 0.3333333333333333 0 0 0 0 0 0 - -0.435866521508459 0 0.435866521508459 0 0 0 0 - -0.3045790611944505 0 0.6379123945277838 0 0 0 0 - 0.2116913105640267 0 -0.6475578320724856 0 0.435866521508459 0 0 - 0.4454209388055495 0 0.8813784805616198 0 -0.993466086033836 0 0 - -0.435866521508459 0 0 0 0 0 0.435866521508459 + 0 0 0 0 0 0 0 0 + 0.3333333333333333 0 0 0 0 0 0 0 + -0.435866521508459 0 0.435866521508459 0 0 0 0 0 + -0.3045790611944505 0 0.6379123945277838 0 0 0 0 0 + 0.2116913105640267 0 -0.6475578320724856 0 0.435866521508459 0 0 0 + 0.4454209388055495 0 0.8813784805616198 0 -0.993466086033836 0 0 0 + -0.435866521508459 0 0 0 0 0 0.435866521508459 0 + 0 0 0 0 0 0 0 0 + 0.2453831999117524 0 0.4204215033044045 0 -1.576992606344066 0 0.9111879031279093 0 Stored stages = 4 @@ -307,36 +331,41 @@ Comparing Solver Statistics: All checks passed Testing method ARKODE_MRI_GARK_ESDIRK46a + type = implicit MRI nmat = 2 - stages = 11 + stages = 12 method order (q) = 4 - embedding order (p) = 0 - c = 0 0.2 0.2 0.4 0.4 0.6 0.6 0.8 0.8 1 1 + embedding order (p) = 3 + c = 0 0.2 0.2 0.4 0.4 0.6 0.6 0.8 0.8 1 1 1 G[0] = - 0 0 0 0 0 0 0 0 0 0 0 - 0.2 0 0 0 0 0 0 0 0 0 0 - -0.25 0 0.25 0 0 0 0 0 0 0 0 - 0.9179311933794375 0 -0.7179311933794374 0 0 0 0 0 0 0 0 - 2.643172353961828 0 -2.893172353961828 0 0.25 0 0 0 0 0 0 - 0.501564151341775 0 0.06834736723773695 0 -0.369911518579512 0 0 0 0 0 0 - 4.342116951031425 0 0.03897604588394062 0 -4.631092996915365 0 0.25 0 0 0 0 - -1.690014953911908 0 0.7232372452056922 0 1.84784916447243 0 -0.681071455766214 0 0 0 0 - 3.315267994849762 0 1.086235127654301 0 -1.202424037428737 0 -3.449079085075326 0 0.25 0 0 - -1.563558636602688 0 1.020883954835773 0 2.489384426659126 0 -0.1865282766779755 0 -1.560181468214235 0 0 - 0.19 0 -0.2433333333333333 0 0.4233333333333333 0 0.4233333333333333 0 -1.043333333333333 0 0.25 + 0 0 0 0 0 0 0 0 0 0 0 0 + 0.2 0 0 0 0 0 0 0 0 0 0 0 + -0.25 0 0.25 0 0 0 0 0 0 0 0 0 + 0.9179311933794375 0 -0.7179311933794374 0 0 0 0 0 0 0 0 0 + 2.643172353961828 0 -2.893172353961828 0 0.25 0 0 0 0 0 0 0 + 0.501564151341775 0 0.06834736723773695 0 -0.369911518579512 0 0 0 0 0 0 0 + 4.342116951031425 0 0.03897604588394062 0 -4.631092996915365 0 0.25 0 0 0 0 0 + -1.690014953911908 0 0.7232372452056922 0 1.84784916447243 0 -0.681071455766214 0 0 0 0 0 + 3.315267994849762 0 1.086235127654301 0 -1.202424037428737 0 -3.449079085075326 0 0.25 0 0 0 + -1.563558636602688 0 1.020883954835773 0 2.489384426659126 0 -0.1865282766779755 0 -1.560181468214235 0 0 0 + 0.19 0 -0.2433333333333333 0 0.4233333333333333 0 0.4233333333333333 0 -1.043333333333333 0 0.25 0 + 0 0 0 0 0 0 0 0 0 0 0 0 + -0.25 0 0.6355065879145843 0 -0.2777146751476601 0 -0.4798955020445252 0 0.5009086778736938 0 -0.1288050885960927 0 G[1] = - 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 - -1.735862386758875 0 1.735862386758875 0 0 0 0 0 0 0 0 - -5.82844997108155 0 5.82844997108155 0 0 0 0 0 0 0 0 - -0.4610230395256553 0 -0.9787999976333687 0 1.439823037159024 0 0 0 0 0 0 - -7.403989721900906 0 0.06115468960863698 0 7.342835032292269 0 0 0 0 0 0 - 2.099785727661873 0 -1.585581271787903 0 -2.976347367406398 0 2.462142911532428 0 0 0 0 - -5.523652150637583 0 -1.829811152193671 0 1.834216697306453 0 5.519246605524801 0 0 0 0 - 2.020233434143436 0 -2.384427012786476 0 -4.40813747576723 0 0.1519681179818014 0 4.62036293642847 0 0 - 0.12 0 -0.09666666666666666 0 0.2366666666666667 0 0.2366666666666667 0 -0.4966666666666666 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 + -1.735862386758875 0 1.735862386758875 0 0 0 0 0 0 0 0 0 + -5.82844997108155 0 5.82844997108155 0 0 0 0 0 0 0 0 0 + -0.4610230395256553 0 -0.9787999976333687 0 1.439823037159024 0 0 0 0 0 0 0 + -7.403989721900906 0 0.06115468960863698 0 7.342835032292269 0 0 0 0 0 0 0 + 2.099785727661873 0 -1.585581271787903 0 -2.976347367406398 0 2.462142911532428 0 0 0 0 0 + -5.523652150637583 0 -1.829811152193671 0 1.834216697306453 0 5.519246605524801 0 0 0 0 0 + 2.020233434143436 0 -2.384427012786476 0 -4.40813747576723 0 0.1519681179818014 0 4.62036293642847 0 0 0 + 0.12 0 -0.09666666666666666 0 0.2366666666666667 0 0.2366666666666667 0 -0.4966666666666666 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 Stored stages = 6 @@ -358,6 +387,7 @@ Comparing Solver Statistics: All checks passed Testing method ARKODE_MRI_GARK_IMPLICIT_MIDPOINT + type = implicit MRI nmat = 1 stages = 4 method order (q) = 2 @@ -368,6 +398,7 @@ Testing method ARKODE_MRI_GARK_IMPLICIT_MIDPOINT 0.5 0 0 0 -0.5 0 0.5 0 0 0 0.5 0 + 0 0 0 0 Stored stages = 2 @@ -389,15 +420,18 @@ Comparing Solver Statistics: All checks passed Testing method ARKODE_MRI_GARK_IRK21a + type = implicit MRI nmat = 1 - stages = 3 + stages = 4 method order (q) = 2 - embedding order (p) = 0 - c = 0 1 1 + embedding order (p) = 1 + c = 0 1 1 1 G[0] = - 0 0 0 - 1 0 0 - -0.5 0 0.5 + 0 0 0 0 + 1 0 0 0 + -0.5 0 0.5 0 + 0 0 0 0 + -0.5 0 0.5 0 Stored stages = 2 @@ -423,6 +457,7 @@ Test IMEX MRI methods ===================== Testing method ARKODE_IMEX_MRI_GARK3a + type = ImEx MRI nmat = 1 stages = 8 method order (q) = 3 @@ -437,6 +472,7 @@ Testing method ARKODE_IMEX_MRI_GARK3a -0.4271371821005074 0 0.1562747733103381 0 0.5529291480359398 0 0 0 0 0 0 0 0 0 0 0 0.1058582960718796 0 0.6555675011400702 0 -1.197292318720409 0 0.435866521508459 0 + 0 0 0 0 0 0 0 0 G[0] = 0 0 0 0 0 0 0 0 @@ -447,6 +483,7 @@ Testing method ARKODE_IMEX_MRI_GARK3a 0.435866521508459 0 0.9264299099302395 0 -1.080229692192928 0 0 0 -0.435866521508459 0 0 0 0 0 0.435866521508459 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 Stored stages = 4 @@ -468,6 +505,7 @@ Comparing Solver Statistics: All checks passed Testing method ARKODE_IMEX_MRI_GARK3b + type = ImEx MRI nmat = 1 stages = 8 method order (q) = 3 @@ -482,6 +520,7 @@ Testing method ARKODE_IMEX_MRI_GARK3b 0.1195213959425454 0 -1.843725226689662 0 2.006270569992887 0 0 0 -0.5466585780430528 0 2 0 -1.453341421956947 0 0 0 0.1058582960718796 0 0.6555675011400702 0 -1.197292318720409 0 0.435866521508459 0 + 0 0 0 0 0 0 0 0 G[0] = 0 0 0 0 0 0 0 0 @@ -492,6 +531,7 @@ Testing method ARKODE_IMEX_MRI_GARK3b 0.1123373143006048 0 1.051807513648115 0 -0.8820780887029493 0 0 0 -0.1123373143006048 0 -0.1253776037178755 0 -0.1981516034899788 0 0.435866521508459 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 Stored stages = 4 @@ -513,6 +553,7 @@ Comparing Solver Statistics: All checks passed Testing method ARKODE_IMEX_MRI_GARK4 + type = ImEx MRI nmat = 2 stages = 12 method order (q) = 4 @@ -531,6 +572,7 @@ Testing method ARKODE_IMEX_MRI_GARK4 -2.424429547752048 0 2.430325019757162 0 1.905479301151525 0 -1.231139266635725 0 -0.5552355065209142 0 0 0 -0.01044135044479749 0 0.07260303614655074 0 -0.1288275951677261 0 0.1129355350093824 0 -0.04626962554340952 0 0 0 -0.8108522787762101 0 0.2560073199220492 0 0.8068294072697528 0 -0.4557148228721824 0 -0.04626962554340952 0 0.25 0 + 0 0 0 0 0 0 0 0 0 0 0 0 W[1] = 0 0 0 0 0 0 0 0 0 0 0 0 @@ -545,6 +587,7 @@ Testing method ARKODE_IMEX_MRI_GARK4 -1.110471013041828 0 0 0 0 0 0 0 1.110471013041828 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 G[0] = 0 0 0 0 0 0 0 0 0 0 0 0 @@ -559,6 +602,7 @@ Testing method ARKODE_IMEX_MRI_GARK4 3.337028151688726 0 1.547057811385124 0 -4.12988801314935 0 0.9260375565964145 0 -1.555235506520914 0 0 0 -0.8212936292210076 0 0.3286103560686 0 0.6780018121020267 0 -0.3427792878628 0 -0.09253925108681904 0 0.25 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 G[1] = 0 0 0 0 0 0 0 0 0 0 0 0 @@ -573,6 +617,7 @@ Testing method ARKODE_IMEX_MRI_GARK4 -2.610471013041828 0 0 0 0 0 0 0 2.610471013041828 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 Stored stages = 6 @@ -594,6 +639,7 @@ Comparing Solver Statistics: All checks passed Testing method ARKODE_IMEX_MRI_GARK_EULER + type = ImEx MRI nmat = 1 stages = 3 method order (q) = 1 @@ -603,11 +649,13 @@ Testing method ARKODE_IMEX_MRI_GARK_EULER 0 0 0 1 0 0 0 0 0 + 0 0 0 G[0] = 0 0 0 1 0 0 -1 0 1 + 0 0 0 Stored stages = 2 @@ -629,6 +677,7 @@ Comparing Solver Statistics: All checks passed Testing method ARKODE_IMEX_MRI_GARK_MIDPOINT + type = ImEx MRI nmat = 1 stages = 4 method order (q) = 2 @@ -639,12 +688,14 @@ Testing method ARKODE_IMEX_MRI_GARK_MIDPOINT 0.5 0 0 0 0 0 0 0 -0.5 0 1 0 + 0 0 0 0 G[0] = 0 0 0 0 0.5 0 0 0 -0.5 0 0.5 0 0 0 0.5 0 + 0 0 0 0 Stored stages = 2 @@ -666,6 +717,7 @@ Comparing Solver Statistics: All checks passed Testing method ARKODE_IMEX_MRI_GARK_TRAPEZOIDAL + type = ImEx MRI nmat = 1 stages = 4 method order (q) = 2 @@ -676,12 +728,14 @@ Testing method ARKODE_IMEX_MRI_GARK_TRAPEZOIDAL 1 0 0 0 0 0 0 0 -0.5 0 0.5 0 + 0 0 0 0 G[0] = 0 0 0 0 1 0 0 0 -0.5 0 0.5 0 0 0 0 0 + 0 0 0 0 Stored stages = 2 @@ -702,5 +756,391 @@ MRIStep Statistics: Comparing Solver Statistics: All checks passed +================= +Test MERK methods +================= + +Testing method ARKODE_MERK21 + type = MERK + nmat = 2 + stages = 3 + method order (q) = 2 + embedding order (p) = 1 + c = 0 0.5 1 + W[0] = + 0 0 0 + 1 0 0 + 1 0 0 + 1 0 0 + + W[1] = + 0 0 0 + 0 0 0 + -2 2 0 + 0 0 0 + + ngroup = 2 + group[0] = 1 3 + group[1] = 2 + Stored stages = 3 + +MRIStep Statistics: + Time = 0.01 + y(t) = 0.980199 + y_n = 0.980199 + Error = -4.12939e-07 + Steps = 1 + Fe evals = 2 + Fi evals = 0 + +Comparing Solver Statistics: +All checks passed + +Testing method ARKODE_MERK32 + type = MERK + nmat = 2 + stages = 4 + method order (q) = 3 + embedding order (p) = 2 + c = 0 0.5 0.6666666666666666 1 + W[0] = + 0 0 0 0 + 1 0 0 0 + 1 0 0 0 + 1 0 0 0 + 1 0 0 0 + + W[1] = + 0 0 0 0 + 0 0 0 0 + -2 2 0 0 + -1.5 0 1.5 0 + -2 2 0 0 + + ngroup = 3 + group[0] = 1 + group[1] = 2 4 + group[2] = 3 + Stored stages = 4 + +MRIStep Statistics: + Time = 0.01 + y(t) = 0.980199 + y_n = 0.980199 + Error = 4.5532e-10 + Steps = 1 + Fe evals = 3 + Fi evals = 0 + +Comparing Solver Statistics: +All checks passed + +Testing method ARKODE_MERK43 + type = MERK + nmat = 3 + stages = 7 + method order (q) = 4 + embedding order (p) = 3 + c = 0 0.5 0.5 0.3333333333333333 0.8333333333333334 0.3333333333333333 1 + W[0] = + 0 0 0 0 0 0 0 + 1 0 0 0 0 0 0 + 1 0 0 0 0 0 0 + 1 0 0 0 0 0 0 + 1 0 0 0 0 0 0 + 1 0 0 0 0 0 0 + 1 0 0 0 0 0 0 + 1 0 0 0 0 0 0 + + W[1] = + 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 + -2 2 0 0 0 0 0 + -2 2 0 0 0 0 0 + -4.999999999999998 0 -4 8.999999999999998 0 0 0 + -4.999999999999998 0 -4 8.999999999999998 0 0 0 + -4.200000000000001 0 0 0 -0.7999999999999999 5.000000000000001 0 + -4.999999999999998 0 -4 8.999999999999998 0 0 0 + + W[2] = + 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 + 5.999999999999998 0 12 -18 0 0 0 + 5.999999999999998 0 12 -18 0 0 0 + 3.6 0 0 0 2.4 -6 0 + 5.999999999999998 0 12 -18 0 0 0 + + ngroup = 4 + group[0] = 1 + group[1] = 3 2 + group[2] = 5 4 7 + group[3] = 6 + Stored stages = 7 + +MRIStep Statistics: + Time = 0.01 + y(t) = 0.980199 + y_n = 0.980199 + Error = -4.19176e-12 + Steps = 1 + Fe evals = 6 + Fi evals = 0 + +Comparing Solver Statistics: +All checks passed + +Testing method ARKODE_MERK54 + type = MERK + nmat = 4 + stages = 11 + method order (q) = 5 + embedding order (p) = 4 + c = 0 0.5 0.5 0.3333333333333333 0.5 0.3333333333333333 0.25 0.7 0.5 0.6666666666666666 1 + W[0] = + 0 0 0 0 0 0 0 0 0 0 0 + 1 0 0 0 0 0 0 0 0 0 0 + 1 0 0 0 0 0 0 0 0 0 0 + 1 0 0 0 0 0 0 0 0 0 0 + 1 0 0 0 0 0 0 0 0 0 0 + 1 0 0 0 0 0 0 0 0 0 0 + 1 0 0 0 0 0 0 0 0 0 0 + 1 0 0 0 0 0 0 0 0 0 0 + 1 0 0 0 0 0 0 0 0 0 0 + 1 0 0 0 0 0 0 0 0 0 0 + 1 0 0 0 0 0 0 0 0 0 0 + 1 0 0 0 0 0 0 0 0 0 0 + + W[1] = + 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 + -2 2 0 0 0 0 0 0 0 0 0 + -2 2 0 0 0 0 0 0 0 0 0 + -4.999999999999998 0 -4 8.999999999999998 0 0 0 0 0 0 0 + -4.999999999999998 0 -4 8.999999999999998 0 0 0 0 0 0 0 + -4.999999999999998 0 -4 8.999999999999998 0 0 0 0 0 0 0 + -9.000000000000007 0 0 0 4 -27 32.00000000000001 0 0 0 0 + -9.000000000000007 0 0 0 4 -27 32.00000000000001 0 0 0 0 + -9.000000000000007 0 0 0 4 -27 32.00000000000001 0 0 0 0 + -4.928571428571431 0 0 0 0 0 0 71.42857142857147 28.00000000000001 -94.50000000000004 0 + -9.000000000000007 0 0 0 4 -27 32.00000000000001 0 0 0 0 + + W[2] = + 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 + 5.999999999999998 0 12 -18 0 0 0 0 0 0 0 + 5.999999999999998 0 12 -18 0 0 0 0 0 0 0 + 5.999999999999998 0 12 -18 0 0 0 0 0 0 0 + 26 0 0 0 -27.99999999999999 162 -160 0 0 0 0 + 26 0 0 0 -27.99999999999999 162 -160 0 0 0 0 + 26 0 0 0 -27.99999999999999 162 -160 0 0 0 0 + 7.999999999999943 0 0 0 0 0 0 -250.0000000000001 -82.00000000000004 324.0000000000002 0 + 26 0 0 0 -27.99999999999999 162 -160 0 0 0 0 + + W[3] = + 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 + -24.00000000000006 0 0 0 47.99999999999999 -216 192.0000000000001 0 0 0 0 + -24.00000000000006 0 0 0 47.99999999999999 -216 192.0000000000001 0 0 0 0 + -24.00000000000006 0 0 0 47.99999999999999 -216 192.0000000000001 0 0 0 0 + -4.285714285714278 0 0 0 0 0 0 214.2857142857144 60.00000000000002 -270.0000000000001 0 + -24.00000000000006 0 0 0 47.99999999999999 -216 192.0000000000001 0 0 0 0 + + ngroup = 5 + group[0] = 1 + group[1] = 3 2 + group[2] = 6 5 4 + group[3] = 8 9 7 11 + group[4] = 10 + Stored stages = 11 + +MRIStep Statistics: + Time = 0.01 + y(t) = 0.980199 + y_n = 0.980199 + Error = -3.58946e-12 + Steps = 1 + Fe evals = 10 + Fi evals = 0 + +Comparing Solver Statistics: +All checks passed + +======================== +Test IMEX MRI SR methods +======================== + +Testing method ARKODE_IMEX_MRI_SR21 + type = MRISR + nmat = 1 + stages = 4 + method order (q) = 2 + embedding order (p) = 1 + c = 0 0.6 0.2666666666666667 1 + W[0] = + 0 0 0 0 + 0.6 0 0 0 + 0.08484848484848485 0.1818181818181818 0 0 + -0.2407407407407407 0.5074074074074074 0.7333333333333333 0 + -0.25 0.5 0.75 0 + + G[0] = + 0 0 0 0 + -0.4782608695652174 0.4782608695652174 0 0 + -0.1277806419583357 -0.3504802276068817 0.4782608695652174 0 + 0.1281737365715925 -0.9496349237862043 0.3432003176493945 0.4782608695652174 + -2.583333333333333 -0.1666666666666667 2.75 0 + + Stored stages = 4 + +MRIStep Statistics: + Time = 0.01 + y(t) = 0.970446 + y_n = 0.970445 + Error = 6.56922e-07 + Steps = 1 + Fe evals = 3 + Fi evals = 6 + NLS iters = 3 + NLS fails = 0 + LS setups = 1 + LS Fi evals = 0 + Ji evals = 1 + +Comparing Solver Statistics: +All checks passed + +Testing method ARKODE_IMEX_MRI_SR32 + type = MRISR + nmat = 2 + stages = 5 + method order (q) = 3 + embedding order (p) = 2 + c = 0 0.6764705882352942 0.8 1.133333333333333 1 + W[0] = + 0 0 0 0 0 + 0.6764705882352942 0 0 0 0 + 1.014285714285714 -0.2142857142857143 0 0 0 + 0.1073593073593074 0.5714285714285714 0.4545454545454545 0 0 + 0.8641357630008525 0.08623188405797101 0.34375 -0.2941176470588235 0 + 1.020324985968944 -1.483870967741935 1.970588235294118 -0.5070422535211268 0 + + W[1] = + 0 0 0 0 0 + 0 0 0 0 0 + -0.2264473168820995 0.2264473168820995 0 0 0 + -1.741503979463316 8.210746794478919 -6.469242815015602 0 0 + -1.295451217034184 2.560595940177763 -2.104988533033297 0.8398438098897179 0 + -1.638681583030989 6.083126027475434 -5.777777777777778 1.333333333333333 0 + + G[0] = + 0 0 0 0 0 + -0.5714285714285714 0.5714285714285714 0 0 0 + -0.8655695979919582 0.2941410265633868 0.5714285714285714 0 0 + 1.211752194844657 -2.237726220818683 0.4545454545454545 0.5714285714285714 0 + 0.02135581474837214 -0.07308298152405064 -0.2010145240388127 -0.3186868806140802 0.5714285714285714 + -0.04323671497584541 0.05514147688060732 0.07142857142857142 -0.08333333333333333 0 + + G[1] = + 0 0 0 0 0 + 0 0 0 0 0 + 0 0 0 0 0 + 0 0 0 0 0 + 0 0 0 0 0 + 0 0 0 0 0 + + Stored stages = 5 + +MRIStep Statistics: + Time = 0.01 + y(t) = 0.970446 + y_n = 0.970446 + Error = -3.76499e-09 + Steps = 1 + Fe evals = 4 + Fi evals = 8 + NLS iters = 4 + NLS fails = 0 + LS setups = 1 + LS Fi evals = 0 + Ji evals = 1 + +Comparing Solver Statistics: +All checks passed + +Testing method ARKODE_IMEX_MRI_SR43 + type = MRISR + nmat = 2 + stages = 7 + method order (q) = 4 + embedding order (p) = 3 + c = 0 0.25 0.75 0.55 0.5 1 1 + W[0] = + 0 0 0 0 0 0 0 + 0.25 0 0 0 0 0 0 + 1.125 -0.375 0 0 0 0 0 + 0.07991452991452991 0.7777777777777778 -0.3076923076923077 0 0 0 0 + 0.3878787878787879 0.1666666666666667 -0.6 0.5454545454545454 0 0 0 + 3.307624927156177 -0.2222222222222222 -0.3636363636363636 -0.1666666666666667 -1.555099674630925 0 0 + 0 0.6363636363636364 -8.344696969696969 13.66792929292929 -7.083333333333333 2.123737373737374 0 + 0.0025 4.083333333333333 7.166666666666667 -0.7 -7.083333333333333 -2.469166666666667 0 + + W[1] = + 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 + -2.75 2.75 0 0 0 0 0 + -0.4198290598290598 -0.4088888888888889 0.8287179487179487 0 0 0 0 + -0.9169340463458111 0.6549019607843137 1.463235294117647 -1.20120320855615 0 0 0 + -6.615249854312355 7.027777777777778 -0.5227272727272727 25.33333333333333 -25.22313398407148 0 0 + 0 0.8106060606060606 14.64772727272727 -11.71085858585859 0 -3.747474747474747 0 + -0.005 -5.708333333333333 -14.6875 15.4625 0 4.938333333333333 0 + + G[0] = + 0 0 0 0 0 0 0 + -0.25 0.25 0 0 0 0 0 + 0.25 -0.5 0.25 0 0 0 0 + 0.13 -0.2333333333333333 -0.1466666666666667 0.25 0 0 0 + 0.07058823529411765 -0.2213235294117647 -0.1819852941176471 0.08272058823529412 0.25 0 0 + 0 -2.25 -0.3958333333333333 -4.6875 7.083333333333333 0.25 0 + 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 + + G[1] = + 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 + + Stored stages = 7 + +MRIStep Statistics: + Time = 0.01 + y(t) = 0.970446 + y_n = 0.970446 + Error = -6.94172e-11 + Steps = 1 + Fe evals = 6 + Fi evals = 11 + NLS iters = 5 + NLS fails = 0 + LS setups = 1 + LS Fi evals = 0 + Ji evals = 1 + +Comparing Solver Statistics: +All checks passed + All tests passed! diff --git a/test/unit_tests/arkode/CXX_serial/ark_test_getjac_mri.cpp b/test/unit_tests/arkode/CXX_serial/ark_test_getjac_mri.cpp index 4737434ff6..3f3da4398a 100644 --- a/test/unit_tests/arkode/CXX_serial/ark_test_getjac_mri.cpp +++ b/test/unit_tests/arkode/CXX_serial/ark_test_getjac_mri.cpp @@ -226,8 +226,8 @@ int main(int argc, char* argv[]) // Create inner stepper MRIStepInnerStepper inner_stepper; - flag = ARKStepCreateMRIStepInnerStepper(inner_arkode_mem, &inner_stepper); - if (check_flag(flag, "ARKStepCreateMRIStepInnerStepper")) { return 1; } + flag = ARKodeCreateMRIStepInnerStepper(inner_arkode_mem, &inner_stepper); + if (check_flag(flag, "ARKodeCreateMRIStepInnerStepper")) { return 1; } // Create MRIStep memory structure void* arkode_mem = MRIStepCreate(nullptr, f, ZERO, y, inner_stepper, sunctx); diff --git a/test/unit_tests/arkode/CXX_serial/ark_test_kpr_mriadapt.cpp b/test/unit_tests/arkode/CXX_serial/ark_test_kpr_mriadapt.cpp new file mode 100644 index 0000000000..67d7d0e162 --- /dev/null +++ b/test/unit_tests/arkode/CXX_serial/ark_test_kpr_mriadapt.cpp @@ -0,0 +1,1442 @@ +/* ---------------------------------------------------------------- + * Programmer(s): Daniel R. Reynolds @ SMU + * ---------------------------------------------------------------- + * SUNDIALS Copyright Start + * Copyright (c) 2002-2024, Lawrence Livermore National Security + * and Southern Methodist University. + * All rights reserved. + * + * See the top-level LICENSE and NOTICE files for details. + * + * SPDX-License-Identifier: BSD-3-Clause + * SUNDIALS Copyright End + * ---------------------------------------------------------------- + * Multirate nonlinear Kvaerno-Prothero-Robinson ODE test problem: + * + * [u]' = [ G e ] [(u^2-r-1)/(2u)] + [ r'(t)/(2u) ] + * [v] [ e -1 ] [(v^2-s-2)/(2v)] [ s'(t)/(2v) ] + * = [ fs(t,u,v) ] + * [ ff(t,u,v) ] + * + * where r(t) = cos(t), and s(t) = cos(w*t*(1+exp(-(t-2)^2))). + * + * This problem has analytical solution given by + * u(t) = sqrt(2+r(t)), v(t) = sqrt(2+s(t)). + * However, we use a reference solver here to assess performance + * of the local multirate adaptivity controller. + * + * This program allows a number of parameters: + * e: fast/slow coupling strength [default = 0.5] + * G: stiffness at slow time scale [default = -1e2] + * w: time-scale separation factor [default = 100] + * + * The stiffness of the slow time scale is essentially determined + * by G, for |G| > 50 it is 'stiff' and ideally suited to a + * multirate method that is implicit at the slow time scale. + * + * Coupling between the two components is determined by e, with + * coupling strength proportional to |e|. + * + * The "fast" variable, v, oscillates at a frequency "w" times + * faster than u. + * + * Additional input options may be used to select between various + * solver options: + * - slow fixed/initial step size: hs [default = 0.01] + * - fast fixed/initial step size: hf [default = 0.0001] + * - set initial adaptive step size as hs/hf above: set_h0 [default 0] + * - relative solution tolerance: rtol [default = 1e-4] + * - absolute solution tolerance: atol [default = 1e-11] + * - relative solution tolerance for fast integrator: fast_rtol [default = 1e-4] + * - use p (0) vs q (1) for slow adaptivity: slow_pq [default = 0] + * - use p (0) vs q (1) for fast adaptivity: fast_pq [default = 0] + * - slow stepsize safety factor: safety [default = 0.96] + * - "slow" MRI method: mri_method [default = ARKODE_MRI_GARK_ERK45a] + * - "fast" ERKStep method order: fast_order [default 4] + * To put all physics at the slow scale, use "0", otherwise + * specify a valid explicit method order. + * - "slow" MRI temporal adaptivity controller: scontrol [default = 6] + * 0: no controller [fixed time steps] + * 5: I controller (as part of MRI-HTOL) + * 6: I controller (alone) + * 7: PI controller (as part of MRI-HTOL) + * 8: PI controller (alone) + * 9: PID controller (as part of MRI-HTOL) + * 10: PID controller (alone) + * 11: ExpGus controller (as part of MRI-HTOL) + * 12: ExpGus controller (alone) + * 13: ImpGus controller (as part of MRI-HTOL) + * 14: ImpGus controller (alone) + * 15: ImExGus controller (as part of MRI-HTOL) + * 16: ImExGus controller (alone) + * - "fast" ERKStep temporal adaptivity controller: fcontrol [default = 1] + * Note that this will only be used for 5 <= scontrol <= 16. + * 0: no controller [fixed time steps] + * 1: I controller + * 2: PI controller + * 3: PID controller + * 4: ExpGus controller + * 5: ImpGus controller + * 6: ImExGus controller + * - "fast" ERKStep accumulated error type: faccum [default = 0] + * Note that this will only be used for multirate scontrol options + * -1: no accumulation + * 0: maximum accumulation + * 1: additive accumulation + * 2: average accumulation + * - controller parameters: (k1s, k2s, k3s, k1f, k2f, k3f, + * bias, htol_relch, htol_minfac, htol_maxfac) + * slow single-rate controllers: use k1s through k3s, as appropriate. + * fast single-rate controllers: use k1f through k3f, as appropriate. + * MRIHTol controllers: use htol_relch, htol_minfac, htol_maxfac. + * all controllers (fast and slow) use bias. + * ** if any one of a relevant set are "-1" then the defaults are used + * + * Outputs and solution error values are printed at equal intervals + * of 0.5 and run statistics are printed at the end. + * ----------------------------------------------------------------*/ + +// Header files +#include // prototypes for ERKStep fcts., consts +#include // prototypes for MRIStep fcts., consts +#include +#include +#include +#include +#include +#include // serial N_Vector type, fcts., macros +#include +#include +#include +#include +#include +#include // dense linear solver +#include // dense matrix type, fcts., macros +#include "../../utilities/test_utilities.hpp" // common utility functions + +#if defined(SUNDIALS_EXTENDED_PRECISION) +#define ESYM "Le" +#define FSYM "Lf" +#else +#define ESYM "e" +#define FSYM "f" +#endif + +#define ZERO SUN_RCONST(0.0) +#define ONE SUN_RCONST(1.0) +#define TWO SUN_RCONST(2.0) + +// Problem options +struct Options +{ + // Problem parameters + sunrealtype e = SUN_RCONST(0.5); + sunrealtype G = SUN_RCONST(-100.0); + sunrealtype w = SUN_RCONST(100.0); + + // Step sizes and tolerances + int set_h0 = 0; + sunrealtype hs = SUN_RCONST(1.0e-2); + sunrealtype hf = SUN_RCONST(1.0e-4); + sunrealtype rtol = SUN_RCONST(1.0e-4); + sunrealtype atol = SUN_RCONST(1.0e-11); + sunrealtype fast_rtol = SUN_RCONST(1.0e-4); + + // Method selection + std::string mri_method = "ARKODE_MRI_GARK_ERK45a"; + int fast_order = 4; + int scontrol = 6; + int fcontrol = 1; + int faccum = 0; + int slow_pq = 0; + int fast_pq = 0; + + // controller parameters + sunrealtype k1s = SUN_RCONST(-1.0); + sunrealtype k2s = SUN_RCONST(-1.0); + sunrealtype k3s = SUN_RCONST(-1.0); + sunrealtype k1f = SUN_RCONST(-1.0); + sunrealtype k2f = SUN_RCONST(-1.0); + sunrealtype k3f = SUN_RCONST(-1.0); + sunrealtype bias = SUN_RCONST(-1.0); + sunrealtype htol_relch = SUN_RCONST(-1.0); + sunrealtype htol_minfac = SUN_RCONST(-1.0); + sunrealtype htol_maxfac = SUN_RCONST(-1.0); + sunrealtype slow_safety = SUN_RCONST(-1.0); +}; + +// User-supplied functions called by the solver +static int fse(sunrealtype t, N_Vector y, N_Vector ydot, void* user_data); +static int fsi(sunrealtype t, N_Vector y, N_Vector ydot, void* user_data); +static int fs(sunrealtype t, N_Vector y, N_Vector ydot, void* user_data); +static int ff(sunrealtype t, N_Vector y, N_Vector ydot, void* user_data); +static int fn(sunrealtype t, N_Vector y, N_Vector ydot, void* user_data); +static int f0(sunrealtype t, N_Vector y, N_Vector ydot, void* user_data); +static int Js(sunrealtype t, N_Vector y, N_Vector fy, SUNMatrix J, + void* user_data, N_Vector tmp1, N_Vector tmp2, N_Vector tmp3); +static int Jsi(sunrealtype t, N_Vector y, N_Vector fy, SUNMatrix J, + void* user_data, N_Vector tmp1, N_Vector tmp2, N_Vector tmp3); +static int Jn(sunrealtype t, N_Vector y, N_Vector fy, SUNMatrix J, + void* user_data, N_Vector tmp1, N_Vector tmp2, N_Vector tmp3); + +// Utility functions +static void InputHelp(); +static int ReadInputs(std::vector& args, Options& opts, + SUNContext ctx); +static void PrintSlowAdaptivity(Options opts); +static void PrintFastAdaptivity(Options opts); +static sunrealtype r(sunrealtype t, Options* opts); +static sunrealtype s(sunrealtype t, Options* opts); +static sunrealtype rdot(sunrealtype t, Options* opts); +static sunrealtype sdot(sunrealtype t, Options* opts); +static sunrealtype utrue(sunrealtype t, Options* opts); +static sunrealtype vtrue(sunrealtype t, Options* opts); +static int Ytrue(sunrealtype t, N_Vector y, Options* opts); + +// Main Program +int main(int argc, char* argv[]) +{ + // SUNDIALS context objects + sundials::Context sunctx; // main solver + sundials::Context refctx; // reference solver + + // Read input options + Options opts; + std::vector args(argv + 1, argv + argc); + int flag = ReadInputs(args, opts, sunctx); + if (check_flag(flag, "ReadInputs")) return 1; + + // General problem parameters + sunrealtype T0 = SUN_RCONST(0.0); // initial time + sunrealtype Tf = SUN_RCONST(5.0); // final time + sunindextype NEQ = 2; // number of dependent vars. + int Nt = 20; // number of output times + + // Initial problem output + // While traversing these, set various function pointers, table constants, and method orders. + ARKRhsFn f_f, f_se, f_si; + ARKLsJacFn J_s; + int retval; + sunbooleantype slowimplicit, slowimex; + slowimplicit = slowimex = SUNFALSE; + f_si = NULL; + J_s = NULL; + f_f = (opts.fast_order == 0) ? f0 : ff; + f_se = (opts.fast_order == 0) ? fn : fs; + if ((opts.mri_method == "ARKODE_MRI_GARK_IRK21a") || + (opts.mri_method == "ARKODE_MRI_GARK_ESDIRK34a") || + (opts.mri_method == "ARKODE_MRI_GARK_ESDIRK46a")) + { + slowimplicit = SUNTRUE; + f_se = NULL; + f_si = (opts.fast_order == 0) ? fn : fs; + J_s = (opts.fast_order == 0) ? Jn : Js; + } + if ((opts.mri_method == "ARKODE_IMEX_MRI_SR21") || + (opts.mri_method == "ARKODE_IMEX_MRI_SR32") || + (opts.mri_method == "ARKODE_IMEX_MRI_SR43")) + { + slowimex = SUNTRUE; + slowimplicit = SUNTRUE; + f_se = (opts.fast_order == 0) ? f0 : fse; + f_si = (opts.fast_order == 0) ? fn : fsi; + J_s = (opts.fast_order == 0) ? Jn : Jsi; + } + std::cout << "\nAdaptive multirate nonlinear Kvaerno-Prothero-Robinson test " + "problem:\n"; + std::cout << " time domain: (" << T0 << "," << Tf << "]\n"; + std::cout << " G = " << opts.G << std::endl; + std::cout << " w = " << opts.w << std::endl; + std::cout << " e = " << opts.e << std::endl; + std::cout << "\n Slow integrator: " << opts.mri_method; + if (slowimex) { std::cout << " (ImEx)" << std::endl; } + else if (slowimplicit) { std::cout << " (implicit)" << std::endl; } + else { std::cout << " (explicit)" << std::endl; } + PrintSlowAdaptivity(opts); + if (opts.fast_order == 0) { std::cout << "\n Fast integrator disabled"; } + else { std::cout << "\n Fast order " << opts.fast_order << std::endl; } + PrintFastAdaptivity(opts); + + // If SUNLogger is enabled, manually disable it for the reference solver + SUNLogger logger = NULL; + retval = SUNLogger_Create(SUN_COMM_NULL, 0, &logger); + retval = SUNContext_SetLogger(refctx, logger); + retval = SUNLogger_SetErrorFilename(logger, "/dev/null"); + retval = SUNLogger_SetWarningFilename(logger, "/dev/null"); + retval = SUNLogger_SetInfoFilename(logger, "/dev/null"); + retval = SUNLogger_SetDebugFilename(logger, "/dev/null"); + + // Create and initialize serial vectors for the solution and reference + N_Vector y = N_VNew_Serial(NEQ, sunctx); + if (check_ptr((void*)y, "N_VNew_Serial")) return 1; + N_Vector yref = N_VNew_Serial(NEQ, refctx); + if (check_ptr((void*)yref, "N_VNew_Serial")) return 1; + sunrealtype* ydata = N_VGetArrayPointer(y); + if (check_ptr((void*)ydata, "N_VGetArrayPointer")) return 1; + sunrealtype* yrefdata = N_VGetArrayPointer(yref); + if (check_ptr((void*)yrefdata, "N_VGetArrayPointer")) return 1; + + // Set initial conditions + retval = Ytrue(T0, y, &opts); + if (check_flag(retval, "Ytrue")) return 1; + N_VScale(ONE, y, yref); + + // Create and configure reference solver object + void* arkode_ref = ERKStepCreate(fn, T0, yref, refctx); + if (check_ptr((void*)arkode_ref, "ERKStepCreate")) return 1; + retval = ARKodeSetUserData(arkode_ref, (void*)&opts); + if (check_flag(retval, "ARKodeSetUserData")) return 1; + retval = ARKodeSetOrder(arkode_ref, 5); + if (check_flag(retval, "ARKodeSetOrder")) return 1; + retval = ARKodeSStolerances(arkode_ref, SUN_RCONST(1.e-10), SUN_RCONST(1.e-12)); + if (check_flag(retval, "ARKodeSStolerances")) return 1; + retval = ARKodeSetMaxNumSteps(arkode_ref, 10000000); + if (check_flag(retval, "ARKodeSetMaxNumSteps")) return (1); + + // Create and configure fast controller object + SUNAdaptController fcontrol = NULL; + switch (opts.fcontrol) + { + case (1): + fcontrol = SUNAdaptController_I(sunctx); + if (check_ptr((void*)fcontrol, "SUNAdaptController_I")) return 1; + if (opts.k1f > -1) + { + retval = SUNAdaptController_SetParams_I(fcontrol, opts.k1f); + if (check_flag(retval, "SUNAdaptController_SetParams_I")) return 1; + } + break; + case (2): + fcontrol = SUNAdaptController_PI(sunctx); + if (check_ptr((void*)fcontrol, "SUNAdaptController_PI")) return 1; + if (std::min(opts.k1f, opts.k2f) > -1) + { + retval = SUNAdaptController_SetParams_PI(fcontrol, opts.k1f, opts.k2f); + if (check_flag(retval, "SUNAdaptController_SetParams_PI")) return 1; + } + break; + case (3): + fcontrol = SUNAdaptController_PID(sunctx); + if (check_ptr((void*)fcontrol, "SUNAdaptController_PID")) return 1; + if (std::min(opts.k1f, std::min(opts.k2f, opts.k3f)) > -1) + { + retval = SUNAdaptController_SetParams_PID(fcontrol, opts.k1f, opts.k2f, + opts.k3f); + if (check_flag(retval, "SUNAdaptController_SetParams_PID")) return 1; + } + break; + case (4): + fcontrol = SUNAdaptController_ExpGus(sunctx); + if (check_ptr((void*)fcontrol, "SUNAdaptController_ExpGus")) return 1; + if (std::min(opts.k1f, opts.k2f) > -1) + { + retval = SUNAdaptController_SetParams_ExpGus(fcontrol, opts.k1f, opts.k2f); + if (check_flag(retval, "SUNAdaptController_SetParams_ExpGus")) return 1; + } + break; + case (5): + fcontrol = SUNAdaptController_ImpGus(sunctx); + if (check_ptr((void*)fcontrol, "SUNAdaptController_ImpGus")) return 1; + if (std::min(opts.k1f, opts.k2f) > -1) + { + retval = SUNAdaptController_SetParams_ImpGus(fcontrol, opts.k1f, opts.k2f); + if (check_flag(retval, "SUNAdaptController_SetParams_ImpGus")) return 1; + } + break; + case (6): + fcontrol = SUNAdaptController_ImExGus(sunctx); + if (check_ptr((void*)fcontrol, "SUNAdaptController_ImExGus")) return 1; + break; + } + if ((opts.bias > -1) && (opts.fcontrol > 0)) + { + retval = SUNAdaptController_SetErrorBias(fcontrol, opts.bias); + if (check_flag(retval, "SUNAdaptController_SetErrorBias")) return 1; + } + + // Create ERKStep (fast) integrator + void* inner_arkode_mem = NULL; // ARKode memory structure + inner_arkode_mem = ERKStepCreate(f_f, T0, y, sunctx); + if (check_ptr((void*)inner_arkode_mem, "ERKStepCreate")) return 1; + retval = ARKodeSetOrder(inner_arkode_mem, opts.fast_order); + if (check_flag(retval, "ARKodeSetOrder")) return 1; + retval = ARKodeSStolerances(inner_arkode_mem, opts.fast_rtol, opts.atol); + if (check_flag(retval, "ARKodeSStolerances")) return 1; + if (opts.fcontrol != 0) + { + retval = ARKodeSetAdaptController(inner_arkode_mem, fcontrol); + if (check_flag(retval, "ARKodeSetAdaptController")) return 1; + if (opts.set_h0 != 0) + { + retval = ARKodeSetInitStep(inner_arkode_mem, opts.hf); + if (check_flag(retval, "ARKodeSetInitStep")) return 1; + } + if (opts.fast_pq == 1) + { + retval = ARKodeSetAdaptivityAdjustment(inner_arkode_mem, 0); + if (check_flag(retval, "ARKodeSetAdaptivityAdjustment")) return 1; + } + } + else + { + retval = ARKodeSetFixedStep(inner_arkode_mem, opts.hf); + if (check_flag(retval, "ARKodeSetFixedStep")) return 1; + } + ARKAccumError acc_type = ARK_ACCUMERROR_NONE; + if (opts.faccum == 0) { acc_type = ARK_ACCUMERROR_MAX; } + if (opts.faccum == 1) { acc_type = ARK_ACCUMERROR_SUM; } + if (opts.faccum == 2) { acc_type = ARK_ACCUMERROR_AVG; } + retval = ARKodeSetAccumulatedErrorType(inner_arkode_mem, acc_type); + if (check_flag(retval, "ARKodeSetAccumulatedErrorType")) return 1; + retval = ARKodeSetMaxNumSteps(inner_arkode_mem, 1000000); + if (check_flag(retval, "ARKodeSetMaxNumSteps")) return 1; + retval = ARKodeSetUserData(inner_arkode_mem, (void*)&opts); + if (check_flag(retval, "ARKodeSetUserData")) return 1; + + // Create inner stepper + MRIStepInnerStepper inner_stepper = NULL; // inner stepper + retval = ARKodeCreateMRIStepInnerStepper(inner_arkode_mem, &inner_stepper); + if (check_flag(retval, "ARKodeCreateMRIStepInnerStepper")) return 1; + + // Create slow controller object, and select orders of accuracy as relevant + SUNAdaptController scontrol = NULL; + SUNAdaptController scontrol_H = NULL; + SUNAdaptController scontrol_Tol = NULL; + switch (opts.scontrol) + { + case (5): + scontrol_H = SUNAdaptController_I(sunctx); + if (check_ptr((void*)scontrol_H, "SUNAdaptController_I (slow H)")) return 1; + scontrol_Tol = SUNAdaptController_I(sunctx); + if (check_ptr((void*)scontrol_Tol, "SUNAdaptController_I (slow Tol)")) + return 1; + if (opts.k1s > -1) + { + retval = SUNAdaptController_SetParams_I(scontrol_H, opts.k1s); + if (check_flag(retval, "SUNAdaptController_SetParams_I")) return 1; + retval = SUNAdaptController_SetParams_I(scontrol_Tol, opts.k1s); + if (check_flag(retval, "SUNAdaptController_SetParams_I")) return 1; + } + scontrol = SUNAdaptController_MRIHTol(scontrol_H, scontrol_Tol, sunctx); + if (check_ptr((void*)scontrol, "SUNAdaptController_MRIHTol")) return 1; + if (std::min(opts.htol_relch, std::min(opts.htol_minfac, opts.htol_maxfac)) > + -1) + { + retval = SUNAdaptController_SetParams_MRIHTol(scontrol, opts.htol_relch, + opts.htol_minfac, + opts.htol_maxfac); + if (check_flag(retval, "SUNAdaptController_SetParams_MRIHTol")) return 1; + } + break; + case (6): + scontrol = SUNAdaptController_I(sunctx); + if (check_ptr((void*)scontrol, "SUNAdaptControllerI (slow)")) return 1; + if (opts.k1s > -1) + { + retval = SUNAdaptController_SetParams_I(scontrol, opts.k1s); + if (check_flag(retval, "SUNAdaptController_SetParams_I")) return 1; + } + break; + case (7): + scontrol_H = SUNAdaptController_PI(sunctx); + if (check_ptr((void*)scontrol_H, "SUNAdaptController_PI (slow H)")) + return 1; + scontrol_Tol = SUNAdaptController_PI(sunctx); + if (check_ptr((void*)scontrol_Tol, "SUNAdaptController_PI (slow Tol)")) + return 1; + if (std::min(opts.k1s, opts.k2s) > -1) + { + retval = SUNAdaptController_SetParams_PI(scontrol_H, opts.k1s, opts.k2s); + if (check_flag(retval, "SUNAdaptController_SetParams_PI")) return 1; + retval = SUNAdaptController_SetParams_PI(scontrol_Tol, opts.k1s, opts.k2s); + if (check_flag(retval, "SUNAdaptController_SetParams_PI")) return 1; + } + scontrol = SUNAdaptController_MRIHTol(scontrol_H, scontrol_Tol, sunctx); + if (check_ptr((void*)scontrol, "SUNAdaptController_MRIHTol")) return 1; + if (std::min(opts.htol_relch, std::min(opts.htol_minfac, opts.htol_maxfac)) > + -1) + { + retval = SUNAdaptController_SetParams_MRIHTol(scontrol, opts.htol_relch, + opts.htol_minfac, + opts.htol_maxfac); + if (check_flag(retval, "SUNAdaptController_SetParams_MRIHTol")) return 1; + } + break; + case (8): + scontrol = SUNAdaptController_PI(sunctx); + if (check_ptr((void*)scontrol, "SUNAdaptController_PI (slow)")) return 1; + if (std::min(opts.k1s, opts.k2s) > -1) + { + retval = SUNAdaptController_SetParams_PI(scontrol, opts.k1s, opts.k2s); + if (check_flag(retval, "SUNAdaptController_SetParams_PI")) return 1; + } + break; + case (9): + scontrol_H = SUNAdaptController_PID(sunctx); + if (check_ptr((void*)scontrol_H, "SUNAdaptController_PID (slow H)")) + return 1; + scontrol_Tol = SUNAdaptController_PID(sunctx); + if (check_ptr((void*)scontrol_Tol, "SUNAdaptController_PID (slow Tol)")) + return 1; + if (std::min(opts.k1s, std::min(opts.k2s, opts.k3s)) > -1) + { + retval = SUNAdaptController_SetParams_PID(scontrol_H, opts.k1s, opts.k2s, + opts.k3s); + if (check_flag(retval, "SUNAdaptController_SetParams_PID")) return 1; + retval = SUNAdaptController_SetParams_PID(scontrol_Tol, opts.k1s, + opts.k2s, opts.k3s); + if (check_flag(retval, "SUNAdaptController_SetParams_PID")) return 1; + } + scontrol = SUNAdaptController_MRIHTol(scontrol_H, scontrol_Tol, sunctx); + if (check_ptr((void*)scontrol, "SUNAdaptController_MRIHTol")) return 1; + if (std::min(opts.htol_relch, std::min(opts.htol_minfac, opts.htol_maxfac)) > + -1) + { + retval = SUNAdaptController_SetParams_MRIHTol(scontrol, opts.htol_relch, + opts.htol_minfac, + opts.htol_maxfac); + if (check_flag(retval, "SUNAdaptController_SetParams_MRIHTol")) return 1; + } + break; + case (10): + scontrol = SUNAdaptController_PID(sunctx); + if (check_ptr((void*)scontrol, "SUNAdaptController_PID (slow)")) return 1; + if (std::min(opts.k1s, std::min(opts.k2s, opts.k3s)) > -1) + { + retval = SUNAdaptController_SetParams_PID(scontrol, opts.k1s, opts.k2s, + opts.k3s); + if (check_flag(retval, "SUNAdaptController_SetParams_PID")) return 1; + } + break; + case (11): + scontrol_H = SUNAdaptController_ExpGus(sunctx); + if (check_ptr((void*)scontrol_H, "SUNAdaptController_ExpGus (slow H)")) + return 1; + scontrol_Tol = SUNAdaptController_ExpGus(sunctx); + if (check_ptr((void*)scontrol_Tol, "SUNAdaptController_ExpGus (slow Tol)")) + return 1; + if (std::min(opts.k1s, opts.k2s) > -1) + { + retval = SUNAdaptController_SetParams_ExpGus(scontrol_H, opts.k1s, + opts.k2s); + if (check_flag(retval, "SUNAdaptController_SetParams_ExpGus")) return 1; + retval = SUNAdaptController_SetParams_ExpGus(scontrol_Tol, opts.k1s, + opts.k2s); + if (check_flag(retval, "SUNAdaptController_SetParams_ExpGus")) return 1; + } + scontrol = SUNAdaptController_MRIHTol(scontrol_H, scontrol_Tol, sunctx); + if (check_ptr((void*)scontrol, "SUNAdaptController_MRIHTol")) return 1; + if (std::min(opts.htol_relch, std::min(opts.htol_minfac, opts.htol_maxfac)) > + -1) + { + retval = SUNAdaptController_SetParams_MRIHTol(scontrol, opts.htol_relch, + opts.htol_minfac, + opts.htol_maxfac); + if (check_flag(retval, "SUNAdaptController_SetParams_MRIHTol")) return 1; + } + break; + case (12): + scontrol = SUNAdaptController_ExpGus(sunctx); + if (check_ptr((void*)scontrol, "SUNAdaptController_ExpGus (slow)")) + return 1; + if (std::min(opts.k1s, opts.k2s) > -1) + { + retval = SUNAdaptController_SetParams_ExpGus(scontrol, opts.k1s, opts.k2s); + if (check_flag(retval, "SUNAdaptController_SetParams_ExpGus")) return 1; + } + break; + case (13): + scontrol_H = SUNAdaptController_ImpGus(sunctx); + if (check_ptr((void*)scontrol_H, "SUNAdaptController_ImpGus (slow H)")) + return 1; + scontrol_Tol = SUNAdaptController_ImpGus(sunctx); + if (check_ptr((void*)scontrol_Tol, "SUNAdaptController_ImpGus (slow Tol)")) + return 1; + if (std::min(opts.k1s, opts.k2s) > -1) + { + retval = SUNAdaptController_SetParams_ImpGus(scontrol_H, opts.k1s, + opts.k2s); + if (check_flag(retval, "SUNAdaptController_SetParams_ImpGus")) return 1; + retval = SUNAdaptController_SetParams_ImpGus(scontrol_Tol, opts.k1s, + opts.k2s); + if (check_flag(retval, "SUNAdaptController_SetParams_ImpGus")) return 1; + } + scontrol = SUNAdaptController_MRIHTol(scontrol_H, scontrol_Tol, sunctx); + if (check_ptr((void*)scontrol, "SUNAdaptController_MRIHTol")) return 1; + if (std::min(opts.htol_relch, std::min(opts.htol_minfac, opts.htol_maxfac)) > + -1) + { + retval = SUNAdaptController_SetParams_MRIHTol(scontrol, opts.htol_relch, + opts.htol_minfac, + opts.htol_maxfac); + if (check_flag(retval, "SUNAdaptController_SetParams_MRIHTol")) return 1; + } + break; + case (14): + scontrol = SUNAdaptController_ImpGus(sunctx); + if (check_ptr((void*)scontrol, "SUNAdaptController_ImpGus (slow)")) + return 1; + if (std::min(opts.k1s, opts.k2s) > -1) + { + retval = SUNAdaptController_SetParams_ImpGus(scontrol, opts.k1s, opts.k2s); + if (check_flag(retval, "SUNAdaptController_SetParams_ImpGus")) return 1; + } + break; + case (15): + scontrol_H = SUNAdaptController_ImExGus(sunctx); + if (check_ptr((void*)scontrol_H, "SUNAdaptController_ImExGus (slow H)")) + return 1; + scontrol_Tol = SUNAdaptController_ImExGus(sunctx); + if (check_ptr((void*)scontrol_Tol, "SUNAdaptController_ImExGus (slow Tol)")) + return 1; + scontrol = SUNAdaptController_MRIHTol(scontrol_H, scontrol_Tol, sunctx); + if (check_ptr((void*)scontrol, "SUNAdaptController_MRIHTol")) return 1; + if (std::min(opts.htol_relch, std::min(opts.htol_minfac, opts.htol_maxfac)) > + -1) + { + retval = SUNAdaptController_SetParams_MRIHTol(scontrol, opts.htol_relch, + opts.htol_minfac, + opts.htol_maxfac); + if (check_flag(retval, "SUNAdaptController_SetParams_MRIHTol")) return 1; + } + break; + case (16): + scontrol = SUNAdaptController_ImExGus(sunctx); + if (check_ptr((void*)scontrol, "SUNAdaptController_ImExGus (slow)")) + return 1; + break; + } + if ((opts.bias > -1) && (opts.scontrol > 0)) + { + retval = SUNAdaptController_SetErrorBias(scontrol, opts.bias); + if (check_flag(retval, "SUNAdaptController_SetErrorBias")) return 1; + } + + // Create MRI (slow) integrator + void* arkode_mem = NULL; // ARKode memory structure + arkode_mem = MRIStepCreate(f_se, f_si, T0, y, inner_stepper, sunctx); + if (check_ptr((void*)arkode_mem, "MRIStepCreate")) return 1; + MRIStepCoupling C = MRIStepCoupling_LoadTableByName((opts.mri_method).c_str()); + if (check_ptr((void*)C, "MRIStepCoupling_LoadTableByName")) return 1; + retval = MRIStepSetCoupling(arkode_mem, C); + if (check_flag(retval, "MRIStepSetCoupling")) return 1; + SUNMatrix As = NULL; // matrix for slow solver + SUNLinearSolver LSs = NULL; // slow linear solver object + if (slowimplicit) + { + As = SUNDenseMatrix(NEQ, NEQ, sunctx); + if (check_ptr((void*)As, "SUNDenseMatrix")) return 1; + LSs = SUNLinSol_Dense(y, As, sunctx); + if (check_ptr((void*)LSs, "SUNLinSol_Dense")) return 1; + retval = ARKodeSetLinearSolver(arkode_mem, LSs, As); + if (check_flag(retval, "ARKodeSetLinearSolver")) return 1; + retval = ARKodeSetJacFn(arkode_mem, J_s); + if (check_flag(retval, "ARKodeSetJacFn")) return 1; + } + retval = ARKodeSStolerances(arkode_mem, opts.rtol, opts.atol); + if (check_flag(retval, "ARKodeSStolerances")) return 1; + retval = ARKodeSetMaxNumSteps(arkode_mem, 100000); + if (check_flag(retval, "ARKodeSetMaxNumSteps")) return 1; + retval = ARKodeSetUserData(arkode_mem, (void*)&opts); + if (check_flag(retval, "ARKodeSetUserData")) return 1; + if (opts.scontrol != 0) + { + retval = ARKodeSetAdaptController(arkode_mem, scontrol); + if (check_flag(retval, "ARKodeSetAdaptController")) return 1; + if (opts.set_h0 != 0) + { + retval = ARKodeSetInitStep(arkode_mem, opts.hs); + if (check_flag(retval, "ARKodeSetInitStep")) return 1; + } + if (opts.slow_pq == 1) + { + retval = ARKodeSetAdaptivityAdjustment(arkode_mem, 0); + if (check_flag(retval, "ARKodeSetAdaptivityAdjustment")) return 1; + } + if (opts.slow_safety > -1) + { + retval = ARKodeSetSafetyFactor(arkode_mem, opts.slow_safety); + if (check_flag(retval, "ARKodeSetSafetyFactor")) return 1; + } + } + else + { + retval = ARKodeSetFixedStep(arkode_mem, opts.hs); + if (check_flag(retval, "ARKodeSetFixedStep")) return 1; + } + + // + // Integrate ODE + // + + // Main time-stepping loop: calls ARKodeEvolve to perform the + // integration, then prints results. Stops when the final time + // has been reached + sunrealtype t = T0; + sunrealtype t2 = T0; + sunrealtype dTout = (Tf - T0) / Nt; + sunrealtype tout = T0 + dTout; + sunrealtype u, v, uerr, verr, uerrtot, verrtot, errtot, accuracy; + uerr = verr = uerrtot = verrtot = errtot = accuracy = ZERO; + printf(" t u v uerr verr\n"); + printf(" ------------------------------------------------------\n"); + printf(" %10.6" FSYM " %10.6" FSYM " %10.6" FSYM " %.2" ESYM " %.2" ESYM + "\n", + t, ydata[0], ydata[1], uerr, verr); + while (Tf - t > SUN_RCONST(1.0e-8)) + { + // reset reference solver so that it begins with identical state + retval = ARKodeReset(arkode_ref, t, y); + + // evolve solution in one-step mode + retval = ARKodeSetStopTime(arkode_mem, tout); + if (check_flag(retval, "ARKodeSetStopTime")) return 1; + retval = ARKodeEvolve(arkode_mem, tout, y, &t, ARK_ONE_STEP); + if (retval < 0) + { + printf("ARKodeEvolve error (%i)\n", retval); + return 1; + } + + // evolve reference solver to same time in "normal" mode + retval = ARKodeSetStopTime(arkode_ref, t); + if (check_flag(retval, "ARKodeSetStopTime")) return 1; + retval = ARKodeEvolve(arkode_ref, t, yref, &t2, ARK_NORMAL); + if (retval < 0) + { + printf("ARKodeEvolve reference solution error (%i)\n", retval); + return 1; + } + + // access/print solution and error + u = ydata[0]; + v = ydata[1]; + uerr = std::abs(yrefdata[0] - u); + verr = std::abs(yrefdata[1] - v); + uerrtot += uerr * uerr; + verrtot += verr * verr; + errtot += uerr * uerr + verr * verr; + accuracy = std::max(accuracy, + uerr / std::abs(opts.atol + opts.rtol * yrefdata[0])); + accuracy = std::max(accuracy, + verr / std::abs(opts.atol + opts.rtol * yrefdata[1])); + + // Periodically output current results to screen + if (t >= tout) + { + tout += dTout; + tout = (tout > Tf) ? Tf : tout; + printf(" %10.6" FSYM " %10.6" FSYM " %10.6" FSYM " %.2" ESYM + " %.2" ESYM "\n", + t, u, v, uerr, verr); + } + } + printf(" ------------------------------------------------------\n"); + + // + // Finalize + // + + // Get some slow integrator statistics + long int nsts, natts, netfs, nfse, nfsi; + retval = ARKodeGetNumSteps(arkode_mem, &nsts); + check_flag(retval, "ARKodeGetNumSteps"); + retval = ARKodeGetNumStepAttempts(arkode_mem, &natts); + check_flag(retval, "ARKodeGetNumStepAttempts"); + retval = ARKodeGetNumErrTestFails(arkode_mem, &netfs); + check_flag(retval, "ARKodeGetNumErrTestFails"); + retval = ARKodeGetNumRhsEvals(arkode_mem, 0, &nfse); + check_flag(retval, "ARKodeGetNumRhsEvals"); + retval = ARKodeGetNumRhsEvals(arkode_mem, 1, &nfsi); + check_flag(retval, "ARKodeGetNumRhsEvals"); + + // Get some fast integrator statistics + long int nstf, nattf, netff, nff; + retval = ARKodeGetNumSteps(inner_arkode_mem, &nstf); + check_flag(retval, "ARKodeGetNumSteps"); + retval = ARKodeGetNumStepAttempts(inner_arkode_mem, &nattf); + check_flag(retval, "ARKodeGetNumStepAttempts"); + retval = ARKodeGetNumErrTestFails(inner_arkode_mem, &netff); + check_flag(retval, "ARKodeGetNumErrTestFails"); + retval = ARKodeGetNumRhsEvals(inner_arkode_mem, 0, &nff); + check_flag(retval, "ARKodeGetNumRhsEvals"); + + // Print some final statistics + uerrtot = std::sqrt(uerrtot / (sunrealtype)nsts); + verrtot = std::sqrt(verrtot / (sunrealtype)nsts); + errtot = std::sqrt(errtot / SUN_RCONST(2.0) / (sunrealtype)nsts); + std::cout << "\nFinal Solver Statistics:\n"; + std::cout << " Slow steps = " << nsts << " (attempts = " << natts + << ", fails = " << netfs << ")\n"; + std::cout << " Fast steps = " << nstf << " (attempts = " << nattf + << ", fails = " << netff << ")\n"; + std::cout << " u error = " << uerrtot << ", v error = " << verrtot + << ", total error = " << errtot << std::endl; + std::cout << " Relative accuracy = " << accuracy << std::endl; + std::cout << " Total RHS evals: Fse = " << nfse << ", Fsi = " << nfsi + << ", Ff = " << nff << std::endl; + + // Get/print slow integrator decoupled implicit solver statistics + if (slowimplicit) + { + long int nnis, nncs, njes; + retval = ARKodeGetNonlinSolvStats(arkode_mem, &nnis, &nncs); + check_flag(retval, "ARKodeGetNonlinSolvStats"); + retval = ARKodeGetNumJacEvals(arkode_mem, &njes); + check_flag(retval, "ARKodeGetNumJacEvals"); + std::cout << " Slow Newton iters = " << nnis << std::endl; + std::cout << " Slow Newton conv fails = " << nncs << std::endl; + std::cout << " Slow Jacobian evals = " << njes << std::endl; + } + + // Clean up and return + N_VDestroy(y); + MRIStepCoupling_Free(C); + if (As) { SUNMatDestroy(As); } + if (LSs) { SUNLinSolFree(LSs); } + if (scontrol) { SUNAdaptController_Destroy(scontrol); } + if (scontrol_H) { SUNAdaptController_Destroy(scontrol_H); } + if (scontrol_Tol) { SUNAdaptController_Destroy(scontrol_Tol); } + if (fcontrol) { SUNAdaptController_Destroy(fcontrol); } + ARKodeFree(&inner_arkode_mem); // Free fast integrator memory + MRIStepInnerStepper_Free(&inner_stepper); // Free inner stepper structure + ARKodeFree(&arkode_mem); // Free slow integrator memory + ARKodeFree(&arkode_ref); // Free reference solver memory + SUNLogger_Destroy(&logger); // Free logger + + return 0; +} + +// ------------------------------ +// Functions called by the solver +// ----------------------------- + +// ff routine to compute the fast portion of the ODE RHS. +static int ff(sunrealtype t, N_Vector y, N_Vector ydot, void* user_data) +{ + Options* opts = (Options*)user_data; + sunrealtype* ydata = N_VGetArrayPointer(y); + sunrealtype* dydata = N_VGetArrayPointer(ydot); + const sunrealtype u = ydata[0]; + const sunrealtype v = ydata[1]; + sunrealtype tmp1, tmp2; + + // fill in the RHS function: + // [0 0]*[(-2+u^2-r(t))/(2*u)] + [ 0 ] + // [e -1] [(-2+v^2-s(t))/(2*v)] [sdot(t)/(2v)] + tmp1 = (-TWO + u * u - r(t, opts)) / (TWO * u); + tmp2 = (-TWO + v * v - s(t, opts)) / (TWO * v); + dydata[0] = ZERO; + dydata[1] = opts->e * tmp1 - tmp2 + sdot(t, opts) / (TWO * v); + + // Return with success + return 0; +} + +// fs routine to compute the slow portion of the ODE RHS. +static int fs(sunrealtype t, N_Vector y, N_Vector ydot, void* user_data) +{ + Options* opts = (Options*)user_data; + sunrealtype* ydata = N_VGetArrayPointer(y); + sunrealtype* dydata = N_VGetArrayPointer(ydot); + const sunrealtype u = ydata[0]; + const sunrealtype v = ydata[1]; + sunrealtype tmp1, tmp2; + + // fill in the RHS function: + // [G e]*[(-2+u^2-r(t))/(2*u)] + [rdot(t)/(2u)] + // [0 0] [(-2+v^2-s(t))/(2*v)] [ 0 ] + tmp1 = (-TWO + u * u - r(t, opts)) / (TWO * u); + tmp2 = (-TWO + v * v - s(t, opts)) / (TWO * v); + dydata[0] = opts->G * tmp1 + opts->e * tmp2 + rdot(t, opts) / (TWO * u); + dydata[1] = ZERO; + + // Return with success + return 0; +} + +// fse routine to compute the slow portion of the ODE RHS. +static int fse(sunrealtype t, N_Vector y, N_Vector ydot, void* user_data) +{ + Options* opts = (Options*)user_data; + sunrealtype* ydata = N_VGetArrayPointer(y); + sunrealtype* dydata = N_VGetArrayPointer(ydot); + const sunrealtype u = ydata[0]; + + // fill in the slow explicit RHS function: + // [rdot(t)/(2u)] + // [ 0 ] + dydata[0] = rdot(t, opts) / (TWO * u); + dydata[1] = ZERO; + + // Return with success + return 0; +} + +// fsi routine to compute the slow portion of the ODE RHS.(currently same as fse) +static int fsi(sunrealtype t, N_Vector y, N_Vector ydot, void* user_data) +{ + Options* opts = (Options*)user_data; + sunrealtype* ydata = N_VGetArrayPointer(y); + sunrealtype* dydata = N_VGetArrayPointer(ydot); + const sunrealtype u = ydata[0]; + const sunrealtype v = ydata[1]; + sunrealtype tmp1, tmp2; + + // fill in the slow implicit RHS function: + // [G e]*[(-2+u^2-r(t))/(2*u)] + // [0 0] [(-2+v^2-s(t))/(2*v)] + tmp1 = (-TWO + u * u - r(t, opts)) / (TWO * u); + tmp2 = (-TWO + v * v - s(t, opts)) / (TWO * v); + dydata[0] = opts->G * tmp1 + opts->e * tmp2; + dydata[1] = ZERO; + + // Return with success + return 0; +} + +static int fn(sunrealtype t, N_Vector y, N_Vector ydot, void* user_data) +{ + Options* opts = (Options*)user_data; + sunrealtype* ydata = N_VGetArrayPointer(y); + sunrealtype* dydata = N_VGetArrayPointer(ydot); + const sunrealtype u = ydata[0]; + const sunrealtype v = ydata[1]; + sunrealtype tmp1, tmp2; + + // fill in the RHS function: + // [G e]*[(-2+u^2-r(t))/(2*u)] + [rdot(t)/(2u)] + // [e -1] [(-2+v^2-s(t))/(2*v)] [sdot(t)/(2v)] + tmp1 = (-TWO + u * u - r(t, opts)) / (TWO * u); + tmp2 = (-TWO + v * v - s(t, opts)) / (TWO * v); + dydata[0] = opts->G * tmp1 + opts->e * tmp2 + rdot(t, opts) / (TWO * u); + dydata[1] = opts->e * tmp1 - tmp2 + sdot(t, opts) / (TWO * v); + + // Return with success + return 0; +} + +static int f0(sunrealtype t, N_Vector y, N_Vector ydot, void* user_data) +{ + N_VConst(ZERO, ydot); + return (0); +} + +static int Js(sunrealtype t, N_Vector y, N_Vector fy, SUNMatrix J, + void* user_data, N_Vector tmp1, N_Vector tmp2, N_Vector tmp3) +{ + Options* opts = (Options*)user_data; + sunrealtype* ydata = N_VGetArrayPointer(y); + const sunrealtype u = ydata[0]; + const sunrealtype v = ydata[1]; + sunrealtype t11, t22; + + // fill in the Jacobian: + // [G e]*[1-(u^2-r(t)-2)/(2*u^2), 0] + [-r'(t)/(2*u^2), 0] + // [0 0] [0, 1-(v^2-s(t)-2)/(2*v^2)] [0, 0] + t11 = ONE - (u * u - r(t, opts) - TWO) / (TWO * u * u); + t22 = ONE - (v * v - s(t, opts) - TWO) / (TWO * v * v); + SM_ELEMENT_D(J, 0, 0) = opts->G * t11 - rdot(t, opts) / (TWO * u * u); + SM_ELEMENT_D(J, 0, 1) = opts->e * t22; + SM_ELEMENT_D(J, 1, 0) = ZERO; + SM_ELEMENT_D(J, 1, 1) = ZERO; + + // Return with success + return 0; +} + +static int Jsi(sunrealtype t, N_Vector y, N_Vector fy, SUNMatrix J, + void* user_data, N_Vector tmp1, N_Vector tmp2, N_Vector tmp3) +{ + Options* opts = (Options*)user_data; + sunrealtype* ydata = N_VGetArrayPointer(y); + const sunrealtype u = ydata[0]; + const sunrealtype v = ydata[1]; + sunrealtype t11, t22; + + // fill in the Jacobian: + // [G e]*[1-(u^2-r(t)-2)/(2*u^2), 0] + // [0 0] [0, 1-(v^2-s(t)-2)/(2*v^2)] + t11 = ONE - (u * u - r(t, opts) - TWO) / (TWO * u * u); + t22 = ONE - (v * v - s(t, opts) - TWO) / (TWO * v * v); + SM_ELEMENT_D(J, 0, 0) = opts->G * t11; + SM_ELEMENT_D(J, 0, 1) = opts->e * t22; + SM_ELEMENT_D(J, 1, 0) = ZERO; + SM_ELEMENT_D(J, 1, 1) = ZERO; + + // Return with success + return 0; +} + +static int Jn(sunrealtype t, N_Vector y, N_Vector fy, SUNMatrix J, + void* user_data, N_Vector tmp1, N_Vector tmp2, N_Vector tmp3) +{ + Options* opts = (Options*)user_data; + sunrealtype* ydata = N_VGetArrayPointer(y); + const sunrealtype u = ydata[0]; + const sunrealtype v = ydata[1]; + sunrealtype t11, t22; + + // fill in the Jacobian: + // [G e]*[1-(u^2-r(t)-2)/(2*u^2), 0] + [-r'(t)/(2*u^2), 0] + // [e -1] [0, 1-(v^2-s(t)-2)/(2*v^2)] [0, -s'(t)/(2*v^2)] + t11 = ONE - (u * u - r(t, opts) - TWO) / (TWO * u * u); + t22 = ONE - (v * v - s(t, opts) - TWO) / (TWO * v * v); + SM_ELEMENT_D(J, 0, 0) = opts->G * t11 - rdot(t, opts) / (TWO * u * u); + SM_ELEMENT_D(J, 0, 1) = opts->e * t22; + SM_ELEMENT_D(J, 1, 0) = opts->e * t11; + SM_ELEMENT_D(J, 1, 1) = -t22 - sdot(t, opts) / (TWO * v * v); + + // Return with success + return 0; +} + +// ------------------------------ +// Private helper functions +// ----------------------------- + +static sunrealtype r(sunrealtype t, Options* opts) { return (cos(t)); } + +static sunrealtype s(sunrealtype t, Options* opts) +{ + return (cos(opts->w * t * (ONE + exp(-(t - TWO) * (t - TWO))))); +} + +static sunrealtype rdot(sunrealtype t, Options* opts) { return (-sin(t)); } + +static sunrealtype sdot(sunrealtype t, Options* opts) +{ + const sunrealtype tTwo = t - TWO; + const sunrealtype eterm = exp(-tTwo * tTwo); + return (-sin(opts->w * t * (ONE + eterm)) * opts->w * + (ONE + eterm * (ONE - TWO * t * tTwo))); +} + +static sunrealtype utrue(sunrealtype t, Options* opts) +{ + return (std::sqrt(TWO + r(t, opts))); +} + +static sunrealtype vtrue(sunrealtype t, Options* opts) +{ + return (std::sqrt(TWO + s(t, opts))); +} + +static int Ytrue(sunrealtype t, N_Vector y, Options* opts) +{ + sunrealtype* ydata = N_VGetArrayPointer(y); + ydata[0] = utrue(t, opts); + ydata[1] = vtrue(t, opts); + return (0); +} + +// ----------------------------------------------------------------------------- +// Utility functions +// ----------------------------------------------------------------------------- + +// Print command line options +void InputHelp() +{ + std::cout << std::endl; + std::cout << "Command line options:" << std::endl; + std::cout << " --help : print options and exit\n"; + std::cout << " --e : fast/slow coupling strength\n"; + std::cout << " --G : stiffness at slow time scale\n"; + std::cout << " --w : time-scale separation factor\n"; + std::cout << " --hs : slow (fixed/initial) step size\n"; + std::cout << " --hf : fast (fixed/initial) step size\n"; + std::cout + << " --set_h0 : use hs/hf above to set the initial step size\n"; + std::cout << " --rtol : relative solution tolerance\n"; + std::cout << " --atol : absolute solution tolerance\n"; + std::cout + << " --fast_rtol : relative solution tolerance for fast method\n"; + std::cout << " --mri_method : MRI method name (valid ARKODE_MRITableID)\n"; + std::cout << " --fast_order : fast RK method order\n"; + std::cout << " --scontrol : slow time step controller, int in [0,16] " + "(see source)\n"; + std::cout << " --fcontrol : fast time step controller, int in [0,6] " + "(see source)\n"; + std::cout << " --faccum : fast error accumulation type {-1,0,1,2}\n"; + std::cout << " --slow_pq : use p (0) vs q (1) for slow adaptivity\n"; + std::cout << " --fast_pq : use p (0) vs q (1) for fast adaptivity\n"; + std::cout << " --k1s, --k2s, ..., -k6s : slow controller parameters\n"; + std::cout << " --k1f, --k2f, -k3f : fast controller parameters\n"; + std::cout << " --bias : slow and fast controller bias factors\n"; + std::cout << " --safety : slow time step safety factor\n"; + std::cout + << " --htol_relch : HTol controller maximum relative tolerance change\n"; + std::cout + << " --htol_minfac : HTol controller minimum relative tolerance factor\n"; + std::cout + << " --htol_maxfac : HTol controller maximum relative tolerance factor\n"; +} + +// Read input options +int ReadInputs(std::vector& args, Options& opts, SUNContext ctx) +{ + if (find(args.begin(), args.end(), "--help") != args.end()) + { + InputHelp(); + return 1; + } + + // Problem options + find_arg(args, "--e", opts.e); + find_arg(args, "--G", opts.G); + find_arg(args, "--w", opts.w); + find_arg(args, "--hs", opts.hs); + find_arg(args, "--hf", opts.hf); + find_arg(args, "--set_h0", opts.set_h0); + find_arg(args, "--rtol", opts.rtol); + find_arg(args, "--atol", opts.atol); + find_arg(args, "--fast_rtol", opts.fast_rtol); + find_arg(args, "--mri_method", opts.mri_method); + find_arg(args, "--fast_order", opts.fast_order); + find_arg(args, "--scontrol", opts.scontrol); + find_arg(args, "--fcontrol", opts.fcontrol); + find_arg(args, "--faccum", opts.faccum); + find_arg(args, "--slow_pq", opts.slow_pq); + find_arg(args, "--fast_pq", opts.fast_pq); + find_arg(args, "--k1s", opts.k1s); + find_arg(args, "--k2s", opts.k2s); + find_arg(args, "--k3s", opts.k3s); + find_arg(args, "--k1f", opts.k1f); + find_arg(args, "--k2f", opts.k2f); + find_arg(args, "--k3f", opts.k3f); + find_arg(args, "--bias", opts.bias); + find_arg(args, "--safety", opts.slow_safety); + find_arg(args, "--htol_relch", opts.htol_relch); + find_arg(args, "--htol_minfac", opts.htol_minfac); + find_arg(args, "--htol_maxfac", opts.htol_maxfac); + + // Check inputs for validity + // 0 < rtol < 1 + if ((opts.rtol < ZERO) || (opts.rtol > ONE)) + { + std::cerr << "ERROR: rtol must be in (0,1), (" << opts.rtol << " input)\n"; + return -1; + } + // 0 < atol < 1 + if ((opts.atol < ZERO) || (opts.atol > ONE)) + { + std::cerr << "ERROR: atol must be in (0,1), (" << opts.atol << " input)\n"; + return -1; + } + // 0 < fast_rtol < 1 + if ((opts.fast_rtol < ZERO) || (opts.fast_rtol > ONE)) + { + std::cerr << "ERROR: fast_rtol must be in (0,1), (" << opts.fast_rtol + << " input)\n"; + return -1; + } + // slow_pq in {0,1} + if ((opts.slow_pq < 0) || (opts.slow_pq > 1)) + { + std::cerr << "ERROR: slow_pq must be in {0,1}, (" << opts.slow_pq + << " input)\n"; + return -1; + } + // fast_pq in {0,1} + if ((opts.fast_pq < 0) || (opts.fast_pq > 1)) + { + std::cerr << "ERROR: fast_pq must be in {0,1}, (" << opts.fast_pq + << " input)\n"; + return -1; + } + // scontrol in [0,16] + if ((opts.scontrol < 0) || (opts.scontrol > 16)) + { + std::cerr << "ERROR: scontrol must be in [0,16], (" << opts.scontrol + << " input)\n"; + return -1; + } + // fcontrol in [0,6] + if ((opts.fcontrol < 0) || (opts.fcontrol > 6)) + { + std::cerr << "ERROR: fcontrol must be in [0,6], (" << opts.fcontrol + << " input)\n"; + return -1; + } + // hs > 0 if scontrol == 0 + if ((opts.hs <= 0) && (opts.scontrol == 0)) + { + std::cerr << "ERROR: positive hs required with scontrol = 0, (" << opts.hs + << " input)\n"; + return -1; + } + // hf > 0 if fcontrol == 0 + if ((opts.hf <= 0) && (opts.fcontrol == 0)) + { + std::cerr << "ERROR: positive hf required with fcontrol = 0, (" << opts.hf + << " input)\n"; + return -1; + } + // G < 0.0 + if (opts.G >= ZERO) + { + std::cerr << "ERROR: G must be a negative real number, (" << opts.G + << " input)\n"; + return -1; + } + // w >= 1.0 + if (opts.w < ONE) + { + std::cerr << "ERROR: w must be >= 1.0, (" << opts.w << " input)\n"; + return -1; + } + + return 0; +} + +static void PrintSlowAdaptivity(Options opts) +{ + switch (opts.scontrol) + { + case (0): + std::cout << " fixed steps, hs = " << opts.hs << std::endl; + std::cout << " rtol = " << opts.rtol << ", atol = " << opts.atol << "\n"; + break; + case (5): + std::cout + << " MRI-HTOL controller (using I for H) based on order of MRI " + << ((opts.slow_pq == 1) ? "method\n" : "embedding\n"); + std::cout << " rtol = " << opts.rtol << ", atol = " << opts.atol << "\n"; + std::cout << " fast error accumulation strategy = " << opts.faccum << "\n"; + if (opts.k1s > -1) + { + std::cout << " slow controller parameter: " << opts.k1s << "\n"; + } + if (std::min(opts.htol_relch, std::min(opts.htol_minfac, opts.htol_maxfac)) > + -1) + { + std::cout << " HTol controller parameters: " << opts.htol_relch << " " + << opts.htol_minfac << " " << opts.htol_maxfac << "\n"; + } + break; + case (6): + std::cout << " Decoupled I controller for slow time scale, based on " + "order of MRI " + << ((opts.slow_pq == 1) ? "method\n" : "embedding\n"); + std::cout << " rtol = " << opts.rtol << ", atol = " << opts.atol << "\n"; + if (opts.k1s > -1) + { + std::cout << " slow controller parameter: " << opts.k1s << "\n"; + } + break; + case (7): + std::cout + << " MRI-HTOL controller (using PI for H) based on order of MRI " + << ((opts.slow_pq == 1) ? "method\n" : "embedding\n"); + std::cout << " rtol = " << opts.rtol << ", atol = " << opts.atol << "\n"; + std::cout << " fast error accumulation strategy = " << opts.faccum << "\n"; + if (std::min(opts.k1s, opts.k2s) > -1) + { + std::cout << " slow controller parameters: " << opts.k1s << " " + << opts.k2s << "\n"; + } + if (std::min(opts.htol_relch, std::min(opts.htol_minfac, opts.htol_maxfac)) > + -1) + { + std::cout << " HTol controller parameters: " << opts.htol_relch << " " + << opts.htol_minfac << " " << opts.htol_maxfac << "\n"; + } + break; + case (8): + std::cout << " Decoupled PI controller for slow time scale, based on " + "order of MRI " + << ((opts.slow_pq == 1) ? "method\n" : "embedding\n"); + std::cout << " rtol = " << opts.rtol << ", atol = " << opts.atol << "\n"; + if (std::min(opts.k1s, opts.k2s) > -1) + { + std::cout << " slow controller parameters: " << opts.k1s << " " + << opts.k2s << "\n"; + } + break; + case (9): + std::cout + << " MRI-HTOL controller (using PID for H) based on order of MRI " + << ((opts.slow_pq == 1) ? "method\n" : "embedding\n"); + std::cout << " rtol = " << opts.rtol << ", atol = " << opts.atol << "\n"; + std::cout << " fast error accumulation strategy = " << opts.faccum << "\n"; + if (std::min(opts.k1s, std::min(opts.k2s, opts.k3s)) > -1) + { + std::cout << " slow controller parameters: " << opts.k1s << " " + << opts.k2s << " " << opts.k3s << "\n"; + } + if (std::min(opts.htol_relch, std::min(opts.htol_minfac, opts.htol_maxfac)) > + -1) + { + std::cout << " HTol controller parameters: " << opts.htol_relch << " " + << opts.htol_minfac << " " << opts.htol_maxfac << "\n"; + } + break; + case (10): + std::cout << " Decoupled PID controller for slow time scale, based on " + "order of MRI " + << ((opts.slow_pq == 1) ? "method\n" : "embedding\n"); + std::cout << " rtol = " << opts.rtol << ", atol = " << opts.atol << "\n"; + if (std::min(opts.k1s, std::min(opts.k2s, opts.k3s)) > -1) + { + std::cout << " slow controller parameters: " << opts.k1s << " " + << opts.k2s << " " << opts.k3s << "\n"; + } + break; + case (11): + std::cout + << " MRI-HTOL controller (using ExpGus for H) based on order of MRI " + << ((opts.slow_pq == 1) ? "method\n" : "embedding\n"); + std::cout << " rtol = " << opts.rtol << ", atol = " << opts.atol << "\n"; + std::cout << " fast error accumulation strategy = " << opts.faccum << "\n"; + if (std::min(opts.k1s, opts.k2s) > -1) + { + std::cout << " slow controller parameters: " << opts.k1s << " " + << opts.k2s << "\n"; + } + if (std::min(opts.htol_relch, std::min(opts.htol_minfac, opts.htol_maxfac)) > + -1) + { + std::cout << " HTol controller parameters: " << opts.htol_relch << " " + << opts.htol_minfac << " " << opts.htol_maxfac << "\n"; + } + break; + case (12): + std::cout << " Decoupled ExpGus controller for slow time scale, based " + "on order of MRI " + << ((opts.slow_pq == 1) ? "method\n" : "embedding\n"); + std::cout << " rtol = " << opts.rtol << ", atol = " << opts.atol << "\n"; + if (std::min(opts.k1s, opts.k2s) > -1) + { + std::cout << " slow controller parameters: " << opts.k1s << " " + << opts.k2s << "\n"; + } + break; + case (13): + std::cout + << " MRI-HTOL controller (using ImpGus for H) based on order of MRI " + << ((opts.slow_pq == 1) ? "method\n" : "embedding\n"); + std::cout << " rtol = " << opts.rtol << ", atol = " << opts.atol << "\n"; + std::cout << " fast error accumulation strategy = " << opts.faccum << "\n"; + if (std::min(opts.k1s, opts.k2s) > -1) + { + std::cout << " slow controller parameters: " << opts.k1s << " " + << opts.k2s << "\n"; + } + if (std::min(opts.htol_relch, std::min(opts.htol_minfac, opts.htol_maxfac)) > + -1) + { + std::cout << " HTol controller parameters: " << opts.htol_relch << " " + << opts.htol_minfac << " " << opts.htol_maxfac << "\n"; + } + break; + case (14): + std::cout << " Decoupled ImpGus controller for slow time scale, based " + "on order of MRI " + << ((opts.slow_pq == 1) ? "method\n" : "embedding\n"); + std::cout << " rtol = " << opts.rtol << ", atol = " << opts.atol << "\n"; + if (std::min(opts.k1s, opts.k2s) > -1) + { + std::cout << " slow controller parameters: " << opts.k1s << " " + << opts.k2s << "\n"; + } + break; + case (15): + std::cout + << " MRI-HTOL controller (using ImExGus for H) based on order of MRI " + << ((opts.slow_pq == 1) ? "method\n" : "embedding\n"); + std::cout << " rtol = " << opts.rtol << ", atol = " << opts.atol << "\n"; + std::cout << " fast error accumulation strategy = " << opts.faccum << "\n"; + break; + case (16): + std::cout << " Decoupled ImExGus controller for slow time scale, based " + "on order of MRI " + << ((opts.slow_pq == 1) ? "method\n" : "embedding\n"); + std::cout << " rtol = " << opts.rtol << ", atol = " << opts.atol << "\n"; + break; + } + if (opts.bias > -1) + { + std::cout << " controller bias factor: " << opts.bias << "\n"; + } + if (opts.slow_safety > -1) + { + std::cout << " slow step safety factor: " << opts.slow_safety << "\n"; + } +} + +static void PrintFastAdaptivity(Options opts) +{ + switch (opts.fcontrol) + { + case (0): + std::cout << " fixed steps, hf = " << opts.hf << std::endl; + std::cout << " fast_rtol = " << opts.fast_rtol + << ", atol = " << opts.atol << "\n"; + break; + case (1): + std::cout << " I controller for fast time scale, based on order of RK " + << ((opts.fast_pq == 1) ? "method\n" : "embedding\n"); + std::cout << " fast_rtol = " << opts.fast_rtol + << ", atol = " << opts.atol << "\n"; + if (opts.k1f > -1) + { + std::cout << " fast controller parameter: " << opts.k1f << "\n"; + } + break; + case (2): + std::cout << " PI controller for fast time scale, based on order of RK " + << ((opts.fast_pq == 1) ? "method\n" : "embedding\n"); + std::cout << " fast_rtol = " << opts.fast_rtol + << ", atol = " << opts.atol << "\n"; + if (std::min(opts.k1f, opts.k2f) > -1) + { + std::cout << " fast controller parameters: " << opts.k1f << " " + << opts.k2f << "\n"; + } + break; + case (3): + std::cout << " PID controller for fast time scale, based on order of RK " + << ((opts.fast_pq == 1) ? "method\n" : "embedding\n"); + std::cout << " fast_rtol = " << opts.fast_rtol + << ", atol = " << opts.atol << "\n"; + if (std::min(opts.k1f, std::min(opts.k2f, opts.k3f)) > -1) + { + std::cout << " fast controller parameters: " << opts.k1f << " " + << opts.k2f << " " << opts.k3f << "\n"; + } + break; + case (4): + std::cout + << " ExpGus controller for fast time scale, based on order of RK " + << ((opts.fast_pq == 1) ? "method\n" : "embedding\n"); + std::cout << " fast_rtol = " << opts.fast_rtol + << ", atol = " << opts.atol << "\n"; + if (std::min(opts.k1f, opts.k2f) > -1) + { + std::cout << " fast controller parameters: " << opts.k1f << " " + << opts.k2f << "\n"; + } + break; + case (5): + std::cout + << " ImpGus controller for fast time scale, based on order of RK " + << ((opts.fast_pq == 1) ? "method\n" : "embedding\n"); + std::cout << " fast_rtol = " << opts.fast_rtol + << ", atol = " << opts.atol << "\n"; + if (std::min(opts.k1f, opts.k2f) > -1) + { + std::cout << " fast controller parameters: " << opts.k1f << " " + << opts.k2f << "\n"; + } + break; + case (6): + std::cout + << " ImExGus controller for fast time scale, based on order of RK " + << ((opts.fast_pq == 1) ? "method\n" : "embedding\n"); + std::cout << " fast_rtol = " << opts.fast_rtol + << ", atol = " << opts.atol << "\n"; + break; + } +} + +//---- end of file ----// diff --git a/test/unit_tests/arkode/CXX_serial/ark_test_kpr_mriadapt_--hs_0.002_--rtol_0.000004_--scontrol_0.out b/test/unit_tests/arkode/CXX_serial/ark_test_kpr_mriadapt_--hs_0.002_--rtol_0.000004_--scontrol_0.out new file mode 100644 index 0000000000..8e57f80640 --- /dev/null +++ b/test/unit_tests/arkode/CXX_serial/ark_test_kpr_mriadapt_--hs_0.002_--rtol_0.000004_--scontrol_0.out @@ -0,0 +1,45 @@ + +Adaptive multirate nonlinear Kvaerno-Prothero-Robinson test problem: + time domain: (0,5] + G = -100 + w = 100 + e = 0.5 + + Slow integrator: ARKODE_MRI_GARK_ERK45a (explicit) + fixed steps, hs = 0.002 + rtol = 4e-06, atol = 1e-11 + + Fast order 4 + I controller for fast time scale, based on order of RK embedding + fast_rtol = 0.0001, atol = 1e-11 + t u v uerr verr + ------------------------------------------------------ + 0.000000 1.732051 1.732051 0.00e+00 0.00e+00 + 0.250000 1.723053 1.584050 5.10e-11 1.74e-10 + 0.500000 1.696344 1.512598 4.30e-11 2.73e-10 + 0.750000 1.652782 1.036015 4.02e-11 3.15e-09 + 1.000000 1.593833 1.458873 3.25e-11 2.89e-09 + 1.250000 1.521618 1.458201 3.35e-11 1.27e-08 + 1.500000 1.439006 1.011474 4.36e-11 6.25e-08 + 1.750000 1.349724 1.730452 3.65e-12 3.67e-09 + 2.000000 1.258512 1.214374 1.24e-11 5.83e-09 + 2.250000 1.171250 1.024071 2.70e-11 1.63e-10 + 2.500000 1.094923 1.471085 4.59e-11 3.37e-13 + 2.750000 1.037158 1.313348 6.43e-11 2.13e-11 + 3.000000 1.004991 1.274175 7.65e-11 2.92e-11 + 3.250000 1.002931 1.043458 7.96e-11 6.41e-12 + 3.500000 1.031282 1.053648 6.81e-11 1.65e-13 + 3.750000 1.086021 1.006374 5.10e-11 3.61e-12 + 4.000000 1.160326 1.571824 3.06e-11 1.90e-11 + 4.250000 1.246560 1.705136 7.61e-12 4.47e-11 + 4.500000 1.337611 1.431830 3.19e-12 5.54e-11 + 4.750000 1.427446 1.162908 1.55e-11 1.82e-10 + 5.000000 1.511179 1.070831 2.51e-11 3.35e-10 + ------------------------------------------------------ + +Final Solver Statistics: + Slow steps = 2500 (attempts = 2500, fails = 0) + Fast steps = 12502 (attempts = 12502, fails = 0) + u error = 4.31846e-11, v error = 9.52053e-09, total error = 6.7321e-09 + Relative accuracy = 0.0160086 + Total RHS evals: Fse = 12500, Fsi = 0, Ff = 65012 diff --git a/test/unit_tests/arkode/CXX_serial/ark_test_slowerror_brusselator.cpp b/test/unit_tests/arkode/CXX_serial/ark_test_slowerror_brusselator.cpp new file mode 100644 index 0000000000..e094279c41 --- /dev/null +++ b/test/unit_tests/arkode/CXX_serial/ark_test_slowerror_brusselator.cpp @@ -0,0 +1,623 @@ +/*----------------------------------------------------------------- + * Programmer(s): Daniel R. Reynolds @ SMU + *--------------------------------------------------------------- + * SUNDIALS Copyright Start + * Copyright (c) 2002-2024, Lawrence Livermore National Security + * and Southern Methodist University. + * All rights reserved. + * + * See the top-level LICENSE and NOTICE files for details. + * + * SPDX-License-Identifier: BSD-3-Clause + * SUNDIALS Copyright End + *--------------------------------------------------------------- + * Routine to test an MRI method's embedding-based error + * estimate. Uses the "stiff Brusselator" test problem with 3 + * components, + * du/dt = a - (w+1)*u + v*u^2 + * dv/dt = w*u - v*u^2 + * dw/dt = (b-w)/ep - w*u + * for t in the interval [0.0, 10.0], with initial conditions + * Y0 = [u0,v0,w0]. + * + * The stiffness of the problem is essentially determined + * by ep, wherein if the dynamical time step is given by H and + * the explicit time step size is given by h, then H/h = 1/(100 ep), + * i.e., the stability-limited step takes over at values of + * ep < 1e-2. This file defaults to a moderately stiff setup with + * ep = 1/2500. + * + * We may run the problem in one of 3 different testing scenarios: + * + * Test 1: u0=3.9, v0=1.1, w0=2.8, a=1.2, b=2.5 + * Here, all three components exhibit a rapid transient change + * during the first 0.2 time units, followed by a slow and + * smooth evolution. + * + * Test 2 [default]: u0=1.2, v0=3.1, w0=3, a=1, b=3.5 + * Here, w experiences a fast initial transient, jumping 0.5 + * within a few steps. All values proceed smoothly until + * around t=6.5, when both u and v undergo a sharp transition, + * with u increaseing from around 0.5 to 5 and v decreasing + * from around 6 to 1 in less than 0.5 time units. After this + * transition, both u and v continue to evolve somewhat + * rapidly for another 1.4 time units, and finish off smoothly. + * + * Test 3: u0=3, v0=3, w0=3.5, a=0.5, b=3 + * Here, all components undergo very rapid initial transients + * during the first 0.3 time units, and all then proceed very + * smoothly for the remainder of the simulation. + * + * We partition the full time integration interval, 0 < t < 5, into + * Npart pieces. We then run a single time step starting at the + * beginning of each partition, using a variety of slow step sizes, + * H = {hmax, hmax/4, hmax/16, hmax/64, hmax/256} with + * hmax=(t_f-t_0)/20/Npart. + * + * We place the entire ODE in the "slow" RHS partition. For IMEX + * methods, the third row is treated implicitly, and the first two + * are treated explicitly. For the fast time scale, all tests use + * ARKODE's default fifth-order ERK method, with relative and + * absolute tolerances set to 1e-10 and 1e-12, respectively. + * + * We select the slow integrator based on a command-line argument, + * with the default being ARKODE_MRI_GARK_ERK33a. + * + * The program should be run with arguments in the following order: + * $ a.out method Npart ep test + * Not all arguments are required, but these must be omitted from + * end-to-beginning, i.e. any one of + * $ a.out method Npart ep + * $ a.out method Npart + * $ a.out method + * $ a.out + * are acceptable. We require: + * * method = string corresponding to a valid embedded ARKODE_MRITableID + * * Npart > 0 + * * ep > 0 + * * test = {1, 2, 3} + *-----------------------------------------------------------------*/ + +// Header files +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#if defined(SUNDIALS_EXTENDED_PRECISION) +#define GSYM "Lg" +#define ESYM "Le" +#define FSYM "Lf" +#else +#define GSYM "g" +#define ESYM "e" +#define FSYM "f" +#endif + +#define ZERO SUN_RCONST(0.0) +#define ONE SUN_RCONST(1.0) +#define TWO SUN_RCONST(2.0) + +using namespace std; + +// User data structure +struct UserData +{ + sunrealtype a; + sunrealtype b; + sunrealtype ep; + int Npart; +}; + +// User-supplied Functions Called by the Solver +static int f0(sunrealtype t, N_Vector y, N_Vector ydot, void* user_data); +static int fn(sunrealtype t, N_Vector y, N_Vector ydot, void* user_data); +static int fi(sunrealtype t, N_Vector y, N_Vector ydot, void* user_data); +static int fe(sunrealtype t, N_Vector y, N_Vector ydot, void* user_data); +static int Jn(sunrealtype t, N_Vector y, N_Vector fy, SUNMatrix J, + void* user_data, N_Vector tmp1, N_Vector tmp2, N_Vector tmp3); +static int Ji(sunrealtype t, N_Vector y, N_Vector fy, SUNMatrix J, + void* user_data, N_Vector tmp1, N_Vector tmp2, N_Vector tmp3); + +// Private utility functions +static int computeErrorWeights(N_Vector ycur, N_Vector weight, sunrealtype rtol, + sunrealtype atol, N_Vector vtemp); +static int check_retval(void* returnvalue, const char* funcname, int opt); +static int run_test(void* mristep_mem, void* arkode_ref, N_Vector y, + sunrealtype T0, sunrealtype Tf, N_Vector* yref, + vector Hvals, string method, + sunrealtype reltol, sunrealtype abstol, UserData& udata); + +// Main Program +int main(int argc, char* argv[]) +{ + // general problem parameters + sunrealtype T0 = SUN_RCONST(0.0); // initial time + sunrealtype Tf = SUN_RCONST(10.0); // final time + sunindextype NEQ = 3; // number of dependent vars. + string method; // MRI method name + int test = 2; // test problem to run + sunrealtype u0, v0, w0; // parameters + sunrealtype reltol = SUN_RCONST(1.e-10); // fast solver tolerances + sunrealtype abstol = SUN_RCONST(1.e-12); + + // general problem variables + int retval; // reusable error-checking flag + UserData udata; // user-data structure + udata.ep = SUN_RCONST(0.0004); // stiffness parameter + udata.Npart = 20; // partition size + + // + // Initialization + // + + // Retrieve the command-line options: method Npart ep test + if (argc > 1) { method = argv[1]; } + else { method = "ARKODE_MRI_GARK_ERK33a"; } + if (argc > 2) udata.Npart = atoi(argv[2]); + if (argc > 3) udata.ep = SUNStrToReal(argv[3]); + if (argc > 4) test = atoi(argv[4]); + + // Check arguments for validity + // Npart > 0 + // ep > 0 + // test = {1, 2, 3} + if (udata.Npart < 1) + { + cerr << "ERROR: Npart must be a positive integer\n"; + return (-1); + } + if (udata.ep <= ZERO) + { + cerr << "ERROR: ep must be a positive real number\n"; + return (-1); + } + if ((test < 1) || (test > 3)) + { + cerr << "ERROR: test type be an integer in {1,2,3} \n"; + return (-1); + } + + // set up the test problem according to the desired test + if (test == 1) + { + u0 = SUN_RCONST(3.9); + v0 = SUN_RCONST(1.1); + w0 = SUN_RCONST(2.8); + udata.a = SUN_RCONST(1.2); + udata.b = SUN_RCONST(2.5); + } + else if (test == 3) + { + u0 = SUN_RCONST(3.0); + v0 = SUN_RCONST(3.0); + w0 = SUN_RCONST(3.5); + udata.a = SUN_RCONST(0.5); + udata.b = SUN_RCONST(3.0); + } + else + { + u0 = SUN_RCONST(1.2); + v0 = SUN_RCONST(3.1); + w0 = SUN_RCONST(3.0); + udata.a = SUN_RCONST(1.0); + udata.b = SUN_RCONST(3.5); + } + + sunbooleantype implicit = SUNFALSE; + sunbooleantype imex = SUNFALSE; + if ((method == "ARKODE_MRI_GARK_IRK21a") || + (method == "ARKODE_MRI_GARK_ESDIRK34a") || + (method == "ARKODE_MRI_GARK_ESDIRK46a")) + { + implicit = SUNTRUE; + } + if ((method == "ARKODE_IMEX_MRI_SR21") || + (method == "ARKODE_IMEX_MRI_SR32") || (method == "ARKODE_IMEX_MRI_SR43")) + { + imex = SUNTRUE; + implicit = SUNTRUE; + } + + // Initial problem output (and set implicit solver tolerances as needed) + cout << "\nSlow error estimation test (stiff Brusselator ODE problem):\n"; + cout << " time domain: (" << T0 << "," << Tf << "]\n"; + cout << " partition size = " << udata.Npart << endl; + cout << " initial conditions: u0 = " << u0 << ", v0 = " << v0 + << ", w0 = " << w0 << endl; + cout << " problem parameters: a = " << udata.a << ", b = " << udata.b + << ", ep = " << udata.ep << endl; + cout << " MRI method: " << method; + if (imex) { cout << " (ImEx)" << endl; } + else if (implicit) { cout << " (implicit)" << endl; } + else { cout << " (explicit)" << endl; } + + // + // Problem Setup + // + + // Create SUNDIALS context + sundials::Context ctx; + + // Create serial vectors for the solution and reference + N_Vector y = N_VNew_Serial(NEQ, ctx); + if (check_retval((void*)y, "N_VNew_Serial", 0)) return 1; + N_Vector* yref = N_VCloneVectorArray(udata.Npart + 1, y); + if (check_retval((void*)yref, "N_VNew_Serial", 0)) return 1; + sunrealtype* ydata = N_VGetArrayPointer(y); + if (check_retval((void*)ydata, "N_VGetArrayPointer", 0)) return 1; + ydata[0] = u0; + ydata[1] = v0; + ydata[2] = w0; + + // Generate reference solution + void* arkode_ref = ERKStepCreate(fn, T0, y, ctx); + if (check_retval((void*)arkode_ref, "ERKStepCreate", 0)) return 1; + retval = ARKodeSetUserData(arkode_ref, (void*)&udata); + if (check_retval(&retval, "ARKodeSetUserData", 1)) return 1; + retval = ARKodeSetOrder(arkode_ref, 5); + if (check_retval(&retval, "ARKodeSetOrder", 1)) return 1; + retval = ARKodeSStolerances(arkode_ref, reltol, abstol); + if (check_retval(&retval, "ARKodeSStolerances", 1)) return 1; + retval = ARKodeSetMaxNumSteps(arkode_ref, 1000000); + if (check_retval(&retval, "ARKodeSetMaxNumSteps", 1)) return (1); + N_VScale(ONE, y, yref[0]); + sunrealtype hpart = (Tf - T0) / udata.Npart; + for (int ipart = 0; ipart < udata.Npart; ipart++) + { + sunrealtype t = T0 + ipart * hpart; + retval = ARKodeSetStopTime(arkode_ref, t + hpart); + if (check_retval(&retval, "ARKodeSetStopTime", 1)) return 1; + retval = ARKodeEvolve(arkode_ref, t + hpart, y, &t, ARK_NORMAL); + if (check_retval(&retval, "ARKodeEvolve", 1)) return 1; + N_VScale(ONE, y, yref[ipart + 1]); + } + + // Set up fast ERKStep integrator as fifth-order adaptive method + ydata[0] = u0; + ydata[1] = v0; + ydata[2] = w0; + void* inner_arkode_mem = ERKStepCreate(f0, T0, y, ctx); + if (check_retval((void*)inner_arkode_mem, "ERKStepCreate", 0)) return 1; + retval = ARKodeSetOrder(inner_arkode_mem, 5); + if (check_retval(&retval, "ARKodeSetOrder", 1)) return 1; + retval = ARKodeSStolerances(inner_arkode_mem, reltol, abstol); + if (check_retval(&retval, "ARKodeSStolerances", 1)) return 1; + retval = ARKodeSetMaxNumSteps(inner_arkode_mem, 1000000); + if (check_retval(&retval, "ARKodeSetMaxNumSteps", 1)) return (1); + + // Create inner stepper wrapper + MRIStepInnerStepper inner_stepper = NULL; // inner stepper + retval = ARKodeCreateMRIStepInnerStepper(inner_arkode_mem, &inner_stepper); + if (check_retval(&retval, "ARKodeCreateMRIStepInnerStepper", 1)) return 1; + + // Set up slow MRIStep integrator + void* mristep_mem = NULL; + if (imex) { mristep_mem = MRIStepCreate(fe, fi, T0, y, inner_stepper, ctx); } + else if (implicit) + { + mristep_mem = MRIStepCreate(NULL, fn, T0, y, inner_stepper, ctx); + } + else { mristep_mem = MRIStepCreate(fn, NULL, T0, y, inner_stepper, ctx); } + if (check_retval((void*)mristep_mem, "MRIStepCreate", 0)) return 1; + MRIStepCoupling C = MRIStepCoupling_LoadTableByName(method.c_str()); + if (check_retval((void*)C, "MRIStepCoupling_LoadTableByName", 0)) return 1; + retval = MRIStepSetCoupling(mristep_mem, C); + if (check_retval(&retval, "MRIStepSetCoupling", 1)) return 1; + SUNMatrix A = NULL; // matrix for slow solver + SUNLinearSolver LS = NULL; // slow linear solver object + if (implicit) + { + A = SUNDenseMatrix(NEQ, NEQ, ctx); + if (check_retval((void*)A, "SUNDenseMatrix", 0)) return 1; + LS = SUNLinSol_Dense(y, A, ctx); + if (check_retval((void*)LS, "SUNLinSol_Dense", 0)) return 1; + retval = ARKodeSetLinearSolver(mristep_mem, LS, A); + if (check_retval(&retval, "ARKodeSetLinearSolver", 1)) return 1; + if (imex) { retval = ARKodeSetJacFn(mristep_mem, Ji); } + else { retval = ARKodeSetJacFn(mristep_mem, Jn); } + if (check_retval(&retval, "ARKodeSetJacFn", 1)) return 1; + retval = ARKodeSetJacEvalFrequency(mristep_mem, 1); + if (check_retval(&retval, "ARKodeSetJacEvalFrequency", 1)) return 1; + retval = ARKodeSetLSetupFrequency(mristep_mem, 1); + if (check_retval(&retval, "ARKodeSetLSetupFrequency", 1)) return 1; + retval = ARKodeSetMaxNonlinIters(mristep_mem, 50); + if (check_retval(&retval, "ARKodeSetMaxNonlinIters", 1)) return 1; + } + retval = ARKodeSStolerances(mristep_mem, reltol, abstol); + if (check_retval(&retval, "ARKodeSStolerances", 1)) return 1; + retval = ARKodeSetUserData(mristep_mem, (void*)&udata); + if (check_retval(&retval, "ARKodeSetUserData", 1)) return 1; + retval = ARKodeSetAccumulatedErrorType(mristep_mem, ARK_ACCUMERROR_MAX); + if (check_retval(&retval, "ARKodeSetAccumulatedErrorType", 1)) return 1; + + // Run test for various H values + sunrealtype hmax = (Tf - T0) / 20.0 / udata.Npart; + vector Hvals(5); + for (size_t i = 0; i < Hvals.size(); i++) + { + Hvals[i] = hmax / SUNRpowerI(SUN_RCONST(4.0), (int)i); + } + retval = run_test(mristep_mem, arkode_ref, y, T0, Tf, yref, Hvals, method, + reltol, abstol, udata); + if (check_retval(&retval, "run_test", 1)) return 1; + + // Clean up and return + MRIStepCoupling_Free(C); + ARKodeFree(&arkode_ref); + ARKodeFree(&inner_arkode_mem); + MRIStepInnerStepper_Free(&inner_stepper); + ARKodeFree(&mristep_mem); + if (LS) { SUNLinSolFree(LS); } // free system linear solver + if (A) { SUNMatDestroy(A); } // free system matrix + N_VDestroy(y); // Free y and yref vectors + N_VDestroyVectorArray(yref, udata.Npart + 1); + return 0; +} + +//------------------------------ +// Functions called by the solver +//------------------------------ + +static int f0(sunrealtype t, N_Vector y, N_Vector ydot, void* user_data) +{ + // fill in the RHS function with zeros and return with success + N_VConst(ZERO, ydot); + return 0; +} + +static int fn(sunrealtype t, N_Vector y, N_Vector ydot, void* user_data) +{ + UserData* udata = (UserData*)user_data; + sunrealtype* ydata = N_VGetArrayPointer(y); + sunrealtype* dydata = N_VGetArrayPointer(ydot); + const sunrealtype u = ydata[0]; // access solution values + const sunrealtype v = ydata[1]; + const sunrealtype w = ydata[2]; + + // fill in the RHS function + dydata[0] = udata->a - (w + ONE) * u + v * u * u; + dydata[1] = w * u - v * u * u; + dydata[2] = (udata->b - w) / udata->ep - w * u; + + // Return with success + return 0; +} + +static int fi(sunrealtype t, N_Vector y, N_Vector ydot, void* user_data) +{ + UserData* udata = (UserData*)user_data; + sunrealtype* ydata = N_VGetArrayPointer(y); + sunrealtype* dydata = N_VGetArrayPointer(ydot); + const sunrealtype u = ydata[0]; // access solution values + const sunrealtype w = ydata[2]; + + // fill in the RHS function + dydata[0] = ZERO; + dydata[1] = ZERO; + dydata[2] = (udata->b - w) / udata->ep - w * u; + + // Return with success + return 0; +} + +static int fe(sunrealtype t, N_Vector y, N_Vector ydot, void* user_data) +{ + UserData* udata = (UserData*)user_data; + sunrealtype* ydata = N_VGetArrayPointer(y); + sunrealtype* dydata = N_VGetArrayPointer(ydot); + const sunrealtype u = ydata[0]; // access solution values + const sunrealtype v = ydata[1]; + const sunrealtype w = ydata[2]; + + // fill in the RHS function + dydata[0] = udata->a - (w + ONE) * u + v * u * u; + dydata[1] = w * u - v * u * u; + dydata[2] = ZERO; + + // Return with success + return 0; +} + +static int Jn(sunrealtype t, N_Vector y, N_Vector fy, SUNMatrix J, + void* user_data, N_Vector tmp1, N_Vector tmp2, N_Vector tmp3) +{ + UserData* udata = (UserData*)user_data; + sunrealtype* ydata = N_VGetArrayPointer(y); + const sunrealtype u = ydata[0]; // access solution values + const sunrealtype v = ydata[1]; + const sunrealtype w = ydata[2]; + + // fill in the Jacobian + SM_ELEMENT_D(J, 0, 0) = -(w + ONE) + TWO * u * v; + SM_ELEMENT_D(J, 0, 1) = u * u; + SM_ELEMENT_D(J, 0, 2) = -u; + + SM_ELEMENT_D(J, 1, 0) = w - TWO * u * v; + SM_ELEMENT_D(J, 1, 1) = -u * u; + SM_ELEMENT_D(J, 1, 2) = u; + + SM_ELEMENT_D(J, 2, 0) = -w; + SM_ELEMENT_D(J, 2, 1) = ZERO; + SM_ELEMENT_D(J, 2, 2) = -ONE / udata->ep - u; + + // Return with success + return 0; +} + +static int Ji(sunrealtype t, N_Vector y, N_Vector fy, SUNMatrix J, + void* user_data, N_Vector tmp1, N_Vector tmp2, N_Vector tmp3) +{ + UserData* udata = (UserData*)user_data; + sunrealtype* ydata = N_VGetArrayPointer(y); + const sunrealtype u = ydata[0]; // access solution values + const sunrealtype w = ydata[2]; + + // fill in the Jacobian + SM_ELEMENT_D(J, 0, 0) = ZERO; + SM_ELEMENT_D(J, 0, 1) = ZERO; + SM_ELEMENT_D(J, 0, 2) = ZERO; + + SM_ELEMENT_D(J, 1, 0) = ZERO; + SM_ELEMENT_D(J, 1, 1) = ZERO; + SM_ELEMENT_D(J, 1, 2) = ZERO; + + SM_ELEMENT_D(J, 2, 0) = -w; + SM_ELEMENT_D(J, 2, 1) = ZERO; + SM_ELEMENT_D(J, 2, 2) = -ONE / udata->ep - u; + + // Return with success + return 0; +} + +//------------------------------ +// Private helper functions +//------------------------------ + +static int run_test(void* mristep_mem, void* arkode_ref, N_Vector y, + sunrealtype T0, sunrealtype Tf, N_Vector* yref, + vector Hvals, string method, + sunrealtype reltol, sunrealtype abstol, UserData& udata) +{ + // Reused variables + int retval; + sunrealtype hpart = (Tf - T0) / udata.Npart; + sunrealtype t, t2; + N_Vector y2 = N_VClone(y); + N_Vector ele = N_VClone(y); + N_Vector ewt = N_VClone(y); + N_Vector vtemp = N_VClone(y); + sunrealtype* ydata = N_VGetArrayPointer(y); + sunrealtype* y2data = N_VGetArrayPointer(y2); + + // Set storage for errors + vector> dsm(Hvals.size(), + vector(udata.Npart, ZERO)); + vector> dsm_est(Hvals.size(), + vector(udata.Npart, ZERO)); + + // Loop over step sizes + for (size_t iH = 0; iH < Hvals.size(); iH++) + { + // Loop over partition + for (int ipart = 0; ipart < udata.Npart; ipart++) + { + // Reset integrators for this run + t = t2 = T0 + ipart * hpart; + N_VScale(ONE, yref[ipart], y); + retval = ARKodeReset(mristep_mem, t, y); + if (check_retval(&retval, "ARKodeReset", 1)) return 1; + retval = ARKodeSetFixedStep(mristep_mem, Hvals[iH]); + if (check_retval(&retval, "ARKodeSetFixedStep", 1)) return 1; + retval = ARKodeResetAccumulatedError(mristep_mem); + if (check_retval(&retval, "ARKodeResetAccumulatedError", 1)) return 1; + N_VScale(ONE, yref[ipart], y2); + retval = ARKodeReset(arkode_ref, t2, y2); + if (check_retval(&retval, "ARKodeReset", 1)) return 1; + retval = ARKodeSetStopTime(arkode_ref, t2 + Hvals[iH]); + if (check_retval(&retval, "ARKodeSetStopTime", 1)) return 1; + + // Run ERKStep to compute reference solution, and MRIStep to compute one step + retval = ARKodeEvolve(arkode_ref, t2 + Hvals[iH], y2, &t2, ARK_NORMAL); + if (check_retval(&retval, "ARKodeEvolve", 1)) return 1; + retval = ARKodeEvolve(mristep_mem, t + Hvals[iH], y, &t, ARK_ONE_STEP); + if (check_retval(&retval, "ARKodeEvolve", 1)) return 1; + retval = ARKodeGetEstLocalErrors(mristep_mem, ele); + if (check_retval(&retval, "ARKodeGetEstLocalErrors", 1)) return 1; + retval = computeErrorWeights(y, ewt, reltol, abstol, vtemp); + if (check_retval(&retval, "computeErrorWeights", 1)) return 1; + dsm_est[iH][ipart] = N_VWrmsNorm(ewt, ele); + + // Compute/print solution error + sunrealtype udsm = abs(ydata[0] - y2data[0]) / + (abstol + reltol * abs(y2data[0])); + sunrealtype vdsm = abs(ydata[1] - y2data[1]) / + (abstol + reltol * abs(y2data[1])); + sunrealtype wdsm = abs(ydata[2] - y2data[2]) / + (abstol + reltol * abs(y2data[2])); + dsm[iH][ipart] = + sqrt((udsm * udsm + vdsm * vdsm + wdsm * wdsm) / SUN_RCONST(3.0)); + cout << " H " << Hvals[iH] << " method " << method << " t " << t + << " dsm " << dsm[iH][ipart] << " dsm_est " << dsm_est[iH][ipart] + << endl; + } + } + + cout << endl << method << " summary:" << endl; + for (size_t iH = 0; iH < Hvals.size(); iH++) + { + cout << " Stepsize " << Hvals[iH] << " \tmaxdsm " + << *max_element(dsm[iH].begin(), dsm[iH].end()) << " \tmaxdsmest " + << *max_element(dsm_est[iH].begin(), dsm_est[iH].end()) << endl; + } + + N_VDestroy(ele); + N_VDestroy(ewt); + N_VDestroy(vtemp); + N_VDestroy(y2); + return (0); +} + +/* Error weight calculation routine (mimics what's in ARKODE already) */ +static int computeErrorWeights(N_Vector ycur, N_Vector weight, sunrealtype rtol, + sunrealtype atol, N_Vector vtemp) +{ + N_VAbs(ycur, vtemp); + N_VScale(rtol, vtemp, vtemp); + N_VAddConst(vtemp, atol, vtemp); + N_VInv(vtemp, weight); + return (0); +} + +/* Check function return value... + opt == 0 means SUNDIALS function allocates memory so check if + returned NULL pointer + opt == 1 means SUNDIALS function returns a retval so check if + retval >= 0 + opt == 2 means function allocates memory so check if returned + NULL pointer +*/ +static int check_retval(void* returnvalue, const char* funcname, int opt) +{ + int* retval; + + // Check if SUNDIALS function returned NULL pointer - no memory allocated + if (opt == 0 && returnvalue == NULL) + { + fprintf(stderr, "\nSUNDIALS_ERROR: %s() failed - returned NULL pointer\n\n", + funcname); + return 1; + } + + // Check if retval < 0 + else if (opt == 1) + { + retval = (int*)returnvalue; + if (*retval < 0) + { + fprintf(stderr, "\nSUNDIALS_ERROR: %s() failed with retval = %d\n\n", + funcname, *retval); + return 1; + } + } + + // Check if function returned NULL pointer - no memory allocated + else if (opt == 2 && returnvalue == NULL) + { + fprintf(stderr, "\nMEMORY_ERROR: %s() failed - returned NULL pointer\n\n", + funcname); + return 1; + } + + return 0; +} + +/*---- end of file ----*/ diff --git a/test/unit_tests/arkode/CXX_serial/ark_test_slowerror_brusselator.out b/test/unit_tests/arkode/CXX_serial/ark_test_slowerror_brusselator.out new file mode 100644 index 0000000000..80f4ea9e89 --- /dev/null +++ b/test/unit_tests/arkode/CXX_serial/ark_test_slowerror_brusselator.out @@ -0,0 +1,114 @@ + +Slow error estimation test (stiff Brusselator ODE problem): + time domain: (0,10] + partition size = 20 + initial conditions: u0 = 1.2, v0 = 3.1, w0 = 3 + problem parameters: a = 1, b = 3.5, ep = 0.0004 + MRI method: ARKODE_MRI_GARK_ERK33a (explicit) + H 0.025 method ARKODE_MRI_GARK_ERK33a t 0.025 dsm 3.18615e+13 dsm_est 2.87651e+09 + H 0.025 method ARKODE_MRI_GARK_ERK33a t 0.525 dsm 837.406 dsm_est 1222.98 + H 0.025 method ARKODE_MRI_GARK_ERK33a t 1.025 dsm 2348.79 dsm_est 726.699 + H 0.025 method ARKODE_MRI_GARK_ERK33a t 1.525 dsm 7973.51 dsm_est 2607.8 + H 0.025 method ARKODE_MRI_GARK_ERK33a t 2.025 dsm 9623.78 dsm_est 2984.3 + H 0.025 method ARKODE_MRI_GARK_ERK33a t 2.525 dsm 8578.19 dsm_est 2152.09 + H 0.025 method ARKODE_MRI_GARK_ERK33a t 3.025 dsm 1758.42 dsm_est 2231.61 + H 0.025 method ARKODE_MRI_GARK_ERK33a t 3.525 dsm 6231.49 dsm_est 2031.06 + H 0.025 method ARKODE_MRI_GARK_ERK33a t 4.025 dsm 581.953 dsm_est 611.637 + H 0.025 method ARKODE_MRI_GARK_ERK33a t 4.525 dsm 18745.1 dsm_est 4370.47 + H 0.025 method ARKODE_MRI_GARK_ERK33a t 5.025 dsm 1260.35 dsm_est 475.824 + H 0.025 method ARKODE_MRI_GARK_ERK33a t 5.525 dsm 883.239 dsm_est 2069.94 + H 0.025 method ARKODE_MRI_GARK_ERK33a t 6.025 dsm 1948.31 dsm_est 14304.8 + H 0.025 method ARKODE_MRI_GARK_ERK33a t 6.525 dsm 61433.5 dsm_est 330405 + H 0.025 method ARKODE_MRI_GARK_ERK33a t 7.025 dsm 742189 dsm_est 1.51629e+06 + H 0.025 method ARKODE_MRI_GARK_ERK33a t 7.525 dsm 9668.21 dsm_est 19961.4 + H 0.025 method ARKODE_MRI_GARK_ERK33a t 8.025 dsm 893.005 dsm_est 6498.9 + H 0.025 method ARKODE_MRI_GARK_ERK33a t 8.525 dsm 844.884 dsm_est 2277.18 + H 0.025 method ARKODE_MRI_GARK_ERK33a t 9.025 dsm 810.509 dsm_est 10912.2 + H 0.025 method ARKODE_MRI_GARK_ERK33a t 9.525 dsm 1454.42 dsm_est 10680.6 + H 0.00625 method ARKODE_MRI_GARK_ERK33a t 0.00625 dsm 4.33933e+11 dsm_est 1.53179e+09 + H 0.00625 method ARKODE_MRI_GARK_ERK33a t 0.50625 dsm 12.1853 dsm_est 19.2231 + H 0.00625 method ARKODE_MRI_GARK_ERK33a t 1.00625 dsm 32.4451 dsm_est 11.3701 + H 0.00625 method ARKODE_MRI_GARK_ERK33a t 1.50625 dsm 109.586 dsm_est 40.659 + H 0.00625 method ARKODE_MRI_GARK_ERK33a t 2.00625 dsm 131.993 dsm_est 46.7335 + H 0.00625 method ARKODE_MRI_GARK_ERK33a t 2.50625 dsm 117.719 dsm_est 33.46 + H 0.00625 method ARKODE_MRI_GARK_ERK33a t 3.00625 dsm 24.1579 dsm_est 34.5477 + H 0.00625 method ARKODE_MRI_GARK_ERK33a t 3.50625 dsm 85.0006 dsm_est 31.747 + H 0.00625 method ARKODE_MRI_GARK_ERK33a t 4.00625 dsm 7.95919 dsm_est 9.62849 + H 0.00625 method ARKODE_MRI_GARK_ERK33a t 4.50625 dsm 255.567 dsm_est 68.3015 + H 0.00625 method ARKODE_MRI_GARK_ERK33a t 5.00625 dsm 17.322 dsm_est 7.33608 + H 0.00625 method ARKODE_MRI_GARK_ERK33a t 5.50625 dsm 12.3537 dsm_est 31.9016 + H 0.00625 method ARKODE_MRI_GARK_ERK33a t 6.00625 dsm 25.1474 dsm_est 221.476 + H 0.00625 method ARKODE_MRI_GARK_ERK33a t 6.50625 dsm 230.645 dsm_est 5222.75 + H 0.00625 method ARKODE_MRI_GARK_ERK33a t 7.00625 dsm 3236.88 dsm_est 24290.4 + H 0.00625 method ARKODE_MRI_GARK_ERK33a t 7.50625 dsm 116.715 dsm_est 305.487 + H 0.00625 method ARKODE_MRI_GARK_ERK33a t 8.00625 dsm 11.908 dsm_est 101.68 + H 0.00625 method ARKODE_MRI_GARK_ERK33a t 8.50625 dsm 13.9795 dsm_est 36.3543 + H 0.00625 method ARKODE_MRI_GARK_ERK33a t 9.00625 dsm 10.4298 dsm_est 164.536 + H 0.00625 method ARKODE_MRI_GARK_ERK33a t 9.50625 dsm 18.0339 dsm_est 165.001 + H 0.0015625 method ARKODE_MRI_GARK_ERK33a t 0.0015625 dsm 4.30937e+09 dsm_est 1.04109e+09 + H 0.0015625 method ARKODE_MRI_GARK_ERK33a t 0.501563 dsm 0.124019 dsm_est 0.300808 + H 0.0015625 method ARKODE_MRI_GARK_ERK33a t 1.00156 dsm 0.4016 dsm_est 0.177725 + H 0.0015625 method ARKODE_MRI_GARK_ERK33a t 1.50156 dsm 1.08417 dsm_est 0.634969 + H 0.0015625 method ARKODE_MRI_GARK_ERK33a t 2.00156 dsm 1.63593 dsm_est 0.730609 + H 0.0015625 method ARKODE_MRI_GARK_ERK33a t 2.50156 dsm 1.21684 dsm_est 0.522198 + H 0.0015625 method ARKODE_MRI_GARK_ERK33a t 3.00156 dsm 0.297567 dsm_est 0.53854 + H 0.0015625 method ARKODE_MRI_GARK_ERK33a t 3.50156 dsm 0.843901 dsm_est 0.496086 + H 0.0015625 method ARKODE_MRI_GARK_ERK33a t 4.00156 dsm 0.0984505 dsm_est 0.150722 + H 0.0015625 method ARKODE_MRI_GARK_ERK33a t 4.50156 dsm 3.172 dsm_est 1.06726 + H 0.0015625 method ARKODE_MRI_GARK_ERK33a t 5.00156 dsm 0.177227 dsm_est 0.114246 + H 0.0015625 method ARKODE_MRI_GARK_ERK33a t 5.50156 dsm 0.153004 dsm_est 0.496739 + H 0.0015625 method ARKODE_MRI_GARK_ERK33a t 6.00156 dsm 0.2503 dsm_est 3.45242 + H 0.0015625 method ARKODE_MRI_GARK_ERK33a t 6.50156 dsm 0.94962 dsm_est 81.8018 + H 0.0015625 method ARKODE_MRI_GARK_ERK33a t 7.00156 dsm 12.9921 dsm_est 381.512 + H 0.0015625 method ARKODE_MRI_GARK_ERK33a t 7.50156 dsm 1.43794 dsm_est 4.74552 + H 0.0015625 method ARKODE_MRI_GARK_ERK33a t 8.00156 dsm 0.120488 dsm_est 1.58917 + H 0.0015625 method ARKODE_MRI_GARK_ERK33a t 8.50156 dsm 0.179682 dsm_est 0.571046 + H 0.0015625 method ARKODE_MRI_GARK_ERK33a t 9.00156 dsm 0.118533 dsm_est 2.54788 + H 0.0015625 method ARKODE_MRI_GARK_ERK33a t 9.50156 dsm 0.220342 dsm_est 2.57065 + H 0.000390625 method ARKODE_MRI_GARK_ERK33a t 0.000390625 dsm 2.73843e+07 dsm_est 2.97866e+07 + H 0.000390625 method ARKODE_MRI_GARK_ERK33a t 0.500391 dsm 0.00068624 dsm_est 0.00470174 + H 0.000390625 method ARKODE_MRI_GARK_ERK33a t 1.00039 dsm 0.00193295 dsm_est 0.00277739 + H 0.000390625 method ARKODE_MRI_GARK_ERK33a t 1.50039 dsm 0.00652841 dsm_est 0.00992044 + H 0.000390625 method ARKODE_MRI_GARK_ERK33a t 2.00039 dsm 0.007873 dsm_est 0.0114169 + H 0.000390625 method ARKODE_MRI_GARK_ERK33a t 2.50039 dsm 0.00699861 dsm_est 0.00815712 + H 0.000390625 method ARKODE_MRI_GARK_ERK33a t 3.00039 dsm 0.00143196 dsm_est 0.00840977 + H 0.000390625 method ARKODE_MRI_GARK_ERK33a t 3.50039 dsm 0.00507095 dsm_est 0.00775185 + H 0.000390625 method ARKODE_MRI_GARK_ERK33a t 4.00039 dsm 0.000473415 dsm_est 0.00235627 + H 0.000390625 method ARKODE_MRI_GARK_ERK33a t 4.50039 dsm 0.0152604 dsm_est 0.0166753 + H 0.000390625 method ARKODE_MRI_GARK_ERK33a t 5.00039 dsm 0.00103306 dsm_est 0.00178339 + H 0.000390625 method ARKODE_MRI_GARK_ERK33a t 5.50039 dsm 0.000737914 dsm_est 0.00775519 + H 0.000390625 method ARKODE_MRI_GARK_ERK33a t 6.00039 dsm 0.00150366 dsm_est 0.0539128 + H 0.000390625 method ARKODE_MRI_GARK_ERK33a t 6.50039 dsm 0.00386116 dsm_est 1.27888 + H 0.000390625 method ARKODE_MRI_GARK_ERK33a t 7.00039 dsm 0.0511055 dsm_est 5.9684 + H 0.000390625 method ARKODE_MRI_GARK_ERK33a t 7.50039 dsm 0.00692078 dsm_est 0.074038 + H 0.000390625 method ARKODE_MRI_GARK_ERK33a t 8.00039 dsm 0.000733274 dsm_est 0.0248325 + H 0.000390625 method ARKODE_MRI_GARK_ERK33a t 8.50039 dsm 0.000872554 dsm_est 0.00893449 + H 0.000390625 method ARKODE_MRI_GARK_ERK33a t 9.00039 dsm 0.000620849 dsm_est 0.0397209 + H 0.000390625 method ARKODE_MRI_GARK_ERK33a t 9.50039 dsm 0.00105929 dsm_est 0.0401369 + H 9.76563e-05 method ARKODE_MRI_GARK_ERK33a t 9.76563e-05 dsm 130431 dsm_est 498019 + H 9.76563e-05 method ARKODE_MRI_GARK_ERK33a t 0.500098 dsm 3.22403e-06 dsm_est 7.35991e-05 + H 9.76563e-05 method ARKODE_MRI_GARK_ERK33a t 1.0001 dsm 8.76951e-06 dsm_est 4.34727e-05 + H 9.76563e-05 method ARKODE_MRI_GARK_ERK33a t 1.5001 dsm 2.85184e-05 dsm_est 0.000154848 + H 9.76563e-05 method ARKODE_MRI_GARK_ERK33a t 2.0001 dsm 3.58103e-05 dsm_est 0.000178405 + H 9.76563e-05 method ARKODE_MRI_GARK_ERK33a t 2.5001 dsm 3.14166e-05 dsm_est 0.000127273 + H 9.76563e-05 method ARKODE_MRI_GARK_ERK33a t 3.0001 dsm 6.6836e-06 dsm_est 0.000131134 + H 9.76563e-05 method ARKODE_MRI_GARK_ERK33a t 3.5001 dsm 2.19334e-05 dsm_est 0.000121472 + H 9.76563e-05 method ARKODE_MRI_GARK_ERK33a t 4.0001 dsm 1.46115e-06 dsm_est 3.65453e-05 + H 9.76563e-05 method ARKODE_MRI_GARK_ERK33a t 4.5001 dsm 6.79441e-05 dsm_est 0.000260953 + H 9.76563e-05 method ARKODE_MRI_GARK_ERK33a t 5.0001 dsm 4.63814e-06 dsm_est 2.73436e-05 + H 9.76563e-05 method ARKODE_MRI_GARK_ERK33a t 5.5001 dsm 3.99263e-06 dsm_est 0.000121193 + H 9.76563e-05 method ARKODE_MRI_GARK_ERK33a t 6.0001 dsm 7.38533e-06 dsm_est 0.000842724 + H 9.76563e-05 method ARKODE_MRI_GARK_ERK33a t 6.5001 dsm 1.91204e-05 dsm_est 0.0199852 + H 9.76563e-05 method ARKODE_MRI_GARK_ERK33a t 7.0001 dsm 0.00020015 dsm_est 0.0932838 + H 9.76563e-05 method ARKODE_MRI_GARK_ERK33a t 7.5001 dsm 3.17543e-05 dsm_est 0.00115569 + H 9.76563e-05 method ARKODE_MRI_GARK_ERK33a t 8.0001 dsm 4.92456e-06 dsm_est 0.000387364 + H 9.76563e-05 method ARKODE_MRI_GARK_ERK33a t 8.5001 dsm 3.86449e-06 dsm_est 0.000139579 + H 9.76563e-05 method ARKODE_MRI_GARK_ERK33a t 9.0001 dsm 3.70097e-06 dsm_est 0.000619442 + H 9.76563e-05 method ARKODE_MRI_GARK_ERK33a t 9.5001 dsm 3.7359e-06 dsm_est 0.000626912 + +ARKODE_MRI_GARK_ERK33a summary: + Stepsize 0.025 maxdsm 3.18615e+13 maxdsmest 2.87651e+09 + Stepsize 0.00625 maxdsm 4.33933e+11 maxdsmest 1.53179e+09 + Stepsize 0.0015625 maxdsm 4.30937e+09 maxdsmest 1.04109e+09 + Stepsize 0.000390625 maxdsm 2.73843e+07 maxdsmest 2.97866e+07 + Stepsize 9.76563e-05 maxdsm 130431 maxdsmest 498019 diff --git a/test/unit_tests/arkode/CXX_serial/ark_test_slowerror_kpr.cpp b/test/unit_tests/arkode/CXX_serial/ark_test_slowerror_kpr.cpp new file mode 100644 index 0000000000..a7346214c4 --- /dev/null +++ b/test/unit_tests/arkode/CXX_serial/ark_test_slowerror_kpr.cpp @@ -0,0 +1,576 @@ +/* ---------------------------------------------------------------- + * Programmer(s): Daniel R. Reynolds @ SMU + * ---------------------------------------------------------------- + * SUNDIALS Copyright Start + * Copyright (c) 2002-2024, Lawrence Livermore National Security + * and Southern Methodist University. + * All rights reserved. + * + * See the top-level LICENSE and NOTICE files for details. + * + * SPDX-License-Identifier: BSD-3-Clause + * SUNDIALS Copyright End + * ---------------------------------------------------------------- + * Routine to test an MRI method's embedding-based error + * estimate. Uses a nonlinear Kvaerno-Prothero-Robinson ODE test + * problem with analytical solution, + * + * [u]' = [ G e ] [(u^2-p-1)/(2u)] + [ p'(t)/(2u) ] + * [v] [ e -1 ] [(v^2-q-2)/(2v)] [ q'(t)/(2v) ] + * + * where p(t) = cos(t), and q(t) = cos(omega*t*(1+exp(-(t-2)^2))). + * This problem has analytical solution given by + * u(t) = sqrt(2+p(t)), v(t) = sqrt(2+q(t)). + * We use the parameters: e = 0.1 and G = -10 [default] + * + * The stiffness of the problem is essentially determined + * by G, for |G| > 50 it is "stiff" and ideally suited to an + * implicit method. + * + * Coupling between the two components is determined by e, with + * coupling strength proportional to |e|. + * + * The "fast" variable, v, oscillates at a frequency "omega" times + * faster than u. + * + * We partition the full time integration interval, 0 < t < 5, into + * Npart pieces. We then run a single time step starting at the + * beginning of each partition, using a variety of slow step sizes, + * H = {hmax, hmax/4, hmax/16, hmax/64, hmax/256} with + * hmax=(t_f-t_0)/20/Npart. + * + * We place the entire ODE in the "slow" RHS partition. For IMEX + * methods, the first row is treated implicitly, and the second is + * treated explicitly. For the fast time scale, all tests use + * ARKODE's default fifth-order ERK method, with relative and + * absolute tolerances set to 1e-10 and 1e-12, respectively. + * + * We select the slow integrator based on a command-line argument, + * with the default being ARKODE_MRI_GARK_ERK33a. + * + * The program should be run with arguments in the following order: + * $ a.out method Npart G e omega + * Not all arguments are required, but these must be omitted from + * end-to-beginning, i.e. any one of + * $ a.out method Npart G e + * $ a.out method Npart G + * $ a.out method Npart + * $ a.out method + * $ a.out + * are acceptable. We require: + * * method = string corresponding to a valid embedded ARKODE_MRITableID + * * Npart > 0 + * * G < 0.0 + * * omega > 0.0 + * ----------------------------------------------------------------*/ + +// Header files +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#if defined(SUNDIALS_EXTENDED_PRECISION) +#define GSYM "Lg" +#define ESYM "Le" +#define FSYM "Lf" +#else +#define GSYM "g" +#define ESYM "e" +#define FSYM "f" +#endif + +#define ZERO SUN_RCONST(0.0) +#define ONE SUN_RCONST(1.0) +#define TWO SUN_RCONST(2.0) + +using namespace std; + +// User data structure +struct UserData +{ + sunrealtype G; + sunrealtype e; + sunrealtype omega; + int Npart; +}; + +// User-supplied functions called by the solver +static int f0(sunrealtype t, N_Vector y, N_Vector ydot, void* user_data); +static int fn(sunrealtype t, N_Vector y, N_Vector ydot, void* user_data); +static int fe(sunrealtype t, N_Vector y, N_Vector ydot, void* user_data); +static int fi(sunrealtype t, N_Vector y, N_Vector ydot, void* user_data); +static int Jn(sunrealtype t, N_Vector y, N_Vector fy, SUNMatrix J, + void* user_data, N_Vector tmp1, N_Vector tmp2, N_Vector tmp3); +static int Ji(sunrealtype t, N_Vector y, N_Vector fy, SUNMatrix J, + void* user_data, N_Vector tmp1, N_Vector tmp2, N_Vector tmp3); + +// Private utility functions +static sunrealtype p(sunrealtype t); +static sunrealtype q(sunrealtype t, UserData& udata); +static sunrealtype pdot(sunrealtype t); +static sunrealtype qdot(sunrealtype t, UserData& udata); +static sunrealtype utrue(sunrealtype t); +static sunrealtype vtrue(sunrealtype t, UserData& udata); +static int Ytrue(sunrealtype t, N_Vector y, UserData& udata); +static int computeErrorWeights(N_Vector ycur, N_Vector weight, sunrealtype rtol, + sunrealtype atol, N_Vector vtemp); +static int check_retval(void* returnvalue, const char* funcname, int opt); +static int run_test(void* mristep_mem, N_Vector y, sunrealtype T0, + sunrealtype Tf, vector Hvals, string method, + sunrealtype reltol, sunrealtype abstol, UserData& udata); + +// Main Program +int main(int argc, char* argv[]) +{ + // general problem parameters + sunrealtype T0 = SUN_RCONST(0.0); // initial time + sunrealtype Tf = SUN_RCONST(5.0); // final time + sunindextype NEQ = 2; // number of dependent vars. + string method; // MRI method name + sunrealtype reltol = SUN_RCONST(1.e-10); // fast solver tolerances + sunrealtype abstol = SUN_RCONST(1.e-12); + + // general problem variables + int retval; // reusable error-checking flag + UserData udata; // user-data structure + udata.G = SUN_RCONST(-10.0); // stiffness parameter + udata.e = SUN_RCONST(0.1); // coupling strength + udata.omega = SUN_RCONST(5.0); // time scale ratio + udata.Npart = 20; // partition size + + // + // Initialization + // + + // Retrieve the command-line options: method Npart G e omega + if (argc > 1) { method = argv[1]; } + else { method = "ARKODE_MRI_GARK_ERK33a"; } + if (argc > 2) udata.Npart = atoi(argv[2]); + if (argc > 3) udata.G = SUNStrToReal(argv[3]); + if (argc > 4) udata.e = SUNStrToReal(argv[4]); + if (argc > 5) udata.omega = SUNStrToReal(argv[5]); + + // Check arguments for validity + // G < 0.0 + // omega > 0.0 + // Npart > 0 + if (udata.G >= ZERO) + { + cerr << "ERROR: G must be a negative real number\n"; + return (-1); + } + if (udata.omega <= ZERO) + { + cerr << "ERROR: omega must be a positive real number\n"; + return (-1); + } + if (udata.Npart < 1) + { + cerr << "ERROR: Npart must be a positive integer\n"; + return (-1); + } + + sunbooleantype implicit = SUNFALSE; + sunbooleantype imex = SUNFALSE; + if ((method == "ARKODE_MRI_GARK_IRK21a") || + (method == "ARKODE_MRI_GARK_ESDIRK34a") || + (method == "ARKODE_MRI_GARK_ESDIRK46a")) + { + implicit = SUNTRUE; + } + if ((method == "ARKODE_IMEX_MRI_SR21") || + (method == "ARKODE_IMEX_MRI_SR32") || (method == "ARKODE_IMEX_MRI_SR43")) + { + imex = SUNTRUE; + implicit = SUNTRUE; + } + + // Initial problem output (and set implicit solver tolerances as needed) + cout << "\nSlow error estimation test (Nonlinear Kvaerno-Prothero-Robinson " + "problem):\n"; + cout << " time domain: (" << T0 << "," << Tf << "]\n"; + cout << " partition size = " << udata.Npart << endl; + cout << " problem parameters: G = " << udata.G << ", e = " << udata.e + << ", omega = " << udata.omega << endl; + cout << " MRI method: " << method; + if (imex) { cout << " (ImEx)" << endl; } + else if (implicit) { cout << " (implicit)" << endl; } + else { cout << " (explicit)" << endl; } + + // + // Problem Setup + // + + // Create SUNDIALS context + sundials::Context ctx; + + // Create and initialize serial vector for the solution + N_Vector y = N_VNew_Serial(NEQ, ctx); + if (check_retval((void*)y, "N_VNew_Serial", 0)) return 1; + retval = Ytrue(T0, y, udata); + if (check_retval(&retval, "Ytrue", 1)) return 1; + + // Set up fast ERKStep integrator as fifth-order adaptive method + void* inner_arkode_mem = ERKStepCreate(f0, T0, y, ctx); + if (check_retval((void*)inner_arkode_mem, "ERKStepCreate", 0)) return 1; + retval = ARKodeSetOrder(inner_arkode_mem, 5); + if (check_retval(&retval, "ARKodeSetOrder", 1)) return 1; + retval = ARKodeSStolerances(inner_arkode_mem, reltol, abstol); + if (check_retval(&retval, "ARKodeSStolerances", 1)) return 1; + retval = ARKodeSetMaxNumSteps(inner_arkode_mem, 1000000); + if (check_retval(&retval, "ARKodeSetMaxNumSteps", 1)) return (1); + + // Create inner stepper wrapper + MRIStepInnerStepper inner_stepper = NULL; // inner stepper + retval = ARKodeCreateMRIStepInnerStepper(inner_arkode_mem, &inner_stepper); + if (check_retval(&retval, "ARKodeCreateMRIStepInnerStepper", 1)) return 1; + + // Set up slow MRIStep integrator + void* mristep_mem = NULL; + if (imex) { mristep_mem = MRIStepCreate(fe, fi, T0, y, inner_stepper, ctx); } + else if (implicit) + { + mristep_mem = MRIStepCreate(NULL, fn, T0, y, inner_stepper, ctx); + } + else { mristep_mem = MRIStepCreate(fn, NULL, T0, y, inner_stepper, ctx); } + if (check_retval((void*)mristep_mem, "MRIStepCreate", 0)) return 1; + MRIStepCoupling C = MRIStepCoupling_LoadTableByName(method.c_str()); + if (check_retval((void*)C, "MRIStepCoupling_LoadTableByName", 0)) return 1; + retval = MRIStepSetCoupling(mristep_mem, C); + if (check_retval(&retval, "MRIStepSetCoupling", 1)) return 1; + SUNMatrix A = NULL; // matrix for slow solver + SUNLinearSolver LS = NULL; // slow linear solver object + if (implicit) + { + A = SUNDenseMatrix(NEQ, NEQ, ctx); + if (check_retval((void*)A, "SUNDenseMatrix", 0)) return 1; + LS = SUNLinSol_Dense(y, A, ctx); + if (check_retval((void*)LS, "SUNLinSol_Dense", 0)) return 1; + retval = ARKodeSetLinearSolver(mristep_mem, LS, A); + if (check_retval(&retval, "ARKodeSetLinearSolver", 1)) return 1; + if (imex) { retval = ARKodeSetJacFn(mristep_mem, Ji); } + else { retval = ARKodeSetJacFn(mristep_mem, Jn); } + if (check_retval(&retval, "ARKodeSetJacFn", 1)) return 1; + retval = ARKodeSetJacEvalFrequency(mristep_mem, 1); + if (check_retval(&retval, "ARKodeSetJacEvalFrequency", 1)) return 1; + retval = ARKodeSetLSetupFrequency(mristep_mem, 1); + if (check_retval(&retval, "ARKodeSetLSetupFrequency", 1)) return 1; + retval = ARKodeSetMaxNonlinIters(mristep_mem, 50); + if (check_retval(&retval, "ARKodeSetMaxNonlinIters", 1)) return 1; + } + retval = ARKodeSStolerances(mristep_mem, reltol, abstol); + if (check_retval(&retval, "ARKodeSStolerances", 1)) return 1; + retval = ARKodeSetUserData(mristep_mem, (void*)&udata); + if (check_retval(&retval, "ARKodeSetUserData", 1)) return 1; + retval = ARKodeSetAccumulatedErrorType(mristep_mem, ARK_ACCUMERROR_MAX); + if (check_retval(&retval, "ARKodeSetAccumulatedErrorType", 1)) return 1; + + // Run test for various H values + sunrealtype hmax = (Tf - T0) / 20 / udata.Npart; + vector Hvals(5); + for (size_t i = 0; i < Hvals.size(); i++) + { + Hvals[i] = hmax / SUNRpowerI(SUN_RCONST(4.0), (int)i); + } + retval = run_test(mristep_mem, y, T0, Tf, Hvals, method, reltol, abstol, udata); + if (check_retval(&retval, "run_test", 1)) return 1; + + // Clean up and return + MRIStepCoupling_Free(C); + ARKodeFree(&inner_arkode_mem); + MRIStepInnerStepper_Free(&inner_stepper); + ARKodeFree(&mristep_mem); + if (LS) { SUNLinSolFree(LS); } // free system linear solver + if (A) { SUNMatDestroy(A); } // free system matrix + N_VDestroy(y); // Free y vector + return 0; +} + +//------------------------------ +// Functions called by the solver +//------------------------------ + +static int f0(sunrealtype t, N_Vector y, N_Vector ydot, void* user_data) +{ + // fill in the RHS function with zeros and return with success + N_VConst(ZERO, ydot); + return 0; +} + +static int fn(sunrealtype t, N_Vector y, N_Vector ydot, void* user_data) +{ + UserData* udata = (UserData*)user_data; + sunrealtype* ydata = N_VGetArrayPointer(y); + sunrealtype* dydata = N_VGetArrayPointer(ydot); + const sunrealtype u = ydata[0]; + const sunrealtype v = ydata[1]; + sunrealtype tmp1, tmp2; + + // fill in the RHS function: + // [G e]*[(-2+u^2-p(t))/(2*u)] + [pdot(t)/(2u)] + // [e -1] [(-2+v^2-s(t))/(2*v)] [qdot(t)/(2v)] + tmp1 = (-TWO + u * u - p(t)) / (TWO * u); + tmp2 = (-TWO + v * v - q(t, *udata)) / (TWO * v); + dydata[0] = udata->G * tmp1 + udata->e * tmp2 + pdot(t) / (TWO * u); + dydata[1] = udata->e * tmp1 - tmp2 + qdot(t, *udata) / (TWO * v); + + // Return with success + return 0; +} + +static int fi(sunrealtype t, N_Vector y, N_Vector ydot, void* user_data) +{ + UserData* udata = (UserData*)user_data; + sunrealtype* ydata = N_VGetArrayPointer(y); + sunrealtype* dydata = N_VGetArrayPointer(ydot); + const sunrealtype u = ydata[0]; + const sunrealtype v = ydata[1]; + sunrealtype tmp1, tmp2; + + // fill in the RHS function: + // [G e]*[(-2+u^2-p(t))/(2*u)] + [pdot(t)/(2u)] + // [0 0] [(-2+v^2-s(t))/(2*v)] [ 0 ] + tmp1 = (-TWO + u * u - p(t)) / (TWO * u); + tmp2 = (-TWO + v * v - q(t, *udata)) / (TWO * v); + dydata[0] = udata->G * tmp1 + udata->e * tmp2 + pdot(t) / (TWO * u); + dydata[1] = ZERO; + + // Return with success + return 0; +} + +static int fe(sunrealtype t, N_Vector y, N_Vector ydot, void* user_data) +{ + UserData* udata = (UserData*)user_data; + sunrealtype* ydata = N_VGetArrayPointer(y); + sunrealtype* dydata = N_VGetArrayPointer(ydot); + const sunrealtype u = ydata[0]; + const sunrealtype v = ydata[1]; + sunrealtype tmp1, tmp2; + + // fill in the RHS function: + // [0 0]*[(-2+u^2-p(t))/(2*u)] + [ 0 ] + // [e -1] [(-2+v^2-s(t))/(2*v)] [qdot(t)/(2v)] + tmp1 = (-TWO + u * u - p(t)) / (TWO * u); + tmp2 = (-TWO + v * v - q(t, *udata)) / (TWO * v); + dydata[0] = ZERO; + dydata[1] = udata->e * tmp1 - tmp2 + qdot(t, *udata) / (TWO * v); + + // Return with success + return 0; +} + +static int Jn(sunrealtype t, N_Vector y, N_Vector fy, SUNMatrix J, + void* user_data, N_Vector tmp1, N_Vector tmp2, N_Vector tmp3) +{ + UserData* udata = (UserData*)user_data; + sunrealtype* ydata = N_VGetArrayPointer(y); + const sunrealtype u = ydata[0]; + const sunrealtype v = ydata[1]; + sunrealtype t11, t22; + + // fill in the Jacobian: + // [G e]*[1-(u^2-p(t)-2)/(2*u^2), 0] + [-p'(t)/(2*u^2), 0] + // [e -1] [0, 1-(v^2-q(t)-2)/(2*v^2)] [0, -q'(t)/(2*v^2)] + t11 = ONE - (u * u - p(t) - TWO) / (TWO * u * u); + t22 = ONE - (v * v - q(t, *udata) - TWO) / (TWO * v * v); + SM_ELEMENT_D(J, 0, 0) = udata->G * t11 - pdot(t) / (TWO * u * u); + SM_ELEMENT_D(J, 0, 1) = udata->e * t22; + SM_ELEMENT_D(J, 1, 0) = udata->e * t11; + SM_ELEMENT_D(J, 1, 1) = -t22 - qdot(t, *udata) / (TWO * v * v); + + // Return with success + return 0; +} + +static int Ji(sunrealtype t, N_Vector y, N_Vector fy, SUNMatrix J, + void* user_data, N_Vector tmp1, N_Vector tmp2, N_Vector tmp3) +{ + UserData* udata = (UserData*)user_data; + sunrealtype* ydata = N_VGetArrayPointer(y); + const sunrealtype u = ydata[0]; + const sunrealtype v = ydata[1]; + + // fill in the Jacobian: + // [G/2 + (G*(1+p(t))-pdot(t))/(2*u^2) e/2+e*(2+s(t))/(2*v^2)] + // [ 0 0 ] + SM_ELEMENT_D(J, 0, 0) = udata->G / TWO + + (udata->G * (ONE + p(t)) - pdot(t)) / (TWO * u * u); + SM_ELEMENT_D(J, 0, 1) = udata->e / TWO + + udata->e * (TWO + q(t, *udata)) / (TWO * v * v); + SM_ELEMENT_D(J, 1, 0) = ZERO; + SM_ELEMENT_D(J, 1, 1) = ZERO; + + // Return with success + return 0; +} + +//------------------------------ +// Private helper functions +//------------------------------ + +static int run_test(void* mristep_mem, N_Vector y, sunrealtype T0, + sunrealtype Tf, vector Hvals, string method, + sunrealtype reltol, sunrealtype abstol, UserData& udata) +{ + // Reused variables + int retval; + sunrealtype hpart = (Tf - T0) / udata.Npart; + sunrealtype t; + N_Vector ele = N_VClone(y); + N_Vector ewt = N_VClone(y); + N_Vector vtemp = N_VClone(y); + sunrealtype* ydata = N_VGetArrayPointer(y); + + // Set storage for errors + vector> dsm(Hvals.size(), + vector(udata.Npart, ZERO)); + vector> dsm_est(Hvals.size(), + vector(udata.Npart, ZERO)); + + // Loop over step sizes + for (size_t iH = 0; iH < Hvals.size(); iH++) + { + // Loop over partition + for (int ipart = 0; ipart < udata.Npart; ipart++) + { + // Reset integrator for this run + t = T0 + ipart * hpart; + retval = Ytrue(t, y, udata); + if (check_retval(&retval, "Ytrue", 1)) return 1; + retval = ARKodeReset(mristep_mem, t, y); + if (check_retval(&retval, "ARKodeReset", 1)) return 1; + retval = ARKodeSetFixedStep(mristep_mem, Hvals[iH]); + if (check_retval(&retval, "ARKodeSetFixedStep", 1)) return 1; + retval = ARKodeResetAccumulatedError(mristep_mem); + if (check_retval(&retval, "ARKodeResetAccumulatedError", 1)) return 1; + + // Run ARKodeEvolve to compute one step + retval = ARKodeEvolve(mristep_mem, t + Hvals[iH], y, &t, ARK_ONE_STEP); + if (check_retval(&retval, "ARKodeEvolve", 1)) return 1; + retval = ARKodeGetEstLocalErrors(mristep_mem, ele); + if (check_retval(&retval, "ARKodeGetEstLocalErrors", 1)) return 1; + retval = computeErrorWeights(y, ewt, reltol, abstol, vtemp); + if (check_retval(&retval, "computeErrorWeights", 1)) return 1; + dsm_est[iH][ipart] = N_VWrmsNorm(ewt, ele); + + // Compute/print solution error + sunrealtype udsm = abs(ydata[0] - utrue(t)) / + (abstol + reltol * abs(utrue(t))); + sunrealtype vdsm = abs(ydata[1] - vtrue(t, udata)) / + (abstol + reltol * abs(vtrue(t, udata))); + dsm[iH][ipart] = sqrt(0.5 * (udsm * udsm + vdsm * vdsm)); + cout << " H " << Hvals[iH] << " method " << method << " t " << t + << " dsm " << dsm[iH][ipart] << " dsm_est " << dsm_est[iH][ipart] + << endl; + } + } + + cout << endl << method << " summary:" << endl; + for (size_t iH = 0; iH < Hvals.size(); iH++) + { + cout << " Stepsize " << Hvals[iH] << " \tmaxdsm " + << *max_element(dsm[iH].begin(), dsm[iH].end()) << " \tmaxdsmest " + << *max_element(dsm_est[iH].begin(), dsm_est[iH].end()) << endl; + } + + N_VDestroy(ele); + N_VDestroy(ewt); + N_VDestroy(vtemp); + return (0); +} + +static sunrealtype p(sunrealtype t) { return (cos(t)); } + +static sunrealtype q(sunrealtype t, UserData& udata) +{ + return (cos(udata.omega * t * (ONE + exp(-(t - 2) * (t - 2))))); +} + +static sunrealtype pdot(sunrealtype t) { return (-sin(t)); } + +static sunrealtype qdot(sunrealtype t, UserData& udata) +{ + return (-sin(udata.omega * t * (ONE + exp(-(t - 2) * (t - 2)))) * udata.omega * + (ONE + exp(-(t - 2) * (t - 2)) - + t * 2 * (t - 2) * (exp(-(t - 2) * (t - 2))))); +} + +static sunrealtype utrue(sunrealtype t) { return (SUNRsqrt(TWO + p(t))); } + +static sunrealtype vtrue(sunrealtype t, UserData& udata) +{ + return (SUNRsqrt(TWO + q(t, udata))); +} + +static int Ytrue(sunrealtype t, N_Vector y, UserData& udata) +{ + sunrealtype* ydata = N_VGetArrayPointer(y); + ydata[0] = utrue(t); + ydata[1] = vtrue(t, udata); + return (0); +} + +static int computeErrorWeights(N_Vector ycur, N_Vector weight, sunrealtype rtol, + sunrealtype atol, N_Vector vtemp) +{ + N_VAbs(ycur, vtemp); + N_VScale(rtol, vtemp, vtemp); + N_VAddConst(vtemp, atol, vtemp); + N_VInv(vtemp, weight); + return (0); +} + +/* Check function return value... + opt == 0 means SUNDIALS function allocates memory so check if + returned NULL pointer + opt == 1 means SUNDIALS function returns a retval so check if + retval < 0 + opt == 2 means function allocates memory so check if returned + NULL pointer +*/ +static int check_retval(void* returnvalue, const char* funcname, int opt) +{ + int* retval; + + // Check if SUNDIALS function returned NULL pointer - no memory allocated + if (opt == 0 && returnvalue == NULL) + { + fprintf(stderr, "\nSUNDIALS_ERROR: %s() failed - returned NULL pointer\n\n", + funcname); + return 1; + } + + // Check if retval < 0 + else if (opt == 1) + { + retval = (int*)returnvalue; + if (*retval < 0) + { + fprintf(stderr, "\nSUNDIALS_ERROR: %s() failed with retval = %d\n\n", + funcname, *retval); + return 1; + } + } + + // Check if function returned NULL pointer - no memory allocated + else if (opt == 2 && returnvalue == NULL) + { + fprintf(stderr, "\nMEMORY_ERROR: %s() failed - returned NULL pointer\n\n", + funcname); + return 1; + } + + return 0; +} + +//---- end of file ---- diff --git a/test/unit_tests/arkode/CXX_serial/ark_test_slowerror_kpr.out b/test/unit_tests/arkode/CXX_serial/ark_test_slowerror_kpr.out new file mode 100644 index 0000000000..87e6b5cc1e --- /dev/null +++ b/test/unit_tests/arkode/CXX_serial/ark_test_slowerror_kpr.out @@ -0,0 +1,113 @@ + +Slow error estimation test (Nonlinear Kvaerno-Prothero-Robinson problem): + time domain: (0,5] + partition size = 20 + problem parameters: G = -10, e = 0.1, omega = 5 + MRI method: ARKODE_MRI_GARK_ERK33a (explicit) + H 0.0125 method ARKODE_MRI_GARK_ERK33a t 0.0125 dsm 59.7276 dsm_est 727.532 + H 0.0125 method ARKODE_MRI_GARK_ERK33a t 0.2625 dsm 159.194 dsm_est 4712.03 + H 0.0125 method ARKODE_MRI_GARK_ERK33a t 0.5125 dsm 496.974 dsm_est 33493.8 + H 0.0125 method ARKODE_MRI_GARK_ERK33a t 0.7625 dsm 712.688 dsm_est 32624.2 + H 0.0125 method ARKODE_MRI_GARK_ERK33a t 1.0125 dsm 1224.36 dsm_est 1716.11 + H 0.0125 method ARKODE_MRI_GARK_ERK33a t 1.2625 dsm 5167.32 dsm_est 267128 + H 0.0125 method ARKODE_MRI_GARK_ERK33a t 1.5125 dsm 4827.92 dsm_est 54878.4 + H 0.0125 method ARKODE_MRI_GARK_ERK33a t 1.7625 dsm 13680.4 dsm_est 176534 + H 0.0125 method ARKODE_MRI_GARK_ERK33a t 2.0125 dsm 130.837 dsm_est 49597.7 + H 0.0125 method ARKODE_MRI_GARK_ERK33a t 2.2625 dsm 162.492 dsm_est 34976.3 + H 0.0125 method ARKODE_MRI_GARK_ERK33a t 2.5125 dsm 287.688 dsm_est 7113.08 + H 0.0125 method ARKODE_MRI_GARK_ERK33a t 2.7625 dsm 382.02 dsm_est 4317.48 + H 0.0125 method ARKODE_MRI_GARK_ERK33a t 3.0125 dsm 301.235 dsm_est 4949.38 + H 0.0125 method ARKODE_MRI_GARK_ERK33a t 3.2625 dsm 258.571 dsm_est 2977.9 + H 0.0125 method ARKODE_MRI_GARK_ERK33a t 3.5125 dsm 218.068 dsm_est 1269.3 + H 0.0125 method ARKODE_MRI_GARK_ERK33a t 3.7625 dsm 162.764 dsm_est 1320.67 + H 0.0125 method ARKODE_MRI_GARK_ERK33a t 4.0125 dsm 130.736 dsm_est 2369.28 + H 0.0125 method ARKODE_MRI_GARK_ERK33a t 4.2625 dsm 20.6137 dsm_est 12728.2 + H 0.0125 method ARKODE_MRI_GARK_ERK33a t 4.5125 dsm 176.78 dsm_est 15676.7 + H 0.0125 method ARKODE_MRI_GARK_ERK33a t 4.7625 dsm 90.7369 dsm_est 3719.41 + H 0.003125 method ARKODE_MRI_GARK_ERK33a t 0.003125 dsm 0.232651 dsm_est 10.9877 + H 0.003125 method ARKODE_MRI_GARK_ERK33a t 0.253125 dsm 0.594785 dsm_est 70.8981 + H 0.003125 method ARKODE_MRI_GARK_ERK33a t 0.503125 dsm 1.46693 dsm_est 527.764 + H 0.003125 method ARKODE_MRI_GARK_ERK33a t 0.753125 dsm 2.86452 dsm_est 520.741 + H 0.003125 method ARKODE_MRI_GARK_ERK33a t 1.00313 dsm 4.48531 dsm_est 12.8296 + H 0.003125 method ARKODE_MRI_GARK_ERK33a t 1.25313 dsm 37.2232 dsm_est 3954.15 + H 0.003125 method ARKODE_MRI_GARK_ERK33a t 1.50313 dsm 17.7805 dsm_est 786.062 + H 0.003125 method ARKODE_MRI_GARK_ERK33a t 1.75313 dsm 58.1561 dsm_est 2999.34 + H 0.003125 method ARKODE_MRI_GARK_ERK33a t 2.00312 dsm 0.615846 dsm_est 764.348 + H 0.003125 method ARKODE_MRI_GARK_ERK33a t 2.25312 dsm 0.208735 dsm_est 542.352 + H 0.003125 method ARKODE_MRI_GARK_ERK33a t 2.50312 dsm 1.15342 dsm_est 106.225 + H 0.003125 method ARKODE_MRI_GARK_ERK33a t 2.75312 dsm 1.54621 dsm_est 59.6688 + H 0.003125 method ARKODE_MRI_GARK_ERK33a t 3.00312 dsm 1.18391 dsm_est 80.2941 + H 0.003125 method ARKODE_MRI_GARK_ERK33a t 3.25312 dsm 1.00984 dsm_est 46.1362 + H 0.003125 method ARKODE_MRI_GARK_ERK33a t 3.50312 dsm 0.853892 dsm_est 19.4476 + H 0.003125 method ARKODE_MRI_GARK_ERK33a t 3.75312 dsm 0.637603 dsm_est 20.4096 + H 0.003125 method ARKODE_MRI_GARK_ERK33a t 4.00312 dsm 0.50676 dsm_est 35.5067 + H 0.003125 method ARKODE_MRI_GARK_ERK33a t 4.25312 dsm 0.0997811 dsm_est 197.159 + H 0.003125 method ARKODE_MRI_GARK_ERK33a t 4.50312 dsm 0.602658 dsm_est 244.1 + H 0.003125 method ARKODE_MRI_GARK_ERK33a t 4.75312 dsm 0.3657 dsm_est 59.8484 + H 0.00078125 method ARKODE_MRI_GARK_ERK33a t 0.00078125 dsm 0.000906789 dsm_est 0.1702 + H 0.00078125 method ARKODE_MRI_GARK_ERK33a t 0.250781 dsm 0.00229725 dsm_est 1.09748 + H 0.00078125 method ARKODE_MRI_GARK_ERK33a t 0.500781 dsm 0.00528907 dsm_est 8.25834 + H 0.00078125 method ARKODE_MRI_GARK_ERK33a t 0.750781 dsm 0.0112664 dsm_est 8.18019 + H 0.00078125 method ARKODE_MRI_GARK_ERK33a t 1.00078 dsm 0.0172485 dsm_est 0.149038 + H 0.00078125 method ARKODE_MRI_GARK_ERK33a t 1.25078 dsm 0.162364 dsm_est 60.7616 + H 0.00078125 method ARKODE_MRI_GARK_ERK33a t 1.50078 dsm 0.0684956 dsm_est 12.019 + H 0.00078125 method ARKODE_MRI_GARK_ERK33a t 1.75078 dsm 0.231817 dsm_est 47.8533 + H 0.00078125 method ARKODE_MRI_GARK_ERK33a t 2.00078 dsm 0.00251159 dsm_est 11.9018 + H 0.00078125 method ARKODE_MRI_GARK_ERK33a t 2.25078 dsm 0.000388484 dsm_est 8.4539 + H 0.00078125 method ARKODE_MRI_GARK_ERK33a t 2.50078 dsm 0.00453393 dsm_est 1.64038 + H 0.00078125 method ARKODE_MRI_GARK_ERK33a t 2.75078 dsm 0.00608412 dsm_est 0.901588 + H 0.00078125 method ARKODE_MRI_GARK_ERK33a t 3.00078 dsm 0.00463348 dsm_est 1.26635 + H 0.00078125 method ARKODE_MRI_GARK_ERK33a t 3.25078 dsm 0.00394414 dsm_est 0.719303 + H 0.00078125 method ARKODE_MRI_GARK_ERK33a t 3.50078 dsm 0.00333765 dsm_est 0.302408 + H 0.00078125 method ARKODE_MRI_GARK_ERK33a t 3.75078 dsm 0.00249229 dsm_est 0.318005 + H 0.00078125 method ARKODE_MRI_GARK_ERK33a t 4.00078 dsm 0.00197527 dsm_est 0.548996 + H 0.00078125 method ARKODE_MRI_GARK_ERK33a t 4.25078 dsm 0.000423031 dsm_est 3.07331 + H 0.00078125 method ARKODE_MRI_GARK_ERK33a t 4.50078 dsm 0.00226465 dsm_est 3.80981 + H 0.00078125 method ARKODE_MRI_GARK_ERK33a t 4.75078 dsm 0.00143499 dsm_est 0.942031 + H 0.000195313 method ARKODE_MRI_GARK_ERK33a t 0.000195313 dsm 2.85013e-06 dsm_est 0.00265424 + H 0.000195313 method ARKODE_MRI_GARK_ERK33a t 0.250195 dsm 9.05953e-06 dsm_est 0.0171084 + H 0.000195313 method ARKODE_MRI_GARK_ERK33a t 0.500195 dsm 2.05759e-05 dsm_est 0.129079 + H 0.000195313 method ARKODE_MRI_GARK_ERK33a t 0.750195 dsm 4.6605e-05 dsm_est 0.127987 + H 0.000195313 method ARKODE_MRI_GARK_ERK33a t 1.0002 dsm 6.66547e-05 dsm_est 0.00213263 + H 0.000195313 method ARKODE_MRI_GARK_ERK33a t 1.2502 dsm 0.000653038 dsm_est 0.945246 + H 0.000195313 method ARKODE_MRI_GARK_ERK33a t 1.5002 dsm 0.000267427 dsm_est 0.186783 + H 0.000195313 method ARKODE_MRI_GARK_ERK33a t 1.7502 dsm 0.000909834 dsm_est 0.751614 + H 0.000195313 method ARKODE_MRI_GARK_ERK33a t 2.0002 dsm 1.02331e-05 dsm_est 0.185807 + H 0.000195313 method ARKODE_MRI_GARK_ERK33a t 2.2502 dsm 1.54333e-06 dsm_est 0.132009 + H 0.000195313 method ARKODE_MRI_GARK_ERK33a t 2.5002 dsm 1.7004e-05 dsm_est 0.0255566 + H 0.000195313 method ARKODE_MRI_GARK_ERK33a t 2.7502 dsm 2.75731e-05 dsm_est 0.0139673 + H 0.000195313 method ARKODE_MRI_GARK_ERK33a t 3.0002 dsm 1.60122e-05 dsm_est 0.0198318 + H 0.000195313 method ARKODE_MRI_GARK_ERK33a t 3.2502 dsm 1.59604e-05 dsm_est 0.0112328 + H 0.000195313 method ARKODE_MRI_GARK_ERK33a t 3.5002 dsm 1.2611e-05 dsm_est 0.00471821 + H 0.000195313 method ARKODE_MRI_GARK_ERK33a t 3.7502 dsm 1.0072e-05 dsm_est 0.00496521 + H 0.000195313 method ARKODE_MRI_GARK_ERK33a t 4.0002 dsm 7.64165e-06 dsm_est 0.00855534 + H 0.000195313 method ARKODE_MRI_GARK_ERK33a t 4.2502 dsm 3.12732e-06 dsm_est 0.0479914 + H 0.000195313 method ARKODE_MRI_GARK_ERK33a t 4.5002 dsm 6.25467e-06 dsm_est 0.0595107 + H 0.000195313 method ARKODE_MRI_GARK_ERK33a t 4.7502 dsm 1.05712e-05 dsm_est 0.0147462 + H 4.88281e-05 method ARKODE_MRI_GARK_ERK33a t 4.88281e-05 dsm 2.01535e-06 dsm_est 4.1115e-05 + H 4.88281e-05 method ARKODE_MRI_GARK_ERK33a t 0.250049 dsm 0 dsm_est 0.000267507 + H 4.88281e-05 method ARKODE_MRI_GARK_ERK33a t 0.500049 dsm 1.50297e-06 dsm_est 0.00201586 + H 4.88281e-05 method ARKODE_MRI_GARK_ERK33a t 0.750049 dsm 1.49086e-06 dsm_est 0.00200068 + H 4.88281e-05 method ARKODE_MRI_GARK_ERK33a t 1.00005 dsm 9.78971e-07 dsm_est 3.2652e-05 + H 4.88281e-05 method ARKODE_MRI_GARK_ERK33a t 1.25005 dsm 3.17142e-06 dsm_est 0.0147541 + H 4.88281e-05 method ARKODE_MRI_GARK_ERK33a t 1.50005 dsm 2.18254e-06 dsm_est 0.0029151 + H 4.88281e-05 method ARKODE_MRI_GARK_ERK33a t 1.75005 dsm 2.39243e-06 dsm_est 0.0117588 + H 4.88281e-05 method ARKODE_MRI_GARK_ERK33a t 2.00005 dsm 1.0054e-06 dsm_est 0.00290265 + H 4.88281e-05 method ARKODE_MRI_GARK_ERK33a t 2.25005 dsm 2.03676e-06 dsm_est 0.00206178 + H 4.88281e-05 method ARKODE_MRI_GARK_ERK33a t 2.50005 dsm 3.37798e-06 dsm_est 0.000398446 + H 4.88281e-05 method ARKODE_MRI_GARK_ERK33a t 2.75005 dsm 4.72989e-06 dsm_est 0.000217912 + H 4.88281e-05 method ARKODE_MRI_GARK_ERK33a t 3.00005 dsm 6.95491e-06 dsm_est 0.000310377 + H 4.88281e-05 method ARKODE_MRI_GARK_ERK33a t 3.25005 dsm 1.55004e-06 dsm_est 0.000175458 + H 4.88281e-05 method ARKODE_MRI_GARK_ERK33a t 3.50005 dsm 9.19766e-07 dsm_est 7.37004e-05 + H 4.88281e-05 method ARKODE_MRI_GARK_ERK33a t 3.75005 dsm 0 dsm_est 7.66833e-05 + H 4.88281e-05 method ARKODE_MRI_GARK_ERK33a t 4.00005 dsm 1.08798e-06 dsm_est 0.000134086 + H 4.88281e-05 method ARKODE_MRI_GARK_ERK33a t 4.25005 dsm 3.12694e-06 dsm_est 0.000748179 + H 4.88281e-05 method ARKODE_MRI_GARK_ERK33a t 4.50005 dsm 1.16508e-06 dsm_est 0.000930348 + H 4.88281e-05 method ARKODE_MRI_GARK_ERK33a t 4.75005 dsm 6.40365e-06 dsm_est 0.000231401 + +ARKODE_MRI_GARK_ERK33a summary: + Stepsize 0.0125 maxdsm 13680.4 maxdsmest 267128 + Stepsize 0.003125 maxdsm 58.1561 maxdsmest 3954.15 + Stepsize 0.00078125 maxdsm 0.231817 maxdsmest 60.7616 + Stepsize 0.000195313 maxdsm 0.000909834 maxdsmest 0.945246 + Stepsize 4.88281e-05 maxdsm 6.95491e-06 maxdsmest 0.0147541 diff --git a/test/unit_tests/arkode/CXX_serial/ark_test_slowerror_polynomial.cpp b/test/unit_tests/arkode/CXX_serial/ark_test_slowerror_polynomial.cpp new file mode 100644 index 0000000000..4d9105c163 --- /dev/null +++ b/test/unit_tests/arkode/CXX_serial/ark_test_slowerror_polynomial.cpp @@ -0,0 +1,414 @@ +/*----------------------------------------------------------------- + * Programmer(s): Daniel R. Reynolds @ SMU + *--------------------------------------------------------------- + * SUNDIALS Copyright Start + * Copyright (c) 2002-2024, Lawrence Livermore National Security + * and Southern Methodist University. + * All rights reserved. + * + * See the top-level LICENSE and NOTICE files for details. + * + * SPDX-License-Identifier: BSD-3-Clause + * SUNDIALS Copyright End + *--------------------------------------------------------------- + * Routine to test an MRI method's embedding-based error + * estimate. Uses a simple polynomial test problem with 1 + * component, + * dy/dt = a*t^2 + b*t + c, y(0) = 1. + * + * We run a single time step, using a variety of slow step sizes, + * H = {1, 1/2, 1/4, 1/8, 1/16}. + * + * We place the entire ODE in the "slow" RHS partition. All tests + * use ARKODE's default fifth-order ERK method, with relative and + * absolute tolerances set to 1e-10 and 1e-12, respectively. + * + * When using an IMEX method (e.g., IMEX-MRI-SR), the entire slow + * partition is treated implicitly. + * + * We select the slow integrator based on a command-line argument, + * with the default being ARKODE_MRI_GARK_ERK22a. + * + * The program should be run with arguments in the following order: + * $ a.out method a b c + * Not all arguments are required, but these must be omitted from + * end-to-beginning, i.e. any one of + * $ a.out method a b + * $ a.out method a + * $ a.out method + * $ a.out + * are acceptable. We require that the "method" argument be a + * string corresponding to a valid embedded ARKODE_MRITableID. + *-----------------------------------------------------------------*/ + +// Header files +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#if defined(SUNDIALS_EXTENDED_PRECISION) +#define GSYM "Lg" +#define ESYM "Le" +#define FSYM "Lf" +#else +#define GSYM "g" +#define ESYM "e" +#define FSYM "f" +#endif + +#define ZERO SUN_RCONST(0.0) +#define ONE SUN_RCONST(1.0) +#define TWO SUN_RCONST(2.0) + +using namespace std; + +// User data structure +struct UserData +{ + sunrealtype a; + sunrealtype b; + sunrealtype c; +}; + +// User-supplied Functions Called by the Solver +static int f0(sunrealtype t, N_Vector y, N_Vector ydot, void* user_data); +static int fn(sunrealtype t, N_Vector y, N_Vector ydot, void* user_data); +static int Jn(sunrealtype t, N_Vector y, N_Vector fy, SUNMatrix J, + void* user_data, N_Vector tmp1, N_Vector tmp2, N_Vector tmp3); + +// Private utility functions +static int Ytrue(sunrealtype t, N_Vector y, UserData& udata); +static int computeErrorWeights(N_Vector ycur, N_Vector weight, sunrealtype rtol, + sunrealtype atol, N_Vector vtemp); +static int check_retval(void* returnvalue, const char* funcname, int opt); +static int run_test(void* mristep_mem, N_Vector y, sunrealtype T0, + vector& Hvals, string method, + sunrealtype reltol, sunrealtype abstol, UserData& udata); + +// Main Program +int main(int argc, char* argv[]) +{ + // general problem parameters + sunrealtype T0 = ZERO; // initial time + sunindextype NEQ = 1; // number of dependent vars. + string method; // MRI method name + sunrealtype reltol = SUN_RCONST(1.e-10); // fast solver tolerances + sunrealtype abstol = SUN_RCONST(1.e-12); + + // general problem variables + int retval; // reusable error-checking flag + UserData udata; // user-data structure + + // + // Initialization + // + + // Retrieve the command-line options: method Npart ep test + if (argc > 1) { method = argv[1]; } + else { method = "ARKODE_MRI_GARK_ERK22a"; } + if (argc > 2) { udata.a = SUNStrToReal(argv[2]); } + else { udata.a = ONE; } + if (argc > 3) { udata.b = SUNStrToReal(argv[3]); } + else { udata.b = ONE; } + if (argc > 4) { udata.c = SUNStrToReal(argv[4]); } + else { udata.c = ONE; } + + sunbooleantype implicit = SUNFALSE; + if ((method == "ARKODE_MRI_GARK_IRK21a") || + (method == "ARKODE_MRI_GARK_ESDIRK34a") || + (method == "ARKODE_MRI_GARK_ESDIRK46a") || + (method == "ARKODE_IMEX_MRI_SR21") || + (method == "ARKODE_IMEX_MRI_SR32") || (method == "ARKODE_IMEX_MRI_SR43")) + { + implicit = SUNTRUE; + } + + // Initial problem output (and set implicit solver tolerances as needed) + cout << "\nSlow error estimation test (polynomial ODE problem):\n"; + cout << " problem parameters: a = " << udata.a << ", b = " << udata.b + << ", c = " << udata.c << endl; + cout << " MRI method: " << method; + if (implicit) { cout << " (implicit)" << endl; } + else { cout << " (explicit)" << endl; } + + // + // Problem Setup + // + + // Create SUNDIALS context + sundials::Context ctx; + + // Create serial vectors for the solution and reference + N_Vector y = N_VNew_Serial(NEQ, ctx); + if (check_retval((void*)y, "N_VNew_Serial", 0)) return 1; + retval = Ytrue(T0, y, udata); + if (check_retval(&retval, "Ytrue", 1)) return 1; + + // Set up fast ARKStep integrator as fifth-order adaptive ERK + void* inner_arkode_mem = ARKStepCreate(f0, NULL, T0, y, ctx); + if (check_retval((void*)inner_arkode_mem, "ARKStepCreate", 0)) return 1; + retval = ARKodeSetOrder(inner_arkode_mem, 5); + if (check_retval(&retval, "ARKodeSetOrder", 1)) return 1; + retval = ARKodeSStolerances(inner_arkode_mem, reltol, abstol); + if (check_retval(&retval, "ARKodeSStolerances", 1)) return 1; + retval = ARKodeSetMaxNumSteps(inner_arkode_mem, 1000000); + if (check_retval(&retval, "ARKodeSetMaxNumSteps", 1)) return (1); + + // Create inner stepper wrapper + MRIStepInnerStepper inner_stepper = NULL; // inner stepper + retval = ARKodeCreateMRIStepInnerStepper(inner_arkode_mem, &inner_stepper); + if (check_retval(&retval, "ARKodeCreateMRIStepInnerStepper", 1)) return 1; + + // Set up slow MRIStep integrator + void* mristep_mem = NULL; + if (implicit) + { + mristep_mem = MRIStepCreate(NULL, fn, T0, y, inner_stepper, ctx); + } + else { mristep_mem = MRIStepCreate(fn, NULL, T0, y, inner_stepper, ctx); } + if (check_retval((void*)mristep_mem, "MRIStepCreate", 0)) return 1; + MRIStepCoupling C = MRIStepCoupling_LoadTableByName(method.c_str()); + if (check_retval((void*)C, "MRIStepCoupling_LoadTableByName", 0)) return 1; + retval = MRIStepSetCoupling(mristep_mem, C); + if (check_retval(&retval, "MRIStepSetCoupling", 1)) return 1; + SUNMatrix A = NULL; // matrix for slow solver + SUNLinearSolver LS = NULL; // slow linear solver object + if (implicit) + { + A = SUNDenseMatrix(NEQ, NEQ, ctx); + if (check_retval((void*)A, "SUNDenseMatrix", 0)) return 1; + LS = SUNLinSol_Dense(y, A, ctx); + if (check_retval((void*)LS, "SUNLinSol_Dense", 0)) return 1; + retval = ARKodeSetLinearSolver(mristep_mem, LS, A); + if (check_retval(&retval, "ARKodeSetLinearSolver", 1)) return 1; + retval = ARKodeSetJacFn(mristep_mem, Jn); + if (check_retval(&retval, "ARKodeSetJacFn", 1)) return 1; + retval = ARKodeSetJacEvalFrequency(mristep_mem, 1); + if (check_retval(&retval, "ARKodeSetJacEvalFrequency", 1)) return 1; + retval = ARKodeSetLSetupFrequency(mristep_mem, 1); + if (check_retval(&retval, "ARKodeSetLSetupFrequency", 1)) return 1; + retval = ARKodeSetMaxNonlinIters(mristep_mem, 20); + if (check_retval(&retval, "ARKodeSetMaxNonlinIters", 1)) return 1; + } + retval = ARKodeSStolerances(mristep_mem, reltol, abstol); + if (check_retval(&retval, "ARKodeSStolerances", 1)) return 1; + retval = ARKodeSetUserData(mristep_mem, (void*)&udata); + if (check_retval(&retval, "ARKodeSetUserData", 1)) return 1; + retval = ARKodeSetAccumulatedErrorType(mristep_mem, ARK_ACCUMERROR_MAX); + if (check_retval(&retval, "ARKodeSetAccumulatedErrorType", 1)) return 1; + + // Run test for various H values + vector Hvals(5); + for (size_t i = 0; i < Hvals.size(); i++) + { + Hvals[i] = SUN_RCONST(0.01) / SUNRpowerI(SUN_RCONST(2.0), (int)i); + } + retval = run_test(mristep_mem, y, T0, Hvals, method, reltol, abstol, udata); + if (check_retval(&retval, "run_test", 1)) return 1; + + // Clean up and return + MRIStepCoupling_Free(C); + ARKodeFree(&inner_arkode_mem); + MRIStepInnerStepper_Free(&inner_stepper); + ARKodeFree(&mristep_mem); + if (LS) { SUNLinSolFree(LS); } // free system linear solver + if (A) { SUNMatDestroy(A); } // free system matrix + N_VDestroy(y); // Free y and yref vectors + return 0; +} + +//------------------------------ +// Functions called by the solver +//------------------------------ + +static int f0(sunrealtype t, N_Vector y, N_Vector ydot, void* user_data) +{ + // fill in the RHS function with zeros and return with success + N_VConst(ZERO, ydot); + return 0; +} + +static int fn(sunrealtype t, N_Vector y, N_Vector ydot, void* user_data) +{ + // fill in the RHS function and return with success + UserData* udata = (UserData*)user_data; + sunrealtype* dydata = N_VGetArrayPointer(ydot); + dydata[0] = udata->a * t * t + udata->b * t + udata->c; + return 0; +} + +static int Jn(sunrealtype t, N_Vector y, N_Vector fy, SUNMatrix J, + void* user_data, N_Vector tmp1, N_Vector tmp2, N_Vector tmp3) +{ + // fill in the Jacobian and return with success + SM_ELEMENT_D(J, 0, 0) = ZERO; + return 0; +} + +//------------------------------ +// Private helper functions +//------------------------------ + +static int run_test(void* mristep_mem, N_Vector y, sunrealtype T0, + vector& Hvals, string method, + sunrealtype reltol, sunrealtype abstol, UserData& udata) +{ + // Reused variables + int retval; + sunrealtype t; + N_Vector vtemp = N_VClone(y); + N_Vector ele = N_VClone(y); + N_Vector ewt = N_VClone(y); + sunrealtype* ydata = N_VGetArrayPointer(y); + sunrealtype* vdata = N_VGetArrayPointer(vtemp); + + // Set storage for errors + vector dsm(Hvals.size(), ZERO); + vector dsm_est(Hvals.size(), ZERO); + + // Loop over step sizes + for (size_t iH = 0; iH < Hvals.size(); iH++) + { + // Reset integrator for this run + t = T0; + retval = Ytrue(t, y, udata); + if (check_retval(&retval, "Ytrue", 1)) return 1; + retval = ARKodeReset(mristep_mem, t, y); + if (check_retval(&retval, "ARKodeReset", 1)) return 1; + retval = ARKodeSetFixedStep(mristep_mem, Hvals[iH]); + if (check_retval(&retval, "ARKodeSetFixedStep", 1)) return 1; + retval = ARKodeResetAccumulatedError(mristep_mem); + if (check_retval(&retval, "ARKodeResetAccumulatedError", 1)) return 1; + + // Run ARKodeEvolve to compute one step + retval = ARKodeEvolve(mristep_mem, t + Hvals[iH], y, &t, ARK_ONE_STEP); + if (check_retval(&retval, "ARKodeEvolve", 1)) return 1; + retval = ARKodeGetEstLocalErrors(mristep_mem, ele); + if (check_retval(&retval, "ARKodeGetEstLocalErrors", 1)) return 1; + retval = computeErrorWeights(y, ewt, reltol, abstol, vtemp); + if (check_retval(&retval, "computeErrorWeights", 1)) return 1; + dsm_est[iH] = N_VWrmsNorm(ewt, ele); + + // Compute/print solution error + retval = Ytrue(t, vtemp, udata); + if (check_retval(&retval, "Ytrue", 1)) return 1; + dsm[iH] = abs(ydata[0] - vdata[0]) / (abstol + reltol * abs(vdata[0])); + if (method == "ARKODE_MRI_GARK_ERK22a") + { + printf(" H %.5f dsm %.2e dsm_est %.2e dsm_anal %.2e " + " dsm_est_anal %.2e\n", + Hvals[iH], dsm[iH], dsm_est[iH], + Hvals[iH] * Hvals[iH] * Hvals[iH] * abs(udata.a / 12.0) / + (abstol + reltol * abs(vdata[0])), + Hvals[iH] * Hvals[iH] * + abs(udata.a * Hvals[iH] / 4.0 + udata.b / 2.0) / + (abstol + reltol * abs(vdata[0]))); + } + else if (method == "ARKODE_MRI_GARK_IRK21a") + { + printf(" H %.5f dsm %.2e dsm_est %.2e dsm_anal %.2e " + " dsm_est_anal %.2e\n", + Hvals[iH], dsm[iH], dsm_est[iH], + Hvals[iH] * Hvals[iH] * Hvals[iH] * abs(udata.a / 6.0) / + (abstol + reltol * abs(vdata[0])), + Hvals[iH] * Hvals[iH] * + abs(udata.a * Hvals[iH] / 2.0 + udata.b / 2.0) / + (abstol + reltol * abs(vdata[0]))); + } + else if (method == "ARKODE_IMEX_MRI_SR21") + { + printf(" H %.5f dsm %.2e dsm_est %.2e dsm_anal %.2e " + " dsm_est_anal %.2e\n", + Hvals[iH], dsm[iH], dsm_est[iH], + Hvals[iH] * Hvals[iH] * Hvals[iH] * abs(udata.a * 3137.0 / 50370.0) / + (abstol + reltol * abs(vdata[0])), + Hvals[iH] * Hvals[iH] * + abs(udata.a * Hvals[iH] * 20191.0 / 755550.0 - + udata.b * 19.0 / 30.0) / + (abstol + reltol * abs(vdata[0]))); + } + else + { + printf(" H %.5f dsm %.2e dsm_est %.2e\n", Hvals[iH], + dsm[iH], dsm_est[iH]); + } + } + + N_VDestroy(ele); + N_VDestroy(ewt); + N_VDestroy(vtemp); + return (0); +} + +static int Ytrue(sunrealtype t, N_Vector y, UserData& udata) +{ + sunrealtype* ydata = N_VGetArrayPointer(y); + ydata[0] = udata.a / SUN_RCONST(3.0) * t * t * t + + udata.b / SUN_RCONST(2.0) * t * t + udata.c * t + ONE; + return (0); +} + +/* Error weight calculation routine (mimics what's in ARKODE already) */ +static int computeErrorWeights(N_Vector ycur, N_Vector weight, sunrealtype rtol, + sunrealtype atol, N_Vector vtemp) +{ + N_VAbs(ycur, vtemp); + N_VScale(rtol, vtemp, vtemp); + N_VAddConst(vtemp, atol, vtemp); + N_VInv(vtemp, weight); + return (0); +} + +/* Check function return value... + opt == 0 means SUNDIALS function allocates memory so check if + returned NULL pointer + opt == 1 means SUNDIALS function returns a retval so check if + retval >= 0 + opt == 2 means function allocates memory so check if returned + NULL pointer +*/ +static int check_retval(void* returnvalue, const char* funcname, int opt) +{ + int* retval; + + // Check if SUNDIALS function returned NULL pointer - no memory allocated + if (opt == 0 && returnvalue == NULL) + { + fprintf(stderr, "\nSUNDIALS_ERROR: %s() failed - returned NULL pointer\n\n", + funcname); + return 1; + } + + // Check if retval < 0 + else if (opt == 1) + { + retval = (int*)returnvalue; + if (*retval < 0) + { + fprintf(stderr, "\nSUNDIALS_ERROR: %s() failed with retval = %d\n\n", + funcname, *retval); + return 1; + } + } + + // Check if function returned NULL pointer - no memory allocated + else if (opt == 2 && returnvalue == NULL) + { + fprintf(stderr, "\nMEMORY_ERROR: %s() failed - returned NULL pointer\n\n", + funcname); + return 1; + } + + return 0; +} + +/*---- end of file ----*/ diff --git a/test/unit_tests/arkode/CXX_serial/ark_test_slowerror_polynomial.out b/test/unit_tests/arkode/CXX_serial/ark_test_slowerror_polynomial.out new file mode 100644 index 0000000000..25faa25bff --- /dev/null +++ b/test/unit_tests/arkode/CXX_serial/ark_test_slowerror_polynomial.out @@ -0,0 +1,9 @@ + +Slow error estimation test (polynomial ODE problem): + problem parameters: a = 1, b = 1, c = 1 + MRI method: ARKODE_MRI_GARK_ERK22a (explicit) + H 0.01000 dsm 8.17e+02 dsm_est 4.93e+05 dsm_anal 8.17e+02 dsm_est_anal 4.93e+05 + H 0.00500 dsm 1.03e+02 dsm_est 1.23e+05 dsm_anal 1.03e+02 dsm_est_anal 1.23e+05 + H 0.00250 dsm 1.29e+01 dsm_est 3.09e+04 dsm_anal 1.29e+01 dsm_est_anal 3.09e+04 + H 0.00125 dsm 1.61e+00 dsm_est 7.73e+03 dsm_anal 1.61e+00 dsm_est_anal 7.73e+03 + H 0.00063 dsm 2.01e-01 dsm_est 1.93e+03 dsm_anal 2.01e-01 dsm_est_anal 1.93e+03 diff --git a/test/unit_tests/arkode/C_serial/ark_test_getuserdata.c b/test/unit_tests/arkode/C_serial/ark_test_getuserdata.c index 25c5de6982..24be91856d 100644 --- a/test/unit_tests/arkode/C_serial/ark_test_getuserdata.c +++ b/test/unit_tests/arkode/C_serial/ark_test_getuserdata.c @@ -165,10 +165,10 @@ int main(int argc, char* argv[]) } /* Create inner stepper */ - retval = ARKStepCreateMRIStepInnerStepper(arkode_inner_mem, &inner_stepper); + retval = ARKodeCreateMRIStepInnerStepper(arkode_inner_mem, &inner_stepper); if (retval) { - fprintf(stderr, "ARKStepCreateMRIStepInnerStepper returned %i", retval); + fprintf(stderr, "ARKodeCreateMRIStepInnerStepper returned %i", retval); return 1; } diff --git a/test/unit_tests/arkode/C_serial/ark_test_reset.c b/test/unit_tests/arkode/C_serial/ark_test_reset.c index 537adbf978..8574dd31a4 100644 --- a/test/unit_tests/arkode/C_serial/ark_test_reset.c +++ b/test/unit_tests/arkode/C_serial/ark_test_reset.c @@ -125,7 +125,7 @@ int main(void) check_retval(&retval, "ARKodeSetStopTime", 1); retval = ARKodeEvolve(arkode_mem, t + dTout, y, &t, ARK_NORMAL); if (check_retval(&retval, "ARKodeEvolve", 1)) { return 1; } - if (check_ans(y, t, SUN_RCONST(0.001), SUN_RCONST(0.000001))) + if (check_ans(y, t, rtol, atol)) { printf(" Initial ARKodeEvolve had insufficient accuracy\n"); printf(" t = %" GSYM "\n", t); @@ -143,7 +143,7 @@ int main(void) check_retval(&retval, "ARKodeReset", 1); retval = ARKodeEvolve(arkode_mem, t + dTout, y, &t, ARK_NORMAL); if (check_retval(&retval, "ARKodeEvolve", 1)) { return 1; } - if (check_ans(y, t, SUN_RCONST(0.001), SUN_RCONST(0.000001))) + if (check_ans(y, t, rtol, atol)) { printf(" Second ARKodeEvolve call had insufficient accuracy\n"); printf(" t = %" GSYM "\n", t); @@ -161,7 +161,7 @@ int main(void) check_retval(&retval, "ARKodeReset", 1); retval = ARKodeEvolve(arkode_mem, t + dTout, y, &t, ARK_NORMAL); if (check_retval(&retval, "ARKodeEvolve", 1)) { return 1; } - if (check_ans(y, t, SUN_RCONST(0.001), SUN_RCONST(0.000001))) + if (check_ans(y, t, rtol, atol)) { printf(" Third ARKodeEvolve call had insufficient accuracy\n"); printf(" t = %" GSYM "\n", t); @@ -179,7 +179,7 @@ int main(void) check_retval(&retval, "ARKodeReset", 1); retval = ARKodeEvolve(arkode_mem, t + dTout, y, &t, ARK_NORMAL); if (check_retval(&retval, "ARKodeEvolve", 1)) { return 1; } - if (check_ans(y, t, SUN_RCONST(0.001), SUN_RCONST(0.000001))) + if (check_ans(y, t, rtol, atol)) { printf(" Fourth ARKodeEvolve call had insufficient accuracy\n"); printf(" t = %" GSYM "\n", t); @@ -218,7 +218,7 @@ int main(void) /* Initially evolve to dTout, and check result */ retval = ARKodeEvolve(arkode_mem, t + dTout, y, &t, ARK_NORMAL); if (check_retval(&retval, "ARKodeEvolve", 1)) { return 1; } - if (check_ans(y, t, SUN_RCONST(0.001), SUN_RCONST(0.000001))) + if (check_ans(y, t, rtol, atol)) { printf(" Initial ARKodeEvolve had insufficient accuracy\n"); printf(" t = %" GSYM "\n", t); @@ -236,7 +236,7 @@ int main(void) check_retval(&retval, "ARKodeReset", 1); retval = ARKodeEvolve(arkode_mem, t + dTout, y, &t, ARK_NORMAL); if (check_retval(&retval, "ARKodeEvolve", 1)) { return 1; } - if (check_ans(y, t, SUN_RCONST(0.001), SUN_RCONST(0.000001))) + if (check_ans(y, t, rtol, atol)) { printf(" Second ARKodeEvolve call had insufficient accuracy\n"); printf(" t = %" GSYM "\n", t); @@ -254,7 +254,7 @@ int main(void) check_retval(&retval, "ARKodeReset", 1); retval = ARKodeEvolve(arkode_mem, t + dTout, y, &t, ARK_NORMAL); if (check_retval(&retval, "ARKodeEvolve", 1)) { return 1; } - if (check_ans(y, t, SUN_RCONST(0.001), SUN_RCONST(0.000001))) + if (check_ans(y, t, rtol, atol)) { printf(" Third ARKodeEvolve call had insufficient accuracy\n"); printf(" t = %" GSYM "\n", t); @@ -272,7 +272,7 @@ int main(void) check_retval(&retval, "ARKodeReset", 1); retval = ARKodeEvolve(arkode_mem, t + dTout, y, &t, ARK_NORMAL); if (check_retval(&retval, "ARKodeEvolve", 1)) { return 1; } - if (check_ans(y, t, SUN_RCONST(0.001), SUN_RCONST(0.000001))) + if (check_ans(y, t, rtol, atol)) { printf(" Fourth ARKodeEvolve call had insufficient accuracy\n"); printf(" t = %" GSYM "\n", t); @@ -299,11 +299,8 @@ int main(void) if (check_retval(&retval, "ARKodeSStolerances", 1)) { return 1; } retval = ARKodeSetMaxNumSteps(arkode_mem, 100); check_retval(&retval, "ARKodeSetMaxNumSteps", 1); - retval = ARKStepCreateMRIStepInnerStepper(arkode_mem, &inner_stepper); - if (check_retval(&retval, "ARKStepCreateMRIStepInnerStepper", 1)) - { - return 1; - } + retval = ARKodeCreateMRIStepInnerStepper(arkode_mem, &inner_stepper); + if (check_retval(&retval, "ARKodeCreateMRIStepInnerStepper", 1)) { return 1; } mristep_mem = MRIStepCreate(NULL, f, t, y, inner_stepper, ctx); if (check_retval((void*)mristep_mem, "MRIStepCreate", 0)) { return 1; } retval = ARKodeSetUserData(mristep_mem, (void*)&lambda); @@ -316,13 +313,13 @@ int main(void) if (check_retval(&retval, "ARKodeSetLinear", 1)) { return 1; } retval = ARKodeSetMaxNumSteps(mristep_mem, 100); check_retval(&retval, "ARKodeSetMaxNumSteps", 1); - retval = ARKodeSetFixedStep(mristep_mem, dTout * SUN_RCONST(0.105)); + retval = ARKodeSetFixedStep(mristep_mem, dTout * SUN_RCONST(0.100)); check_retval(&retval, "ARKodeSetFixedStep", 1); /* Initially evolve to dTout, and check result */ retval = ARKodeEvolve(mristep_mem, t + dTout, y, &t, ARK_NORMAL); if (check_retval(&retval, "ARKodeEvolve", 1)) { return 1; } - if (check_ans(y, t, SUN_RCONST(0.001), SUN_RCONST(0.000001))) + if (check_ans(y, t, rtol, atol)) { printf(" Initial ARKodeEvolve had insufficient accuracy\n"); printf(" t = %" GSYM "\n", t); @@ -340,7 +337,7 @@ int main(void) check_retval(&retval, "ARKodeReset", 1); retval = ARKodeEvolve(mristep_mem, t + dTout, y, &t, ARK_NORMAL); if (check_retval(&retval, "ARKodeEvolve", 1)) { return 1; } - if (check_ans(y, t, SUN_RCONST(0.001), SUN_RCONST(0.000001))) + if (check_ans(y, t, rtol, atol)) { printf(" Second ARKodeEvolve call had insufficient accuracy\n"); printf(" t = %" GSYM "\n", t); @@ -358,7 +355,7 @@ int main(void) check_retval(&retval, "ARKodeReset", 1); retval = ARKodeEvolve(mristep_mem, t + dTout, y, &t, ARK_NORMAL); if (check_retval(&retval, "ARKodeEvolve", 1)) { return 1; } - if (check_ans(y, t, SUN_RCONST(0.001), SUN_RCONST(0.000001))) + if (check_ans(y, t, rtol, atol)) { printf(" Third ARKodeEvolve call had insufficient accuracy\n"); printf(" t = %" GSYM "\n", t); @@ -376,7 +373,7 @@ int main(void) check_retval(&retval, "ARKodeReset", 1); retval = ARKodeEvolve(mristep_mem, t + dTout, y, &t, ARK_NORMAL); if (check_retval(&retval, "ARKodeEvolve", 1)) { return 1; } - if (check_ans(y, t, SUN_RCONST(0.001), SUN_RCONST(0.000001))) + if (check_ans(y, t, rtol, atol)) { printf(" Fourth ARKodeEvolve call had insufficient accuracy\n"); printf(" t = %" GSYM "\n", t); diff --git a/test/unit_tests/utilities/test_utilities.hpp b/test/unit_tests/utilities/test_utilities.hpp new file mode 100644 index 0000000000..6798740d63 --- /dev/null +++ b/test/unit_tests/utilities/test_utilities.hpp @@ -0,0 +1,110 @@ +/* ----------------------------------------------------------------------------- + * Programmer(s): David J. Gardner @ LLNL + * Daniel R. Reynolds @ SMU + * ----------------------------------------------------------------------------- + * 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 + * ----------------------------------------------------------------------------- + * Utility functions for C++ unit tests. + * ---------------------------------------------------------------------------*/ + +#include +#include +#include +#include + +// Check function return flag +static int check_flag(const int flag, const std::string funcname) +{ + if (!flag) return 0; + if (flag < 0) std::cerr << "ERROR: "; + std::cerr << funcname << " returned " << flag << std::endl; + return 1; +} + +// Check if a function returned a NULL pointer +static int check_ptr(const void* ptr, const std::string funcname) +{ + if (ptr) return 0; + std::cerr << "ERROR: " << funcname << " returned NULL" << std::endl; + return 1; +} + +inline void find_arg(std::vector& args, const std::string key, + sunrealtype& dest) +{ + auto it = std::find(args.begin(), args.end(), key); + if (it != args.end()) + { +#if defined(SUNDIALS_SINGLE_PRECISION) + dest = stof(*(it + 1)); +#elif defined(SUNDIALS_DOUBLE_PRECISION) + dest = stod(*(it + 1)); +#elif defined(SUNDIALS_EXTENDED_PRECISION) + dest = stold(*(it + 1)); +#endif + args.erase(it, it + 2); + } +} + +inline void find_arg(std::vector& args, const std::string key, + long long& dest) +{ + auto it = std::find(args.begin(), args.end(), key); + if (it != args.end()) + { + dest = stoll(*(it + 1)); + args.erase(it, it + 2); + } +} + +inline void find_arg(std::vector& args, const std::string key, + long int& dest) +{ + auto it = std::find(args.begin(), args.end(), key); + if (it != args.end()) + { + dest = stol(*(it + 1)); + args.erase(it, it + 2); + } +} + +inline void find_arg(std::vector& args, const std::string key, + int& dest) +{ + auto it = std::find(args.begin(), args.end(), key); + if (it != args.end()) + { + dest = stoi(*(it + 1)); + args.erase(it, it + 2); + } +} + +inline void find_arg(std::vector& args, const std::string key, + bool& dest, bool store = true) +{ + auto it = std::find(args.begin(), args.end(), key); + if (it != args.end()) + { + dest = store; + args.erase(it); + } +} + +inline void find_arg(std::vector& args, const std::string key, + std::string& dest) +{ + auto it = std::find(args.begin(), args.end(), key); + if (it != args.end()) + { + dest = *(it + 1); + args.erase(it, it + 2); + } +}