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.
조회 수: 1 (최근 30일)
이전 댓글 표시
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
dpb
2022년 6월 24일
>> 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...
채택된 답변
Walter Roberson
2022년 6월 24일
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
Walter Roberson
2022년 6월 29일
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.
추가 답변 (1개)
Cris LaPierre
2022년 6월 24일
편집: Cris LaPierre
2022년 6월 27일
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
Walter Roberson
2022년 6월 27일
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()
참고 항목
카테고리
Help Center 및 File Exchange에서 Calculus에 대해 자세히 알아보기
제품
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!