I'm trying to fit experimental data with FindFit and implicitly calculated function. It seems, that function works fine and satisfactorily approximates data when parameters are fed manually. However when trying to apply FindFit with the same set of parameters as starting values, it returns "Tensors {..1..} and {..2..} have incompatible shapes". These tensors are equal. Manual calculation shows, that their elements are differences between experimental and fitted values (for starting values of parameters) for each experimental point. Thus by multiplying them, FindFit probably tries to calculate the sum of squared residuals. If above is correct, why does this error emerge? I tried substituting the fitting function with simple second-order polynomial and it works. Here is the code:
Remove["Global`*"]
Hk = 952.45844; Rahe = 815; const = 797; AngCr =
54.35 \[Degree]; Ang = 45 \[Degree];
a[b_?NumericQ] := ArcSin[Tan[b]/Tan[AngCr] ];
NewH[b_?NumericQ, c_?NumericQ, Ang_?NumericQ, Hamp_?NumericQ] :=
Flatten[({
{Cos[c], -Sin[c], 0},
{Sin[c], Cos[c], 0},
{0, 0, 1}
}).({
{Cos[b], 0, Sin[b]},
{0, 1, 0},
{-Sin[b], 0, Cos[b]}
}).({
{1, 0, 0},
{0, Cos[a[b]], -Sin[a[b]]},
{0, Sin[a[b]], Cos[a[b]]}
}).({
{Hamp*Cos[Ang \[Degree]]},
{Hamp*(-Sin[Ang \[Degree]])},
{0}
})];
(* Implicit fitting function: *)
Rfit[b_?NumericQ, c_?NumericQ, Ang_?NumericQ, Hamp_?NumericQ,
Rphe_?NumericQ] :=
Rahe*Sin[theta] -
Rphe*Cos[theta]^2*
Abs[(NewH[b, c, Ang, Hamp][[1]]*NewH[b, c, Ang, Hamp][[2]])/(
NewH[b, c, Ang, Hamp][[1]]^2 + NewH[b, c, Ang, Hamp][[2]]^2)] +
const /.
Quiet@NSolve[
Tan[theta] == (Hk*Sin[theta] + NewH[b, c, Ang, Hamp][[3]])/Sqrt[
NewH[b, c, Ang, Hamp][[1]]^2 + NewH[b, c, Ang, Hamp][[2]]^2] &&
theta <= Pi/2 && theta > 0.5, theta, Reals]
FindFit[ExpData,
Rfit[b, c, Ang, Hamp,
Rphe], {{b, 0, -0.1, 0.1}, {c, 0, -0.1, 0.1}, {Rphe, 450, 400,
500}}, Hamp]
(* Manual approximation works fine: *)
Show[
ListPlot[
Parallelize[
Table[Flatten[{Hamp,
Rfit[-2.5 \[Degree], 0 \[Degree], 45, Hamp, 465]}], {Hamp, -401,
401, 10}]], PlotStyle -> {Red, AbsolutePointSize[6]}],
ListPlot[ExpData, PlotStyle -> {Black, AbsolutePointSize[5]}],
PlotRange -> All
]
Here is the piece of experimental data:
ExpData = {{-377.4285`, 1503.685`}, {-366.8757`,
1509.651`}, {-357.7828`, 1514.686`}, {-347.0045`,
1520.59`}, {-338.1022`, 1525.638`}, {-327.2154`,
1530.05`}, {-318.4717`, 1534.859`}, {-307.7064`,
1539.4`}, {-299.1506`, 1543.492`}, {-288.0877`,
1548.19`}, {-279.8359`, 1552.482`}, {-268.8763`,
1557.043`}, {-260.4716`, 1560.633`}, {-249.6292`,
1563.926`}, {-240.9715`, 1567.46`}, {-230.3227`,
1570.869`}, {-220.9978`, 1573.732`}, {-209.8838`,
1578.208`}, {-202.0967`, 1580.598`}, {-191.8868`,
1583.704`}, {-181.9674`, 1586.1`}, {-172.2505`,
1588.278`}, {-162.1441`, 1591.064`}, {-152.7795`,
1592.871`}, {-142.4023`, 1594.542`}, {-133.2651`,
1597.427`}, {-125.6026`, 1597.731`}, {-113.7561`,
1601.733`}, {-103.0388`, 1603.187`}, {-94.00935`,
1604.345`}, {-83.34793`, 1605.78`}, {-74.33023`,
1606.449`}, {-63.44335`, 1608.238`}, {-54.81877`,
1608.54`}, {-44.04633`, 1608.988`}, {-35.41862`,
1610.753`}, {-24.58675`, 1610.793`}, {-17.20935`,
1610.65`}, {-5.281529`, 1612.059`}, {2.261039`,
1610.745`}, {13.69646`, 1611.337`}, {23.07399`,
1611.651`}, {33.15822`, 1609.854`}, {43.12982`,
1609.793`}, {52.70468`, 1608.815`}, {62.87678`,
1608.523`}, {72.25062`, 1607.767`}, {82.43324`,
1606.551`}, {91.69639`, 1605.46`}, {97.61601`,
1601.687`}, {111.4225`, 1602.904`}, {121.9307`,
1601.799`}, {130.9983`, 1599.582`}, {141.4585`,
1598.096`}, {150.7068`, 1595.881`}, {161.252`,
1593.875`}, {170.2011`, 1591.611`}, {180.8177`,
1588.666`}, {189.7459`, 1585.693`}, {200.3986`,
1583.918`}, {209.3968`, 1581.302`}, {219.8005`,
1578.068`}, {227.8856`, 1574.321`}, {239.7572`,
1571.973`}, {249.5857`, 1568.514`}, {259.3328`,
1565.229`}, {269.4772`, 1561.71`}, {279.0915`,
1558.152`}, {289.2914`, 1553.891`}, {298.7476`,
1549.908`}, {308.9017`, 1545.625`}, {318.3074`,
1541.339`}, {328.4131`, 1536.248`}, {337.7596`,
1532.195`}, {347.9528`, 1528.05`}, {357.3661`,
1522.416`}, {367.6034`, 1517.481`}, {377.0643`, 1512.4`}};
Thanks a lot in advance.
Reals
. If for your parameter set or during the fitting procedure no real solution is found, this will probably result in a problem down the road. This might cause your incompatible tensors. $\endgroup$Ang
in degrees already, but later define a function usingAng Degree
. This is probably not wanted and in general dangerous causing many errors difficult to find. Try not to use a degree conversion inside your functions, but only on function call, i.e. on parameter definition. $\endgroup$Degree
comment, missed it, now it's fixed. As forReals
, I believe it's OK, because I tuned theRfit
function so that it returns exactly one real value (for sets of parameters, which are experimentally reasonable). $\endgroup$