将 fsolve 嵌入到 ODE 中,而不是在 Scilab 中使用 DAE 求解器

Embedding an fsolve into an ODE as opposed to using DAE solver in Scilab

我试图在 Scilab 中嵌入一个 Fsolve 来求解这个非线性系统。

我已经解决了 DAE 的问题,所以我知道会发生什么,但我正在努力嵌入 Fsolve。

这是代码的完整副本,包括 DAE。

我不确定在哪里嵌入 fsolve 函数。

//dassl approach
//given data
p=[20.086, 8100, 20.086, 20.086, 4050, 1E-17, 1E-11, 1E-17] //mol/kgh
ynames = ['y1' 'y2' 'y3' 'y4' 'y5' 'y6' 'y7' 'y8' 'y9' 'y10']
y0=[1.5776, 0.32, 0, 0, 0, 0.0131, 4.0E-06, 4.0E-06, 0, 0]'//initial conditions 
t0=0
t=linspace(0,1,1000)

dy0 = [0 0 0 0 0 0 0 0 0 0]'
function [f,r]=BatchRXorDassl(t,y,dy)
    f(1)=-p(3)*y(2)*y(8)-dy(1)
    f(2)=-p(1)*y(2)*y(6)+p(2)*y(10)-p(3)*y(2)*y(8)-dy(2)
    f(3)=p(3)*y(2)*y(8)+p(4)*y(4)*y(6)-p(5)*y(9)-dy(3)
    f(4)=-p(4)*y(4)*y(6)+p(5)*y(9)-dy(4)
    f(5)=p(1)*y(2)*y(6)-p(2)*y(10)-dy(5)
    f(6)=-p(1)*y(2)*y(6)-p(4)*y(4)*y(6)+p(2)*y(10)+p(5)*y(9)-dy(6)
    f(7)=-0.0131+y(6)+y(8)+y(9)+y(10)-y(7)
    f(8)=p(7)*y(1)-y(8)*(p(7)+y(7))
    f(9)=p(8)*y(3)-y(9)*(p(8)+y(7))
    f(10)=p(6)*y(5)-y(10)*(p(6)+y(7))
    r=0
endfunction

y=dassl([y0,dy0],t0,t,BatchRXorDassl)
y=y'
tplot = y(:,1)
yplot = y(:,2:11)

clf(11), scf(11)
plot(tplot,yplot)
xlabel('t (s)')
ylabel('C')
legend(ynames,-4)
xtitle('Batch Reactor Concentration Profiles')

////embedded fsolve approach
////given data
//p=[20.086, 8100, 20.086, 20.086, 4050, 1E-17, 1E-11, 1E-17] //mol/kgh
//ynames = ['y1' 'y2' 'y3' 'y4' 'y5' 'y6' 'y7' 'y8' 'y9' 'y10']
//y0=[1.5776, 0.32, 0, 0, 0, 0.0131, 4.0E-06, 4.0E-06, 0, 0]'//initial conditions 
//t0=0
//t=linspace(0,1,1000)
//function ff=fsolvve(y)
//    y1 = y(1)
//    y2 = y(2)
//    y3 = y(3)
//    y4 = y(4)
//    y5 = y(5)
//    y6 = y(6)
//    y7 = y(7)
//    y8 = y(8)
//    y9 = y(9)
//    y10 = y(10)
//    ff(1) = -0.0131+y(6)+y(8)+y(9)+y(10)-y(7)
//    ff(2) = p(7)*y(1)-y(8)*(p(7)+y(7))
//    ff(3) = p(8)*y(3)-y(9)*(p(8)+y(7))
//    ff(4) = p(6)*y(5)-y(10)*(p(6)+y(7))
//    ff(5) = -p(3)*y(2)*y(8)
//    ff(6) = -p(1)*y(2)*y(6)+p(2)*y(10)-p(3)*y(2)*y(8)
//    ff(7) = p(3)*y(2)*y(8)+p(4)*y(4)*y(6)-p(5)*y(9)
//    ff(8) = -p(4)*y(4)*y(6)+p(5)*y(9)
//    ff(9) = p(1)*y(2)*y(6)-p(2)*y(10)
//    ff(10) = -p(1)*y(2)*y(6)-p(4)*y(4)*y(6)+p(2)*y(10)+p(5)*y(9)
//endfunction
//yfsolve0 = [0 0 0 0 0 0 0 0 0 0]'
//yfsolve = fsolve(yfsolve0,fsolvve)

如果您大大放宽 ode 的默认 RTOL 和 ATOL,则以下代码可以满足您的需求:

p = [20.086, 8100, 20.086, 20.086, 4050, 1E-17, 1E-11, 1E-17] //mol/kgh
ynames = ['y1' 'y2' 'y3' 'y4' 'y5' 'y6' 'y7' 'y8' 'y9' 'y10']
y0 = [1.5776, 0.32, 0, 0, 0, 0.0131, 4.0E-06, 4.0E-06, 0, 0]'//initial condition 
t0 = 0
t = linspace(0,1,1000)

function dy = rhs(t,y1)
    y2 = fsolve([1;1;1;1],list(cstr,y1));
    y = [y1;y2];
    dy = [-p(3)*y(2)*y(8)
           p(1)*y(2)*y(6)+p(2)*y(10)-p(3)*y(2)*y(8)
           p(3)*y(2)*y(8)+p(4)*y(4)*y(6)-p(5)*y(9)
          -p(4)*y(4)*y(6)+p(5)*y(9)
           p(1)*y(2)*y(6)-p(2)*y(10)
          -p(1)*y(2)*y(6)-p(4)*y(4)*y(6)+p(2)*y(10)+p(5)*y(9)];
endfunction

function g = cstr(y2,y1)
    g = [-0.0131+y1(6)+y2(2)+y2(3)+y2(4)-y2(1)
         p(7)*y1(1)-y2(2)*(p(7)+y2(1))
         p(8)*y1(3)-y2(3)*(p(8)+y2(1))
         p(6)*y1(5)-y2(4)*(p(6)+y2(1))];
endfunction

y1 = ode(y0(1:6),t0,t,1e-3,1e-3,rhs)

必须这样做表明以这种方式进行是无稽之谈。请注意 fsolve 使用迭代算法,使用这种方法您甚至无法为其获取足够的初始向量。如果您绝对想使用 ode,我可以提出一种使用隐式微分的更好方法。