From 436293fd9df932ec4e1b45893a1f0efd471fc031 Mon Sep 17 00:00:00 2001 From: Andrew Chen <48723787+chuenchen309@users.noreply.github.com> Date: Fri, 17 Jul 2026 15:07:53 +0800 Subject: [PATCH 1/2] Fix perez ZeroDivisionError on scalar dhi=0 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `irradiance.perez` documents `dhi` as valid for any value `>= 0`, and `dhi == 0` occurs at every nighttime timestamp. The clearness term divides by `dhi`, and the author wrapped it in `np.errstate(invalid='ignore')` so the `dhi == 0` path flows through `np.digitize` to a finite result. That works for array and NumPy scalar input, but a native Python scalar `dhi` uses Python's `/`, which raises `ZeroDivisionError` — and `np.errstate` does not affect native scalar division. So `perez(..., dhi=0.0, ...)` with plain floats crashed while the identical array input, a `np.float64` scalar, and the sibling `perez_driesse` all returned a clean value. Compute the division with `np.true_divide` (and add `divide='ignore'`) so a native scalar takes the same inf/nan path the array input already does. The scalar result now matches the array result exactly (`0.0`), `dhi == dni == 0` gives `nan` as the array does, and non-zero `dhi` is unchanged. Adds a regression test asserting scalar `dhi=0` no longer crashes and matches the array result. Co-Authored-By: Claude Opus 4.8 (1M context) --- pvlib/irradiance.py | 8 ++++++-- tests/test_irradiance.py | 10 ++++++++++ 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/pvlib/irradiance.py b/pvlib/irradiance.py index 98bd948286..e10da59609 100644 --- a/pvlib/irradiance.py +++ b/pvlib/irradiance.py @@ -1146,8 +1146,12 @@ def perez(surface_tilt, surface_azimuth, dhi, dni, dni_extra, delta = dhi * airmass / dni_extra # epsilon is the sky's "clearness" - with np.errstate(invalid='ignore'): - eps = ((dhi + dni) / dhi + kappa * (z ** 3)) / (1 + kappa * (z ** 3)) + # np.true_divide so a Python-scalar dhi=0 yields inf/nan like the array + # path (handled below via digitize) instead of raising ZeroDivisionError, + # which np.errstate cannot suppress for native scalar division. + with np.errstate(invalid='ignore', divide='ignore'): + eps = (np.true_divide(dhi + dni, dhi) + kappa * (z ** 3)) \ + / (1 + kappa * (z ** 3)) # numpy indexing below will not work with a Series if isinstance(eps, pd.Series): diff --git a/tests/test_irradiance.py b/tests/test_irradiance.py index fbe9906358..0e33f60f73 100644 --- a/tests/test_irradiance.py +++ b/tests/test_irradiance.py @@ -429,6 +429,16 @@ def test_perez_scalar(): assert_allclose(out, 109.084332) +def test_perez_scalar_dhi_zero(): + # dhi=0 (e.g. nighttime) is documented-valid input (dhi >= 0). A native + # Python scalar division raised ZeroDivisionError (which np.errstate cannot + # suppress) while the array path returns a finite value; they must match. + out = irradiance.perez(30, 180, 0.0, 800.0, 1400.0, 40.0, 120.0, 1.5) + expected = irradiance.perez(30, 180, np.array([0.0]), np.array([800.0]), + 1400.0, 40.0, 120.0, np.array([1.5])) + assert_allclose(out, expected[0]) + + def test_perez_driesse_scalar(): # copied values from fixtures out = irradiance.perez_driesse(40, 180, 118.458, 939.954, From 5920f91f156668fdba9b15f65b510e1ae1634c78 Mon Sep 17 00:00:00 2001 From: Andrew Chen <48723787+chuenchen309@users.noreply.github.com> Date: Fri, 17 Jul 2026 15:08:54 +0800 Subject: [PATCH 2/2] Add whatsnew entry for perez scalar dhi=0 fix --- docs/sphinx/source/whatsnew/v0.16.0.rst | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/sphinx/source/whatsnew/v0.16.0.rst b/docs/sphinx/source/whatsnew/v0.16.0.rst index 6d62b9e1c6..9bbafb16ca 100644 --- a/docs/sphinx/source/whatsnew/v0.16.0.rst +++ b/docs/sphinx/source/whatsnew/v0.16.0.rst @@ -19,6 +19,9 @@ Deprecations Bug fixes ~~~~~~~~~ +* :py:func:`~pvlib.irradiance.perez` no longer raises ``ZeroDivisionError`` on + scalar ``dhi=0`` input (e.g. nighttime); the scalar path now returns the same + finite value as the array path. (:pull:`2826`) Enhancements @@ -48,3 +51,4 @@ Maintenance Contributors ~~~~~~~~~~~~ * Carolina Crespo (:ghuser:`cbcrespo`) +* Andrew Chen (:ghuser:`chuenchen309`)