我最近对我的一些代码有这个问题。“最简单”的解决方案是执行以下操作,首先,一旦解决方案达到 0,您必须将其保持在 0,从而更改
dx = 1/(1+y*z) - x;
to(注意x == 0
评估案例的位置)
if x > 0
dx = 1/(1+y*z) - x;
else % if x <= 0
dx = 0;
end
或者可能(取决于为什么它可能永远不会是 0)
dxTmp = 1/(1+y*z) - x;
if x > 0
dx = dxTmp;
elseif dxTmp > 0
% x becomes positive again
dx = dxTmp;
else
dx = 0;
end
但是请注意,这会在一阶导数中产生跳跃不连续性,当 DDE 求解器到达该点t - delay
附近的点时,它不会非常有效地求解它,除非它知道该不连续性的确切位置(通常您使用告诉 Matlab 它在哪里的额外选项,但如果您按照以下步骤操作,则不需要)。
要确定这种不连续性的位置,您需要使用事件的 DDE 选项(向下滚动到“事件位置属性”,您还可以查看这些示例,其中一个示例实际上处理的是不允许负值的类似系统在 ODE 中 - ODE 和 DDE 的事件几乎相同)。基本上,事件是具有向量输出的 Matlab 函数,向量的每个条目都是对变量的某种或其他评估;在每一步,Matlab 检查其中一个是否等于 0,当其中一个等于 0 时,DDE 停止并返回一个直到该点的解决方案,您必须从该部分解决方案作为您的历史记录重新启动 DDE,即,而不是运行
sol = dde23(ddefun, lags, history, [t0 tEnd], options);
你跑(注意sol
并t0
改变)
sol = dde23(ddefun, lags, sol, [tCurrent tEnd], options);
在这种情况下,向量的条目之一将是(因为您希望 DDE 在等于 0x
时停止)。x
代码行还elseif dxTmp <= 0
创建了另一个不连续性,因此您需要一个何时dxTmp
变为 0 的事件,1/(1+y*z) - x
即将是向量输出的另一个组成部分。
现在,当您重新启动 ODE 时,Matlab 会自动假定此时存在不连续性,因此您不必担心告诉 Matlab 那里存在不连续性。
下一个问题是,Matlab 从未完全正确地实现它x
,y
、z
和的值X
将略微为负。因此,如果它会产生问题,您将需要更正 的值x
(以及类似的其他值)
if x < 0
x = 0;
end
在计算导数之前。但这只会改变x
本地的值。因此,您可能还希望将最终x
解决方案中的所有负值更改为 0。我建议您在输入之前不要尝试更改,因为我对此进行了多次尝试,但无法使其正常工作。sol
sol = dde23(ddefun, lags, sol, [tCurrent tEnd], options);