User functions Coding user functions used by SUNDIALS solvers

## Introduction

To solve nonlinear equations, ODEs (Ordinary Differential Equations) or DAEs (Differential Algebraic Equations) different functions have to be provided to the solver. The right hand side (which denotes a different function depending on the kind of equations) has to be computed by the user and is the only mandatory function. In addition, all solvers allow to give a user Jacobian to help the solver and a user Callback function can also be called at each internal or user time step.

For ODEs and DAEs only, the roots of a set of user Events functions can be determined during the iterations, projection on a constraint manifold can be performed during the integration (cvode only)--> sensitivity with respect to a parameter can be computed during the integration (cvode and ida only) and a Mass matrix can be provided (arkode only).

The usual way is to write these user functions in the Scilab language but if speed is a concern, entrypoints of dynamically linked shared libraries (DLL) should be used instead, as at least one order of magnitude in speed is typically achieved. All entrypoints have to follow the SUNDIALS API and for the moment the supported modules are NVECTOR_SERIAL (for vector data structures), SUNMATRIX_DENSE, SUNMATRIX_BAND and SUNMATRIX_SPARSE (for matrix data structures). A very rich library of utility functions and accessor macros can be used and are documented in the online SUNDIALS documentation at the following adresses:

- NVector API: https://sundials.readthedocs.io/en/latest/nvectors/NVector_API_link.html
- NVECTOR_SERIAL module: https://sundials.readthedocs.io/en/latest/nvectors/NVector_links.html
- SUNMatrix API: https://sundials.readthedocs.io/en/latest/sunmatrix/SUNMatrix_API_link.html
- SUNMATRIX_DENSE module: https://sundials.readthedocs.io/en/latest/sunmatrix/SUNMatrix_links.html#
- SUNMATRIX_BAND module: https://sundials.readthedocs.io/en/latest/sunmatrix/SUNMatrix_links.html#the-sunmatrix-band-module
- SUNMATRIX_SPARSE module: https://sundials.readthedocs.io/en/latest/sunmatrix/SUNMatrix_links.html#the-sunmatrix-sparse-module

## Passing extra parameters

Extra parameters can be passed to user Scilab functions or entrypoints by replacing the corresponding argument or option by a list, where the first element is the usual argument (a function identifier or a string with the entrypoint name) and the subsequent elements are the parameters to be passed after the mandatory arguments.

Note that SUNDIALS DLL entrypoints accept only one extra parameter as a Scilab double array, which is passed as a `void *` pointer in the `user_data` argument. When no extra parameter has been passed to the solver this pointer is `NULL`. We give below two examples where we solve the same ODE using user parameters with a Scilab function then a SUNDIALS DLL:

                    function yd = f(t,y,a,b)
                      yd = a*y+b;
                    end
                    [t,y] = cvode(list(f,-1,1),[0 10],0);

                   code=[
                       "#include <nvector/nvector_serial.h>"
                       "int sunRhs(realtype t, N_Vector Y, N_Vector Yd, void *user_data)"
                       "{"
                       "double *y = NV_DATA_S(Y);"
                       "double *yd = NV_DATA_S(Yd);"
                       "double *par = (double *)user_data;"
                       "yd[0] = par[0]*y[0]+par[1];"
                       "return 0;"
                       "}"];
                       mputl(code,"code.c");
                   SUN_Clink("sunRhs","code.c",load=%t);
                   [t,y] = cvode(list("sunRhs",[-1,1]),[0 10],0);

## See also

- arkode
- cvode
- ida
- kinsol
- User Jacobian
- User Events
- User Callback
- SUN_Clink