You are actually fitting two vectors, ‘COD’ and ‘Fcl’. (That was not immediately obvious.) They have to be in one matrix, that you then pass to lsqcurvefit as the dependent variables you want to fit. You also have to return both columns of ‘Sv’ to fit them.
This works, however you may need to experiment with different initial values to get parameters that fit well (or just run it a few times with the same initial parameters to see if different runs produce different results, as they often will):
function S = Kinetics(B, t)
x0 = [305,25];
[T,Sv] = ode45(@DifEq, t,x0);
function dS = DifEq(t, x)
xdot = zeros(2,1);
xdot(1) = B(1);
xdot(2) = -B(2) .* x(2) .* x(1);
dS = xdot;
end
S = Sv;
end
Time = [0 2 4 6 8 10 12];
COD=[307.18 394.39 441.93 516.62 565.13 636.74 653.68];
Fcl = [21.06666667 15.4 9.633333333 4.666666667 0.753333333 0.403333333 0.206666667];
COD_Fcl = [COD(:) Fcl(:)];
B0 = [COD(1),Fcl(1)];
[B,Rsdnrm,Rsd,ExFlg,OptmInfo,Lmda,Jmat] = lsqcurvefit(@Kinetics, B0, Time(:), COD_Fcl);
parameters = B
Tv = linspace(min(Time), max(Time), 25);
Sv = Kinetics(B,Tv);
figure
plot3(Time, COD, Fcl, 'p')
hold on
plot3(Tv, Sv(:,1), Sv(:,2), '-r')
hold off
grid
This takes a very long time to run. You might get better results using your own fitness function based on your ODE system, and using the Global Optimization Toolbox genetic algorithm ga function to estimate the parameters.
If you want to let the optimization algorithm determine the initial conditions for the ODEs as well as the parameters, change ‘Kinetics’ to:
function S = Kinetics(Bv, t)
x0 = Bv(3:4);
B = Bv(1:2);
[T,Sv] = ode45(@DifEq, t,x0);
function dS = DifEq(t, x)
xdot = zeros(2,1);
xdot(1) = B(1);
xdot(2) = -B(2) .* x(2) .* x(1);
dS = xdot;
end
S = Sv;
end
and ‘B0’ to:
or some vector with 4 elements.
Best Answer