2
$\begingroup$

I'm trying to fit the function $f(x;a,b,s)=a\left( \frac{\sin\left(b \sin(s x) \right)}{b \sin(s x)} \right)^2 $ on the data below using NonlinearModelFit but I'm getting an error message: Indeterminate expression, Complex infinity.

Ord = Array[1. # &, 21, -10];
Int = {1.233, 1.725, 1.737, 0.941, 0.453, 2.297, 11.06, 24.05, 41.6, 
58.8, 1630, 55.7, 39.0, 26.7, 12.98, 2.936, 0.472, 1.11, 2.21, 
2.38, 1.725};
OrdInt = Transpose[{Ord, Int}];
NonlinearModelFit[OrdInt,{a (Sin[ b Sin[s x/2]/(Sin[s x]/2))^2,50<a<70&&20<b<50&&0.02<s<0.05}, 
{a,b,s},x]

Does anyone know how to fix this or anyother way to do this fit ?

$\endgroup$
4
  • 2
    $\begingroup$ It might have to do with 0 being one of the x values. $\endgroup$ Commented Jul 14, 2022 at 12:59
  • 2
    $\begingroup$ Replace 0. in Ord to 0.001 for example. $\endgroup$
    – cvgmt
    Commented Jul 14, 2022 at 13:03
  • 3
    $\begingroup$ Why aren't you using Sinc[]? $\endgroup$ Commented Jul 14, 2022 at 13:56
  • 1
    $\begingroup$ Hi @Physor, Thanks for accepting my answer, but I think you were too hasty doing that. While accepting is one of the things to do after your question is answered, we recommend that users should test answers before voting and wait 24 hours before accepting the best one. That allows people in all timezones to answer your question and an opportunity for other users to point out alternatives, caveats or limitations of the available answers. $\endgroup$
    – rhermans
    Commented Jul 14, 2022 at 14:48

2 Answers 2

6
$\begingroup$

Evaluating your function around zero is complicated, better calculate the Limit and make it an explicit part of the definition.

Limit[
    a (Sin[ b Sin[s x/2]]/(Sin[s x]/2))^2
    , x -> 0
]
a  b^2

Also, you can restrict your function to be evaluated only for NumericQ arguments and avoid some problems with the symbolic evaluation.

ClearAll[f];
f[a_,b_,s_][0.|0] = a  b^2
f[a_,b_,s_][x_?NumericQ] := a (Sin[ b Sin[s x/2]]/(Sin[s x]/2))^2

Now you can do the fitting with NonlinearModelFit, and reasonable initial guess and constraints.

fit=NonlinearModelFit[
    OrdInt
    ,{
        f[a,b,s][x],
        And[
            40 < a b^2 < 70,
            0  < s < 0.1,
            20 < b < 40
        ]
    }
    ,{
        {a, 0.04},
        {b, 40},
        {s, 0.03}
    }
    ,x
]

And Plot

Show[
    ListPlot[
        OrdInt
        , PlotTheme -> "Scientific"
        , PlotStyle -> Blue
    ],
    Plot[
        fit[x]
        , {x,-10,10}
        , PlotStyle->Red
    ]
]

enter image description here

$\endgroup$
4
  • $\begingroup$ Did you omit that data point with x=0 in your fit ? $\endgroup$
    – Physor
    Commented Jul 14, 2022 at 14:34
  • $\begingroup$ @Physor no, I did not omit any data, but that point ({0., 1630} ) is well above the plot range. Your fitting equation has problems, anyhow. I think my answer addresses your question, but it is not necessarily a good fit for your data and does not endorse the function you are using. $\endgroup$
    – rhermans
    Commented Jul 14, 2022 at 14:38
  • $\begingroup$ Where can I find more about this piece of code f[a_,b_,s_][0.|0] ? I've never seen that in the definition of functions before $\endgroup$
    – Physor
    Commented Jul 14, 2022 at 14:40
  • 1
    $\begingroup$ @Physor, Read about Function definitions and the Alternatives operator (|). f[0.|0] = c means f evaluate on Machine Precision 0.0 or exact 0 . $\endgroup$
    – rhermans
    Commented Jul 14, 2022 at 14:42
5
$\begingroup$

Using the hint by @J.M.'spersistentexhaustion, we set the fit function to Sinc and set the restriction a > 0, b > 0, 0 < s < .1 instead of presupposing 50 < a < 70,20 < b < 50,0.02 < s < 0.05.

  • Add a translation x -> x + δ
Clear[fit];
fit = NonlinearModelFit[
  OrdInt, {a (Sinc[b Sin[s x/2]])^2 /. x -> x + δ, a > 0, 
   b > 0, 0 < s < .1, 0 < δ < .1}, {a, b, s, δ}, x]
Show[ListPlot[OrdInt, PlotTheme -> "Scientific", PlotStyle -> Blue, 
  PlotRange -> All], 
 Plot[fit[x], {x, -10, 10}, PlotStyle -> Red, PlotRange -> All]]

enter image description here

  • NMinimize
Ord = Array[1. # &, 21, -10];
Int = {1.233, 1.725, 1.737, 0.941, 0.453, 2.297, 11.06, 24.05, 41.6, 
   58.8, 1630, 55.7, 39.0, 26.7, 12.98, 2.936, 0.472, 1.11, 2.21, 
   2.38, 1.725};
OrdInt = Transpose[{Ord, Int}];
fitfun[x_] = a (Sinc[b Sin[s x/2]])^2;
sol = NMinimize[{Dot[fitfun /@ Ord - Int, fitfun /@ Ord - Int], a > 0,
    b > 0, 0 < s < .1}, {a, b, s}, Method -> Automatic]
Show[ListPlot[OrdInt, PlotRange -> All], 
 Plot[fitfun[x] /. sol[[2]], {x, -10, 10}, PlotStyle -> Red, 
  PlotRange -> All]]

{33.1874, {a -> 1629.95, b -> 178.54, s -> 0.0294933}}

enter image description here

$\endgroup$
2
  • $\begingroup$ The point at $x=0$ is quite bad. It makes it impossible for the model function to be fitted well on the data. But thanks for the answer. I'll try to understand it. $\endgroup$
    – Physor
    Commented Jul 14, 2022 at 14:46
  • $\begingroup$ This avoids using the NonlinearModelFit, it even makes the center point look not as an odd point. $\endgroup$
    – Physor
    Commented Jul 14, 2022 at 19:18

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.