C++ 直观GSL僵硬江户

C++ 直观GSL僵硬江户,c++,c,ode,differential-equations,gsl,C++,C,Ode,Differential Equations,Gsl,我需要解决一个行为僵硬的颂歌。说颂歌将由 int odefunc (double x, const double y[], double f[], void *params) { double k=1e12; //At k=1e7 it works (doesn't show stiffness) double y_eq=-1.931+1.5*log(x)-x; f[0] = k*(exp(2*y_eq-y[0])-exp(y[0])); return GS

我需要解决一个行为僵硬的颂歌。说颂歌将由

int odefunc (double x, const double y[], double f[], void *params)
{
    double k=1e12; //At k=1e7 it works (doesn't show stiffness)
    double y_eq=-1.931+1.5*log(x)-x;
    f[0] = k*(exp(2*y_eq-y[0])-exp(y[0]));   
    return GSL_SUCCESS;
}
我不太习惯C(虽然我是C++),文档中没有很多注释让我理解它。我曾经理解过它(也是因为我只有一首颂歌,没有一个体系),在某种程度上它是有用的,但对我来说仍然有点困惑。在我的测试中,我使用了我的函数而不是给定的函数,虽然我不理解代码,但我还是使用了它。但现在这是我理解的关键,因为


我需要修改他们给我的例子,我需要使用一种求解刚性方程的算法,最好是
gsl\u odeiv2\u step\u msbdf
,具有自适应步长或类似的步长(BDF方法似乎在学术界大量使用)。这需要雅可比矩阵,如果您不习惯GSL或C,这一部分就非常复杂。

要手动实现算法微分,需要包含明确的中间步骤

int odefunc (double x, const double y[], double f[], void *params)
{
    double k=1e12; //At k=1e7 it works (doesn't show stiffness)
    double y_eq=-1.931+1.5*log(x)-x;
    double v1 = exp(2*y_eq-y[0]);
    double v2 = exp(y[0]);
    double z = k*(v1-v2);   
    f[0] = z;
    return GSL_SUCCESS;
}
然后,您可以使用其导数传播增强每个步骤

int jac (double x, const double y[], double *dfdy,
     double dfdx[], void *params)
{
    double k=1e12; //At k=1e7 it works (doesn't show stiffness)
    // Dx_dx=Dy_dy=1, Dx_dy=Dy_dx=0 are used without naming them
    double y_eq = -1.931+1.5*log(x)-x, 
          Dy_eq_dx=1.5/x-1, 
          Dy_eq_dy=0;
    double v1 = exp(2*y_eq-y[0]),
          Dv1_dx=v1*(2*Dy_eq_dx-0),
          Dv1_dy=v1*(2*Dy_eq_dy-1);
    double v2 = exp(y[0]), 
          Dv2_dx=v2*(0), 
          Dv2_dy=v2*(1);
    double z = k*(v1-v2), 
          Dz_dx=k*(Dv1_dx-Dv2_dx), 
          Dz_dy=k*(Dv1_dy-Dv2_dy);   
    dfdx[0] = Dz_dx;
    dfdy[0] = Dz_dy;
    return GSL_SUCCESS;
}
对于较大的代码,请使用自动执行这些步骤的代码重写工具。auto-diff.org应该有一个合适的列表