Finding Unknown Parameters from Monod Equations

7 views (last 30 days)
Hi, new to Matlab and still learning.
I am using a modified code provided by Star Strider.Thanks Star Strider! I am making this as a new post so I can accept this one as well =).
The code is shown below. I got the data from another Matlab post. The equation is as shown in the screenshot: I converted all constants into theta. When I run the code below, I get huge constants that doesn't makes sense. Anything I'm doing wrong? Is it my equations? C0 or theta0? Thank you!
Function Igor_Mour
function C=kinetics(theta,t)
c0=[0.1;9;0.1];
[T,Cv]=ode45(@DifEq,t,c0);
%
function dC=DifEq(t,c)
dcdt=zeros(3,1);
dcdt(1)=-theta(1).*c(1).*c(2)/(theta(2)+c(1));
dcdt(2)= -(1/theta(3)).*theta(1).*c(1).*c(2)/(theta(2)+c(1));
dcdt(3)= (1/theta(4)).*theta(1).*c(1).*c(2)/(theta(2)+c(1));
dC=dcdt;
end
C=Cv;
end
t = [0 3 5 8 9.5 11.5 14 16 18 20 25 27]'
x = [0.0904 0.1503 0.2407 0.3864 0.5201 0.6667 0.8159 0.9979 1.0673 1.1224 1.1512 1.2093]';
s = [9.0115 8.8088 7.9229 7.2668 5.3347 4.911 3.5354 1.4041 0 0 0 0]';
p = [0.0151 0.0328 0.0621 0.1259 0.2949 0.3715 0.4199 0.522 0.5345 0.6081 0.07662 0.7869]';
%Note: x,s and p are combined (in separate columns) to form c.
theta0=[1;1;1;1;1;1];
[theta,Rsdnrm,Rsd,ExFlg,OptmInfo,Lmda,Jmat]=lsqcurvefit(@kinetics,theta0,t,c);
fprintf(1, '\tRate Constants:\n')
for k1 = 1:length(theta)
fprintf(1, '9\t\tTheta(%d) = %8.5f\n', k1, theta(k1))
end
tv = linspace(min(t), max(t));
Cfit = kinetics(theta, tv);
figure(1)
plot(t, c, 'p')
hold on
hlp = plot(tv, Cfit);
hold off
grid
xlabel(Time)
ylabel(Concentration)
legend(hlp, 'C_1(t)','C_2(t)','C_3(t)','C_4(t)', 'Location','N')
end
  1 Comment
Alex Sha
Alex Sha on 16 Oct 2022
Hi, 0.07662, one of data for p, should be 0.7662? if so, see the result below:
Sum Squared Error (SSE): 1.43925599360388
Root of Mean Square Error (RMSE): 0.208839215637285
Correlation Coef. (R): 0.982548927303979
R-Square: 0.9654023945462
Parameter Best Estimate
--------- -------------
theta1 0.0214068471653595
theta2 -1.28632596117882
theta3 -0.113732223600425
theta4 -1.55421915737194

Sign in to comment.

Accepted Answer

Star Strider
Star Strider on 14 Oct 2022
The estimated value for ‘theta(1)’ definitely does not appear to be as expected for a rate constant, however if it is than it could be appropriate. I am not certain what the other parameters are by comparing the code to the symbolic expressions It would help to have them clarified.
According to the posted symbolic differntial equations, the first differential equation should not be negated. Changing that gives a decent fit to the data. Beyond that, I suggest checking to be certain that the equations are coded correctly. Here, I have ‘x’ as ‘c(1)’, ‘s’ as ‘c(2)’, and ‘p’ as ‘c(3)’. Change those if necessary to be the correct columns.
t = [0 3 5 8 9.5 11.5 14 16 18 20 25 27]' ;
x = [0.0904 0.1503 0.2407 0.3864 0.5201 0.6667 0.8159 0.9979 1.0673 1.1224 1.1512 1.2093]';
s = [9.0115 8.8088 7.9229 7.2668 5.3347 4.911 3.5354 1.4041 0 0 0 0]';
p = [0.0151 0.0328 0.0621 0.1259 0.2949 0.3715 0.4199 0.522 0.5345 0.6081 0.07662 0.7869]';
%Note: x,s and p are combined (in separate columns) to form c.
c = [x s p];
theta0=rand(7,1);
[theta,Rsdnrm,Rsd,ExFlg,OptmInfo,Lmda,Jmat]=lsqcurvefit(@kinetics,theta0,t,c,zeros(1,numel(theta0)));
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.
fprintf(1,'\tRate Constants:\n')
Rate Constants:
for k1 = 1:numel(theta)
fprintf(1, '\t\tTheta(%2d) = %8.5f\n', k1, theta(k1))
end
Theta( 1) = 432.22494 Theta( 2) = 11061.84689 Theta( 3) = 0.13367 Theta( 4) = 2.38808 Theta( 5) = 0.02007 Theta( 6) = 8.88929 Theta( 7) = 0.05209
tv = linspace(min(t), max(t));
Cfit = kinetics(theta, tv);
figure
hd = plot(t, c, 'p');
for k1 = 1:size(c,2)
CV(k1,:) = hd(k1).Color;
hd(k1).MarkerFaceColor = CV(k1,:);
end
hold on
hlp = plot(tv, Cfit);
for k1 = 1:size(c,2)
hlp(k1).Color = CV(k1,:);
end
hold off
grid
xlabel('Time')
ylabel('Concentration')
legend(hlp, compose('C_%d',1:size(c,2)), 'Location','best')
function C=kinetics(theta,t)
c0=theta(5:7);
[T,Cv]=ode45(@DifEq,t,c0);
%
function dC=DifEq(t,c)
dcdt=zeros(3,1);
dcdt(1)= theta(1).*c(1).*c(2)./(theta(2)+c(1));
dcdt(2)= -(1./theta(3)).*theta(1).*c(1).*c(2)./(theta(2)+c(1));
dcdt(3)= (1./theta(4)).*theta(1).*c(1).*c(2)./(theta(2)+c(1));
dC=dcdt;
end
C=Cv;
end
Please define the parameters in terms of the symbolic equations. With that information, it will be easier to determine if there are any inconsistencies.
.
  12 Comments
Learning
Learning on 3 Dec 2022
Thanks for your response! My final question is how do I implement this in real time? Say I identify the parameters for the series of odes, do I need to have another set of data to estimate the parameters? Or I can fix the parameters if I know the process doesn’t change that much? Real time in the sense that assuming I have live stream data from a hardware that I want to compare with the concentrations estimated by the ode at specific times.
Thank you!
Star Strider
Star Strider on 3 Dec 2022
As always, my pleasure!
Updating the parameter estimates in real time is not something I’ve considered. I’ve not done real time parameter estimation in decades.
I’m not sure that a real time application of this is possible, however it depends on what ‘real time’ actually means. If there is time between samples to numerically integrate the differential equations, and good estimates of the existing paramerers are known, then the current approach could be used without alteration, using the existing estimates for the initial estimates for parameter estimates with the additional data.
Otherwise, a Kalman filter approach could be possible, however I’ve little experience with Kalman filters so I don’t know if one could be used in this instance. There are a large number of Kalman filter functions in MATLAB that might be possible to use. One such is kalman, and there are more than 50 others in the online documentation that come up with a search for ‘kalman’.

Sign in to comment.

More Answers (1)

Torsten
Torsten on 14 Oct 2022
Works for me.
t = [0 3 5 8 9.5 11.5 14 16 18 20 25 27]' ;
x = [0.0904 0.1503 0.2407 0.3864 0.5201 0.6667 0.8159 0.9979 1.0673 1.1224 1.1512 1.2093]';
s = [9.0115 8.8088 7.9229 7.2668 5.3347 4.911 3.5354 1.4041 0 0 0 0]';
p = [0.0151 0.0328 0.0621 0.1259 0.2949 0.3715 0.4199 0.522 0.5345 0.6081 0.7662 0.7869]';
c = [x s p];
theta0=[1;1;1;1;1;1];
options = optimset('MaxFunEvals',100000,'MaxIter',100000);
[theta,Rsdnrm,Rsd,ExFlg,OptmInfo,Lmda,Jmat]=lsqcurvefit(@kinetics,theta0,t,c,[],[],options);
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.
theta
theta = 6×1
-3.5510 133.8605 -0.1503 -1.9775 1.0000 1.0000
C = kinetics(theta,t)
C = 12×3
0.0904 9.0115 0.0151 0.1811 8.4079 0.0610 0.2782 7.7620 0.1101 0.4889 6.3604 0.2166 0.6186 5.4979 0.2822 0.8008 4.2856 0.3743 1.0126 2.8768 0.4814 1.1491 1.9684 0.5505 1.2507 1.2924 0.6019 1.3212 0.8237 0.6375
hold on
plot(t,c,'o')
plot(t,C)
hold off
function C=kinetics(theta,t)
%c0=[0.1;9;0.1];
c0 = [0.0904;9.0115;0.0151];
[T,Cv]=ode45(@DifEq,t,c0);
%
function dC=DifEq(t,c)
dcdt=zeros(3,1);
dcdt(1)=-theta(1).*c(1).*c(2)/(theta(2)+c(1));
dcdt(2)= -(1/theta(3)).*theta(1).*c(1).*c(2)/(theta(2)+c(1));
dcdt(3)= (1/theta(4)).*theta(1).*c(1).*c(2)/(theta(2)+c(1));
dC=dcdt;
end
C=Cv;
end

Products


Release

R2019b

Community Treasure Hunt

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

Start Hunting!