Skip to content

Commit ae3b8ff

Browse files
Handle 0/0 in perez without NaNs
1 parent c34058d commit ae3b8ff

2 files changed

Lines changed: 27 additions & 6 deletions

File tree

pvlib/irradiance.py

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1147,12 +1147,21 @@ def perez(surface_tilt, surface_azimuth, dhi, dni, dni_extra,
11471147
kappa = 1.041 # for solar_zenith in radians
11481148
z = np.radians(solar_zenith) # convert to radians
11491149

1150-
# delta is the sky's "brightness"
1150+
# delta is the sky's "brightness", assumes dni_extra > 0
11511151
delta = dhi * airmass / dni_extra
11521152

1153-
# epsilon is the sky's "clearness"
1154-
with np.errstate(invalid='ignore'):
1155-
eps = ((dhi + dni) / dhi + kappa * (z ** 3)) / (1 + kappa * (z ** 3))
1153+
# epsilon is the sky's "clearness". Preserves NaNs for dni or dhi.
1154+
# Assumes:
1155+
# - dni >=0 and dhi >= 0.
1156+
# - dni->0^+ faster than dhi->0^+.
1157+
irr_ratio = np.zeros(np.broadcast(dni, dhi).shape)
1158+
with np.errstate(divide="raise"):
1159+
irr_ratio = np.divide(
1160+
dni, dhi, out=irr_ratio, where=np.logical_not(
1161+
np.logical_and(dhi == 0, dni == 0)
1162+
)
1163+
)
1164+
eps = 1 + irr_ratio / (1 + kappa * (z ** 3))
11561165

11571166
# numpy indexing below will not work with a Series
11581167
if isinstance(eps, pd.Series):

tests/test_irradiance.py

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,9 @@
77
import pandas as pd
88

99
import pytest
10-
from numpy.testing import (assert_almost_equal,
11-
assert_allclose)
10+
from numpy.testing import (
11+
assert_almost_equal, assert_allclose, assert_equal, assert_raises
12+
)
1213
from pvlib import irradiance, albedo
1314

1415
from .conftest import (
@@ -393,6 +394,17 @@ def test_perez_negative_horizon():
393394
assert_series_equal(sum_components, expected_for_sum, check_less_precise=2)
394395

395396

397+
def test_perez_zero_dhi_and_dni(dni_et):
398+
out = irradiance.perez(20, 180, 0.0, 0.0, dni_et, 89.96, 256.28, 37.32)
399+
expected = 0.0
400+
assert_equal(out, expected)
401+
402+
403+
def test_perez_zero_dhi_nonzero_dni(dni_et):
404+
with assert_raises(FloatingPointError):
405+
irradiance.perez(20, 180, 0.0, 100.0, dni_et, 89.96, 256.28, 37.32)
406+
407+
396408
def test_perez_arrays(irrad_data, ephem_data, dni_et, relative_airmass):
397409
dni = irrad_data['dni'].copy()
398410
dni.iloc[2] = np.nan

0 commit comments

Comments
 (0)