I'm currently trying to fit some complicated data sets and I am having some luck. The higher temperature data works just fine with FindFit
.
Unfortunately, however, the lower temperature data refuses to fit, regardless of how close the starting parameters are.
The code is below. You will also need a data set to import, which you can download from this link to GoogleDrive.
axisFlip = # /. {x_Line | x_GraphicsComplex :>
MapAt[#~Reverse~2 &, x, 1],
x : (PlotRange -> _) :> x~Reverse~2} &;
SetDirectory["F:\\IVsandtemplatesdesktop\\IVTD_T793_02_27_2015"];
filename = "T793_Dark_150_2015-02-26 18-17-09.txt";
dataimp = Import[filename, "Table"][[11 ;;]];
jvdata = {Thread[{dataimp[[;; , 1]], 0.001*Abs[dataimp[[;; , 2]]]}]};
jvdata = Select[Table[{jvdata[[1, i, 1]], jvdata[[1, i, 2]]}, {i, 1, Length[jvdata[[1, ;; , 1]]]}],
NumericQ[#[[1]]] && NumericQ[#[[2]]] && #[[2]] != 0 &];
jvdata = Sort[jvdata, #1[[1]] < #2[[1]] &];
vjdata = Transpose[{Sign[jvdata[[;; , 1]]] jvdata[[;; , 2]], jvdata[[;; , 1]]}];
vjdataforward = Select[vjdata, #[[2]] > 0 &];
vjdatareverse = Select[vjdata, #[[2]] < 0 &];
Clear[Jfunction];
Jfunction[V_?NumericQ, J01_?NumericQ, A1_?NumericQ, J02_?NumericQ,
A2_?NumericQ, Rs_?NumericQ, Rsh_?NumericQ, k_?NumericQ,
m_?NumericQ] :=
J /. FindRoot[
J == Abs[J01 (Exp[A1 (V - Sign[V] J Rs)] - 1)] +
Abs[J02 (Exp[A2 (V - Sign[V] J Rs)] - 1)] +
k Abs[(V - Sign[V] J Rs)]^m +
Abs[(V - Sign[V] J Rs)/Rsh], {J, -5, 4}, AccuracyGoal -> 6,
PrecisionGoal -> 6, MaxIterations -> 100000];
Clear[Vfunction];
Vfunction[J_?NumericQ, J01_?NumericQ, A1_?NumericQ, J02_?NumericQ,
A2_?NumericQ, Rs_?NumericQ, Rsh_?NumericQ, k_?NumericQ,
m_?NumericQ] :=
V /. FindRoot[
J == J01 (Exp[A1 (V - J Rs)] - 1) + J02 (Exp[A2 (V - J Rs)] - 1) +
Sign[J] k Abs[(V - J Rs)]^m + (V - J Rs)/
Rsh, {V, -3 HeavisideTheta[-J], 3 HeavisideTheta[J]},
AccuracyGoal -> 6, PrecisionGoal -> 6, MaxIterations -> 100000];
T = 150; (* Temperature in Kelvin *)
q = 1.602176565*10^-19;(*C*)
kb = 1.3806488*10^-23;(*J/K*)
J01init = 1.2*^-33;
A1init = 63;
J02init = 2.601488095513*^-12;
A2init = 13.339343747213;
Rsinit = 4500.0;
Rshinit = 5.9*^9;
kinit = 1.5*^-9;
minit = 2.6;
Show[
ListLogLinearPlot[MapAt[Abs[#] &, #, 1] & /@ vjdata, Joined -> True],
LogLinearPlot[{Vfunction[j, J01init, A1init, J02init, A2init,
Rsinit, Rshinit, kinit, minit],
Vfunction[-j, J01init, A1init, J02init, A2init, Rsinit, Rshinit,
kinit, minit]}, {j, Min[Abs[vjdata[[;; , 1]]]],
1.5*Max[Abs[vjdata[[;; , 1]]]]},
PlotStyle -> Directive[Dashed, Red]]
] // axisFlip
fit = Quiet[
FindFit[vjdata, {Vfunction[j, J01, Abs[A1], J02, Abs[A2], Abs[Rs],
Abs[Rsh], Abs[k], Abs[m]]},
{{J01, J01init}, {A1, A1init}, {J02, J02init}, {A2, A2init}, {Rs,
Rsinit}, {Rsh, Rshinit}, {k, kinit}, {m, minit}}, j,
MaxIterations -> 10000(*,EvaluationMonitor :> Print[
"J01:",J01," A1:",A1," J02:",J02," A2:",A2," Rs:",Rs," Rsh:",Rsh,
" k:",k," m:",m]*)]]
Method -> NMinimize
? $\endgroup$Jfunction
in your code above seems irrelevant to your current issue, so it should probably be removed for the sake of clarity and readability. Similarly,jvdata
seems to be unused. $\endgroup$