How can I get this code to work? I am trying to fit the equation that contains step and delta function to experimental data. But I am getting the following error.
2 views (last 30 days)
Show older comments
Bibek Dhami
on 24 Jun 2022
Commented: Bibek Dhami
on 30 Jun 2022
A=xlsread('Data');
xdata= A(:,1);
ydata = A(:,2) ;
plot(xdata,ydata,'r.','markersize',30);
set(gca,'XDir','reverse');
box on
options =optimoptions(@lsqcurvefit,'Algorithm','trust-region-reflective','StepTolerance',1e-19,'MaxFunctionEvaluations',1e10)
MI=lsqcurvefit(@model,[0.2,0.0403,2.03],xdata,ydata,[],[],options);
fitdata=model(MI,xdata);
hold on
plot(xdata, fitdata,'k--','linewidth',2);
function alpha=model(var,energy)
alpha = var(1)*heaviside(energy-var(3)).*((pi.*exp(pi.*energy))./sinh(pi.*energy))+...
dirac(energy-var(3)+(var(2)))+dirac(energy-var(3)+(var(2)./4))+...
dirac(energy-var(3)+(var(2)./9));
end
1 Comment
dpb
on 24 Jun 2022
>> F=model([0.2,0.043,2.03],A(:,1));
'heaviside' requires Symbolic Math Toolbox.
Error in model (line 2)
alpha = x(1)*heaviside(energy-x(3)).*((pi.*exp(pi.*energy))./sinh(pi.*energy))+...
>>
so can't run your function here...first thing to do, however, is to debug your model function before trying it inside lsqcurvefit
The error is telling you something ain't right there -- you've not returning values that are defined and finite at the start point...
Accepted Answer
Walter Roberson
on 24 Jun 2022
Your Energy are in the 500 range. exp(pi*energy) overflows double precision. Your code then divides by large values, but you have already overflowed.
Ideally your code should be revised to deliberately avoid overflowing. For example, instead of exp(pi*energy)/sinh(something) you could try exp(pi*energy - log(sinh(something)) expecting the sinh to be large enough for the log to be comparable to pi*energy.
filename = 'https://www.mathworks.com/matlabcentral/answers/uploaded_files/1044920/Data.xlsx';
A = readmatrix(filename);
xdata = A(:,1);
ydata = A(:,2) ;
plot(xdata, ydata, 'r.', 'markersize', 30);
set(gca,'XDir','reverse');
box on
options =optimoptions(@lsqcurvefit,'Algorithm','trust-region-reflective','StepTolerance',1e-19,'MaxFunctionEvaluations',1e10)
MI = lsqcurvefit(@model,[0.2,0.0403,2.03],xdata,ydata,[],[],options);
fitdata = model(MI,xdata);
hold on
plot(xdata, fitdata,'k--','linewidth',2);
function alpha = model(var,Energy)
energy = sym(Energy);
alpha = var(1)*heaviside(energy-var(3)).*((pi.*exp(pi.*energy))./sinh(pi.*energy))+...
dirac(energy-var(3)+(var(2)))+dirac(energy-var(3)+(var(2)./4))+...
dirac(energy-var(3)+(var(2)./9));
alpha = double(alpha);
end
4 Comments
Walter Roberson
on 29 Jun 2022
Your energy is your x data, which is input. It does not make sense to integrate over your input.
There is a sense in which Heaviside is the integral of dirac delta; see https://en.wikipedia.org/wiki/Heaviside_step_function .
Reminder: you can only int() a symbolic expression or symbolic function, and the result will be a symbolic expression (or possibly the unevaluated int() expression, if MATLAB cannot figure out what the integral is.) But for lsqcurvefit you need to return double()
Reminder: if you have an input variable named energy and you do
syms energy
then that is equivalent to
energy = sym('energy');
which overwrites the input parameter energy with a new value.
More Answers (1)
Cris LaPierre
on 24 Jun 2022
Edited: Cris LaPierre
on 27 Jun 2022
The problem is that your objective function is returning NaN values. It is specifically the exp and sinh parts of the equation. You may need to consider the scale of your x values.
A=readmatrix('https://www.mathworks.com/matlabcentral/answers/uploaded_files/1044920/Data.xlsx')
xdata= A(:,1);
ydata = A(:,2);
var = [0.2,0.0403,2.03];
energy = xdata;
% exp part retuning inf
pi.*exp(pi.*energy)
% sinh part returning inf
sinh(pi.*energy)
% dividing an inf by inf returns a nan
((pi.*exp(pi.*energy))./sinh(pi.*energy))
5 Comments
Walter Roberson
on 27 Jun 2022
syms energy
is the same as
energy = sym('energy') ;
which creates a variable named energy inside the symbolic toolbox workspace, and stores a reference to it inside the local function workspace, overwriting the parameter named energy that was passed in. It does not convert the parameter into symbolic representation. To convert the input energy to symbolic form, use the technique I used in my code involving sym()
See Also
Categories
Find more on Special Values in Help Center and File Exchange
Products
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!