C 什么是“的等价物?”;MaxSteps";使用GSL';什么是ODE解算器?

C 什么是“的等价物?”;MaxSteps";使用GSL';什么是ODE解算器?,c,wolfram-mathematica,solver,gsl,ode,C,Wolfram Mathematica,Solver,Gsl,Ode,我想用Mathematicawith复制一个ODE解算器 这是使用NDSolve的Mathematica代码: result[r_] := NDSolve[{ s'[t] == theta - (mu*s[t]) - ((betaA1*IA1[t] + betaA2*IA2[t] + betaB1*IB1[t] + betaB2*IB2[t]) + (betaA1T*TA1[t] + betaA2T*TA2[t] + b

我想用
Mathematica
with复制一个ODE解算器

这是使用
NDSolve
的Mathematica代码:

result[r_] := NDSolve[{
    s'[t] == theta - (mu*s[t]) - ((betaA1*IA1[t] + betaA2*IA2[t] + betaB1*IB1[t] + betaB2*IB2[t]) +
                                  (betaA1T*TA1[t] + betaA2T*TA2[t] + betaB1T*TB1[t] + betaB2T*TB2[t])) * s[t] - 
                                 ((gammaA1*IA1[t] + gammaA2*IA2[t] + gammaB1*IB1[t] + gammaB2*IB2[t]) + 
                                  (gammaA1T*TA1[t] + gammaA2T*TA2[t] + gammaB1T*TB1[t] + gammaB2T*TB2[t])),

//... Some other equations



s[0] = sinit,IA1[0] = IA1init,IA2[0] = IA2init,
IB1[0] = IB1init,IB2[0] = IB2init,TA1[0] = TA1init,
TA2[0] = TA2init,TB1[0] = TB1init,TB2[0] = TB2init},
{s,IA1,IA2,IB1,IB2,TA1,TA2,TB1,TB2},{t,0,tmax},
MaxSteps->100000, StartingStepSize->0.1, Method->{"ExplicitRungeKutta"}];
尝试使用GSL获得精确的等效值:

int run_simulation() {
    gsl_odeiv_evolve*  e = gsl_odeiv_evolve_alloc(nbins);
    gsl_odeiv_control* c = gsl_odeiv_control_y_new(1e-17, 0);
    gsl_odeiv_step*    s = gsl_odeiv_step_alloc(gsl_odeiv_step_rkf45, nbins);
    gsl_odeiv_system sys = {function, NULL, nbins, this };
    while (_t < _tmax) {  //convergence check here
        int status = gsl_odeiv_evolve_apply(e, c, s, &sys, &_t, _tmax, &_h, y);
        if (status != GSL_SUCCESS) { return status; }
    }
    return 0;
}
int运行模拟(){
gsl_odeiv_evolve*e=gsl_odeiv_evolve_alloc(nbins);
gsl_odeiv_control*c=gsl_odeiv_control_y_new(1e-17,0);
gsl_odeiv_step*s=gsl_odeiv_step_alloc(gsl_odeiv_step_rkf45,nbins);
gsl_odeiv_system sys={function,NULL,nbins,this};
而(\u t<\u tmax){//在这里检查收敛性
int status=gsl_odeiv_evolution_apply(e、c、s和sys、&u t、&u tmax、&u h、y);
if(status!=GSL_SUCCESS){return status;}
}
返回0;
}
其中,
nbins
是给定给解算器的方程数,
\u h
是当前步长

这里我不提供方程本身,但我发现限制步骤数的唯一方法(如Mathematica下的
MaxSteps->100000
)是调整
gsl\u odeiv\u control\u y_new
control特性的第一个参数。这里
1e-17
给出了大约140000个步骤

有人知道如何强制GSL的ODE解算器使用给定的最大步数吗?正如您可能理解的,对我来说,重要的是要有能够在这两种工具之间进行真正比较的结果


感谢您的帮助。

MaxSteps
在Mathematica中,只有当RK(Runge Kutta)陷入困境,从而无法正确发展您的系统时,才是重要的。它不会固定您想要采取的步骤数或所需的精度。当然,更高的精度要求更小的步长,这意味着在固定的间隔内需要更多的步长。但我的观点是,除非你有一个奇怪的系统,RK被卡住并失败(在本例中,你会清楚地看到Mathematica错误消息),或者你将maxsteps设置得非常小,否则maxsteps不会帮助你正确地比较Mathematica和GSL

为了进行适当的比较,您需要在两个程序中设置相同的精度要求和控制功能。事实上,除了标准选项外,您还可以通过API
GSL\u odeiv2\u control\u alloc
GSL\u odeiv2\u control\u hadjust
函数在GSL中设置任意控制函数。您还必须检查Mathematica代码中使用的确切停止条件

另一种选择是在两个程序中使用非自适应固定步骤RK(在gsl中,您可以通过调用
gsl\u odeiv2\u driver\u apply\u fixed\u step
,调用evolve the system with fix steps)


最后一件事。1e-17似乎是一个疯狂的相对精度要求。请记住,舍入误差通常不允许RK达到这种精度水平。实际上,舍入错误是使RK陷入困境和/或使Mathematica/GSL彼此不一致的原因之一!!!!您应该将精度设置为>1e-10。

非常感谢。在进一步挖掘之后,我得出了你提到的关于
MaxSteps
的相同结论。。。关于你的其他观点,这听起来很有趣,我将尝试这些可能性(我不知道gsl\u odeiv2\u control\u hadust,也不知道我们可以在gsl中使用固定步骤)。谢谢!还有一个问题:你的…\uOdeiv
2
\uOdeiv在哪里。。。功能来自哪里?我没有。我的GSL版本是否有点太旧了?