我开发了一个R包,它提供了SUNDIALS(ODE求解库)的CVODE函数的包装器。
该软件包包含源函数(在src
和inst/include
文件夹中)并动态编译静态链接(.a
)和.dll
文件(同时编译包),因此它不需要在系统上安装SUNDIALS
包作为先决条件。包源可以在
https://github.com/sn248/Rcppsbmod
但是,SUNDIALS
要求ODE函数具有以下签名
int ODE_fun (realtype time, N_Vector y, N_Vector ydot, void *user_data);
realtype
,N_Vector
是SUNDIALS库定义的数据类型。因此,示例ODE函数将定义如下
#include <Rcpp.h>
using namespace Rcpp;
#include <cvode/cvode.h> /* prototypes for CVODE fcts., consts. */
#include <nvector/nvector_serial.h> /* serial N_Vector types, fcts., macros */
#define Ith(v,i) NV_Ith_S(v,i-1)
#define k1 0.04
#define k2 1e04
#define k3 3e07
int test1 (realtype t, N_Vector y, N_Vector ydot){ // , void *user_data
// static keyword before int is not really required here
realtype y1 = Ith(y, 1);
realtype y2 = Ith(y, 2);
realtype y3 = Ith(y, 3);
realtype yd1 = Ith(ydot, 1);
realtype yd2 = Ith(ydot, 2);
realtype yd3 = Ith(ydot, 3);
yd1 = -k1 * y1 + k2 * y2 * y3;
yd3 = k3 * y2 * y2;
yd2 = -y1 - y3;
return(0);
}
但是,编译此函数需要cvode.h
和nvector_serial.h
头文件,因此需要安装SUNDIALS。
但是,我希望用户能够仅使用Rcpp
来定义ODE,即
#include <Rcpp.h>
using namespace Rcpp;
#define k1 0.04
#define k2 1e04
#define k3 3e07
int test2 (double t, NumericVector y, NumericVector ydot, void *user_data) {
ydot[0] = -k1 * y[0] + k2 * y[1] * y[2];
ydot[2] = k3 * y[1] * y[1];
ydot[1] = -y[0] - y[2];
return(0);
}
然后将从具有签名
的包中作为cvode
(此处为SEXP
参数)提供给ODE_fun
函数
cvode(NumericVector time_vec, NumericVector IC,
SEXP ODE_fun, double reltolerance, NumericVector abstolerance)
目前ODE_fun
是一个带有typedef
typedef int (*funcPtr)(realtype t, N_Vector y, N_Vector ydot, void *user_data);
test1
使用以下代码转换为XPtr
// [[Rcpp::export]]
XPtr<funcPtr> putFunPtrInXPtr() {
XPtr<funcPtr> testptr(new funcPtr(&test), false);
return testptr;
}
可以在包wiki找到运行示例示例的整个过程。
我不确定如何输入test2
(仅使用Rcpp
定义的ODE函数)并将其转换为包中CVODE
解算器所需签名的函数。任何建议或指示,或者如果有更好的方法来达到我的目的,我们将非常欢迎!
谢谢