0
$\begingroup$

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]*)]]
$\endgroup$
6
  • 2
    $\begingroup$ Your notebook includes pages and pages of code. Very few people will have the time and patience to wade through that much code and results to even try to understand what you are trying to do. You want to generate a minimal working example instead: add the specific data that is giving your trouble and the code that you are using to attempt the fit directly to your question. $\endgroup$
    – MarcoB
    Mar 20, 2016 at 1:15
  • $\begingroup$ Haha fair enough. I shall edit and include just one temperature $\endgroup$ Mar 20, 2016 at 1:17
  • $\begingroup$ Okay so finished editing. For some reason it wouldn't let me keep my link in the topic so I'm adding the shortened notebook and data set link here: drive.google.com/… $\endgroup$ Mar 20, 2016 at 1:39
  • $\begingroup$ What happens if you use Method -> NMinimize? $\endgroup$ Mar 20, 2016 at 2:08
  • 1
    $\begingroup$ @Anthony The definition of 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$
    – MarcoB
    Mar 20, 2016 at 3:17

1 Answer 1

1
$\begingroup$

I'm afraid that this is a comment, rather than a proper answer.

Your problem may actually lie within your Vfunction, rather than with FindFit, but it has been hidden by the fact that you wrapped FindFit in Quiet, thus suppressing all errors and warnings.

If you add Method -> NMinimize to FindFit and remove the Quiet wrapper, you will receive repeated warnings:

fit = 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 -> 10, Method -> NMinimize
 ]

FindRoot::cvmit: Failed to converge to the requested accuracy or precision within 100000 iterations. >>

This must come from within your Vfunction expression, which is repeatedly evaluated by FindFit, since it is the only expression invoked here that has a maximum number of iterations set to 100,000.

This may be due to some "brittleness" in your Vfunction, i.e. very strong sensitivity to the input parameters. Since you have a very good idea of what the values of the parameters should be, you may want to try and restrict the search regions on those parameters e.g. using constraints.

$\endgroup$

Your Answer

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

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