Skip to content

Commit 00b4dfd

Browse files
committed
_fit_desoto_pvsyst_sandia: refactoring and np.errstates
1 parent 10edc65 commit 00b4dfd

File tree

2 files changed

+26
-18
lines changed

2 files changed

+26
-18
lines changed

pvlib/singlediode.py

Lines changed: 16 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -696,27 +696,34 @@ def _lambertw_v_from_i(current, photocurrent, saturation_current,
696696

697697
# Only compute using LambertW if there are cases with Gsh>0
698698
if np.any(idx_p):
699+
700+
# use only the relevant subset for what follows
701+
I = I[idx_p]
702+
IL = IL[idx_p]
703+
I0 = I0[idx_p]
704+
Rs = Rs[idx_p]
705+
Gsh = Gsh[idx_p]
706+
a = a[idx_p]
707+
699708
# LambertW argument, cannot be float128, may overflow to np.inf
700709
# overflow is explicitly handled below, so ignore warnings here
701710
with np.errstate(over='ignore'):
702-
argW = (I0[idx_p] / (Gsh[idx_p] * a[idx_p]) *
703-
np.exp((-I[idx_p] + IL[idx_p] + I0[idx_p]) /
704-
(Gsh[idx_p] * a[idx_p])))
711+
argW = I0 / (Gsh * a) * np.exp((-I + IL + I0) / (Gsh * a))
705712

706713
# lambertw typically returns complex value with zero imaginary part
707714
# may overflow to np.inf
708715
lambertwterm = lambertw(argW).real
709716

710717
# Record indices where lambertw input overflowed output
711-
idx_inf = np.logical_not(np.isfinite(lambertwterm))
718+
idx_inf = np.isinf(lambertwterm)
712719

713720
# Only re-compute LambertW if it overflowed
714721
if np.any(idx_inf):
715722
# Calculate using log(argW) in case argW is really big
716-
logargW = (np.log(I0[idx_p]) - np.log(Gsh[idx_p]) -
717-
np.log(a[idx_p]) +
718-
(-I[idx_p] + IL[idx_p] + I0[idx_p]) /
719-
(Gsh[idx_p] * a[idx_p]))[idx_inf]
723+
logargW = (np.log(I0[idx_inf]) - np.log(Gsh[idx_inf]) -
724+
np.log(a[idx_inf]) +
725+
(-I[idx_inf] + IL[idx_inf] + I0[idx_inf]) /
726+
(Gsh[idx_inf] * a[idx_inf]))
720727

721728
# Three iterations of Newton-Raphson method to solve
722729
# w+log(w)=logargW. The initial guess is w=logargW. Where direct
@@ -730,8 +737,7 @@ def _lambertw_v_from_i(current, photocurrent, saturation_current,
730737
# Eqn. 3 in Jain and Kapoor, 2004
731738
# V = -I*(Rs + Rsh) + IL*Rsh - a*lambertwterm + I0*Rsh
732739
# Recast in terms of Gsh=1/Rsh for better numerical stability.
733-
V[idx_p] = (IL[idx_p] + I0[idx_p] - I[idx_p]) / Gsh[idx_p] - \
734-
I[idx_p] * Rs[idx_p] - a[idx_p] * lambertwterm
740+
V[idx_p] = (IL + I0 - I) / Gsh - I * Rs - a * lambertwterm
735741

736742
if output_is_scalar:
737743
return V.item()

tests/ivtools/sdm/test__fit_desoto_pvsyst_sandia.py

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,8 @@ def test__update_io(voc, iph, io, rs, rsh, nnsvth, expected):
5656
(2., 2., 2., 2., 2., 0.),
5757
(-1., -1., -1., -1., -1., -1.)])
5858
def test__update_io_nan(voc, iph, io, rs, rsh, nnsvth):
59-
outio = _update_io(voc, iph, io, rs, rsh, nnsvth)
59+
with np.errstate(invalid='ignore', divide='ignore'):
60+
outio = _update_io(voc, iph, io, rs, rsh, nnsvth)
6061
assert np.isnan(outio)
6162

6263

@@ -89,13 +90,14 @@ def test__calc_theta_phi_exact_one_nan():
8990

9091

9192
def test__calc_theta_phi_exact_vector():
92-
theta, phi = _calc_theta_phi_exact(imp=np.array([1., -1.]),
93-
iph=np.array([-1., 1.]),
94-
vmp=np.array([1., -1.]),
95-
io=np.array([-1., 1.]),
96-
nnsvth=np.array([1., -1.]),
97-
rs=np.array([-1., 1.]),
98-
rsh=np.array([1., -1.]))
93+
with np.errstate(invalid='ignore'):
94+
theta, phi = _calc_theta_phi_exact(imp=np.array([1., -1.]),
95+
iph=np.array([-1., 1.]),
96+
vmp=np.array([1., -1.]),
97+
io=np.array([-1., 1.]),
98+
nnsvth=np.array([1., -1.]),
99+
rs=np.array([-1., 1.]),
100+
rsh=np.array([1., -1.]))
99101
assert np.isnan(theta[0])
100102
assert np.isnan(theta[1])
101103
assert np.isnan(phi[0])

0 commit comments

Comments
 (0)