[英]Compiled C ODE gives different results to R's using deSolve
I have an ODE which I would like to solve using compiled C code called from R's deSolve package. The ODE in question is I an exponential decay model (y'=-d* exp(g* time)*y): But running the compiled code from within R gives different results to R's native deSolve.我有一个 ODE,我想使用从 R 的 deSolve package 调用的已编译代码 C 来解决。有问题的 ODE 是指数衰减 model (y'=-d* exp(g* time)*y):但是运行R 中的编译代码给出了与 R 的原生 deSolve 不同的结果。 It's as is there they are flipped 180º.
就好像它们被翻转了 180º。 What's going on?
这是怎么回事?
/* file testODE.c */
#include <R.h>
static double parms[4];
#define C parms[0] /* left here on purpose */
#define d parms[1]
#define g parms[2]
/* initializer */
void initmod(void (* odeparms)(int *, double *))
{
int N=3;
odeparms(&N, parms);
}
/* Derivatives and 1 output variable */
void derivs (int *neq, double t, double *y, double *ydot,
double *yout, int *ip)
{
// if (ip[0] <1) error("nout should be at least 1");
ydot[0] = -d*exp(-g*t)*y[0];
}
/* END file testODEod.c */
testODE <- function(time_space, initial_contamination, parameters){
with(
as.list(c(initial_contamination, parameters)),{
dContamination <- -d*exp(-g*time_space)*Contamination
return(list(dContamination))
}
)
}
parameters <- c(C = -8/3, d = -10, g = 28)
Y=c(y=1200)
times <- seq(0, 6, by = 0.01)
initial_contamination=c(Contamination=1200)
out <- ode(initial_contamination, times, testODE, parameters, method = "radau",atol = 1e-4, rtol = 1e-4)
plot(out)
library(deSolve)
library(scatterplot3d)
dyn.load("Code/testODE.so")
Y <-c(y1=initial_contamination) ;
out <- ode(Y, times, func = "derivs", parms = parameters,
dllname = "testODE", initfunc = "initmod")
plot(out)
Compiled code does not give different results to deSolve models implemented in R , except potential rounding errors within the limits of atol
and rtol
.编译代码不会给R中实现的deSolve模型带来不同的结果,除了
atol
和rtol
限制内的潜在舍入误差。
The reasons of the differences in the original post where two errors in the code.差异的原因在原帖中代码中有两处错误。 One can correct it as follows:
可以按如下方式更正它:
static double
as parms[3];
static double
声明为parms[3];
instead of parms[4]
parms[4]
t
in derivs is a pointer, ie *t
t
是一个指针,即*t
so that the code reads as:这样代码就变成了:
/* file testODE.c */
#include <R.h>
#include <math.h>
static double parms[3];
#define C parms[0] /* left here on purpose */
#define d parms[1]
#define g parms[2]
/* initializer */
void initmod(void (* odeparms)(int *, double *)) {
int N=3;
odeparms(&N, parms);
}
/* Derivatives and 1 output variable */
void derivs (int *neq, double *t, double *y, double *ydot,
double *yout, int *ip) {
ydot[0] = -d * exp(-g * *t) * y[0];
}
Here the comparison between the two simulations, somewhat adapted and generalized:这里是两个模拟之间的比较,经过一定程度的改编和概括:
library(deSolve)
testODE <- function(t, y, parameters){
with(
as.list(c(y, parameters)),{
dContamination <- -d * exp(-g * t) * contamination
return(list(dContamination))
}
)
}
system("R CMD SHLIB testODE.c")
dyn.load("testODE.dll")
parameters <- c(c = -8/3, d = -10, g = 28)
Y <- c(contamination = 1200)
times <- seq(0, 6, by = 0.01)
out1 <- ode(Y, times, testODE,
parms = parameters, method = "radau", atol = 1e-4, rtol = 1e-4)
out2 <- ode(Y, times, func = "derivs", dllname = "testODE", initfunc = "initmod",
parms = parameters, method = "radau", atol = 1e-4, rtol = 1e-4)
plot(out1, out2) # no visible difference
summary(out1 - out2) # differences should be (close to) zero
dyn.unload("testODE.dll") # always unload before editing .c file !!
Note: set .dll
or .so
according to your OS, or detect it with .Platform$dynlib.ext
.注意:根据您的操作系统设置
.dll
或.so
,或者使用.Platform$dynlib.ext
检测它。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.