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 visualizaciones (últimos 30 días)
Mostrar comentarios más antiguos
Bibek Dhami
el 24 de Jun. de 2022
Comentada: Bibek Dhami
el 30 de Jun. de 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 comentario
dpb
el 24 de Jun. de 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...
Respuesta aceptada
Walter Roberson
el 24 de Jun. de 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 comentarios
Walter Roberson
el 29 de Jun. de 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.
Más respuestas (1)
Cris LaPierre
el 24 de Jun. de 2022
Editada: Cris LaPierre
el 27 de Jun. de 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 comentarios
Walter Roberson
el 27 de Jun. de 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()
Ver también
Categorías
Más información sobre Calculus en Help Center y File Exchange.
Productos
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!