我正在编写应解微分方程的代码,这已经使用欧拉方法给出了。得到结果后,我将它们绘制在图形上。但是我得到的值不正确。
这样做是为了获得传递函数的反馈响应。我已经尝试以其他方式编写euler方法(结果相同)。我检查了几次我的微分方程是否正确编写。我想知道问题是在这里还是在其他地方。我没想到这段代码有什么问题。
public static double inputSignal(double t, double A, double f, int typeOfSignal) {
switch (typeOfSignal) {
case 1:
return A*cos(2*Math.PI*f*t);
case 2:
return A*(2/Math.PI)*asin(sin(2*Math.PI*f*t));
case 3:
return A*signum(sin(2*Math.PI*f*t));
default:
break;
}
return 0;
}
public static double equation(double x, double xDerivative, double u, double uDerivative, double a0, double a1, double b0, double b1, double b2) {
return (a1*uDerivative + a0*u - (a0+b0)*x - (a1+b1)*xDerivative)/b2;
}
public static void eulerMethod(double h, double A, double f, double a0, double a1, double b0, double b1, double b2, int typeOfSignal) {
double xn = 0, yn = 0, tn = 0, tn1; //x' = y; y' = f(x, y, u)
double uDerivative;
for (int i = 0; i < 10000; i++) {
tn1 = tn + h;
uDerivative= (inputSignal(tn1+h, A, f, typeOfSignal)-inputSignal(tn1, A, f, typeOfSignal))/h;
xn = xn + h*equation(xn, yn, pobudzenie(tn1, A, f, typeOfSignal), uDerivative, a0, a1, b0, b1, b2);
yn = yn + h*xn;
System.out.println("Step" + i);
System.out.println("Y(" + tn1 + ") " + " = " + yn);
tn = tn1;
results[i] = yn;
inputGraph[i] = inputSignal(tn, A, f, typeOfSignal);
}
}
微分方程为:b2*x'' = a1*u' + a0*u - (a0+b0)*x - (a1+b1)*x'
我想为euler2(0.0025, 1, 0.01, 1, 5, 1, 2, 1, 1)
获得的是
this,但是我从代码中得到的是this.
您可以看到我的函数具有不希望出现的波动,并且幅度低于预期(为0.2,应为0.7)。
答案 0 :(得分:0)
您在一阶系统中混入了一些东西。你有
x'' = f(t,x,x',u,u')
并设置y=x'
应该会导致一阶系统
x' = y
y' = f(t,x,y,u,u')
但是,您在计算x
和y
的更新时互换了右边,有效地将方程式更改为x''=f(t,x',x,u,u')
并显示了x'
。
在半显式Euler实现中,正确的方法实现应为
yn = yn + h*equation(xn, yn, inputSignal(tn1, A, f, typeOfSignal), uDerivative, a0, a1, b0, b1, b2);
xn = xn + h*yn;
在严格的显式Euler实现中,您不会在yn
更新中使用新计算的xn
,而是使用旧值。需要涉及一些临时缓存变量。
通过设置
,您将获得更直接的一阶系统y=b2*x'+(a1+b1)*x-a1*u
这样
x' = ( y - (a1+b1)*x+a1*u )/b2;
y' = a0*u-(a0+b0)*x
从一阶系统中删除u
的所有导数。
如果为每个系统生成具有不同步长的图,则视觉收敛表明正确的实现。那么与控制图的任何差异都意味着传递到此处的求解器和控制求解器的ODE中可能存在差异。