2
$\begingroup$

I'm trying to fit linear combination of 2 functions to my experimental data set (it represents voltage of 2 photodiodes - Voc1 and Voc2 - connected in series under illumination - S)

A=0.02585

Voc1 = Voc /. Solve[S == Jos*(Exp[-Voc/A/n] (*correction: + -> -*) - 1) + Voc/R1, Voc] (*analytical solution for Voc1(S) exists/ n in range 1-1.3*)

S = Jo1*(Exp[Voc2/A] - 1) + Jo2*(Exp[Voc2/2/A] - 1) + Voc2/R2 (*there is no analytical solution for Voc2(S)*)

Sumaric formula:

V = Voc2 - Voc1 
(*Data have a format {S, V}*)
FindFit[Data1, {V, n>=1, n<1.3}, {{Jos, 0.001}, {Jo1, 0.001}, {Jo2, 0.001}, {R1, 1}, {R2, 1}, {n,1}}, S] 

Is there a method to force Mathematica to search fitting parameters Jo1, Jo2 and R2 through the relation S(Voc2)? I have no experience in using Mathematica so I would be much greatful for any help.

Unfortunately, fitting of inverse function S(V) does not apply for my data sets. Here is a sample of it:

    Data1={{8.17926024190235, 0.0049607354},{9.11306735079205, 0.0060270454}, {9.1096811048767, 0.0068196254}, {9.06089104262243, 0.0073612254}, {9.00914826766689, 0.0079031154}, {8.95623378132195, 0.0083917854}, {8.90293263021852, 0.0087984254}, {8.84699512848895, 0.0091917854}, {8.78935864524477, 0.0095545854}, {8.73051529926951, 0.0098653254}, {8.66971519527397, 0.0101341754}, {8.60693489903036, 0.0103706954}, {8.54230329879151, 0.0105664954}, {8.47485959121811, 0.0107404254}, {8.40413509175443, 0.0108061454}, {8.33084454434797, 0.0108637654}, {8.25396856008997, 0.0109089754}, {8.17310875710804, 0.0108933554}, {8.0870817068989, 0.0108352454}, {7.99578195543749, 0.0107799754}, {7.89778001482876, 0.0107143454}, {7.79149407469702, 0.0105488154}, {7.67407687636607, 0.0103703054}, {7.54384115543517, 0.0101757754}, {7.39703743545827, 0.0099686454}, {7.22675261923796, 0.0097743054}, {7.02357786431742, 0.0095367154}, {6.77334717999891, 0.0092961854}, {6.45889499442783, 0.0090206954}, {6.06518825047829, 0.0087113154}, {5.61240381827561, 0.0084199154}, {5.14708207420644, 0.0081176654}, {4.70470243914156, 0.0077849554}, {4.29643132262188, 0.0074848554}, {3.92319437664502, 0.0072034054}, {3.58317544855741, 0.0069027254}, {3.27268364748247, 0.0065216754}, {2.98914120836355, 0.0061539954}, {2.73028672821911, 0.0057656154}, {2.49241759905868, 0.0054350454}, {2.27620169637421, 0.0051090754}, {2.08003377556223, 0.0047700154}, {1.90123061754104, 0.0044163954}, {1.73719102302619, 0.0040777254}, {1.58757519571475, 0.0037371954}, {1.4501217326252, 0.0034328054}, {1.32410417269611, 0.0031199154}, {1.20862029815765, 0.0027365154}, {1.10151533176473, 0.0025803654}, {1.00379108675529, 0.0022939354}, {0.914453951871111, 0.0019085854}, {0.832662638334616, 0.0015910074}, {0.756827133790399, 0.0013745034}, {0.686850186193142, 0.0011051674}, {0.622520887492753, 0.000778995400000001}, {0.563666996114991, 0.000530460400000001}, {0.510116270485618, 0.000317374400000001}, {0.461221925917687, 7.94834000000012*10^-5}, {0.416653539799391, -0.000145414599999999}, {0.375254632989399, -0.000345804599999999}, {0.338380875565239, -0.000547764599999999}, {0.305174574789875, -0.000737704599999999}, {0.27520688429479, -0.000907034599999999}, {0.248208310460424, -0.0011045946}, {0.224041763054218, -0.0012166146}, {0.202604131473906, -0.0013332146}, {0.183238085630038, -0.0014990346}, {0.165885039953145, -0.0016193446}, {0.150684428098565, -0.0017063546}, {0.137342150507561, -0.0018159246}, {0.125315704806843, -0.0019337946}, {0.114720387397129, -0.0020096746}, {0.105217339344606, -0.0020616246}, {0.0972590755878564, -0.0021219846}, {0.0895411298370715, -0.0021967846}, {0.0828873323701323, -0.0022448346}, {0.0772919418012306, -0.0023145546}, {0.0722972876616702, -0.0023672946}, {0.0674342167111384, -0.0024032346}, {0.0630688887588203, -0.0024410246}, {0.0591613484463375, -0.0024695346}, {0.0559288310652834, -0.0025231546}, {0.0525933202531018, -0.0025415146}, {0.0502933679668646, -0.0025812546}, {0.0475128968398378, -0.0026536246}, {0.0450412888350547, -0.0027130946}, {0.0434278422518622, -0.0027144646}, {0.0404413842625804, -0.0026979546}, {0.039045407313259, -0.0027078246}, {0.0378725242124778, -0.0027299846}, {0.0353323710914153, -0.0027638746}, {0.0337875867956411, -0.0027842846}, {0.033192591752108, -0.0027982546}, {0.0322256955135818, -0.0028089946}, {0.0306523214599065, -0.0028189546}, {0.0288157810281738, -0.0028417046}, {0.0278889573191649, -0.0028650446}, {0.0275513872678811, -0.0028357546}, {0.0271165651712778, -0.0029846746}, {0.0260924894169494, -0.0030191446}, {0.0248109886703715, -0.0029347746}, {0.0235980330400731, -0.0029162146}, {0.0227226474610585, -0.0029559646}, {0.0221677249470426, -0.0029830146}, {0.0219160413406012, -0.0029375046}, {0.0216299094193117, -0.0029340946}, {0.0211035766631969, -0.0029735446}, {0.0206344234228844, -0.0029864346}, {0.0195587923674228, -0.0029925846}, {0.0187978829911517, -0.0030057746}, {0.01791113181166, -0.0029968846}, {0.0172016605653833, -0.0029860446}, {0.0167211417245937, -0.0029816446}, {0.0164921893191065, -0.0029580146}, {0.0162462470984732, -0.0029940546}, {0.0161603606536308, -0.0030289146}, {0.0159259012046135, -0.0029600646}, {0.0157427627144515, -0.0029598746}, {0.0153766029052666, -0.0029816446}, {0.0150104430960816, -0.0029687546}, {0.0144555205820657, -0.0029468846}, {0.0142266853477175, -0.0029402446}, {0.0133512997687028, -0.0029616246}, {0.012824967012588, -0.0029624146}, {0.0001, 0}}

Other sample of data

   Data2={{7.66998, 0.0746971}, {8.71071, 0.0744526}, {8.72344, 0.0753476}, {8.66343, 0.0760575}, {8.59626, 0.0767095}, {8.52452, 0.0773267}, {8.44956, 0.077879}, {8.37184, 0.0783796}, {8.29023, 0.0788011}, {8.20451, 0.079142}, {8.1135, 0.0794288}, {8.01715, 0.0796146}, {7.91307, 0.0797254}, {7.8004, 0.0797356}, {7.67546, 0.0796569}, {7.53709, 0.0794985}, {7.38014, 0.0792506}, {7.19697, 0.0788934}, {6.97599, 0.0784274}, {6.70041, 0.0778609}, {6.34991, 0.0772021}, {5.9158, 0.0764115}, {5.43354, 0.0755682}, {4.95797, 0.0745928}, {4.51491, 0.0735294}, {4.11132, 0.0723891}, {3.74501, 0.0711492}, {3.41368, 0.0698042}, {3.11236, 0.0683672}, {2.8393, 0.0668464}, {2.59098, 0.0652619}, {2.36483, 0.063601}, {2.15964, 0.0618814}, {1.973, 0.0600974}, {1.80241, 0.058253}, {1.64752, 0.056351}, {1.50627, 0.0543909}, {1.37775, 0.0524134}, {1.26045, 0.0504159}, {1.15298, 0.0483989}, {1.05403, 0.0463526}, {0.964072, 0.0442964}, {0.882035, 0.0422363}, {0.806784, 0.0401821}, {0.737677, 0.0381474}, {0.674572, 0.0361018}, {0.616495, 0.0340911}, {0.563087, 0.0320886}, {0.514206, 0.0301336}, {0.469659, 0.0282288}, {0.428232, 0.0263684}, {0.389654, 0.0245556}, {0.354342, 0.0227987}, {0.322342, 0.0210955}, {0.292936,0.0194458}, {0.266132, 0.0178668}, {0.241347, 0.0163532}, {0.218908, 0.0149263}, {0.198124, 0.0135607}, {0.179512,0.0122718}, {0.162514, 0.0110569}, {0.147147, 0.00991298}, {0.132918, 0.0088625}, {0.120297, 0.00788408}, {0.108803, 0.00697392}, {0.0984935, 0.00612861}, {0.0889791, 0.00535918}, {0.0807749, 0.00466298}, {0.0732857, 0.00403193}, {0.0666891, 0.00346289}, {0.0604873, 0.00293222}, {0.0553439, 0.00246484}, {0.0509042, 0.00204863}, {0.0464759, 0.00167333}, {0.0431976, 0.001358}, {0.0397535, 0.00104218}, {0.036767, 0.000766985}, {0.0342095, 0.000534075}, {0.032436, 0.000330364}, {0.0297928, 0.000160051}, {0.0283739, -0.000018073}, {0.0275158, -0.000172373}, {0.0256506, -0.000303523}, {0.0236883, -0.000438773}, {0.0228186, -0.000542683}, {0.0222522, -0.000659383}, {0.0213253, -0.000726663}, {0.0201468, -0.000851663}, {0.0186535, -0.000914073}, {0.0176065, -0.00102354}, {0.0170974, -0.00109473}, {0.0168513, -0.00115342}, {0.0164909, -0.00121641}, {0.0158558, -0.00130352}, {0.0149747, -0.00135586}, {0.0140136, -0.00140098}, {0.0130982, -0.00145264}, {0.0125661, -0.00150489}, {0.011891, -0.0015501}, {0.0114791, -0.00159756}, {0.0113417, -0.00164112}, {0.0111873, -0.00168077}, {0.0111014, -0.00172334}, {0.0109699, -0.00174454}, {0.010844, -0.0017795}, {0.0105637, -0.00179297}, {0.0103348, -0.0018253}, {0.010003, -0.00185059}, {0.00971119, -0.00188653}, {0.00918483, -0.00190098}, {0.00895027, -0.00191885}, {0.00837813, -0.00192256}, {0.0080978, -0.00195332}, {0.00774308, -0.00197413}, {0.00743985, -0.0019918}, {0.00714235, -0.00200928}, {0.00686201, -0.0020253}, {0.00658738, -0.00204131}, {0.00636426, -0.00206768}, {0.00615257, -0.00207178}, {0.00595233, -0.00208672},{0.0058894, -0.00210313}, {0.00583791, -0.00211602}, {0.00576353, -0.00213135}, {0.0001, 0}}
$\endgroup$
4
  • $\begingroup$ try to define a function voc2[s_?NumericQ]:= FindRoot[s==Jo1..etc..] and then you will need to use NonLinearModelFit $\endgroup$
    – george2079
    Nov 12, 2015 at 15:42
  • $\begingroup$ I wonder, why are you trying to measure the voltage of series-connected photodiodes? A photodiode is a current source, so if I were you, I would connect them in parallel and measure the total photocurrent. But maybe you have some special reason to be doing this. $\endgroup$ Nov 14, 2015 at 17:57
  • 1
    $\begingroup$ @Oleksandr R. This is a kind of unwanted element in the circuit - under high carriers injection, another (Schottky) junction shows up between semiconductor (part of pn photodiode) and rear metal contact. $\endgroup$
    – P_M
    Nov 14, 2015 at 19:29
  • $\begingroup$ @george2079 Thank you for the advice, I have tried to use following definition for voc2 voc2[S_?NumericQ, Jo1_?NumericQ, Jo2_?NumericQ, R2_?NumericQ] := y /. FindRoot[ S == Voc2/R2 + Jo1 ( Exp[Voc2/A] - 1) + Jo2 (Exp[Voc2/A/2] - 1), {Voc2, 0.005}] // for all tested combinations of starting values for fit and data sets I got message: NonlinearModelFit::sszero: The step size in the search has become less than the tolerance prescribed by the PrecisionGoal (...) or NonlinearModelFit::nrlnum: The function value (...) is not a list of real numbers with dimensions {125} at {Jos,Jo1,Jo2,R1,R2} $\endgroup$
    – P_M
    Nov 14, 2015 at 19:57

1 Answer 1

1
$\begingroup$

Update

To start you have one data point that needs to be fixed.

7.94834000000012*E-05 -> 7.94834000000012*10^-5.

Probably copied from a different format for numbers.

Examine the data

I am going to use the form from your original question. Using the minus sign in the exponent Jos*(Exp[-Voc/A/n] is not helpful.

My understanding is that you have a measurement of illumination, S, and the difference between two photodiode voltages, V = Voc2 - Voc1.

You have a model which relates S to Voc1 which is invertible.

S = Jos*(Exp[Voc1/A] - 1) + Voc1/R1

We can invert this so that Voc1 is a function of S

Voc1[S_, Jos_, R1_] := R1 (Jos + S) -
  517/20000 ProductLog[20000/517 Jos R1 Exp[20000/517 (Jos + S) R1]]

The relationship between S and Voc2 can not be inverted.

A function is defined to relate the two.

S[Voc2_, Jo1_, Jo2_, R2_] := 
 Jo1*(Exp[Voc2/A] - 1) + Jo2*(Exp[Voc2/2/A] - 1) + Voc2/R2

We can use this function to derive a pseudo-function that has Voc2 as the input and outputs the illumination, S.

Voc2[Sdata_, Jo1_, Jo2_, R2_] := Module[
  {
   voc2
   },
  voc2 /. FindRoot[Sdata - S[voc2, Jo1, Jo2, R2], {voc2, 0}]
  ]

We can validate it via:

S[0.1, 0.001, 0.001, 1]
(* 0.152788 *)

and then

Voc2[0.152788, 0.001, 0.001, 1]
(* 0.1 *)

I analyzed the individual relationships to get an idea of the order of magnitude and shape of the data.

Eventually I was able to come up with numbers for the parameters that look somewhat like your data (see Grid Search below).

Sorry for the long piece of code below. It essentially plots the individual components of the contribution to S from Voc1 in the upper left plot, the contributions to S from Voc2 in the lower left plot, S from Voc1, Voc2 and the difference (plus the data) in the upper right plot and finally only S vs Voc2 - Voc1 and the data in the lower right plot.

Here is the code (that you can shrink in a notebook) followed by an image of the Manipulate.

Manipulate[
 Row[{
   Column[{
     Column[{
       Style["Jos*(Exp[voc1/A]-1)", Red],
       Style["voc1/R1", Blue],
       Style["S[Voc1]", Black]
       }],
     Show[
      ParametricPlot[
       {
        Jos*(Exp[voc1/A] - 1) + voc1/R1, voc1
        },
       {voc1, 0, voc2Max},
       PlotStyle -> Black,
       AxesLabel -> {"S", "Voc1"}],
      ParametricPlot[
       {
        Jos*(Exp[voc1/A] - 1), voc1
        },
       {voc1, 0, voc2Max},
       PlotStyle -> Red],
      ParametricPlot[
       {
        voc1/R1, voc1
        },
       {voc1, 0, voc2Max},
       PlotStyle -> Blue],
      PlotRange -> All,
      AspectRatio -> 1/GoldenRatio,
      ImageSize -> 380
      ],

     Column[{
       Style["Jo1*(Exp[voc2/A]-1)", Red],
       Style["Jo2*(Exp[voc2/2/A]-1)", RGBColor[0, 0.7, 0]],
       Style["voc2/R2", Blue],
       Style["S[Voc2]", Black]
       }],
     Show[
      ParametricPlot[
       {
        Jo1*(Exp[voc2/A] - 1) + Jo2*(Exp[voc2/2/A] - 1) + voc2/R2, voc2
        },
       {voc2, 0, voc2Max},
       PlotStyle -> Black,
       AxesLabel -> {"S", "Voc2"}],
      ParametricPlot[
       {
        Jo1*(Exp[voc2/A] - 1), voc2
        },
       {voc2, 0, voc2Max},
       PlotStyle -> Red],
      ParametricPlot[
       {
        Jo2*(Exp[voc2/2/A] - 1), voc2
        },
       {voc2, 0, voc2Max},
       PlotStyle -> RGBColor[0, 0.7, 0]],
      ParametricPlot[
       {
        voc2/R2, voc2
        },
       {voc2, 0, voc2Max},
       PlotStyle -> Blue],
      PlotRange -> All,
      AspectRatio -> 1/GoldenRatio,
      ImageSize -> 380
      ]
     },
    Alignment -> Center],

   Column[{
     Column[{
       Style["Voc1[S]", Blue],
       Style["Voc2[S]", Black],
       Style["Voc2[S]-Voc1[S]", Red]
       }],
     Show[
      Plot[Voc1[S, Jos, R1], {S, 0, 9.1},
       PlotStyle -> Blue, AxesLabel -> {"S", "V"}
       ],
      ParametricPlot[
       {
        S[voc2, Jo1, Jo2, R2], voc2
        },
       {voc2, 0, voc2Max},
       PlotStyle -> Black],
      ParametricPlot[
       {
        S[voc2, Jo1, Jo2, R2], 
        voc2 - Voc1[S[voc2, Jo1, Jo2, R2], Jos, R1]
        },
       {voc2, 0, voc2Max},
       PlotStyle -> Red],
      ListPlot[data1, PlotStyle -> Red],
      PlotRange -> All,
      AspectRatio -> 1/GoldenRatio,
      ImageSize -> 380
      ],

     Column[{
       "",
       "",
       Style["Voc2[S]-Voc1[S]", Red],
       Style["data (dots)", Red]
       }],
     Show[
      ParametricPlot[
       {
        S[voc2, Jo1, Jo2, R2], 
        voc2 - Voc1[S[voc2, Jo1, Jo2, R2], Jos, R1]
        },
       {voc2, 0, voc2Max},
       PlotStyle -> Red],
      ListPlot[data1, PlotStyle -> Red],
      PlotRange -> All,
      AspectRatio -> 1/GoldenRatio,
      ImageSize -> 380
      ]
     },
    Alignment -> Center]
   }],

 Grid[{
  {Control[{{Jos, 0.0032}, 0.001, 0.05, Appearance -> "Open"}],
   Control[{{R1, 1.4}, 0.0001, 5., Appearance -> "Open"}],
   Control[{{voc2Max, 0.215}, 0.01, 10., Appearance -> "Open"}]},
  {Control[{{Jo1, 0.002}, 0.0001, 0.1, Appearance -> "Open"}],
   Control[{{Jo2, 0.015}, 0.0001, 0.1, Appearance -> "Open"}],
   Control[{{R2, 2}, 0.0001, 5., Appearance -> "Open"}]
   }
  }]
 ]

Now the image of the Manipulate.

Mathematica graphics

I needed to use my full screen in order to see this as two rows and two columns. The image in stack exchange appears as a single column.

Optimization

I created a function which computes the reconstructed voltage, V, from the input illumination, S.

modelFunction[Sdata_, Jos_, R1_, Jo1_, Jo2_, R2_] := Module[
  {
   voc1,
   voc2
   },

  voc1 = Voc1[Sdata, Jos, R1];
  voc2 = Voc2[Sdata, Jo1, Jo2, R2];

  voc2 - voc1
  ]

Unfortunately when I attempted to use NonlinearModelFit it would not run and gave error messages.

nlm = NonlinearModelFit[data1,
  {
   modelFunction[Sdata, Jos, R1, Jo1, Jo2, R2],
   0.01 > Jos > 0.0001, 3 > R1 > 0.1,
   01 > Jo1 > 0.0001, 0.5 > Jo2 > 0.001, 3 > R2 > 2
   },
  {
   {Jos, 0.0019}, {R1, 1},
   {Jo1, 0.001}, {Jo2, 0.024}, {R2, 2}
   },
  Sdata]

Here are the two error messages that repeated:

FindRoot::nlnum: The function value {0. +Sdata} is not a list of numbers with dimensions {1} at {voc2$21459204} = {0.}. >>

ReplaceAll::reps: {FindRoot[Sdata-S[voc2$21459204,Jo1,Jo2,R2],{voc2$21459204,0}]} is neither a list of replacement rules nor a valid dispatch table, and so cannot be used for replacing. >>

NMinimize

I was able to use NMinimize but it didn't really give meaningful results.

Grid Search

Finally I constructed a function to sweep each variable over a region that I hoped covered the minimum.

searchData = Table[
   {
    objectiveFunction[data1[[20 ;; 124]], Jos, R1, Jo1, Jo2, R2],
    Jos, R1, Jo1, Jo2, R2
    },
   {Jos, 0.0014, 0.0033, 0.0002},
   {R1, 0.5, 1.4, 0.1},
   {Jo1, 0.0011, 0.002, 0.0001},
   {Jo2, 0.015, 0.034, 0.002},
   {R2, 1, 2.9, 0.2}
   ];

The objective function computes the cumulative error squared between the measured and reconstructed voltage:

objectiveFunction[data_, Jos_, R1_, Jo1_, Jo2_, R2_] := Module[
  {
   Sdata,
   V,
   voc1,
   voc2,
   Vrecon,
   residual
   },

  Sdata = data[[All, 1]];
  V = data[[All, 2]];
  Vrecon = Map[modelFunction[#, Jos, R1, Jo1, Jo2, R2] &, Sdata];

  (*Compute the residual*)
  residual = Vrecon - V;

  (*The objective function is the sum of the residuals squared*)
  Total@Map[#^2 &, residual]
  ]

On my machine it took an hour and a half to compute the 100,000 points.

Mathematica graphics

The quality of the fit can be examined by looking at the Manipulate. Indeed the starting value for the parameters were adjusted to be the output from the grid search.

$\endgroup$
3
  • $\begingroup$ Dear Jack. Thank you so much for all this work! Your understanding of the problem is absolutely correct. I have tried to do some adjust of fitting parameters and you exactly pointed out mistake in the model - since 1st diode is polarised in opposite direction (V=Voc2-Voc1), the "-" should be also included in exp component (also there can be added little more freedom to Voc1 by introducing ideality factor n)- I corrected the code and added other sample of data (perhaps in 1st case something went wrong during measurments). Thank you again and I much appreciate your answer! $\endgroup$
    – P_M
    Nov 14, 2015 at 19:17
  • $\begingroup$ For sure: V=0 at S=0 is the solution, but when correction is applied this is only 1 from 3 allowed cross points with S axis at V=0 (the "manual" example can be Jos=0.33, R1=0.07, Jo1=0.002 and Jo2=0.064). However still missing can be a factor which describes the difference in light intensity between reference solar cell and tested photodiode (S->a*S). Thanks again Jack! $\endgroup$
    – P_M
    Nov 15, 2015 at 14:46
  • $\begingroup$ BTW. Big miss that I cannot vote due to low reputation. I found your answer very useful, with your code simulations go much faster! $\endgroup$
    – P_M
    Nov 15, 2015 at 14:50

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.