让我们首先复制原版解决方案
% z = [x,y]
f = @(t,z) [ z(1).^2+t; z(1).*z(2)-2 ];
z0 = [ 2; 1];
[ T, Z ] = ode45(f, [0, 10], z0);
plot(T,Z); legend(["x";"y"]);
集成器失败并显示警告
警告:求解不成功。在到达tend = 10.000000 的端点之前,迭代集成循环在时间t = 0.494898 退出。如果步长变得太小,可能会发生这种情况。尝试使用命令'odeset' 减小'InitialStep' 和/或'MaxStep' 的值。
在关键时间前不久重复集成
opt = odeset('MaxStep',0.01);
[ T, Z ] = ode45(f, [0, 0.49], z0, opt);
clf; plot(T,Z); legend(["x";"y"]);
图表中的结果
我们可以看到,第一个方程中的二次项会导致增长失控。由于某种原因,求解器只识别不断减小的步长,而不识别解的失控值。
确实,第一个是 Riccati 方程,已知它在有限时间具有极点。使用典型的参数化x(t)=-u'(t)/u(t) 具有乘积/商规则的导数
x' = -u''(t)/u(t) - u'(t)* (-u'(t)/u(t)^2) = -u''(t)/u(t) + x(t)^2
然后导致 u 的 ODE
u''(t)+t*u(t)=0, u(0)=-1, u'(0)=x(0)=2,
这是一个艾里方程,带有t>0 的振荡分支。 u 的第一个根是x 的极点,没有办法将解扩展到这一点之外。
g=@(t,u) [u(2); -t.*u(1)]
u0 = [ 1; -2];
function [val,term, dir] = event(t,u)
val = u(1);
term = 0;
dir = 0;
end
opt = odeset('MaxStep',0.1, 'Events', @(t,u) event(t,u));
[T,U,Te,Ue,Ie] = ode45(g,[0,4],u0,opt);
disp(Te)
clf; plot(T,U); legend(["u";"u'"]);
将u 的零列为0.4949319379979706, 2.886092605590324,再次确认警告的原因,并给出情节