使用Runga - Kutta方法在MATLAB中求解ODE

时间:2017-04-28 04:28:12

标签: matlab

我需要在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解决方案代码是否错误?它应该比欧拉解更快地收敛吗?

抱歉格式不佳。

1 个答案:

答案 0 :(得分:1)

Runge-Kutta整合不正确。

了解独立依赖(也称为 state 和其他许多名称)变量之间的区别至关重要。时间是这个问题的自变量。给定时间,您可以提供高度和速度;相反的情况并非如此。当您阅读Runge-Kutta公式时,例如the one provided by Wikipediat是自变量,y向量的因变量。此外,当执行方程组的时间积分时(这里我们有一个两个方程的系统),如果你要执行行为元素,跟踪哪个右侧属于哪个方程是非常重要的,为简单起见,我会这样做。

所有这一切,当前RK积分器的问题是双重的

  • v正在被视为t;这是不正确的。 vy的步骤相似。
  • y应与r个变量同步,因为r变量来自y的右侧等式z。同样,vk变量同步。

因此,积分器的更新核心是:

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

请注意vy如何以类似的方式更新,因此需要彼此锁定更新。这种形式的积分器将提供比欧拉更好的性能。

最后,如果您对未知的解决方案有疑问,请务必记住您可以使用MATLAB ODE套件,并快速调用经过广泛审查且非常强大的ode45可以解除很多顾虑。我实际上用过这个电话

[t45,w45] = ode45(@(t,w) [z(w(2));q(w(2),w(1))],linspace(0,T,200).',[0;0]);

检查我的工作。