Monod nonlinear regression solved with Ode45

조회 수: 3 (최근 30일)
Jack95
Jack95 2023년 2월 8일
댓글: Jack95 2023년 3월 14일
Hi everyone! I'm trying to estimate the parameters of the monod model solved with Ode45 through nlinfit, but I get the following errors:
Error in MONOD>ParameterJack (line 58)
mu = (Miumax*C(2))/(Ks+C(2));
Error in MONOD (line 10)
w=ParameterJack(ps,t);
Thanks in advance for the help!
The code is as follows
load dati.txt
y=dati;
t=y(:,1); X=y(:,2); S=y(:,3)
ps=[Miumax Ks Yxs];
w=ParameterJack(ps,t);
figure(1)
plot(t,w,'b.')
hold on
plot(t,yp,'r.')
pause
options=statset('Display','final','TolX',1e-12,'TolFun',1.e-12,'MaxIter',10000,'FunValCheck','off');
ip=0;
[pr,r,J] = nlinfit(t,yp,@ParameterJack,ps,options);
ci = nlparci(pr,r,J);
disp(ci);
w=ParameterJack(pr,t);
figure(2)
plot(t,w,'b.')
hold on
plot(t,yp,'.r')
function Substrate5
Rentang = [0:30];
C0 = [50 300]
Miumax=0.2;
Ks=10;
Yxs=0.5;
[t,C]=ode45(@(t,C)ParameterJack(t,C,ps),Rentang,C0);
figure
plot(t,C(:,1),'-g',t,C(:,2));
legend('acetogeni','idrogeno','metanogeni','acetato','metano', 'Location','best')
end
function dCdt=ParameterJack(t,C,Miumax,Ks,Yxs)
mu = (Miumax*C(2))/(Ks+C(2));
dCdt(1,:) = mu*C(1); %crescita acetogeni
dCdt(2,:) = -C(1)*(mu/Yxs) %consumo globale di idrogeno
end
  댓글 수: 1
Jan
Jan 2023년 2월 8일
@jacopo ferretti: You have posted only the part of the error message, which explains where the error occurs, but not the part, wich mentions what the problem is. Please post the complete message.
You code would be much easier to read, if you avoid the pile of blank lines.

댓글을 달려면 로그인하십시오.

답변 (4개)

Star Strider
Star Strider 2023년 2월 10일
편집: Star Strider 2023년 2월 11일
It could possibly work with your data.
Note — As posted, ‘S’ has 21 elements, however ‘Rentang’ (that I assume is the associated time vector) has 31.
EDIT — (11 Feb 2023 at 16:49)
Using my Monod Kinetics code —
t=[0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20];
C=[50 52 55 58 61 64 67 70 71 71 71 71 71 71 71 71 71 71 71 71 7
370 327 281 234 184 132 78 23 0 0 0 0 0 0 0 0 0 0 0 0 0];
t = t(:);
C = C.';
B0 = [rand(4,1); C(1,:).'];
[B,Rsdnrm,Rsd,ExFlg,OptmInfo,Lmda,Jmat] = lsqcurvefit(@MonodKinetics1,B0,t, C, zeros(size(B0)));
Local minimum possible. lsqcurvefit stopped because the final change in the sum of squares relative to its initial value is less than the value of the function tolerance.
B % B(1:4): Kinetic Parameters, B(5:6): Initial Conditions
B = 6×1
0.1803 17.0729 0.0000 0.4445 50.4131 415.1698
Cfit = MonodKinetics1(B, t);
figure
plot(t,C(:,1),'pb')
hold on
plot(t,C(:,2),'pr')
plot(t, Cfit(:,1), '-b')
plot(t, Cfit(:,2), '-r')
hold off
grid
function S = MonodKinetics1(B, t)
% MONODKINETICS1 codes the system of differential equations describing one
% version of Monod kinetics:
% dS/dt = (mmax * X * S)/(Y * (Ks + S));
% dX/dt = (mmax * X * S)/ (Ks + S) - (b * X);
% with:
% Variables: x(1) = S, x(2) = X
% Parameters: mmax = B(1), Y = B(2), Ks = B(3), b = B(4)
x0 = B(end-1:end);
[T,Sv] = ode45(@DifEq, t, x0);
function dS = DifEq(t, x)
xdot = zeros(2,1);
xdot(1) = (B(1) .* x(2) .* x(1)) ./ (B(2) .* (B(3) + x(1)));
xdot(2) = (B(1) .* x(2) .* x(1)) ./ (B(3) + x(1)) - (B(4) .* x(2));
dS = xdot;
end
S = Sv;
% S = Sv(:,1);
end
That is a reasonably decent approximation.
.
  댓글 수: 20
Star Strider
Star Strider 2023년 3월 4일
That is exactly what it should do.
You defined the time for the second integration as:
t1=7:14
so I incorporated that into my‘t’ matrix.
.
Jack95
Jack95 2023년 3월 14일
HI! I'm back to working on this code, I'm trying to add a third dataset (and then I'll have to add yet another). I generally work by loading data from txt files, but in this case I don't quite understand how to do it, because there is an error that I can't find. can you explain me quickly? thanks as always!
% t=[0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20];
% C=[50 52 55 58 61 64 67 70 71 71 71 71 71 71 71 71 71 71 71 71 71
% 370 327 281 234 184 132 78 23 370 327 281 250 230 200 180 170 140 100 40 30 0];
t = [0:7; 7:14]; % Concatenate Time Vectors
% t1=7:14
Cc{1}=[113 128 123 96 136 117 120 151
387 333 320 302 254 187 124 87
0 26 75 81 87 91 167 227]; % I want to add this serie
Cc{2}=[170 182 195 208 211 224 257 290
420 307 261 240 220 180 140 110];
t = t.';
% C = Cc.';
B0 = [rand(4,1); Cc{1}(1,:).'];
for k = 1:2
[B,Rsdnrm,Rsd,ExFlg,OptmInfo,Lmda,Jmat] = lsqcurvefit(@MonodKinetics1,B0,t(:,k), Cc{k}.', zeros(size(B0)));
Bk(:,k) = B;
Cfit{k} = MonodKinetics1(Bk(:,k), t(:,k));
end
% Cfit = MonodKinetics1(B, t);
figure
% plot(t,Ck{k}(:,1),'pb')
hold on
% plot(t,C(:,2),'pr')
for k = 1:2
Cc{k} = Cc{k}.';
tv = t(:,k);
plot(tv, Cc{k}(:,1),'pb')
plot(tv, Cc{k}(:,2),'pr')
plot(tv, Cfit{k}(:,1), '-b')
plot(tv, Cfit{k}(:,2), '-r')
end
hold off
grid
function S = MonodKinetics1(B, t)
x0 = B(end-1:end);
[T,Sv] = ode45(@DifEq, t, x0);
function dS = DifEq(t, x)
xdot = zeros(2,1);
xdot(1) = (B(1) .* x(2) .* x(1)) ./ (B(2) .* (B(3) + x(1)));
xdot(2) = (B(1) .* x(2) .* x(1)) ./ (B(3) + x(1)) * x(2);
xdot(3) = 1/B(2) .*x(2)
dS = xdot;
end
S = Sv;
% S = Sv(:,1);
end

댓글을 달려면 로그인하십시오.


Jan
Jan 2023년 2월 8일
A guess: You call the function ParameterJack with 2 inputs:
w=ParameterJack(ps,t);
But the function requires 5:
function dCdt=ParameterJack(t,C,Miumax,Ks,Yxs)
Then this lines fails:
mu = (Miumax*C(2))/(Ks+C(2));
because Miumax and Ks are not defined. The error message should reveal this already.
  댓글 수: 2
Jack95
Jack95 2023년 2월 10일
HI! Thanks for the reply! I removed the spaces from the code and put the data directly in the code at least you can try it directly if you want. I followed your indication and now the problem seems to be another:
>> MONOD
dCdt =
9.7368
-19.4737
Error using plot
Vectors must be the same length.
Error in MONOD (line 12)
plot(t,w,'b.')
The code is:
t=[0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20];
C=[50 52 55 58 61 64 67 70 71 71 71 71 71 71 71 71 71 71 71 71 7
370 327 281 234 184 132 78 23 0 0 0 0 0 0 0 0 0 0 0 0 0];
Miumax=0.2;
Ks=10;
Yxs=0.5;
ps=[Miumax Ks Yxs];
w=ParameterJack(t,C,Miumax,Ks,Yxs);
figure(1)
plot(t,w,'b.')
hold on
plot(t,yp,'r.')
pause
options=statset('Display','final','TolX',1e-12,'TolFun',1.e-12,'MaxIter',10000,'FunValCheck','off');
ip=0;
[pr,r,J] = nlinfit(t,yp,@ParameterJack,ps,options);
ci = nlparci(pr,r,J);
disp(ci);
w=ParameterJack(pr,t);
figure(2)
plot(t,w,'b.')
hold on
plot(t,yp,'.r')
function Substrate5
Rentang = [0:30];
C0 = [50 300]
Miumax=0.2;
Ks=10;
Yxs=0.5;
[t,C]=ode45(@(t,C)ParameterJack(t,C,Miumax,Ks,Yxs),Rentang,C0);
figure
plot(t,C(:,1),'-g',t,C(:,2));
legend('acetogeni','idrogeno','metanogeni','acetato','metano', 'Location','best')
end
function dCdt=ParameterJack(t,C,Miumax,Ks,Yxs)
mu = (Miumax*C(2))/(Ks+C(2));
dCdt(1,:) = mu*C(1);
dCdt(2,:) = -C(1)*(mu/Yxs)
end
Jan
Jan 2023년 2월 10일
@jacopo ferretti: The error message is clear: "Vectors must be the same length." ParameterJack() uses the 1st 2 elements of C only. maybe you mean:
function dCdt=ParameterJack(t, C, Miumax, Ks, Yxs)
mu = (Miumax * C(2, :)) ./ (Ks + C(2, :));
dCdt(1,:) = mu * C(1, :);
dCdt(2,:) = -C(1, :) .* (mu / Yxs)
end

댓글을 달려면 로그인하십시오.


Jack95
Jack95 2023년 2월 24일
I think I can stay on this topic. How do you set the confidence interval (e.g. 95%) of the parameters? i'm trying with nlparci but it doesn't work with lsqcurvefit. Thanks again!

Jack95
Jack95 2023년 3월 2일
Hi everyone! based on this code:
Tspan1 = 0:20;
Tspan2 = 20:70;
C01 = [50 300 0 10 0];
Miumax=0.07;
Ks=10;
Yxs=0.1;
alfa=0.9;
betha=0;
y=0.2;
km=100;
ka=3;
a2=0.8;
a1=0.559;
u=0.1;
[t1,C1] = ode45(@(t,C)ParameterJack(t,C,betha),Tspan1,C01);
C02 = C1(end,:);
C02(1,2) = 300;
[t2,C2] = ode45(@(t,C)ParameterJack(t,C,betha),Tspan2,C02);
t = [t1; t2];
C = [C1; C2];
figure
hold on
yyaxis left
plot(t,C(:,1),'-g',t,C(:,2),'-b',t,C(:,4),'-m');
ylabel('acetogens (mgCOD/L), hidrogen (mgCOD/L),metanogens')
ylim([min(C(:,1)) max(ylim)])
ylim([min(C(:,2)) max(ylim)])
yyaxis right
plot(t,C(:,3),'r', t,C(:,5),'-o');
ylabel('acetate (mgCOD/L), methane (mgCOD/L)')
ylim([0 max(ylim)])
hold off
xlabel('tempo (giorni)')
grid
legend('acetogens','Hidrogen','metanogens','acetate','methane', 'Location','best')
function dCdt=ParameterJack(t,C,betha)
Miumax=0.07;
alfa=0.9;
u=0.1;
Ks = 80;
y=0.2;
km=100;
Yxs = 0.175;
mu = (Miumax*C(2))/(Ks+C(2));
if t<24
term2 = 0,
term3 = 0;
term4 = 0;
term5 = 0;
else
ka = 60;
a2=0.121;
km=10;
y=0.2
a3= (C(4)/C(5))*a2
mum = (u)*(C(2))/(km+C(2));
mo=(u)*(C(3))/(ka+C(3));
u= 0.1
term2 = (C(4)*(mum/(1-y)));
term3 = (C(4)*(mo/(1-a2)));
term4 = mum*C(4)+(u)*((C(3)/((C(3))+ka))*C(4));
term5 = term3+(C(2)*y);
end
dCdt(1,:) = mu*C(1);
dCdt(2,:) = -C(1)*(mu/Yxs)-term2;
dCdt(3,:) = (C(1)*((alfa*mu)+betha))-term3;
dCdt(4,:) = term4;
dCdt(5,:) = term5;
end
where I have two tspans which correspond to two moments in which I administered substrate, and the graph is:
I'm now trying to figure out how to bring the same concept back into the nonlinear regression code (considering for now only the terms hydrogen, biomass, acetate).
clear all
load data2.txt
y=data2;
t=y(:,1);
x=y(:,2);
s=y(:,3);
p=y(:,4);
c = [x s p];
Tspan1 = 0:20;
Tspan2 = 20:70;
options = optimset('MaxFunEvals',100000,'MaxIter',100000);
theta0=rand(3,1);
options = optimoptions('lsqcurvefit','Algorithm','levenberg-marquardt');
[theta,Rsdnrm,Rsd,ExFlg,OptmInfo,Lmda,Jmat]=lsqcurvefit(@kinetics,theta0,t,c,zeros(Tspan1,(theta0)));
[theta,Rsdnrm,Rsd,ExFlg,OptmInfo,Lmda,Jmat]=lsqcurvefit(@kinetics,theta0,t,c,zeros(Tspan2,(theta0)));
ci = nlparci(theta,Rsd,'Jacobian',Jmat);
fmt = format;
format longE
ParametersCI = table(ci(:,1), theta, ci(:,2), 'VariableNames',{'Lower 95% CI','Parmaeter Estimate','Upper 95% CI'})
C = kinetics(theta,t);
hold on
plot(t,c(:,1),'pb')
plot(t,c(:,2),'pr')
plot(t,c(:,3),'pg')
plot(t, C(:,1), '-b')
plot(t, C(:,2), '-r')
plot(t, C(:,3), '-g')
legend('biomassa','idrogeno','acetato')
hold off
function C=kinetics(theta,t)
%c0=[0.1;9;0.1];
c0 = [20;375;13];
u=0.1
[T1,C1]=ode45(@DifEq,t,c0); %FISSA Yxs e umax E TROVA Ks!
C02 = C1(end,:);
C02(1,2) = 300;
%
function dC=DifEq(t,c)
dcdt=zeros(3,1);
dcdt(1)=u*(c(2)/(theta(1)+c(2)))*c(1);
dcdt(2)= -(1/theta(2))*u*c(1)*c(2)/(theta(1)+c(2));
dcdt(3)= (1/theta(3))*u*c(1)*c(2)/(theta(1)+c(2));
dC=dcdt;
end
C=C;
ERROR:
>> testrefil
Error using zeros
Size inputs must be scalar.
Error in testrefil (line 15)
[theta,Rsdnrm,Rsd,ExFlg,OptmInfo,Lmda,Jmat]=lsqcurvefit(@kinetics,theta0,t,c,zeros(Tspan1,(theta0)));
I'm trying to work this way, but I think there is some programming error! it's a bit advanced for me and I can't find the error, if you can help me I would be grateful!

카테고리

Help CenterFile Exchange에서 Octave에 대해 자세히 알아보기

제품


릴리스

R2020a

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by