Skip to content

Commit 610bbb2

Browse files
committed
accept float, restrict to x>=0, simplify test
1 parent f0897ba commit 610bbb2

3 files changed

Lines changed: 25 additions & 34 deletions

File tree

docs/sphinx/source/whatsnew/v0.15.1.rst

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,6 @@ Enhancements
2626
* Use ``k`` and ``cap_adjustment`` from :py:func:`pvlib.pvsystem.Array.module_parameters`
2727
in :py:func:`pvlib.pvsystem.PVSystem.pvwatts_dc`
2828
(:issue:`2714`, :pull:`2715`)
29-
* Add :py:func:`pvlib.tools._lambertw_pvlib` to speed up calculations when using
30-
LambertW single diode equation methods.
31-
(:discuss:`2720`, :pull:`2723`)
3229

3330
Documentation
3431
~~~~~~~~~~~~~

pvlib/ivtools/utils.py

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -552,7 +552,6 @@ def _log_lambertw(logx):
552552
Parameters
553553
----------
554554
logx : numeric
555-
Log(x) of
556555
557556
Returns
558557
-------
@@ -571,29 +570,30 @@ def _log_lambertw(logx):
571570

572571

573572
def _lambertw_pvlib(x):
574-
r'''Lambert's W function principal branch, :math:`W_0(x)`, for :math:`x`
575-
real valued.
573+
r'''Lambert's W function principal branch, :math:`W_0(x)`, for
574+
:math:`x>=0`.
576575
577576
Parameters
578577
----------
579-
x : np.array
578+
x : float or np.array
580579
Must be real numbers.
581580
582581
Returns
583582
-------
584-
np.array
583+
float or np.array
585584
586585
'''
587-
w = np.full_like(x, np.nan)
588-
small = x <= 10
586+
localx = np.asarray(x, float)
587+
w = np.full_like(localx, np.nan)
588+
small = localx <= 10
589589
# for large x, solve 0 = f(w) = w + log(w) - log(x) using Newton's
590-
w[~small] = _log_lambertw(np.log(x[~small]))
591-
592590
# w will contain nan for these numbers due to log(w) = log(log(x))
591+
w[~small] = _log_lambertw(np.log(localx[~small]))
592+
593593
# for small x, solve 0 = g(w) = w * exp(w) - x using Halley's method
594-
if any(small):
595-
z = x[small]
596-
temp = np.log(x[small] + 1)
594+
if np.any(small):
595+
z = localx[small]
596+
temp = np.log(localx[small] + 1)
597597
g = temp - np.log(temp + 1)
598598
for _ in range(0, 3):
599599
expg = np.exp(g)
@@ -603,4 +603,4 @@ def _lambertw_pvlib(x):
603603
(expg * g_p1**2 - 0.5*(g + 2)*g_expg_z)
604604
w[small] = g
605605

606-
return w
606+
return w[0] if w.shape==1 else w

tests/ivtools/test_utils.py

Lines changed: 12 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -175,26 +175,20 @@ def test_astm_e1036_fit_points(v_array, i_array):
175175

176176

177177
def test_lambertw_pvlib():
178-
test_exp = np.arange(-10., 300, step=10)
179-
test_x = 10.**test_exp
178+
test_x = np.array([0., 1.e-10, 1., 10., 100., 1.e+10, 1.e+100, 1.e+300])
180179
# known solution from scipy.special.lambertw
181180
# scipy 1.7.1, python 3.13.1, numpy 2.3.5
182181
expected = np.array([
183-
9.9999999989999997e-11, 5.6714329040978384e-01,
184-
2.0028685413304952e+01, 4.2306755091738395e+01,
185-
6.4904633770046118e+01, 8.7630277151947183e+01,
186-
1.1042491882731335e+02, 1.3326278259180333e+02,
187-
1.5613026581351718e+02, 1.7901931374150624e+02,
188-
2.0192476320084489e+02, 2.2484310644511851e+02,
189-
2.4777185185877809e+02, 2.7070916610249782e+02,
190-
2.9365366103997610e+02, 3.1660426041503479e+02,
191-
3.3956011295458728e+02, 3.6252053376149752e+02,
192-
3.8548496362161768e+02, 4.0845294003314166e+02,
193-
4.3142407612718210e+02, 4.5439804503371403e+02,
194-
4.7737456808796901e+02, 5.0035340579834485e+02,
195-
5.2333435083468805e+02, 5.4631722251791496e+02,
196-
5.6930186244110166e+02, 5.9228813095427859e+02,
197-
6.1527590431628334e+02, 6.3826507236734335e+02,
198-
6.6125553661218726e+02])
182+
0.0000000000000000e+00, 9.9999999989999997e-11, 5.6714329040978384e-01,
183+
1.7455280027406994e+00, 3.3856301402900502e+00, 2.0028685413304952e+01,
184+
2.2484310644511851e+02, 6.8424720862976085e+02])
199185
result = _lambertw_pvlib(test_x)
200186
assert np.allclose(result, expected, rtol=1e-14)
187+
# with float input
188+
for x, k in zip([1.e-10, 1.e+10], [1, 5]):
189+
result = _lambertw_pvlib(x)
190+
assert np.isclose(result, expected[k])
191+
# with 1d array
192+
for x, k in zip([1.e-10, 1.e+10], [1, 5]):
193+
result = _lambertw_pvlib(np.array([x]))
194+
assert np.isclose(result, expected[k])

0 commit comments

Comments
 (0)