# 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.

6 views (last 30 days)
Bibek Dhami on 24 Jun 2022
Commented: Bibek Dhami on 30 Jun 2022
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)
options =
lsqcurvefit options: Options used by current Algorithm ('trust-region-reflective'): (Other available algorithms: 'levenberg-marquardt') Set properties: Algorithm: 'trust-region-reflective' MaxFunctionEvaluations: 1.0000e+10 StepTolerance: 1.0000e-19 Default properties: CheckGradients: 0 Display: 'final' FiniteDifferenceStepSize: 'sqrt(eps)' FiniteDifferenceType: 'forward' FunctionTolerance: 1.0000e-06 JacobianMultiplyFcn: [] MaxIterations: 400 OptimalityTolerance: 1.0000e-06 OutputFcn: [] PlotFcn: [] SpecifyObjectiveGradient: 0 SubproblemAlgorithm: 'factorization' TypicalX: 'ones(numberOfVariables,1)' UseParallel: 0
MI=lsqcurvefit(@model,[0.2,0.0403,2.03],xdata,ydata,[],[],options);
Error using lsqncommon
Objective function is returning undefined values at initial point. lsqcurvefit cannot continue.

Error in lsqcurvefit (line 295)
lsqncommon(funfcn,xCurrent,lb,ub,options,defaultopt,optimgetFlag,caller,...
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
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...

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.
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)
options =
lsqcurvefit options: Options used by current Algorithm ('trust-region-reflective'): (Other available algorithms: 'levenberg-marquardt') Set properties: Algorithm: 'trust-region-reflective' MaxFunctionEvaluations: 1.0000e+10 StepTolerance: 1.0000e-19 Default properties: CheckGradients: 0 Display: 'final' FiniteDifferenceStepSize: 'sqrt(eps)' FiniteDifferenceType: 'forward' FunctionTolerance: 1.0000e-06 JacobianMultiplyFcn: [] MaxIterations: 400 OptimalityTolerance: 1.0000e-06 OutputFcn: [] PlotFcn: [] SpecifyObjectiveGradient: 0 SubproblemAlgorithm: 'factorization' TypicalX: 'ones(numberOfVariables,1)' UseParallel: 0
MI = lsqcurvefit(@model,[0.2,0.0403,2.03],xdata,ydata,[],[],options);
Local minimum found. Optimization completed because the size of the gradient is less than the value of the optimality tolerance.
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
Bibek Dhami on 30 Jun 2022
Thank you so much @Walter Roberson. It makes sense.

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 = 83×2
496.7700 0.2983 497.3600 0.3010 497.9500 0.3000 498.5400 0.3009 499.1300 0.3037 499.7200 0.3059 500.3000 0.3065 500.8900 0.3088 501.4800 0.3101 502.0700 0.3113
xdata= A(:,1);
ydata = A(:,2);
var = [0.2,0.0403,2.03];
energy = xdata;
% exp part retuning inf
pi.*exp(pi.*energy)
ans = 83×1
Inf Inf Inf Inf Inf Inf Inf Inf Inf Inf
% sinh part returning inf
sinh(pi.*energy)
ans = 83×1
Inf Inf Inf Inf Inf Inf Inf Inf Inf Inf
% dividing an inf by inf returns a nan
((pi.*exp(pi.*energy))./sinh(pi.*energy))
ans = 83×1
NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
Bibek Dhami on 27 Jun 2022
HI @Walter Roberson I just used your technique but the code keeps running without giving output. I need to stop the code after 5 minutes.