我有一个ODE,我想用从R的deSolve包中调用的编译C代码来解决它.讨论中的ODE是一个指数衰减模型(y'=-d*exp(g*time)*y):

C code implementation

/* 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 */

R implementation - Native deSolve

  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)

R implementation - Run compiled code from deSolve

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)

推荐答案

编译代码does not giveR中实现的deSolve个模型的结果不同,但潜在的舍入误差在atolrtol范围内.

产生差异的原因在原来的帖子里有两个errors码.人们可以通过以下方式进行纠正:

  1. 宣布static doubleparms[3];而不是parms[4]
  2. derivs中的时间t是一个指针,即*t

因此,代码如下所示:

/* 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];
}

以下是两个模拟之间的比较,经过一定程度的调整和推广:

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 !!

comparison between R and C code

注意:根据你的操作系统设置.dll.so,或者用.Platform$dynlib.ext检测.

C++相关问答推荐

当我try 计算一个多项时,看到segfault.我做错了什么?

获取二维数组的最大元素

使用SWI—Prolog的qsave_program生成二进制文件有什么好处?'

来自stdarg.h的c中的va_args无法正常工作<>

__VA_OPT__(,)是否可以检测后面没有任何内容的尾随逗号?

如何在C中从函数返回指向数组的指针?

将 struct 变量赋给自身(通过指针取消引用)是否定义了行为?

带有sigLongjMP中断I/O的异常处理程序

fwrite无法写入满(非常大)缓冲区

实现简单字典时C语言中的段错误

在WSL关闭/重新启动后,是什么原因导致共享对象依赖关系发生更改?

预处理器宏扩展(ISO/IEC 9899:1999(E)§;6.10.3.5示例3)

如何在VSCode中创建和使用我自己的C库?

S,在 struct 中创建匿名静态缓冲区的最佳方式是什么?

如何在zOS上编译共享C库

为什么会导致分段故障?(C语言中的一个程序,统计文件中某个单词的出现次数)

在我的第一个C语言中观察到的错误';你好世界';程序

x86-64平台上的int_fast8_t大小与int_fast16_t大小

分支预测和UB(未定义的行为)

使用fread()函数读取txt文件