仍然遇到Matlab工作方式的麻烦......
我建立了一个由微分方程组成的模型,由ode45求解器调用。 ode45求解器本身将v0的函数传递给系统。
这是我的模特:
%chemostat model, based on:
%DCc=-v0*Cc/V + umax*Cs*Cc/(Ks+Cs)-rd -->Change of cell concentration over time
%Dcs=(v0/V)*(Cs0-Cs) - Cc*(Ys*umax*Cs/(Ks+Cs)-m) -->Change of substrate concentration over time
function dydt=sys(t,y,v0,V,umax,Ks,rd,Cs0,Ys,m)
dydt=[-(v0(t,y)/V)*y(1)+(umax*y(1)*y(2))/(Ks+y(2))-rd;
(v0(t,y)/V)*(Cs0-y(2))-(Ys*umax*y(2)*y(1))/(Ks+y(2))];
这是我的v0的功能: `
function v0 = funV0( t,y )
persistent i
if isempty(i)
i=0;
end
if y(1) > 5 || i==1
v0=20
v0 = 20+200*t % As an example, if [Y1] > 5, then set v0 = [Y2]
i=1
else
v0=0
i=0
end
end
如果我只是通过,模型就可以正常工作:
v0=20
v0=v0+200*t
但是,上面的代码与if条件不起作用。即使y(1)最初为1(并且随时间缓慢增加),if条件也会被忽略。
有人可以解释这种行为并指出解决方案吗?
提前致谢并特别感谢Rollen D'Souza,他们首先帮助我完成了代码。
答案 0 :(得分:0)
我在这里看到两个问题。
v0
视为标量功能与标量
当您定义function v0 = funV0( t,y )
时,此语句的含义是函数调用funV0(t,y)
返回值v0
。
在funV0
功能中,您可以将v0
设置为v0 = 20+200*t
或v0=0
,具体取决于条件。除非t
是向量或矩阵,否则v0
将是标量值。
在sys
函数中,您传入v0
。我假设这指的是与上面相同的值。然后你做v0(t,y)
。如果v0
是矩阵,则会在(t,y)处检索元素。但是,它不会调用我认为你想要做的函数funV0(t,y)
。
而不是v0(t,y)
,您应该使用函数调用funV0(t,y)
。
如果声明条件
这是我为funV0
函数观察到的行为。
你描述y(1)最初是1,所以我设置y=1
来测试你的功能。
我调用了funV0(1,1)并设置了断点,以便我可以浏览代码。这是发生了什么。
function v0 = funV0( t,y )
% breakpoint here
%i is initialized to []
persistent i
% enter this if statement
if isempty(i)
i=0; % i is now 0
end
%Here y(1)==1 and i==0 so we skip the if statement and enter the else statement
if y(1) > 5 || i==1
v0=20
v0 = 20+200*t
i=1
else
% We end up here
v0=0
i=0
end
end
在函数结束时,返回v0
,其值为0.
如果我再次使用funV0(1, 6)
调用该函数,我将输入if语句,因为y(1)>5
。
如果要在y(1)==1
时输入if语句,则应更改if语句的条件。按原样,未输入if语句,因为不满足条件。
答案 1 :(得分:0)
最后回到这里,对所有贡献的人抱歉!不过,谢谢大家。所有建议都帮助我找到了正确的方向。
所以,我认为MatLab忽略了我的if语句。根据patrik的建议使用调试器后,结果证明这是错误的。正确调用了该函数,并且正确输入了if语句。
我遇到了三个导致问题的问题:
另外还有一件事让我质疑代码: 当y(1,1)首先大于阈值时,ode-solver会在某些时间点跳回。这导致了v0的负值,使模型偏斜。这是通过v0函数中的其他代码行解决的。
您可以在下面找到更新的代码:
微分方程:
%chemostat model, based on:
%DCc=-v0*Cc/V + umax*Cs*Cc/(Ks+Cs)-rd
%Dcs=(v0/V)*(Cs0-Cs) - Cc*(Ys*umax*Cs/(Ks+Cs)-m)
function dydt=systemEquations(t,y,funV0,V,umax,Ks,rd,Cs0,Ys,m)
v=funV0(t,y);
dydt=[-(v/V)*y(1)+(umax*y(1)*y(2))/(Ks+y(2))-rd;
(v/V)*(Cs0-y(2))-(Ys*umax*y(2)*y(1))/(Ks+y(2))];
end
v0的功能:
function v0 = funV0( t,y )
persistent i %has to be persistent to be carried over for the next function call
persistent j %has to be persistent to be carried over for the next function call
if isempty(i) %for initial assignment of i
i=0;
end
if y(1,1) > 5.00 || i==1 %y(1,1) reads value if y-matrix
if isempty(j) %initial assignment of j, reads t value from system equations
j=t
end
v0=20
a=t-j
v0=v0+a*2000
if v0<0 %ode-solver jumps to time points before Cc>threshold --> negative values for v0 --> skews model
v0=0
end
i=1
else
v0=0
i=0
end
end
致电代码:
%ODE solver for model
%first brackets determine timespan (e.g. [0 20] means hour 0 to 20)
[t,y]=ode23(@systemEquations, [0 5],[Cc0 Cs0],[],@funV0,V,umax,Ks,rd,Cs0,Ys,m);
%plotting
plot(t,y);
%clearing of persistent variables
clear funV0;