Skip to content

Handle aoi>90 correctly in spectrum.spectrl2 #1349

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 3 commits into from
Dec 8, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion docs/sphinx/source/whatsnew/v0.9.1.rst
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
.. _whatsnew_0910:

v0.9.1 (December 1, 2021)
v0.9.1 (TBD)
--------------------------

Breaking changes
Expand All @@ -16,6 +16,9 @@ Bug fixes
~~~~~~~~~
* Address round-off effects in :py:func:`pvlib.ivtools.utils._schumaker_qspline`
(:issue:`1311`, :pull:`1315`)
* Fixed a bug in :py:func:`pvlib.spectrum.spectrl2` where negative spectral irradiance
values were returned when the sun is behind the plane of array (:issue:`1348`, :pull:`1349`)


Testing
~~~~~~~
Expand All @@ -31,3 +34,5 @@ Contributors
* Cliff Hansen (:ghuser:`cwhanse`)
* :ghuser:`Antoine-0`
* :ghuser:`Carlosbogo`
* Christian Weickhmann (:ghuser:`cweickhmann`)
* Kevin Anderson (:ghuser:`kanderso-nrel`)
19 changes: 15 additions & 4 deletions pvlib/spectrum/spectrl2.py
Original file line number Diff line number Diff line change
Expand Up @@ -260,6 +260,11 @@ def spectrl2(apparent_zenith, aoi, surface_tilt, ground_albedo,
2-5 kasten1966 kasten1966 kastenyoung1989
=================== ========== ========== ===============

This implementation also deviates from the reference by including a
check for angles of incidence greater than 90 degrees; without this,
the model might return negative spectral irradiance values when the
sun is behind the plane of array.

References
----------
.. [1] Bird, R, and Riordan, C., 1984, "Simple solar spectral model for
Expand Down Expand Up @@ -357,10 +362,16 @@ def spectrl2(apparent_zenith, aoi, surface_tilt, ground_albedo,
Is = (Ir + Ia + Ig) * Cs # Eq 3-1

# calculate spectral irradiance on a tilted surface, Eq 3-18
Ibeam = Id * cosd(aoi)

# don't need surface_azimuth if we provide projection_ratio
projection_ratio = cosd(aoi) / cosZ
# Note: clipping cosd(aoi) to >=0 is not in the reference, but is necessary
# to prevent nonsense values when the sun is behind the plane of array.
# The same constraint is applied in irradiance.haydavies when not
# supplying `projection_ratio`.
aoi_projection_nn = np.maximum(cosd(aoi), 0) # GH 1348
Ibeam = Id * aoi_projection_nn

# don't need surface_azimuth if we provide projection_ratio.
# Also constrain cos zenith to avoid blowup, as in irradiance.haydavies
projection_ratio = aoi_projection_nn / np.maximum(cosZ, 0.01745)
Isky = pvlib.irradiance.haydavies(surface_tilt=surface_tilt,
surface_azimuth=None,
dhi=Is,
Expand Down
14 changes: 14 additions & 0 deletions pvlib/tests/test_spectrum.py
Original file line number Diff line number Diff line change
Expand Up @@ -92,3 +92,17 @@ def test_dayofyear_missing(spectrl2_data):
kwargs.pop('dayofyear')
with pytest.raises(ValueError, match='dayofyear must be specified'):
_ = spectrum.spectrl2(**kwargs)


def test_aoi_gt_90(spectrl2_data):
# test that returned irradiance values are non-negative when aoi > 90
# see GH #1348
kwargs, _ = spectrl2_data
kwargs['apparent_zenith'] = 70
kwargs['aoi'] = 130
kwargs['surface_tilt'] = 60

spectra = spectrum.spectrl2(**kwargs)
for key in ['poa_direct', 'poa_global']:
message = f'{key} contains negative values for aoi>90'
assert np.all(spectra[key] >= 0), message