how to fit the coupled differential equations and get the coefficients?
1 view (last 30 days)
Show older comments
Hi! I'm trying to fit the coupled differential equations to my data and get the coefficients. Below is the equations that I use
d(N) = -(2/3)*L1*N^2*K - (1/3)*L2*N*K^2;
d(K) = -(1/3)*L1*N^2*K - (2/3)*L2*N*K^2;
Here, N and K are the data from the experiments, and L1 and L2 are what I want to get from the fit.
I'm not sure what method I should use to get L1 and L2.. Any tips are very appreciated!
0 Comments
Answers (3)
Sam Chak
on 6 Nov 2023
Edited: Sam Chak
on 6 Nov 2023
Hi @영훈 임
Update: The solution is updated at your request to plot the comparisons. The Batch Least Squares algorithm does not change.
%% For generating data purposes (real data can skip)
tspan = linspace(0, 10, 101);
[t, y1] = ode45(@odefcn1, tspan, [1 0.5]);
N = y1(:,1); % data N
K = y1(:,2); % data K
%% Batch Least Squares method to estimate L1 & L2
dN = gradient(N)./gradient(t);
dK = gradient(K)./gradient(t);
phi1 = [-(2/3)*(N.^2).*K -(1/3)*N.*(K.^2)];
phi2 = [-(1/3)*(N.^2).*K -(2/3)*(N.*K.^2)];
phi = [phi1; phi2];
Y = [dN; dK];
L = ((phi'*phi)\eye(length(phi'*phi)))*phi'*Y
%% Testing the fitness
tspan = linspace(0, 10, 101);
[t, y2] = ode45(@(t, y) odefcn2(t, y, L), tspan, [N(1) K(1)]);
subplot(211)
plot(t, N, 'o'), hold on
plot(t, y2(:,1), 'linewidth', 1.5), title('Comparison between data N and numerical N')
grid on, xlabel('t'), ylabel('N'), legend('data N', 'numerical N')
subplot(212)
plot(t, K, 'o'), hold on
plot(t, y2(:,2), 'linewidth', 1.5), title('Comparison between data K and numerical K')
grid on, xlabel('t'), ylabel('K'), legend('data K', 'numerical K')
%% differential equations (for generating data purposes)
function dydt = odefcn1(t, y)
dydt = zeros(2, 1);
L1 = 2; % true value of L1
L2 = 3; % true value of L2
N = y(1);
K = y(2);
dydt(1) = - (2/3)*L1*N^2*K - (1/3)*L2*N*K^2;
dydt(2) = - (1/3)*L1*N^2*K - (2/3)*L2*N*K^2;
end
%% differential equations (for testing purposes)
function dydt = odefcn2(t, y, L)
dydt = zeros(2, 1);
L1 = L(1); % estimated value of L1
L2 = L(2); % estimated value of L2
N = y(1);
K = y(2);
dydt(1) = - (2/3)*L1*N^2*K - (1/3)*L2*N*K^2;
dydt(2) = - (1/3)*L1*N^2*K - (2/3)*L2*N*K^2;
end
2 Comments
Sam Chak
on 6 Nov 2023
Hi @영훈 임
I have updated my answer to show the comparison. I hope this helps. Also study @Star Strider's approach.
Star Strider
on 6 Nov 2023
See: Parameter Estimation for a System of Differential Equations (and similar posts) for an easy way to estimate the parameters.
2 Comments
Star Strider
on 6 Nov 2023
The original problem was that ode45 was crashing (saturating) and stopped. The result was that the returned matrix had fewer rows than the data matrix, throwing the error.
This works (in the sense that it runs completely), however it does not come close to fitting the data —
Tbody2
function Tbody2
t = [0.4
0.6
0.8
1
1.2
1.5
1.8
2
2.5
3
3.5
4
4.5
5
7
10
15
20
30
50];
% c(:,1) = [770211; 715721.400000000;779650.800000000;807933.200000000;718145.600000000;746019.400000000;680262.600000000;643406.400000000;654130.600000000;597111.400000000;662146;578453;531229.400000000;574800.200000000;513836.800000000;400240.200000000;287214.400000000;308158.400000000;216808;191333.200000000];
% c(:,2) = [556098.903900000;597496.722600000;564025.111900000;506661.652400000;517884.943100000;500070.435600000;500966.444800000;517265.509000000;448318.326500000;509527.419300000;432720.902200000;434608.807900000;468438.727900000;401627.602100000;339789.050100000;351852.917000000;337195.730400000;241086.271400000;236918.419200000;161586.537200000];
c = [770211 556098.9039
715721.4 597496.7
779650.8 564025.1
807933.2 506661.6
718145.6 517884.9
746019.4 500070.4
680262.6 500966.4
643406.4 517265.5
654130.6 448318.3
597111.4 509527.4
662146 432720.9
578453 434608.8
531229.4 468438.7
574800.2 401627.6
513836.8 339789.0
400240.2 351852.9
287214.4 337195.7
308158.4 241086.2
216808 236918.40
191333.2 161586.5];
% theta0 = [1e-12; 1e-12];
theta0 = [rand(2,1)*1E-14; c(1,:).'];
[theta,Rsdnrm,Rsd,ExFlg,OptmInfo,Lmda,Jmat]=lsqcurvefit(@Loss,theta0,t,c);
fprintf(1,'\tRate Constants:\n')
for k1 = 1:length(theta)
fprintf(1, '\t\tTheta(%d) = %13.5E\n', k1, theta(k1))
end
tv = linspace(min(t), max(t));
Cfit = Loss(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')
function C=Loss(theta,t)
% c0=[1e6; 5e5];
c0 = theta(3:4)*0.9;
[T,Cv]=ode45(@DifEq,t,c0);
%
function dC=DifEq(t,c)
dcdt=zeros(2,1);
dcdt(1) = -theta(1).*(-2/3)*c(1).^2.*c(2) - theta(2).*(-1/3)*c(1).*c(2).^2;
dcdt(2) = -theta(1).*(-1/3)*c(1).^2.*c(2) - theta(2).*(-2/3)*c(1).*c(2).^2;
dC=dcdt;
end
C=Cv;
end
end
The changes I made specifically adding ther initial conditions for the differential equation as the last two elements of‘theta’ since that usually results in a successful fit, however that is only marginally successful here.
I am not certain what the problem is, since I do not understand the system you are modeling and estimating. One option may be to re-scale the data so that it is possible to estimate the parameters (that are currently approaching the eps value and so are likely not actually doing anything) to fit the data and then scale the parameters appropriately after estimating them. The model and the data are currently stretching the limits of floating-point computations.
You might also consider using ode15s even though your system is not specifically ‘stiff’. (I got good results with it in MATLAB Online, and better than I got here, however I was still not pleased with the results.)
.
Alex Sha
on 20 Nov 2023
Refer to the results below:
Sum Squared Error (SSE): 46715596564.0427
Root of Mean Square Error (RMSE): 35062.1990798768
Correlation Coef. (R): 0.977599960330532
R-Square: 0.955701682438257
Parameter Best Estimate
--------- -------------
L1 3.57062147972612E-13
L2 7.93804069320317E-14
0 Comments
See Also
Categories
Find more on Interpolation in Help Center and File Exchange
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!