Reputation: 33
I am trying to fit an equation of the Arrhenius form to some datapoints using lsqcurvefit.
D = D0 * exp( -Ea / ( R * T )); % Arrhenius equation for curve fitting
D0 and Ea are the values I am looking for. T is temperature and represents X, D is a coefficient and represents Y and R is the Gas constant. Since matlab wouldn't find a solution without supplying a jacobian I calculated the jacobian and included a function, as demonstrated by @m7913d in an earlier post by me ([Matlab curve-fitting won't work for small values (1e-12), what can I do? thanks again!).
When I try to run the code, Matlab returns an Error stating that the supplied Jacobian has the wrong dimensions and that it should have the size of 5-by-2.
Error using lsqncommon (line 45)
Supplied Jacobian is not the correct size:
the Jacobian matrix should be 5-by-2.
But the Jacobian that corresponds to the main fit-equation is returned by Matlab as a 1-by-4 Matrix. I calculated it in the following way:
syms D0 Ea R T
F = D0 * exp(-Ea./(R.* T));
J = jacobian(F)
J = [ exp(-Ea/(R*T)), -(D0*exp(-Ea/(R*T)))/(R*T), ...
(D0*Ea*exp(-Ea/(R*T)))/(R^2*T), (D0*Ea*exp(-Ea/(R*T)))/(R*T^2)]
But Matlab wouldn't accept this jacobian Matrix to execute the lsqcurvefit operation.
What can I do about it? Did I miss something somewhere? I know that D0 should be something in the order of 1e-5 and Ea is around 170e3.
Any help would be kindly appreciated. Here is a minimum example of the code I use. Please note that this code will result in the Error mentioned above.
clear all
R1F = [1250 2.5e-11; 1300 2.7e-11; 1350 7.1e-11; 1400 7.2e-11; 1450 1.1e-10]; % test data
R = 8.3144598; % [(kg*m^2) / (s^2 * mol * K)]
xdata = [R1F(:,1)+272]';
ydata = R1F(:,2)';
D0 = 0.1; % start guess
Ea = 0.1; % start guess
options = optimoptions('lsqcurvefit', 'StepTolerance', 1e-12, ...
'OptimalityTolerance', 1e-12, 'FunctionTolerance', 1e-12, ...
'FiniteDifferenceType', 'central', 'SpecifyObjectiveGradient', true);
[X, resnorm, residual, EXITFLAG, OUTPUT] = lsqcurvefit(@(x, xdata) ...
z(x(1), x(2), xdata, R),[D0 Ea], xdata, ydata, [], [], options);
D0 = X(1);
Ea = X(2);
semilogy(10000./xdata,ydata, '*')
hold on
semilogy(10000./xdata, z(D0, Ea, xdata, R))
hold off
function [F, J] = z(D0, Ea, T, R)
F = D0 * exp(-Ea./(R.* T)); % function to fit to the datapoints
J = [ exp(-Ea./(R.*T)), -(D0.*exp(-Ea./(R.*T)))./(R.*T), ...
(D0*Ea*exp(-Ea./(R.*T)))./(R.^2*T), (D0*Ea*exp(-Ea./(R.*T)))./(R.*T.^2)]; % Jacobian of the fit function
end
Upvotes: 0
Views: 490
Reputation: 33
I didn't solve the exact problem I was asking for, but I found a way to work around it. The jacobian I calculated was correct but Matlab just wouldn't find a proper solution for the fit.
So I translated the equation into linear form in log-space. The form of the equation now is:
log(D) = - (Ea / (ln(10)*R*T) + log(D0)
I was able to fit the parameters using "fit" and calculate values for Ea and D0 from the resulting fit parameters.
So, for me this problem is solved, but if somebody else knows a solution to the initial problem of matlab not finding a solution for the exponential equation, please feel free to share.
Upvotes: 0
Reputation: 11064
The jacobian should indeed have a size of 5x2
:
xdata
)Therefore, T
should be a column vector and while calculating the
jacobian, you should specify to which variables he has to calculate the
derivatives. Note that even the order matters!
Upvotes: 1