Fitting kinetic model to estimate kinetic parameter
115 visualizzazioni (ultimi 30 giorni)
Mostra commenti meno recenti
Nadya Shalsabila salman
il 4 Nov 2021
Commentato: Star Strider
circa 23 ore fa
Hello, I want to ask a question. I want to curve fit the data with the kinetic model. I am able to run the code (written and attached below), but the result is still far from my expectation.
function trycurvefitlunaflores
function C=kinetics(theta,t)
c0=[0.6178; 28.90; 0.4589];
[T,Cv]=ode45(@DifEq,t,c0);
function dC=DifEq(t,c)
dcdt=zeros(3,1);
mu = ((theta(1).*c(2))./(theta(2)+c(2)+(c(2)^2./(theta(3))))).*((1-c(3)./theta(4)).^theta(5));
dcdt(1) = mu.*c(1);
dcdt(2) = -c(1).*((mu./(theta(6))+theta(7)));
dcdt(3) = c(1).*((theta(8).*mu)+theta(9));
dC=dcdt;
end
C=Cv;
end
t = [0
12
24
36
48
60
72];
c = [0.6178489703 28.90160183 0.7586206897
0.823798627 28.83295195 4.045977011
2.402745995 21.62471396 6.827586207
5.972540046 13.04347826 18.5862069
8.306636156 6.178489703 34.01149425
9.885583524 2.402745995 44.88505747
9.542334096 2.059496568 50.44827586];
theta0 = [1;1;1;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, '\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)', 'Location','N')
end
In the normal circumstance, the plot line (from kinetic model) should follow the data's tren, like this figure below.
Could you help me to fix the plot to make it more similar to the data? Any little advice or help will be much appreciated. Thank you.
7 Commenti
Risposta accettata
Alex
il 12 Nov 2021
Modificato: Alex
il 16 Nov 2021
Using fminsearch, defining a custom cost-function and using the initial values of Alex Sha finally did the trick.
I seperated the program into seperate files. The main file:
clear
close all
clc
global t c
t = [0
12
24
36
48
60
72];
c = [0.6178489703 28.90160183 0.7586206897
0.823798627 28.83295195 4.045977011
2.402745995 21.62471396 6.827586207
5.972540046 13.04347826 18.5862069
8.306636156 6.178489703 34.01149425
9.885583524 2.402745995 44.88505747
9.542334096 2.059496568 50.44827586];
theta0 = [-0.024;-12.55;-28.80;50.63;0.168;0.3501;0.003146;1.9802;0.0954];
options = optimset('display','iter');
options.MaxFunEvals = 10e8;
options.TolX = 10e-5;
options.TolFun = 10e-5;
options.MaxIter = 10e3;
[theta] = fminsearch(@minfunction, theta0, options);
tv = linspace(min(t), max(t));
Cfit = kinetics(theta, tv, c(1,:));
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)', 'Location','N')
the kinetics function:
function C=kinetics(theta, t, c0)
[T,Cv]=ode45(@DifEq,t, c0);
function dC=DifEq(t,c)
dcdt=zeros(3,1);
mu = ((theta(1).*c(2))./(theta(2)+c(2)+(c(2)^2./(theta(3))))).*((1-c(3)./theta(4)).^theta(5));
dcdt(1) = mu.*c(1);
dcdt(2) = -c(1).*((mu./(theta(6))+theta(7)));
dcdt(3) = c(1).*((theta(8).*mu)+theta(9));
dC=dcdt;
end
C=Cv;
end
and the cost function:
function error = minfunction(theta)
global t c
c0 = c(1,:);
c_estim = kinetics(theta,t,c0);
w1 = 1;
w2 = 1;
w3 = 1;
error_temp = w1*abs(c(:,1)-c_estim(:,1)) + ...
w2*abs(c(:,2)-c_estim(:,2)) + ...
w3*abs(c(:,3)-c_estim(:,3)) ;
error = sum(error_temp);
end
In the cost function one could use different weights for the error of c1, c2 and c3. This could be of interest if one would worry more about the error for example of c1 than c2.
fminsearch now tries to find parameters for the differential equation which minimizes:
Hope this helps.
6 Commenti
Alex
il 16 Nov 2021
Modificato: Alex
il 16 Nov 2021
The idea behind the weights was to give you the option to say: "i worry more about the error of c3, than c2 and therefore want to give the error a higher weight".
Looking again at the cost function makes me think about an error I made there. Maybe it is better to define the cost function like:
function error = minfunction(theta)
global t c
c0 = c(1,:);
c_estim = kinetics(theta,t,c0);
w1 = 1;
w2 = 1;
w3 = 1;
error_temp = w1*abs(c(:,1)-c_estim(:,1)) + ...
w2*abs(c(:,2)-c_estim(:,2)) + ...
w3*abs(c(:,3)-c_estim(:,3)) ;
error = sum(error_temp);
end
The error is now defined the following way:
(Before it would have been possible that errors cancel out each other, which could have been the reason why I had to add the weights. This is of course not the prefered way.). As you can see I now have set the weights to 1, since it looks as if they are not really necessary anymore. But if you want to play around with the weights, you are of course free to go if it improves the results.
I will update the original answer.
Più risposte (2)
Alex
il 5 Nov 2021
Modificato: Alex
il 5 Nov 2021
Your basic structure seems to be ok. Here are some hints you could consider:
- Try playing around with the solver options, like using different algorithms, different initial points and tolerances:
theta0 = [1;1;1;1;1;1;1;1;1];
options = optimoptions('lsqcurvefit', 'Algorithm','trust-region-reflective');
options.MaxFunctionEvaluations = 10e5;
options.StepTolerance = 10e-7;
options.FunctionTolerance = 10e-7;
options.MaxIterations = 10e5;
[theta,Rsdnrm,Rsd,ExFlg,OptmInfo,Lmda,Jmat]=lsqcurvefit(@kinetics,theta0,t,c, [],[], options);
- Use the accurate intitial condition for your differential equation:
c0=[0.6178489703 28.90160183 0.7586206897];
- Watch out for local minimum warnings. Matlab provides further thoughts on how to avoid local minimum convergence when clicking on the link in the matlab console (or directly via this link):
>> trycurvefitlunaflores
Local minimum possible.
After playing around a bit I was able to produce the following result:
I am sure that with a little tweaking you will be able to also fit C_1 correctly. Let me know if you found a solution.
9 Commenti
Manish
il 24 Nov 2024 alle 17:42
function C=kinetics(theta,t)
c0=[0.6178; 28.90; 0.4589];
[T,Cv]=ode45(@DifEq,t,c0);
function dC=DifEq(t,c)
dcdt=zeros(3,1);
mu = ((theta(1).*c(2))./(theta(2)+c(2)+(c(2)^2./(theta(3))))).*((1-c(3)./theta(4)).^theta(5));
dcdt(1) = mu.*c(1);
dcdt(2) = -c(1).*((mu./(theta(6))+theta(7)));
dcdt(3) = c(1).*((theta(8).*mu)+theta(9));
dC=dcdt;
end
C=Cv;
end
t = [0
12
24
36
48
60
72];
c = [0.6178489703 28.90160183 0.7586206897
0.823798627 28.83295195 4.045977011
2.402745995 21.62471396 6.827586207
5.972540046 13.04347826 18.5862069
8.306636156 6.178489703 34.01149425
9.885583524 2.402745995 44.88505747
9.542334096 2.059496568 50.44827586];
theta0 = [1;1;1;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, '\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)', 'Location','N')
end
0 Commenti
Vedere anche
Categorie
Scopri di più su Eigenvalue Problems in Help Center e File Exchange
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!