【发布时间】:2013-05-12 20:11:09
【问题描述】:
我试图用倍频程求解一个微分方程,但我选择的微分单位需要很长时间,所以我决定用 C 对其进行编码。算法如下:
#include <stdio.h>
double J = 5.78e-5; // (N.m)/(rad/s^2)
double bo = 6.75e-4; // (N.m)/(rad/s)
double ko = 5.95e-4; // (N.m)/rad
double Ka = 1.45e-3; // (N.m)/A
double Kb = 1.69e-3; // V/(rad/s)
double L = 0.311e-3; // mH
double R = 150; // ohms
double E = 5; // V
// Simulacion
int tf = 2;
double h = 1e-6;
double dzdt, dwdt, didt;
void solver(double t, double z, double w, double i) {
printf("%f %f %f\n", z, w, i);
if (t >= tf) {
printf("Finished!\n");
return; // End simulation
}
else {
dzdt = w;
dwdt = 1/J*( Ka*i - ko*z - bo*w );
didt = 1/L*( E - R*i - Kb*w );
// Solve next step with newly calculated "initial conditions"
solver(t+h, z+h*dzdt, w+h*dwdt, i+h*didt);
}
}
int main() {
solver(0, 0, 0, 0);
// Solve data
// Write data to file
return 0;
}
定义为h(如您所见)的微分单位必须那么小,否则值会失控并且解决方案将不正确。现在,h 的数值更大,程序从头到尾都没有错误(nan 值除外),但是我选择了h,我得到了分段错误;是什么原因造成的?
替代 Octave 解决方案
在我的一个朋友告诉我他能够使用 MATLAB 使用 1e-3 的微分步长求解方程后,我发现 MATLAB 有一个“僵硬”版本的 ode23 模块——“僵硬”对于求解那些需要极小步长的微分方程有特殊意义。后来我在 Octave 中搜索了“僵硬”的 ODE 求解器,发现 lsode 属于该类别。在第一次尝试中,lsode 在微秒内解决了方程(都比 MATLAB 和我的 C 实现快),并且得到了完美的解决方案。 FOSS 万岁!
【问题讨论】:
标签: c math segmentation-fault numerical-methods differential-equations