matlab - 不带计数器的自定义周期函数

标签 matlab differential-equations numerical-integration

我正在使用ode45求解一个简单的 ODE:

function dCdt=u_vent(t,C)
if t>   600 &&  t<= 720
    Q=Q2;               
elseif t>   1320    &&  t<= 1440
    Q=Q2;           
elseif t>   2040    &&  t<= 2160
    Q=Q2;           
elseif t>   2760    &&  t<= 2880
    Q=Q2;               
elseif t>   3480    &&  t<= 3600
    Q=Q2;
else
    Q=Q1;
end

V=100;
C_i=400;
S=100;

dCdt=Q/V*C_i+S/V-Q/V*C(1);
return

我用then来解决:

[t,C]=ode45(@u_vent, [0 1*3600], 400);

我想创建一个周期函数,如图中的 Q 所示。 , 0<t<3600 ,不使用那些 if声明...有什么想法吗?

enter image description here

最佳答案

这是一种常见的问题。用户通常希望不连续地更改 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 进行积分。然后,在先前积分结束时,使用新的不连续初始条件或不同参数重新开始积分。这会导致 transient 。您可能不喜欢代码的外观,但这就是它的完成方式。如果参数相对于状态变量不连续地变化,那就更棘手了。

可选。每次调用/重新启动 ode45 时,该函数都必须计算出要使用的初始步长。这是重新启动求解器的主要(最小)成本/开销。在某些情况下,您可以通过指定 'InitialStep' 来帮助求解器。基于上次调用中使用的最后步长的选项。通过在命令窗口中输入 edit ballode 来查看 ballode 演示,了解更多详细信息。

一个注释。 toutCout 数组在每个集成步骤后都会附加到自身。这实际上是动态内存分配。只要 NPeriods 相当小,这可能就不会成为问题,因为最新版本的 Matlab 中的动态内存分配可能非常快,并且您只需在大块中重新分配几次。如果您指定固定步长输出(例如,TSpan = 0:1e-2:600;),那么您将确切知道要预分配给 toutCout.

关于matlab - 不带计数器的自定义周期函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20429065/

相关文章:

c - 在 matlab r2013 中编译 metismex 时出错

python - 使用 Python 的耦合微分方程

python - 如何计算多变量方程的输出

python - 如何将 GEKKO 解决方案转换为浮子

python - 如何改进这种自适应梯形法则?

c++ - CUDA 中的递归返回非法内存访问

c - Piketec TPT java 自动化

matlab - 如何在 MATLAB 的 for 循环中调用函数?

matlab - 调用 fprintf 或 disp 时如何抛出错误?

python - 使用涉及积分的方程提高 scipy.optimize.fsolve 的精度