我试图在Matlab中求解二阶微分方程。我能够使用前向欧拉方法做到这一点,但由于这需要相当短的时间步骤来获得准确的结果,我已经研究了其他一些选项。更具体地说,改进的欧拉方法(Heun'方法)。
我理解改进欧拉方法的原理,它首先估计速度,然后使用该信息将其校正到当前条件。但我不完全确定我所写的内容是否完全正确。
1)你能检查我的代码是否正确使用了改进的Euler方法吗?
2)在我的代码中,end
之前的最后一行,第二个B(ii)
应为B(ii+1)
?
我为这两个选项编写了一个简化代码。这是:
t = 0:0.01:100;
dt = t(2)-t(1); % Time step
%Constants%
M = 20000;
m_a = 10000;
c= 15000;
k_spring = 40000;
B = rand(1,length(t)+1);
%% Forward Euler Method %%
x = zeros(1,length(t)+1); % Pre-allocation
u = zeros(1,length(t)+1); % Pre-allocation
x(1) = 1; % Initial condition
u(1) = 0; % Initial condition
for ii = 1:length(t)
x(ii+1) = x(ii) + dt*u(ii);
u(ii+1) = u(ii) + dt * ((1/(M+m_a)) * -(c+k_spring+B(ii))*x(ii));
end
%% Improved Euler Method %%
x1 = zeros(1,length(t)+1); % Pre-allocation
u1 = zeros(1,length(t)+1); % Pre-allocation
x1(1) = 1; % Initial condition
u1(1) = 0; % Initial condition
for ii = 1:length(t)
x1(ii+1) = x1(ii) + dt*u1(ii);
u1(ii+1) = u1(ii) + dt * ((1/(M+m_a)) * -(c+k_spring+B(ii))*x1(ii)); %Estimate
u1(ii+1) = u1(ii) + (dt/2) * ( ((1/(M+m_a)) * -(c+k_spring+B(ii))*x1(ii)) + ((1/(M+m_a)) * -(c+k_spring+B(ii))*x1(ii+1)) ); %Correction
end
谢谢!
答案 0 :(得分:0)
你应该遵循主要的编程思想,将重复使用的东西制作成额外的程序。假设你这样做了,评估ODE函数的函数叫做odefunc。
function [dotx, dotu] = odefunc(x,u,B)
dotx = u;
dotu =(1/(M+m_a)) * -(c+k_spring+B)*x);
end
然后
for ii = 1:length(t)
%% Predictor
[dotx1,dotu1] = odefunc(x1(ii), u1(ii), B(ii));
%% One corrector step
[dotx2,dotu2] = odefunc(x1(ii)+dotx1*dt, u1(ii)+dotu1*dt, B(ii+1));
x1(ii+1) = x1(ii) + 0.5*(dotx1+dotx2)*dt;
u1(ii+1) = u1(ii) + 0.5*(dotu1+dotu2)*dt;
end