@@ -310,6 +310,9 @@ def fv(x, v, *a):
310
310
if method == 'brentq' :
311
311
# first bound the search using voc
312
312
voc_est = estimate_voc (photocurrent , saturation_current , nNsVth )
313
+ # start iteration slightly less than NsVbi when voc_est > NsVbi, to
314
+ # avoid the asymptote at NsVbi
315
+ xp = np .where (voc_est < NsVbi , voc_est , 0.9999 * NsVbi )
313
316
314
317
# brentq only works with scalar inputs, so we need a set up function
315
318
# and np.vectorize to repeatedly call the optimizer with the right
@@ -323,7 +326,7 @@ def vd_from_brent(voc, v, iph, isat, rs, rsh, gamma, d2mutau, NsVbi,
323
326
** method_kwargs )
324
327
325
328
vd_from_brent_vectorized = np .vectorize (vd_from_brent )
326
- vd = vd_from_brent_vectorized (voc_est , voltage , * args )
329
+ vd = vd_from_brent_vectorized (xp , voltage , * args )
327
330
elif method == 'newton' :
328
331
x0 , (voltage , * args ), method_kwargs = \
329
332
_prepare_newton_inputs (voltage , (voltage , * args ), method_kwargs )
@@ -443,6 +446,9 @@ def bishop88_v_from_i(current, photocurrent, saturation_current,
443
446
444
447
# first bound the search using voc
445
448
voc_est = estimate_voc (photocurrent , saturation_current , nNsVth )
449
+ # start iteration slightly less than NsVbi when voc_est > NsVbi, to avoid
450
+ # the asymptote at NsVbi
451
+ xp = np .where (voc_est < NsVbi , voc_est , 0.9999 * NsVbi )
446
452
447
453
def fi (x , i , * a ):
448
454
# calculate current residual given diode voltage "x"
@@ -461,10 +467,10 @@ def vd_from_brent(voc, i, iph, isat, rs, rsh, gamma, d2mutau, NsVbi,
461
467
** method_kwargs )
462
468
463
469
vd_from_brent_vectorized = np .vectorize (vd_from_brent )
464
- vd = vd_from_brent_vectorized (voc_est , current , * args )
470
+ vd = vd_from_brent_vectorized (xp , current , * args )
465
471
elif method == 'newton' :
466
472
x0 , (current , * args ), method_kwargs = \
467
- _prepare_newton_inputs (voc_est , (current , * args ), method_kwargs )
473
+ _prepare_newton_inputs (xp , (current , * args ), method_kwargs )
468
474
vd = newton (func = lambda x , * a : fi (x , current , * a ), x0 = x0 ,
469
475
fprime = lambda x , * a : bishop88 (x , * a , gradients = True )[3 ],
470
476
args = args , ** method_kwargs )
@@ -579,6 +585,9 @@ def bishop88_mpp(photocurrent, saturation_current, resistance_series,
579
585
580
586
# first bound the search using voc
581
587
voc_est = estimate_voc (photocurrent , saturation_current , nNsVth )
588
+ # start iteration slightly less than NsVbi when voc_est > NsVbi, to avoid
589
+ # the asymptote at NsVbi
590
+ xp = np .where (voc_est < NsVbi , voc_est , 0.9999 * NsVbi )
582
591
583
592
def fmpp (x , * a ):
584
593
return bishop88 (x , * a , gradients = True )[6 ]
@@ -592,12 +601,13 @@ def fmpp(x, *a):
592
601
vbr_a , vbr , vbr_exp ),
593
602
** method_kwargs )
594
603
)
595
- vd = vec_fun (voc_est , * args )
604
+ vd = vec_fun (xp , * args )
596
605
elif method == 'newton' :
597
606
# make sure all args are numpy arrays if max size > 1
598
607
# if voc_est is an array, then make a copy to use for initial guess, v0
608
+
599
609
x0 , args , method_kwargs = \
600
- _prepare_newton_inputs (voc_est , args , method_kwargs )
610
+ _prepare_newton_inputs (xp , args , method_kwargs )
601
611
vd = newton (func = fmpp , x0 = x0 ,
602
612
fprime = lambda x , * a : bishop88 (x , * a , gradients = True )[7 ],
603
613
args = args , ** method_kwargs )
0 commit comments