@@ -509,12 +509,12 @@ def _lambertw_v_from_i(current, photocurrent, saturation_current,
509509 # Ensure that we are working with read-only views of numpy arrays
510510 # Turns Series into arrays so that we don't have to worry about
511511 # multidimensional broadcasting failing
512- I , IL , I0 , Rs , Gsh , a = \
512+ current , IL , I0 , Rs , Gsh , a = \
513513 np .broadcast_arrays (current , photocurrent , saturation_current ,
514514 resistance_series , conductance_shunt , nNsVth )
515515
516- # Intitalize output V (I might not be float64)
517- V = np .full_like (I , np .nan , dtype = np .float64 )
516+ # Intitalize output voltage (current might not be float64)
517+ voltage = np .full_like (current , np .nan , dtype = np .float64 )
518518
519519 # Determine indices where 0 < Gsh requires implicit model solution
520520 idx_p = 0. < Gsh
@@ -524,17 +524,21 @@ def _lambertw_v_from_i(current, photocurrent, saturation_current,
524524
525525 # Explicit solutions where Gsh=0
526526 if np .any (idx_z ):
527- V [idx_z ] = a [idx_z ] * np .log1p ((IL [idx_z ] - I [idx_z ]) / I0 [idx_z ]) - \
528- I [idx_z ] * Rs [idx_z ]
527+ voltage [idx_z ] = (
528+ a [idx_z ] * np .log1p ((IL [idx_z ] - current [idx_z ]) / I0 [idx_z ]) -
529+ current [idx_z ] * Rs [idx_z ]
530+ )
529531
530532 # Only compute using LambertW if there are cases with Gsh>0
531533 if np .any (idx_p ):
532534 # LambertW argument, cannot be float128, may overflow to np.inf
533535 # overflow is explicitly handled below, so ignore warnings here
534536 with np .errstate (over = 'ignore' ):
535- argW = (I0 [idx_p ] / (Gsh [idx_p ] * a [idx_p ]) *
536- np .exp ((- I [idx_p ] + IL [idx_p ] + I0 [idx_p ]) /
537- (Gsh [idx_p ] * a [idx_p ])))
537+ argW = (
538+ I0 [idx_p ] / (Gsh [idx_p ] * a [idx_p ]) *
539+ np .exp ((- current [idx_p ] + IL [idx_p ] + I0 [idx_p ]) /
540+ (Gsh [idx_p ] * a [idx_p ]))
541+ )
538542
539543 # lambertw typically returns complex value with zero imaginary part
540544 # may overflow to np.inf
@@ -546,10 +550,12 @@ def _lambertw_v_from_i(current, photocurrent, saturation_current,
546550 # Only re-compute LambertW if it overflowed
547551 if np .any (idx_inf ):
548552 # Calculate using log(argW) in case argW is really big
549- logargW = (np .log (I0 [idx_p ]) - np .log (Gsh [idx_p ]) -
550- np .log (a [idx_p ]) +
551- (- I [idx_p ] + IL [idx_p ] + I0 [idx_p ]) /
552- (Gsh [idx_p ] * a [idx_p ]))[idx_inf ]
553+ logargW = (
554+ np .log (I0 [idx_p ]) - np .log (Gsh [idx_p ]) -
555+ np .log (a [idx_p ]) +
556+ (- current [idx_p ] + IL [idx_p ] + I0 [idx_p ]) /
557+ (Gsh [idx_p ] * a [idx_p ])
558+ )[idx_inf ]
553559
554560 # Three iterations of Newton-Raphson method to solve
555561 # w+log(w)=logargW. The initial guess is w=logargW. Where direct
@@ -563,13 +569,15 @@ def _lambertw_v_from_i(current, photocurrent, saturation_current,
563569 # Eqn. 3 in Jain and Kapoor, 2004
564570 # V = -I*(Rs + Rsh) + IL*Rsh - a*lambertwterm + I0*Rsh
565571 # Recast in terms of Gsh=1/Rsh for better numerical stability.
566- V [idx_p ] = (IL [idx_p ] + I0 [idx_p ] - I [idx_p ]) / Gsh [idx_p ] - \
567- I [idx_p ] * Rs [idx_p ] - a [idx_p ] * lambertwterm
572+ voltage [idx_p ] = (
573+ (IL [idx_p ] + I0 [idx_p ] - current [idx_p ]) / Gsh [idx_p ] -
574+ current [idx_p ] * Rs [idx_p ] - a [idx_p ] * lambertwterm
575+ )
568576
569577 if output_is_scalar :
570- return V .item ()
578+ return voltage .item ()
571579 else :
572- return V
580+ return voltage
573581
574582
575583def _lambertw_i_from_v (voltage , photocurrent , saturation_current ,
@@ -586,12 +594,12 @@ def _lambertw_i_from_v(voltage, photocurrent, saturation_current,
586594 # Ensure that we are working with read-only views of numpy arrays
587595 # Turns Series into arrays so that we don't have to worry about
588596 # multidimensional broadcasting failing
589- V , IL , I0 , Rs , Gsh , a = \
597+ voltage , IL , I0 , Rs , Gsh , a = \
590598 np .broadcast_arrays (voltage , photocurrent , saturation_current ,
591599 resistance_series , conductance_shunt , nNsVth )
592600
593- # Intitalize output I (V might not be float64)
594- I = np .full_like (V , np .nan , dtype = np .float64 ) # noqa: E741, N806
601+ # Intitalize output current (voltage might not be float64)
602+ current = np .full_like (voltage , np .nan , dtype = np .float64 ) # noqa: E741, N806
595603
596604 # Determine indices where 0 < Rs requires implicit model solution
597605 idx_p = 0. < Rs
@@ -601,17 +609,20 @@ def _lambertw_i_from_v(voltage, photocurrent, saturation_current,
601609
602610 # Explicit solutions where Rs=0
603611 if np .any (idx_z ):
604- I [idx_z ] = IL [idx_z ] - I0 [idx_z ] * np .expm1 (V [idx_z ] / a [idx_z ]) - \
605- Gsh [idx_z ] * V [idx_z ]
612+ current [idx_z ] = (
613+ IL [idx_z ] - I0 [idx_z ] * np .expm1 (voltage [idx_z ] / a [idx_z ]) -
614+ Gsh [idx_z ] * voltage [idx_z ]
615+ )
606616
607617 # Only compute using LambertW if there are cases with Rs>0
608618 # Does NOT handle possibility of overflow, github issue 298
609619 if np .any (idx_p ):
610620 # LambertW argument, cannot be float128, may overflow to np.inf
611- argW = Rs [idx_p ] * I0 [idx_p ] / (
612- a [idx_p ] * (Rs [idx_p ] * Gsh [idx_p ] + 1. )) * \
613- np .exp ((Rs [idx_p ] * (IL [idx_p ] + I0 [idx_p ]) + V [idx_p ]) /
614- (a [idx_p ] * (Rs [idx_p ] * Gsh [idx_p ] + 1. )))
621+ argW = (
622+ Rs [idx_p ] * I0 [idx_p ] / (a [idx_p ] * (Rs [idx_p ] * Gsh [idx_p ] + 1. ))
623+ * np .exp ((Rs [idx_p ] * (IL [idx_p ] + I0 [idx_p ]) + voltage [idx_p ]) /
624+ (a [idx_p ] * (Rs [idx_p ] * Gsh [idx_p ] + 1. )))
625+ )
615626
616627 # lambertw typically returns complex value with zero imaginary part
617628 # may overflow to np.inf
@@ -620,14 +631,16 @@ def _lambertw_i_from_v(voltage, photocurrent, saturation_current,
620631 # Eqn. 2 in Jain and Kapoor, 2004
621632 # I = -V/(Rs + Rsh) - (a/Rs)*lambertwterm + Rsh*(IL + I0)/(Rs + Rsh)
622633 # Recast in terms of Gsh=1/Rsh for better numerical stability.
623- I [idx_p ] = (IL [idx_p ] + I0 [idx_p ] - V [idx_p ] * Gsh [idx_p ]) / \
624- (Rs [idx_p ] * Gsh [idx_p ] + 1. ) - (
625- a [idx_p ] / Rs [idx_p ]) * lambertwterm
634+ current [idx_p ] = (
635+ (IL [idx_p ] + I0 [idx_p ] - voltage [idx_p ] * Gsh [idx_p ]) /
636+ (Rs [idx_p ] * Gsh [idx_p ] + 1. ) -
637+ (a [idx_p ] / Rs [idx_p ]) * lambertwterm
638+ )
626639
627640 if output_is_scalar :
628- return I .item ()
641+ return current .item ()
629642 else :
630- return I
643+ return current
631644
632645
633646def _lambertw (photocurrent , saturation_current , resistance_series ,
@@ -675,8 +688,9 @@ def _pwr_optfcn(df, loc):
675688 Function to find power from ``i_from_v``.
676689 '''
677690
678- I = _lambertw_i_from_v (df [loc ], df ['photocurrent' ],
679- df ['saturation_current' ], df ['resistance_series' ],
680- df ['resistance_shunt' ], df ['nNsVth' ])
691+ current = _lambertw_i_from_v (df [loc ], df ['photocurrent' ],
692+ df ['saturation_current' ],
693+ df ['resistance_series' ],
694+ df ['resistance_shunt' ], df ['nNsVth' ])
681695
682- return I * df [loc ]
696+ return current * df [loc ]
0 commit comments