Skip to content

Commit 4841fbf

Browse files
authored
Merge branch 'main' into isotropic_components
2 parents 48b669c + 38586c1 commit 4841fbf

3 files changed

Lines changed: 95 additions & 12 deletions

File tree

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

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,11 @@ Bug fixes
2323

2424
Enhancements
2525
~~~~~~~~~~~~
26-
* Add ``return_components`` kwarg to :py:func:`pvlib.irradiance.isotropic`. (:issue:`2750`, :pull:`2787`)
26+
* Add ``return_components`` kwarg to :py:func:`pvlib.irradiance.isotropic`.
27+
(:issue:`2750`, :pull:`2787`)
28+
* Add ``return_components`` kwarg to :py:func:`pvlib.irradiance.reindl` to
29+
support returning the components of sky diffuse irradiance.
30+
(:issue:`2750`, :pull:`2775`)
2731
* Add iotools functions to retrieve irradiance and weather data from NSRDB PSM4 Polar,
2832
which provides satellite-derived irradiance data above 60 degree latitude.
2933
:py:func:`~pvlib.iotools.get_nsrdb_psm4_polar` and
@@ -68,3 +72,4 @@ Contributors
6872
* Yonry Zhu (:ghuser:`yonryzhu`)
6973
* Darshan Gowda (:ghuser:`dgowdaan-cmyk`)
7074
* Leonardo Scappatura (:ghuser:`Leonard013`)
75+
* Carolina Crespo (:ghuser:`cbcrespo`)

pvlib/irradiance.py

Lines changed: 50 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -902,7 +902,7 @@ def haydavies(surface_tilt, surface_azimuth, dhi, dni, dni_extra,
902902

903903

904904
def reindl(surface_tilt, surface_azimuth, dhi, dni, ghi, dni_extra,
905-
solar_zenith, solar_azimuth):
905+
solar_zenith, solar_azimuth, return_components=False):
906906
r'''
907907
Determine the diffuse irradiance from the sky on a tilted surface using
908908
the Reindl (1990) model.
@@ -941,10 +941,30 @@ def reindl(surface_tilt, surface_azimuth, dhi, dni, ghi, dni_extra,
941941
solar_azimuth : numeric
942942
Solar azimuth angles. See :term:`solar_azimuth`. [°]
943943
944+
return_components : bool, default ``False``
945+
If ``False``, ``poa_sky_diffuse`` is returned.
946+
If ``True``, ``diffuse_components`` is returned.
947+
944948
Returns
945949
-------
950+
numeric, dict, or DataFrame
951+
Return type controlled by ``return_components`` argument.
952+
If ``return_components=False``, ``poa_sky_diffuse`` is returned.
953+
If ``return_components=True``, ``diffuse_components`` is returned.
954+
946955
poa_sky_diffuse : numeric
947-
The sky diffuse component of the solar radiation. [Wm⁻²]
956+
The sky diffuse component of irradiance on a tilted plane. [Wm⁻²]
957+
958+
diffuse_components : dict (array input) or DataFrame (Series input)
959+
Keys/columns are:
960+
* poa_sky_diffuse: The sky diffuse component of irradiance on a
961+
tilted plane. [Wm⁻²]
962+
* poa_isotropic: The portion of sky diffuse irradiance on a tilted
963+
plane from the isotropic sky dome. [Wm⁻²]
964+
* poa_circumsolar: The portion of sky diffuse irradiance on a
965+
tilted plane from the circumsolar region. [Wm⁻²]
966+
* poa_horizon: The portion of sky diffuse irradiance on a tilted
967+
plane from the horizon. [Wm⁻²]
948968
949969
Notes
950970
-----
@@ -968,8 +988,12 @@ def reindl(surface_tilt, surface_azimuth, dhi, dni, ghi, dni_extra,
968988
Implementation is based on Loutzenhiser et al.
969989
(2007) [3]_, Equation 8. The beam and ground reflectance portion of the
970990
equation have been removed, therefore the model described here generates
971-
ONLY the diffuse radiation from the sky and circumsolar, so the form of the
972-
equation varies slightly from Equation 8 in [3]_.
991+
ONLY the diffuse radiation from the sky, circumsolar, and horizon
992+
brightening, so the form of the equation varies slightly from Equation 8
993+
in [3]_.
994+
995+
For clarity, the horizon component in ``reindl`` corresponds to the term
996+
added on top of the ``haydavies`` formulation, on which ``reindl`` builds.
973997
974998
References
975999
----------
@@ -1005,16 +1029,31 @@ def reindl(surface_tilt, surface_azimuth, dhi, dni, ghi, dni_extra,
10051029
HB = dni * cos_solar_zenith
10061030
HB = np.maximum(HB, 0)
10071031

1008-
# these are the () and [] sub-terms of the second term of eqn 8
1009-
term1 = 1 - AI
1010-
term2 = 0.5 * (1 + tools.cosd(surface_tilt))
1032+
SVF = (1 + tools.cosd(surface_tilt)) / 2
1033+
10111034
with np.errstate(invalid='ignore', divide='ignore'):
10121035
hb_to_ghi = np.where(ghi == 0, 0, np.divide(HB, ghi))
1013-
term3 = 1 + np.sqrt(hb_to_ghi) * (tools.sind(0.5 * surface_tilt)**3)
1014-
sky_diffuse = dhi * (AI * Rb + term1 * term2 * term3)
1015-
sky_diffuse = np.maximum(sky_diffuse, 0)
1036+
h = np.sqrt(hb_to_ghi) * (tools.sind(surface_tilt / 2) ** 3)
10161037

1017-
return sky_diffuse
1038+
term1 = (1 - AI) * SVF
1039+
term2 = AI * Rb
1040+
term3 = term1 * h
1041+
1042+
poa_sky_diffuse = dhi * (term1 + term2 + term3)
1043+
1044+
if return_components:
1045+
diffuse_components = {
1046+
'poa_sky_diffuse': poa_sky_diffuse,
1047+
'poa_isotropic': dhi * term1,
1048+
'poa_circumsolar': dhi * term2,
1049+
'poa_horizon': dhi * term3
1050+
}
1051+
1052+
if isinstance(poa_sky_diffuse, pd.Series):
1053+
diffuse_components = pd.DataFrame(diffuse_components)
1054+
return diffuse_components
1055+
else:
1056+
return poa_sky_diffuse
10181057

10191058

10201059
def king(surface_tilt, dhi, ghi, solar_zenith):

tests/test_irradiance.py

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -275,6 +275,45 @@ def test_reindl(irrad_data, ephem_data, dni_et):
275275
assert_allclose(result, [0., 27.9412, 104.1317, 34.1663], atol=1e-4)
276276

277277

278+
def test_reindl_components(irrad_data, ephem_data, dni_et):
279+
keys = ['poa_sky_diffuse', 'poa_isotropic', 'poa_circumsolar',
280+
'poa_horizon']
281+
expected = pd.DataFrame(np.array(
282+
[[0, 27.941170, 104.131724, 34.166258],
283+
[0, 27.177514, 30.181807, 27.983728],
284+
[0, 0, 72.813055, 5.207138],
285+
[0, 0.763656, 1.136862, 0.975393]]).T,
286+
columns=keys,
287+
index=irrad_data.index
288+
)
289+
# pandas
290+
result = irradiance.reindl(
291+
40, 180, irrad_data['dhi'], irrad_data['dni'], irrad_data['ghi'],
292+
dni_et, ephem_data['apparent_zenith'], ephem_data['azimuth'],
293+
return_components=True)
294+
assert_frame_equal(result, expected, check_less_precise=4)
295+
# numpy
296+
result = irradiance.reindl(
297+
40, 180, irrad_data['dhi'].to_numpy(), irrad_data['dni'].to_numpy(),
298+
irrad_data['ghi'].to_numpy(), dni_et,
299+
ephem_data['apparent_zenith'].to_numpy(),
300+
ephem_data['azimuth'].to_numpy(), return_components=True)
301+
for key in keys:
302+
assert_allclose(result[key], expected[key], atol=1e-4)
303+
assert isinstance(result, dict)
304+
# scalar
305+
result = irradiance.reindl(
306+
40, 180, irrad_data['dhi'].to_numpy()[-1],
307+
irrad_data['dni'].to_numpy()[-1],
308+
irrad_data['ghi'].to_numpy()[-1], dni_et[-1],
309+
ephem_data['apparent_zenith'].to_numpy()[-1],
310+
ephem_data['azimuth'].to_numpy()[-1],
311+
return_components=True)
312+
for key in keys:
313+
assert_allclose(result[key], expected[key].iloc[-1], atol=1e-4)
314+
assert isinstance(result, dict)
315+
316+
278317
def test_king(irrad_data, ephem_data):
279318
result = irradiance.king(40, irrad_data['dhi'], irrad_data['ghi'],
280319
ephem_data['apparent_zenith'])

0 commit comments

Comments
 (0)