@@ -260,6 +260,11 @@ def spectrl2(apparent_zenith, aoi, surface_tilt, ground_albedo,
260260 2-5 kasten1966 kasten1966 kastenyoung1989
261261 =================== ========== ========== ===============
262262
263+ This implementation also deviates from the reference by including a
264+ check for angles of incidence greater than 90 degrees; without this,
265+ the model might return negative spectral irradiance values when the
266+ sun is behind the plane of array.
267+
263268 References
264269 ----------
265270 .. [1] Bird, R, and Riordan, C., 1984, "Simple solar spectral model for
@@ -357,10 +362,16 @@ def spectrl2(apparent_zenith, aoi, surface_tilt, ground_albedo,
357362 Is = (Ir + Ia + Ig ) * Cs # Eq 3-1
358363
359364 # calculate spectral irradiance on a tilted surface, Eq 3-18
360- Ibeam = Id * cosd (aoi )
361-
362- # don't need surface_azimuth if we provide projection_ratio
363- projection_ratio = cosd (aoi ) / cosZ
365+ # Note: clipping cosd(aoi) to >=0 is not in the reference, but is necessary
366+ # to prevent nonsense values when the sun is behind the plane of array.
367+ # The same constraint is applied in irradiance.haydavies when not
368+ # supplying `projection_ratio`.
369+ aoi_projection_nn = np .maximum (cosd (aoi ), 0 ) # GH 1348
370+ Ibeam = Id * aoi_projection_nn
371+
372+ # don't need surface_azimuth if we provide projection_ratio.
373+ # Also constrain cos zenith to avoid blowup, as in irradiance.haydavies
374+ projection_ratio = aoi_projection_nn / np .maximum (cosZ , 0.01745 )
364375 Isky = pvlib .irradiance .haydavies (surface_tilt = surface_tilt ,
365376 surface_azimuth = None ,
366377 dhi = Is ,
0 commit comments