[R-sig-dyn-mod] deSolve with compiled code and varying size of parms

Thomas Petzoldt thomas.petzoldt at tu-dresden.de
Thu Mar 30 08:36:36 CEST 2017


Hi,

Am 30.03.2017 um 00:41 schrieb Tim Keitt:
> Unlike more
> integrated solvers, that framework puts more onus on the user to not supply
> invalid parameters, or perhaps it would be better to say that the user has
> to avoid certain corner cases.

Tim made a good point here. It is not easy to prevent all corner cases 
that potentially break R, if compiled code is allowed, both in odeintr 
(based on ODEINT), deSolve (based partly on ODEPACK) and other packages 
that were built on top of them.

In the meantime, I had a look again in the deSolve sources. The 
initialisation routine is a little bit tricky to enable communication 
between the user-dll and deSolve.dll. It would be possible, in 
principle, to relax the "confusion over the length ..." error message or 
to enable passing more complex parameter constructions other than double 
precision vectors, i.e. a complete SEXP that could then be 
de-constructed by the user.

I assume that the decision about the length check was made with the 
intent to make the interface easy to use, and to request a minimum of 
self-check from the user (here, thinking about the parameter length 
him/herself) -- so I would leave it as is.

Besides this intrinsically fixed match between the C and R vector, there 
are several methods that can make parameter passing more flexible, i.e. 
using C vectors directly instead of #define macros, or employ UNIONs 
between numbered vector arguments and named arguments.

One can then pass a bigger vector with some reserve (e.g. Nmax 100), and 
then to fill only the parameters that are needed.

A small example is shown below, another example with UNIONs can be 
posted on request.

Thomas


-------------- next part --------------
/* file lorenz.c */
#include <R.h>

#define Nmax 3

double p[Nmax];


/* initializer  */
void initmod(void (* odeparms)(int *, double *))
{
    int N = Nmax;
    odeparms(&N, p);
}

/* Derivatives */
void derivs (int *neq, double *t, double *y, double *ydot,
             double *yout, int *ip)
{
    ydot[0] = p[0] * y[0] + y[1] * y[2];
    ydot[1] = p[1] * (y[1] - y[2]);
    ydot[2] = - y[0] * y[1] + p[2] * y[1] - y[2];
}
-------------- next part --------------
library(deSolve)
library(scatterplot3d)

system("R CMD SHLIB lorenzc_pvar.c")
dyn.load("lorenzc_pvar.dll")

parameters <- c(a = -8/3, b = -10, c =  28)
state <- c(X = 1, Y = 1, Z = 1)
times <- seq(0, 100, by = 0.01)

out <- ode(state, times, func = "derivs", parms = parameters,
           dllname = "lorenzc_pvar", initfunc = "initmod")
plot(out)
scatterplot3d(out[,-1], type="l")

dyn.unload("lorenzc_pvar.dll")




More information about the R-sig-dynamic-models mailing list