Labfans是一个针对大学生、工程师和科研工作者的技术社区。 论坛首页 | 联系我们(Contact Us)
MATLAB爱好者论坛-LabFans.com
返回   MATLAB爱好者论坛-LabFans.com > 工程数学软件 > MATLAB论坛
MATLAB论坛 一切MATLAB相关问题在此讨论。
回复
 
主题工具 显示模式
旧 2021-02-02, 17:14   #1
wertshw
初级会员
 
注册日期: 2021-02-02
帖子: 1
声望力: 0
wertshw 正向着好的方向发展
帖子 matlab 新方法数值求解非光滑ode时遇到的问题

大家好!我在用一种新的数值求解方法求解非光滑ode,这种方法叫QSS(量化状态系统),原先的程序可以求解,可是为了以后方便,我把这个程序矢量化实现,需要像在用ODE45时一样定义包含ode的自定义函数,因为是非光滑ode,需要用到if else来判断条件,可是矢量化后的程序中,if else 语句似乎没有激活,结果中变量x(1)和x(2)应该在19.5和20.5之间来回波动,可是在这里却是在很小的范围内波动,这会不会是因为if else 语句定义在了自定义函数中了,求求各位老师能够帮我看一下问题出在了哪里,我将不胜感激!
第一个程序是原先没有矢量化的程序,复制、粘贴、运行可以得到正确的结果;
第二个程序是矢量化的程序,得到的结果可以和第一个程序对比一下,就会发现它的结果波动很小。
第一个程序:
代码:
clc
clear
tic
%为各变量赋初值
delta_q=1e-4;
q1=21;q2=25;q3=17;
x1=q1;x2=q2;x3=q3;
t=0;delta_t=0;
A=zeros(105609,6);
n=0;
C1=550;C2=600;Cw=580;R1=1.8;R2=2.2;R1w=2;R2w=2;Ta=32;p1=6;p2=6;m1=1;m2=1;T_ref=20;pi=3.1415926;
%开始while循环
while (t<3600*12)
    if(x1>T_ref+0.5)
        m1=1;
    elseif(x1<T_ref-0.5)
        m1=0;
    end
    if(x2>T_ref+0.5)
        m2=1;
    elseif(x2<T_ref-0.5)
        m2=0;
    end
     Ta=10*sin(pi*3.4722e-05*t-pi/2)+20;
     TTa=pi*3.4722e-05*10*cos(pi*3.4722e-05*t-pi/2);
    TTTa=-(pi*3.4722e-05)^2*10*sin(pi*3.4722e-05*t-pi/2);
    Dx1=((Ta-q1)/R1+(q3-q1)/R1w-m1*p1)/C1;  
    Dx2=((Ta-q2)/R2+(q3-q2)/R2w-m2*p2)/C2; 
    Dx3=((q1-q3)/R1w+(q2-q3)/R2w)/Cw;
    DDx1=((TTa-Dx1)/R1+(Dx3-Dx1)/R1w)/C1;
    DDx2=((TTa-Dx2)/R2+(Dx3-Dx2)/R2w)/C2;
    DDx3=((Dx1-Dx3)/R1w+(Dx2-Dx3)/R2w);
   %求Δt1和Δt2的值
       delta_t1=sqrt(2*delta_q/abs(DDx1));
       delta_t2=sqrt(2*delta_q/abs(DDx2));
       delta_t3=sqrt(2*delta_q/abs(DDx3));
       
     delta_tmin=min([delta_t1 delta_t2 delta_t3]);


   %比较Δt1和Δt2的大小,进而确定q1和q2谁先跃迁
   if (delta_t1==delta_tmin)
       delta_t=delta_t1;
       t=t+delta_t;
       x1=x1+Dx1*delta_t+0.5*DDx1*delta_t^2;
       x2=x2+Dx2*delta_t+0.5*DDx2*delta_t^2;
       x3=x3+Dx3*delta_t+0.5*DDx3*delta_t^2;
       q1=x1;
       q2=q2+Dx2*delta_t;
       q3=q3+Dx3*delta_t;
   elseif (delta_t2==delta_tmin)
       delta_t=delta_t2;
       t=t+delta_t;
       x1=x1+Dx1*delta_t+0.5*DDx1*delta_t^2;
       x2=x2+Dx2*delta_t+0.5*DDx2*delta_t^2;
       x3=x3+Dx3*delta_t+0.5*DDx3*delta_t^2;
       q2=x2;
       q1=q1+Dx1*delta_t;
       q3=q3+Dx3*delta_t;
   elseif (delta_t3==delta_tmin)
       delta_t=delta_t3;
       t=t+delta_t;
       x1=x1+Dx1*delta_t+0.5*DDx1*delta_t^2;
       x2=x2+Dx2*delta_t+0.5*DDx2*delta_t^2;
       x3=x3+Dx3*delta_t+0.5*DDx3*delta_t^2;
       q3=x3;
       q1=q1+Dx1*delta_t;
       q2=q2+Dx2*delta_t;
   end
   n=n+1;
   A(n,1)=t;
   A(n,2)=x1;
   A(n,3)=x2;
   A(n,4)=x3;
   A(n,5)=m1;
   A(n,6)=m2;
end
tt=0:3600*12;
yy=10*sin(pi*3.4722e-05*tt-pi/2)+20;
figure
  plot(A(:,1),A(:,2),'--','LineWidth',1.25);hold on
  plot(A(:,1),A(:,3),'-.','LineWidth',1.25);
  plot(A(:,1),A(:,4),'-','LineWidth', 1.25);
  plot(tt,yy,'-k');
  xticks(0:3600:13*3600); %这样x轴会每隔10显示一个刻度
  xticklabels({'6','7','8','9','10','11','12','13','14','15','16','17','18'});%为说明效果,省略了部分内容,写代码时应该与xticks对应写够10+1个label
  xlabel('时刻(h)','FontSize',12,'FontWeight','bold','Color','k');
  ylabel('摄氏度(℃)','FontSize',12,'FontWeight','bold','Color','k');
  grid on
   legend('room1','room2','wall','室外温度')
% figure
%    plot(A(:,1),A(:,5));hold on
%    plot(A(:,1),A(:,6));
toc
第二个程序:
代码:
% QSS1矢量化
clc
clear
tic
%为各变量赋初值
delta_q=[1; 1; 1]*1e-4;
q=[21; 25; 17];
x=q;
t=0;
A=zeros(107666,length(q)+1);
delta_x=zeros(length(q),1);
n=0;
%开始while循环
while (t<3600*12)
    
    ff=Dx(t,q);
    aa=ff(1:length(q));
    aaa=ff(length(q)+1:end);
   %求Δt1和Δt2的值
    delta_t=sqrt(2*delta_q./abs(aaa));
   %比较Δt1和Δt2的大小,进而确定q1和q2谁先跃迁
    cc=find(delta_t==min(delta_t));
   %存在多个最小值相等,取第一个最小值
    if length(cc)>1
        cc=cc(1);
    end
    dd=find(delta_t~=min(delta_t));
    t=t+delta_t(cc);
    x=x+aa.*delta_t(cc)+0.5*aaa.*delta_t(cc)^2;
    q(cc)=x(cc);
    q(dd)=q(dd)+aa(dd).*delta_t(cc);
   %赋值 循环
    n=n+1;
    A(n,1)=t;
    A(n,2)=x(1);
    A(n,3)=x(2);
    A(n,4)=x(3);
end
toc

% % 绘图
hold all;
LineWidth=1.25;
tt=0:3600*12;
yy=10*sin(pi*3.4722e-05*tt-pi/2)+20;
plot(A(:,1),A(:,2),'--','LineWidth',LineWidth);
plot(A(:,1),A(:,3),'-.','LineWidth',LineWidth);
plot(A(:,1),A(:,4),'-','LineWidth', LineWidth);
plot(tt,yy,'-k');
xticks(0:3600:13*3600); %这样x轴会每隔10显示一个刻度
xticklabels({'6','7','8','9','10','11','12','13','14','15','16','17','18'});%为说明效果,省略了部分内容,写代码时应该与xticks对应写够10+1个label
  xlabel('时刻(h)','FontSize',12,'FontWeight','bold','Color','k');
  ylabel('摄氏度(℃)','FontSize',12,'FontWeight','bold','Color','k');
grid on; grid minor;
% title({'QSS量子=',string(delta_q(1)) });
% legend
% legend('QSS求解');
%比较误差

function f=Dx(t,x)
    C1=550;C2=600;Cw=580;R1=1.8;R2=2.2;R1w=2;R2w=2;
    p1=6;p2=6;m1=1;m2=1;T_ref=20;pi=3.1415926;
    if(x(1)>T_ref+0.5)
        m1=1;
    elseif(x(1)<T_ref-0.5)
        m1=0;
    end
    if(x(2)>T_ref+0.5)
        m2=1;
    elseif(x(2)<T_ref-0.5)
        m2=0;
    end
     Ta=10*sin(pi*3.4722e-05*t-pi/2)+20;
     TTa=pi*3.4722e-05*10*cos(pi*3.4722e-05*t-pi/2);
    f=zeros(6,1);
    f(1)=((Ta-x(1))/R1+(x(3)-x(1))/R1w-m1*p1)/C1;
    f(2)=((Ta-x(2))/R2+(x(3)-x(2))/R2w-m2*p2)/C2; 
    f(3)=((x(1)-x(3))/R1w+(x(2)-x(3))/R2w)/Cw;
    f(4)=((TTa-f(1))/R1+(f(3)-f(1))/R1w)/C1;
    f(5)=((TTa-f(2))/R2+(f(3)-f(2))/R2w)/C2;
    f(6)=((f(1)-f(3))/R1w+(f(2)-f(3))/R2w);
end
wertshw 当前离线   回复时引用此帖
回复


发帖规则
不可以发表新主题
不可以发表回复
不可以上传附件
不可以编辑自己的帖子

启用 BB 代码
论坛启用 表情符号
论坛启用 [IMG] 代码
论坛禁用 HTML 代码



所有时间均为北京时间。现在的时间是 10:06


Powered by vBulletin
版权所有 ©2000 - 2025,Jelsoft Enterprises Ltd.