我正在尝试在MATLAB中实现Runge-Kutta Method for Systems of DEs。我没有得到correct answers,我不确定代码或我用来运行它的命令是否有问题。
这是我的代码:
function RKSystems(a, b, m, N, alpha, f)
h = (b - a)/N;
t = a;
w = zeros(1, m);
for j = 1:m
w(j) = alpha(j);
end
fprintf('t = %.2f;', t);
for i = 1:m
fprintf(' w(%d) = %.10f;', i, w(i));
end
fprintf('\n');
k = zeros(4, m);
for i = 1:N
for j = 1:m
k(1, j) = h*f{j}(t, w);
end
for j = 1:m
k(2, j) = h*f{j}(t + h/2, w + (1/2)*k(1));
end
for j = 1:m
k(3, j) = h*f{j}(t + h/2, w + (1/2)*k(2));
end
for j = 1:m
k(4, j) = h*f{j}(t + h, w + k(3));
end
for j = 1:m
w(j) = w(j) + (k(1, j) + 2*k(2, j) + 2*k(3, j) + k(4, j))/6;
end
t = a + i*h;
fprintf('t = %.2f;', t);
for k = 1:m
fprintf(' w(%d) = %.10f;', k, w(k));
end
fprintf('\n');
end
end
我正试图在this problem上测试一下。 这是我的命令和输出:
>> U1 = @(t,u)3 * u(1)+ 2 * u(2) - (2 * t ^ 2 + 1)* exp(2 * t);
>> U2 = @(t,u)4 * u(1)+ u(2)+(t ^ 2 + 2 * t - 4)* exp(2 * t);
>> a = 0; b = 1; alpha = [1 1]; m = 2; h = 0.2; N =(b - a)/ h;
>> RKSystems(a,b,m,N,alpha,{U1 U2});
t = 0.00; w(1)= 1.0000000000; w(2)= 1.0000000000;
t = 0.20; w(1)= 2.2930309680; w(2)= 1.6186020410;
t = 0.40; w(1)= 5.0379629523; w(2)= 3.7300162165;
t = 0.60; w(1)= 11.4076339762; w(2)= 9.7009491301;
t = 0.80; w(1)= 27.0898576892; w(2)= 25.6603894354;
t = 1.00; w(1)= 67.1832886708; w(2)= 67.6103125539;
答案 0 :(得分:2)
所以...这就是我将如何做到这一点,我很难阅读你的代码片段中发生的事情,但我希望这可以帮助你。另外,matlab内置了rk求解器,我建议熟悉它们。
%rk4 solver
dt = .2;
t = 0:dt:1;
u = zeros(2,numel(t));
u(:,1) = 1;
for jj = 2:numel(t)
u_ = u(:,jj-1);
t_ = t(jj-1);
fa = rhs(u_,t_);
fb = rhs(u_+dt/2.*fa,t_+dt/2);
fc = rhs(u_+dt/2.*fb,t_+dt/2);
fd = rhs(u_+dt.*fc,t_+dt);
u(:,jj) = u(:,jj-1) + dt/6*(fa+2*fb+2*fc+fd);
end
disp([t;u]')
和rhs.m如下:
function dudt = rhs(u,t)
dudt = [(3*u(1) + 2*u(2) - (2*t^2 + 1)*exp(2*t));
(4*u(1) + u(2) + (t^2 + 2*t - 4)*exp(2*t))];
返回以下内容:
>> rkorder4
0 1.0000 1.0000
0.2000 2.1204 1.5070
0.4000 4.4412 3.2422
0.6000 9.7391 8.1634
0.8000 22.6766 21.3435
1.0000 55.6612 56.0305
或者,您可以使用以下内容调用ode45:
dt = .2;
t = 0:dt:1;
rhs=@(t,u)[(3*u(1) + 2*u(2) - (2*t^2 + 1)*exp(2*t));
(4*u(1) + u(2) + (t^2 + 2*t - 4)*exp(2*t))];
[ts,us]=ode45(@(t,u) rhs(t,u),t,[1 1],[]);
disp([ts us]);
这给了你:
0 1.000000000000000 1.000000000000000
0.200000000000000 2.125018862140859 1.511597928697035
0.400000000000000 4.465156492097592 3.266022178547346
0.600000000000000 9.832481410895053 8.256418221678395
0.800000000000000 23.003033457636558 21.669270713784108
1.000000000000000 56.738351357036301 57.106230777717208
这与我从代码中获得的内容非常接近。通过减少时间步长dt
可以增加两者之间的协议。它们在t的低值时总是最大的一致,两者之间的差异随着t的增加而增加。这两种实现方式也与分析解决方案非常接近。
答案 1 :(得分:1)
我的问题出在以下几行代码中:
k(2, j) = h*f{j}(t + h/2, w + (1/2)*k(1));
k(3, j) = h*f{j}(t + h/2, w + (1/2)*k(2));
k(4, j) = h*f{j}(t + h, w + k(3));
我希望k(1)
将整个k
的第一行(4 x m矩阵)添加到矩阵w
(1 x m矩阵),但它只是添加第一行的第一个元素。为了解决这个问题,我按如下方式修改了这些行:
k(2, j) = h*f{j}(t + h/2, w + (1/2)*k(1, :));
k(3, j) = h*f{j}(t + h/2, w + (1/2)*k(2, :));
k(4, j) = h*f{j}(t + h, w + k(3, :));