我需要在MATLAB中使用数值方法解决这些特定的ODEs。 ODE基本上模拟质量m的下降,连接到具有弹簧常数k的弹性件。这些ODE的解决方案是在离散位置及时表示身体的位置和速度。
ODE的参数是,
H = 74
D = 31
c = 0.9
m = 80
L = 25
k = 90
g = 9.8
C = c/m
K = k/m
T = 60
n = 10000
我实施了以下两种方法;欧拉和四阶龙格 - Kutta近似区间[0,60]的解。
这是我的 Runge Kutta功能 ,
function [t, y, v, h] = rk4_approx(T, n, g, C, K, L)
%% calculates interval width h for each iteration
h = (T / n);
%% creates time array t
t = 0:h:T;
%% initialises arrays y and v to hold solutions
y = zeros(1,n+1);
v = zeros(1,n+1);
%% functions
z = @(v) v;
q = @(v, y) (g - C*abs(v)*v - max(0, K*(y - L)));
%% initial values
v(1) = 0;
y(1) = 0;
%% performs iterations
for j = 1:n
%% jumper's position at each time-step
r1 = h*z(v(j));
r2 = h*z(v(j) + 0.5*h);
r3 = h*z(v(j) + 0.5*h);
r4 = h*z(v(j) + h);
y(j+1) = y(j) + (1/6)*(r1 + 2*r2 + 2*r3 + r4); %position solution
%% jumper's velocity at each time-step
k1 = h*q(v(j), y(j));
k2 = h*q(v(j) + 0.5*h, y(j) + 0.5*k1);
k3 = h*q(v(j) + 0.5*h, y(j) + 0.5*k2);
k4 = h*q(v(j) + h, y(j) + k3);
v(j+1) = v(j) + (1/6)*(k1 + 2*k2 + 2*k3 + k4); %velocity solution
end
end
这是我的 Euler函数 ,
function [t, y, v, h] = euler_approx(T, n, g, C, K, L)
% calculates interval width h
h = T / n;
% creates time array t
t = 0:h:T;
% initialise solution arrays y and v
y = zeros(1,n+1);
v = zeros(1,n+1);
% perform iterations
for j = 1:n
y(j+1) = y(j) + h*v(j);
v(j+1) = v(j) + h*(g - C*abs(v(j))*v(j) - max(0, K*(y(j) - L)));
end
end
然而,在改变参数' n' (其中n是迭代中'步骤的数量),看起来身体位置的欧拉解决方案收敛到Runge-Kutta解决方案的最大值约为y = 50。由于这个ODE没有一个封闭的解决方案,我没有什么比较我的答案。我怀疑答案是y = 50。
因此,我怀疑我的回答。
我的Runge - Kutta解决方案代码是否错误?它应该比欧拉解更快地收敛吗?
抱歉格式不佳。
答案 0 :(得分:1)
Runge-Kutta整合不正确。
了解独立和依赖(也称为 state 和其他许多名称)变量之间的区别至关重要。时间是这个问题的自变量。给定时间,您可以提供高度和速度;相反的情况并非如此。当您阅读Runge-Kutta公式时,例如the one provided by Wikipedia,t
是自变量,y
是向量的因变量。此外,当执行方程组的时间积分时(这里我们有一个两个方程的系统),如果你要执行行为元素,跟踪哪个右侧属于哪个方程是非常重要的,为简单起见,我会这样做。
所有这一切,当前RK积分器的问题是双重的
v
正在被视为t
;这是不正确的。 v
和y
的步骤相似。y
应与r
个变量同步,因为r
变量来自y
的右侧等式z
。同样,v
与k
变量同步。因此,积分器的更新核心是:
r1 = h*z(v(j));
k1 = h*q(v(j), y(j));
r2 = h*z(v(j) + 0.5*k1);
k2 = h*q(v(j) + 0.5*k1, y(j) + 0.5*r1);
r3 = h*z(v(j) + 0.5*k2);
k3 = h*q(v(j) + 0.5*k2, y(j) + 0.5*r2);
r4 = h*z(v(j) + k3);
k4 = h*q(v(j) + k3, y(j) + r3);
y(j+1) = y(j) + (1/6)*(r1 + 2*r2 + 2*r3 + r4); %position solution
v(j+1) = v(j) + (1/6)*(k1 + 2*k2 + 2*k3 + k4); %velocity solution
请注意v
和y
如何以类似的方式更新,因此需要彼此锁定更新。这种形式的积分器将提供比欧拉更好的性能。
最后,如果您对未知的解决方案有疑问,请务必记住您可以使用MATLAB ODE套件,并快速调用经过广泛审查且非常强大的ode45
可以解除很多顾虑。我实际上用过这个电话
[t45,w45] = ode45(@(t,w) [z(w(2));q(w(2),w(1))],linspace(0,T,200).',[0;0]);
检查我的工作。