Skip to content

Update infinite_sheds.py to add shaded fraction to returned variables in infinite_sheds.get_irradiance and infinite_sheds.get_irradiance_poa #1871

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 10 commits into from
Oct 4, 2023
5 changes: 4 additions & 1 deletion docs/sphinx/source/whatsnew/v0.10.3.rst
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,9 @@ v0.10.3 (Anticipated December, 2023)

Enhancements
~~~~~~~~~~~~

* :py:func:`pvlib.bifacial.infinite_sheds.get_irradiance` and
:py:func:`pvlib.bifacial.infinite_sheds.get_irradiance_poa` now include
shaded fraction in returned variables. (:pull:`1871`)

Bug fixes
~~~~~~~~~
Expand All @@ -26,3 +28,4 @@ Contributors
~~~~~~~~~~~~
* Arjan Keeman (:ghuser:`akeeman`)
* Miguel Sánchez de León Peque (:ghuser:`Peque`)
* Will Hobbs (:ghuser:`williamhobbs`)
12 changes: 11 additions & 1 deletion pvlib/bifacial/infinite_sheds.py
Original file line number Diff line number Diff line change
Expand Up @@ -276,6 +276,8 @@ def get_irradiance_poa(surface_tilt, surface_azimuth, solar_zenith,
[W/m^2]
- ``poa_ground_diffuse`` : total ground-reflected diffuse irradiance on the
plane of array. [W/m^2]
- ``shaded_fraction`` : fraction of row slant height from the bottom that
is shaded from direct irradiance by adjacent rows. [unitless]

References
----------
Expand Down Expand Up @@ -369,7 +371,7 @@ def get_irradiance_poa(surface_tilt, surface_azimuth, solar_zenith,
output = {
'poa_global': poa_global, 'poa_direct': poa_direct,
'poa_diffuse': poa_diffuse, 'poa_ground_diffuse': poa_gnd_pv,
'poa_sky_diffuse': poa_sky_pv}
'poa_sky_diffuse': poa_sky_pv, 'shaded_fraction': f_x}
if isinstance(poa_global, pd.Series):
output = pd.DataFrame(output)
return output
Expand Down Expand Up @@ -502,6 +504,9 @@ def get_irradiance(surface_tilt, surface_azimuth, solar_zenith, solar_azimuth,
cells from the front surface. [W/m^2]
- ``poa_front_ground_diffuse`` : ground-reflected diffuse irradiance
reaching the module cells from the front surface. [W/m^2]
- ``shaded_fraction_front`` : fraction of row slant height from the bottom
that is shaded from direct irradiance on the front surface by adjacent
rows. [unitless]
- ``poa_back_direct`` : direct irradiance reaching the module cells from
the back surface. [W/m^2]
- ``poa_back_diffuse`` : total diffuse irradiance reaching the module
Expand All @@ -510,6 +515,9 @@ def get_irradiance(surface_tilt, surface_azimuth, solar_zenith, solar_azimuth,
cells from the back surface. [W/m^2]
- ``poa_back_ground_diffuse`` : ground-reflected diffuse irradiance
reaching the module cells from the back surface. [W/m^2]
- ``shaded_fraction_back`` : fraction of row slant height from the bottom
that is shaded from direct irradiance on the back surface by adjacent
rows. [unitless]

References
----------
Expand Down Expand Up @@ -545,13 +553,15 @@ def get_irradiance(surface_tilt, surface_azimuth, solar_zenith, solar_azimuth,
'poa_diffuse': 'poa_front_diffuse',
'poa_sky_diffuse': 'poa_front_sky_diffuse',
'poa_ground_diffuse': 'poa_front_ground_diffuse',
'shaded_fraction': 'shaded_fraction_front',
}
colmap_back = {
'poa_global': 'poa_back',
'poa_direct': 'poa_back_direct',
'poa_diffuse': 'poa_back_diffuse',
'poa_sky_diffuse': 'poa_back_sky_diffuse',
'poa_ground_diffuse': 'poa_back_ground_diffuse',
'shaded_fraction': 'shaded_fraction_back',
}

if isinstance(ghi, pd.Series):
Expand Down
34 changes: 33 additions & 1 deletion pvlib/tests/bifacial/test_infinite_sheds.py
Original file line number Diff line number Diff line change
Expand Up @@ -100,9 +100,11 @@ def test_get_irradiance_poa():
expected_diffuse = np.array([300.])
expected_direct = np.array([700.])
expected_global = expected_diffuse + expected_direct
expected_shaded_fraction = np.array([0.])
assert np.isclose(res['poa_global'], expected_global)
assert np.isclose(res['poa_diffuse'], expected_diffuse)
assert np.isclose(res['poa_direct'], expected_direct)
assert np.isclose(res['shaded_fraction'], expected_shaded_fraction)
# vector inputs
surface_tilt = np.array([0., 0., 0., 0.])
height = 1.
Expand All @@ -115,13 +117,16 @@ def test_get_irradiance_poa():
expected_direct = np.array(
[700., 350. * np.sqrt(2), 350. * np.sqrt(2), 0.])
expected_global = expected_diffuse + expected_direct
expected_shaded_fraction = np.array(
[0., 0., 0., 0.])
res = infinite_sheds.get_irradiance_poa(
surface_tilt, surface_azimuth, solar_zenith, solar_azimuth,
gcr, height, pitch, ghi, dhi, dni,
albedo, iam=iam, npoints=npoints)
assert np.allclose(res['poa_global'], expected_global)
assert np.allclose(res['poa_diffuse'], expected_diffuse)
assert np.allclose(res['poa_direct'], expected_direct)
assert np.allclose(res['shaded_fraction'], expected_shaded_fraction)
# series inputs
surface_tilt = pd.Series(surface_tilt)
surface_azimuth = pd.Series(data=surface_azimuth, index=surface_tilt.index)
Expand All @@ -133,15 +138,19 @@ def test_get_irradiance_poa():
data=expected_direct, index=surface_tilt.index)
expected_global = expected_diffuse + expected_direct
expected_global.name = 'poa_global' # to match output Series
expected_shaded_fraction = pd.Series(
data=expected_shaded_fraction, index=surface_tilt.index)
expected_shaded_fraction.name = 'shaded_fraction' # to match output Series
res = infinite_sheds.get_irradiance_poa(
surface_tilt, surface_azimuth, solar_zenith, solar_azimuth,
gcr, height, pitch, ghi, dhi, dni,
albedo, iam=iam, npoints=npoints)
assert isinstance(res, pd.DataFrame)
assert_series_equal(res['poa_global'], expected_global)
assert_series_equal(res['shaded_fraction'], expected_shaded_fraction)
assert all(k in res.columns for k in [
'poa_global', 'poa_diffuse', 'poa_direct', 'poa_ground_diffuse',
'poa_sky_diffuse'])
'poa_sky_diffuse', 'shaded_fraction'])


def test__backside_tilt():
Expand Down Expand Up @@ -177,10 +186,16 @@ def test_get_irradiance(vectorize):
expected_front_diffuse = np.array([300.])
expected_front_direct = np.array([700.])
expected_front_global = expected_front_diffuse + expected_front_direct
expected_shaded_fraction_front = np.array([0.])
expected_shaded_fraction_back = np.array([0.])
assert np.isclose(result['poa_front'], expected_front_global)
assert np.isclose(result['poa_front_diffuse'], expected_front_diffuse)
assert np.isclose(result['poa_front_direct'], expected_front_direct)
assert np.isclose(result['poa_global'], result['poa_front'])
assert np.isclose(result['shaded_fraction_front'],
expected_shaded_fraction_front)
assert np.isclose(result['shaded_fraction_back'],
expected_shaded_fraction_back)
# series inputs
ghi = pd.Series([1000., 500., 500., np.nan])
dhi = pd.Series([300., 500., 500., 500.], index=ghi.index)
Expand All @@ -200,7 +215,12 @@ def test_get_irradiance(vectorize):
expected_poa_global = pd.Series(
[1000., 500., result_front['poa_global'][2] * (1 + 0.8 * 0.98),
np.nan], index=ghi.index, name='poa_global')
expected_shaded_fraction = pd.Series(
result_front['shaded_fraction'], index=ghi.index,
name='shaded_fraction_front')
assert_series_equal(result['poa_global'], expected_poa_global)
assert_series_equal(result['shaded_fraction_front'],
expected_shaded_fraction)


def test_get_irradiance_limiting_gcr():
Expand Down Expand Up @@ -230,6 +250,8 @@ def test_get_irradiance_limiting_gcr():
expected_direct = np.array([0.])
expected_diffuse = expected_ground_diffuse + expected_sky_diffuse
expected_poa = expected_diffuse + expected_direct
expected_shaded_fraction_front = np.array([0.])
expected_shaded_fraction_back = np.array([0.])
assert np.isclose(result['poa_front'], expected_poa, rtol=0.01)
assert np.isclose(result['poa_front_diffuse'], expected_diffuse, rtol=0.01)
assert np.isclose(result['poa_front_direct'], expected_direct)
Expand All @@ -244,6 +266,10 @@ def test_get_irradiance_limiting_gcr():
result['poa_back_sky_diffuse'])
assert np.isclose(result['poa_front_ground_diffuse'],
result['poa_back_ground_diffuse'])
assert np.isclose(result['shaded_fraction_front'],
expected_shaded_fraction_front)
assert np.isclose(result['shaded_fraction_back'],
expected_shaded_fraction_back)


def test_get_irradiance_with_haydavies():
Expand Down Expand Up @@ -272,10 +298,16 @@ def test_get_irradiance_with_haydavies():
expected_front_diffuse = np.array([151.38])
expected_front_direct = np.array([848.62])
expected_front_global = expected_front_diffuse + expected_front_direct
expected_shaded_fraction_front = np.array([0.])
expected_shaded_fraction_back = np.array([0.])
assert np.isclose(result['poa_front'], expected_front_global)
assert np.isclose(result['poa_front_diffuse'], expected_front_diffuse)
assert np.isclose(result['poa_front_direct'], expected_front_direct)
assert np.isclose(result['poa_global'], result['poa_front'])
assert np.isclose(result['shaded_fraction_front'],
expected_shaded_fraction_front)
assert np.isclose(result['shaded_fraction_back'],
expected_shaded_fraction_back)
# test for when dni_extra is not supplied
with pytest.raises(ValueError, match='supply dni_extra for haydavies'):
result = infinite_sheds.get_irradiance(
Expand Down