Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/matlab/13.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Matlab:可变步长ODE解算器中的if语句和abs()函数_Matlab_If Statement_Ode_Absolute Value - Fatal编程技术网

Matlab:可变步长ODE解算器中的if语句和abs()函数

Matlab:可变步长ODE解算器中的if语句和abs()函数,matlab,if-statement,ode,absolute-value,Matlab,If Statement,Ode,Absolute Value,我在线阅读了这篇文章,其中有人提到使用“if语句”和“abs()”函数可能会对MATLAB的变步长ODE解算器(如ODE45)产生负面影响。根据OP,它会显著影响时间步长(要求时间步长太低),并在微分方程最终积分时给出较差的结果。我想知道这是不是真的,如果是,为什么。此外,如何在不使用固定步骤解决方案的情况下缓解此问题。关于我的意思,我在下面给出了一个示例代码: function [Z,Y] = sauters(We,Re,rhos,nu_G,Uinj,Dinj,theta,ts,SMDs0,U

我在线阅读了这篇文章,其中有人提到使用“if语句”和“abs()”函数可能会对MATLAB的变步长ODE解算器(如ODE45)产生负面影响。根据OP,它会显著影响时间步长(要求时间步长太低),并在微分方程最终积分时给出较差的结果。我想知道这是不是真的,如果是,为什么。此外,如何在不使用固定步骤解决方案的情况下缓解此问题。关于我的意思,我在下面给出了一个示例代码:

function [Z,Y] = sauters(We,Re,rhos,nu_G,Uinj,Dinj,theta,ts,SMDs0,Uzs0,...
Uts0,Vzs0,zspan,K)

Y0 = [SMDs0;Uzs0;Uts0;Vzs0]; %Initial Conditions
options = odeset('RelTol',1e-7,'AbsTol',1e-7); %Tolerance Levels
[Z,Y] = ode45(@func,zspan,Y0,options);

function DY = func(z,y)

    DY = zeros(4,1);

    %Calculate Local Droplet Reynolds Numbers
    Rez = y(1)*abs(y(2)-y(4))*Dinj*Uinj/nu_G;
    Ret = y(1)*abs(y(3))*Dinj*Uinj/nu_G;

    %Calculate Droplet Drag Coefficient
    Cdz = dragcof(Rez);
    Cdt = dragcof(Ret);

    %Calculate Total Relative Velocity and Droplet Reynolds Number
    Utot = sqrt((y(2)-y(4))^2 + y(3)^2);
    Red = y(1)*abs(Utot)*Dinj*Uinj/nu_G;

    %Calculate Derivatives
    %SMD
    if(Red > 1)
        DY(1) = -(We/8)*rhos*y(1)*(Utot*Utot/y(2))*(Cdz*(y(2)-y(4)) + ...
            Cdt*y(3)) + (We/6)*y(1)*y(1)*(y(2)*DY(2) + y(3)*DY(3)) + ...
            (We/Re)*K*(Red^0.5)*Utot*Utot/y(2);
    elseif(Red < 1)
        DY(1) = -(We/8)*rhos*y(1)*(Utot*Utot/y(2))*(Cdz*(y(2)-y(4)) + ...
        Cdt*y(3)) + (We/6)*y(1)*y(1)*(y(2)*DY(2) + y(3)*DY(3)) + ...
        (We/Re)*K*(Red)*Utot*Utot/y(2);
    end
    %Axial Droplet Velocity
    DY(2) = -(3/4)*rhos*(Cdz/y(1))*Utot*(1 - y(4)/y(2));
    %Tangential Droplet Velocity
    DY(3) = -(3/4)*rhos*(Cdt/y(1))*Utot*(y(3)/y(2));
    %Axial Gas Velocity
    DY(4) = (3/8)*((ts - ts^2)/(z^2))*(cos(theta)/(tan(theta)^2))*...
        (Cdz/y(1))*(Utot/y(4))*(1 - y(4)/y(2)) - y(4)/z;

end

end
function[Z,Y]=sauters(We,Re,rhos,nu_G,Uinj,Dinj,theta,ts,SMDs0,Uzs0,。。。
Uts0、Vzs0、zspan、K)
Y0=[SMDs0;Uzs0;Uts0;Vzs0];%初始条件
选项=odeset('RelTol',1e-7,'ABSTROL',1e-7);%容忍水平
[Z,Y]=ode45(@func,zspan,Y0,options);
函数DY=func(z,y)
DY=零(4,1);
%计算局部液滴雷诺数
Rez=y(1)*abs(y(2)-y(4))*Dinj*Uinj/nu\G;
Ret=y(1)*abs(y(3))*Dinj*Uinj/nu\G;
%计算液滴阻力系数
Cdz=牵引力(Rez);
Cdt=牵引力(Ret);
%计算总相对速度和液滴雷诺数
Utot=sqrt((y(2)-y(4))^2+y(3)^2);
红色=y(1)*abs(自动变速箱)*Dinj*Uinj/nu\G;
%计算导数
%贴片
如果(红色>1)
DY(1)=-(We/8)*rhos*y(1)*(Utot*Utot/y(2))*(Cdz*(y(2)-y(4))+。。。
Cdt*y(3))+(We/6)*y(1)*y(1)*(y(2)*DY(2)+y(3)*DY(3))+。。。
(We/Re)*K*(红色^0.5)*Utot*Utot/y(2);
elseif(红色<1)
DY(1)=-(We/8)*rhos*y(1)*(Utot*Utot/y(2))*(Cdz*(y(2)-y(4))+。。。
Cdt*y(3))+(We/6)*y(1)*y(1)*(y(2)*DY(2)+y(3)*DY(3))+。。。
(We/Re)*K*(红色)*Utot*Utot/y(2);
结束
%轴向液滴速度
DY(2)=-(3/4)*rhos*(Cdz/y(1))*Utot*(1-y(4)/y(2));
%切向液滴速度
DY(3)=-(3/4)*rhos*(Cdt/y(1))*Utot*(y(3)/y(2));
%轴向气速
DY(4)=(3/8)*((ts-ts^2)/(z^2))*(cos(θ)/(tan(θ)^2))*。。。
(Cdz/y(1))*(Utot/y(4))*(1-y(4)/y(2))-y(4)/z;
结束
结束
其中,函数“dragcof”由以下公式给出:

function Cd = dragcof(Re)    
if(Re <= 0.01)

    Cd = (0.1875) + (24.0/Re);

elseif(Re > 0.01 && Re <= 260.0)

    Cd = (24.0/Re)*(1.0 + 0.1315*Re^(0.32 - 0.05*log10(Re)));

else

    Cd = (24.0/Re)*(1.0 + 0.1935*Re^0.6305);
end
end
函数Cd=dragcof(Re)

如果(Re 0.01&&Re是,则为真,这是因为您的解决方案在某些点上不够平滑

假设你想积分。
y'(t)=f(t,y)
。然后,在
f
中发生的事情会被积分成
y
。因此,如果在
f
的定义中

  • abs()
  • 如果
    ,那么
    f
    有一个跳跃,而
    y
    有一个扭结,没有更多的可微性
Matlab的ODE45假定您的解是5次可微的,并试图确保4阶精度。函数的非光滑点被误解为刚度,从而导致步长变小,甚至出现故障


你能做的:由于缺乏平滑度,你无论如何都不能期望高精度。因此,ODE23可能是一个更好的选择。在最坏的情况下,你必须坚持一阶格式。

这是因为使用
if
-语句、模运算(
abs()
)计算的导数,或单位阶跃函数、dirac delta等会在解或其导数的值中引入不连续性,从而导致扭结、跳跃、拐点等

这意味着ODE的解决方案在相关时间的行为发生了完全的变化

  • 检测这个
  • 认识到他们将无法直接使用“问题点”以外的信息
  • 减少步骤,从顶部重复,直到问题点满足精度要求
因此,在问题点附近将有许多失败的步骤和步骤大小的减少,对总体集成时间产生负面影响

然而,可变步长积分器将继续产生良好的结果。恒定步长积分器不是解决这类问题的好方法,因为它们首先无法检测此类问题(没有误差估计)

你所能做的只是将问题分成多个部分。如果你事先知道变化将在什么时间点发生,你只需为每个时间间隔启动一个新的积分,每次都使用上一次积分的输出作为下一次积分的初始值

如果您事先不知道问题将出现在哪里,您可以在Matlab的ODE解算器中使用这一非常好的功能,称为事件函数(请参阅)。您可以让Matlab的一个解算器检测事件(导数中的符号变化,If
-语句中的条件变化,或其他任何情况),并在检测到此类事件时终止集成。然后开始新的集成,从上一次开始,使用上一次集成的初始条件,如前所述,直到达到最终时间


这样,总体执行时间仍然会有轻微的损失,因为Matlab将尝试准确地检测事件的位置。但是,在执行时间和结果的准确性方面,它仍然比盲目地运行积分要好得多。

我不确定您的答案是否回答了我的问题。这是为什么特别是与可变时间步长解算器有关,而不是固定时间步长?此外,仅仅因为有if语句,并不意味着解决方案中存在跳跃。只要“if语句”下的变量在if语句之间具有收敛限制,解决方案中就不应存在跳跃。对于“abs()”也是如此。是步长控制减小了步长。使用固定时间步长解算器,您只需运行这些非光滑点。但您观察到的是顺序的分解