这是一种常见的问题。用户经常希望不连续地更改 Matlab 的 ODE 求解器使用的积分函数中的变量。不幸的是,这通常是个坏主意。这些求解器假设微分方程是平滑且连续的。充其量你的代码会更慢。在最坏的情况下,你会有更大的错误甚至完全错误的结果。使用诸如此类的刚性求解器ode15s
可能会有所帮助,但它也假定了连续性。由于您指定的系统具有解析解决方案,因此“模拟”它的最简单方法实际上可能是通过这个时间函数传递脉冲序列。
参数随时间不连续变化的情况,即相对于自变量,很容易解决。只需在每个时间跨度上整合您想要的周期数:
t1 = 600;
t2 = 120;
TSpan = [0 t1]; % Initial time vector
NPeriods = 5; % Number of periods
C0 = 400; % Initial condition
Q1 = ...
Q2 = ...
V = 100;
C_i = 400;
S = 100;
u_vent = @(t,C,Q)(Q*(C_i-C(1))+S)/V; % Integration function as anonymous function
Cout = C0; % Array to store solution states
tout = Tspan(1); % Array to store solution times
for i = 1:NPeriods
[t,C] = ode45(@(t,C)u_vent(t,C,Q1), TSpan, C0);
tout = [tout;t(2:end)]; % Append time, 2:end used to avoid avoid duplicates
Cout = [Cout;C(2:end,:)]; % Append state
TSpan = [0 t2]+t(end); % New time vector
C0 = C(end); % New initial conditions
[t,C] = ode45(@(t,C)u_vent(t,C,Q2), TSpan, C0);
tout = [tout;t(2:end)];
Cout = [Cout;C(2:end,:)];
TSpan = [0 t1]+t(end);
C0 = C(end);
end
这允许ode45
从一组初始条件对指定时间的 ODE 进行积分。然后在上一次积分结束时重新开始积分,新的不连续初始条件或不同的参数。这导致瞬态。您可能不喜欢代码的外观,但这就是它的完成方式。如果参数相对于状态变量不连续地变化,那就更棘手了。
可选的。每次调用/重新启动ode45
该函数时,都必须确定要使用的初始步长。这是重新启动求解器的主要(最小)成本/开销。在某些情况下,您可以通过'InitialStep'
根据上一次调用中使用的最后一步大小指定一个选项来帮助求解器。通过在命令窗口中键入来查看ballode
演示以获取更多详细信息。edit ballode
一张纸条。和数组在每个集成步骤之后附加到自身tout
。Cout
这实际上是动态内存分配。只要NPeriods
相当小,这可能不会成为问题,因为最近版本的 Matlab 中的动态内存分配可能非常快,并且您只需在大块中重新分配几次。如果您指定固定步长输出(例如TSpan = 0:1e-2:600;
),那么您将确切知道要预分配多少内存到tout
和Cout
。