From 40faa286fabb07eb41106621643ebdc9d9242600 Mon Sep 17 00:00:00 2001 From: Karel De Brabandere Date: Fri, 11 Nov 2022 14:54:55 +0100 Subject: [PATCH 1/2] add support for zero gcr --- pvlib/bifacial/infinite_sheds.py | 4 ++-- pvlib/shading.py | 4 ++-- pvlib/tests/bifacial/test_infinite_sheds.py | 8 ++++++++ pvlib/tests/test_shading.py | 7 +++++++ 4 files changed, 19 insertions(+), 4 deletions(-) diff --git a/pvlib/bifacial/infinite_sheds.py b/pvlib/bifacial/infinite_sheds.py index 3dd37e3b05..47cf7c2d4d 100644 --- a/pvlib/bifacial/infinite_sheds.py +++ b/pvlib/bifacial/infinite_sheds.py @@ -216,8 +216,8 @@ def _ground_angle(x, surface_tilt, gcr): # : \ v *-.\ # : \<-----P---->\ - x1 = x * sind(surface_tilt) - x2 = (x * cosd(surface_tilt) + 1 / gcr) + x1 = gcr * x * sind(surface_tilt) + x2 = gcr * x * cosd(surface_tilt) + 1 psi = np.arctan2(x1, x2) # do this first because it handles 0 / 0 return np.rad2deg(psi) diff --git a/pvlib/shading.py b/pvlib/shading.py index 9479eb1739..01d725207c 100644 --- a/pvlib/shading.py +++ b/pvlib/shading.py @@ -52,8 +52,8 @@ def masking_angle(surface_tilt, gcr, slant_height): # The original equation (8 in [1]) requires pitch and collector width, # but it's easy to non-dimensionalize it to make it a function of GCR # by factoring out B from the argument to arctan. - numerator = (1 - slant_height) * sind(surface_tilt) - denominator = 1/gcr - (1 - slant_height) * cosd(surface_tilt) + numerator = gcr * (1 - slant_height) * sind(surface_tilt) + denominator = 1 - gcr * (1 - slant_height) * cosd(surface_tilt) phi = np.arctan(numerator / denominator) return np.degrees(phi) diff --git a/pvlib/tests/bifacial/test_infinite_sheds.py b/pvlib/tests/bifacial/test_infinite_sheds.py index 05d1bc58db..696d10568c 100644 --- a/pvlib/tests/bifacial/test_infinite_sheds.py +++ b/pvlib/tests/bifacial/test_infinite_sheds.py @@ -106,6 +106,14 @@ def test__ground_angle(test_system): assert np.allclose(angles, expected_angles) +def test__ground_angle_zero_gcr(): + surface_tilt = 30.0 + x = np.array([0.0, 0.5, 1.0]) + angles = infinite_sheds._ground_angle(x, surface_tilt, 0) + expected_angles = np.array([0, 0, 0]) + assert np.allclose(angles, expected_angles) + + def test__vf_row_ground(test_system): ts, _, _ = test_system x = np.array([0., 0.5, 1.0]) diff --git a/pvlib/tests/test_shading.py b/pvlib/tests/test_shading.py index 8a9fd46a69..0558cb76ad 100644 --- a/pvlib/tests/test_shading.py +++ b/pvlib/tests/test_shading.py @@ -45,6 +45,13 @@ def test_masking_angle_scalar(surface_tilt, masking_angle): assert np.isclose(masking_angle_actual, angle) +def test_masking_angle_zero_gcr(surface_tilt): + # scalar inputs and outputs, including zero + for tilt in surface_tilt: + masking_angle_actual = shading.masking_angle(tilt, 0, 0.25) + assert np.isclose(masking_angle_actual, 0) + + def test_masking_angle_passias_series(surface_tilt, average_masking_angle): # pandas series inputs and outputs masking_angle_actual = shading.masking_angle_passias(surface_tilt, 0.5) From 7292749aa724e31b6be0b2ed638c5dcaee456a7b Mon Sep 17 00:00:00 2001 From: Karel De Brabandere Date: Fri, 11 Nov 2022 15:20:39 +0100 Subject: [PATCH 2/2] update whatsnew --- docs/sphinx/source/whatsnew/v0.9.4.rst | 3 +++ 1 file changed, 3 insertions(+) diff --git a/docs/sphinx/source/whatsnew/v0.9.4.rst b/docs/sphinx/source/whatsnew/v0.9.4.rst index 00bc89207a..b4cd977432 100644 --- a/docs/sphinx/source/whatsnew/v0.9.4.rst +++ b/docs/sphinx/source/whatsnew/v0.9.4.rst @@ -20,6 +20,8 @@ Enhancements Bug fixes ~~~~~~~~~ +* Fixed bug in :py:func:`pvlib.shading.masking_angle` and :py:func:`pvlib.bifacial.infinite_sheds._ground_angle` + where zero ``gcr`` input caused a ZeroDivisionError (:issue:`1576`, :pull:`1589`) Testing ~~~~~~~ @@ -43,3 +45,4 @@ Contributors * Christian Orner (:ghuser:`chrisorner`) * Saurabh Aneja (:ghuser:`spaneja`) * Marcus Boumans (:ghuser:`bowie2211`) +* Karel De Brabandere (:ghuser:`kdebrab`)