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 ビュー (過去 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!