@@ -310,6 +310,9 @@ def fv(x, v, *a):
310310 if method == 'brentq' :
311311 # first bound the search using voc
312312 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 )
313316
314317 # brentq only works with scalar inputs, so we need a set up function
315318 # 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,
323326 ** method_kwargs )
324327
325328 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 )
327330 elif method == 'newton' :
328331 x0 , (voltage , * args ), method_kwargs = \
329332 _prepare_newton_inputs (voltage , (voltage , * args ), method_kwargs )
@@ -443,6 +446,9 @@ def bishop88_v_from_i(current, photocurrent, saturation_current,
443446
444447 # first bound the search using voc
445448 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 )
446452
447453 def fi (x , i , * a ):
448454 # calculate current residual given diode voltage "x"
@@ -461,10 +467,10 @@ def vd_from_brent(voc, i, iph, isat, rs, rsh, gamma, d2mutau, NsVbi,
461467 ** method_kwargs )
462468
463469 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 )
465471 elif method == 'newton' :
466472 x0 , (current , * args ), method_kwargs = \
467- _prepare_newton_inputs (voc_est , (current , * args ), method_kwargs )
473+ _prepare_newton_inputs (xp , (current , * args ), method_kwargs )
468474 vd = newton (func = lambda x , * a : fi (x , current , * a ), x0 = x0 ,
469475 fprime = lambda x , * a : bishop88 (x , * a , gradients = True )[3 ],
470476 args = args , ** method_kwargs )
@@ -579,6 +585,9 @@ def bishop88_mpp(photocurrent, saturation_current, resistance_series,
579585
580586 # first bound the search using voc
581587 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 )
582591
583592 def fmpp (x , * a ):
584593 return bishop88 (x , * a , gradients = True )[6 ]
@@ -592,12 +601,13 @@ def fmpp(x, *a):
592601 vbr_a , vbr , vbr_exp ),
593602 ** method_kwargs )
594603 )
595- vd = vec_fun (voc_est , * args )
604+ vd = vec_fun (xp , * args )
596605 elif method == 'newton' :
597606 # make sure all args are numpy arrays if max size > 1
598607 # if voc_est is an array, then make a copy to use for initial guess, v0
608+
599609 x0 , args , method_kwargs = \
600- _prepare_newton_inputs (voc_est , args , method_kwargs )
610+ _prepare_newton_inputs (xp , args , method_kwargs )
601611 vd = newton (func = fmpp , x0 = x0 ,
602612 fprime = lambda x , * a : bishop88 (x , * a , gradients = True )[7 ],
603613 args = args , ** method_kwargs )
0 commit comments