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应该有一个合适的列表