diff --git a/docs/sphinx/source/whatsnew/v0.15.2.rst b/docs/sphinx/source/whatsnew/v0.15.2.rst index 37f8692280..7cad308c58 100644 --- a/docs/sphinx/source/whatsnew/v0.15.2.rst +++ b/docs/sphinx/source/whatsnew/v0.15.2.rst @@ -21,7 +21,10 @@ Bug fixes Enhancements ~~~~~~~~~~~~ - +* Added the ``front_side_fraction`` parameter to + :py:func:`pvlib.snow.loss_townsend` to support bifacial Townsend snow-loss + workflows where the calculated loss is scaled by the front-side energy + fraction. (:pull:`2756`) (:ghuser:`shethkajal7`) Documentation ~~~~~~~~~~~~~ @@ -53,3 +56,4 @@ Contributors ~~~~~~~~~~~~ * :ghuser:`Omesh37` * Cliff Hansen (:ghuser:`cwhanse`) +* :ghuser:`shethkajal7` diff --git a/pvlib/snow.py b/pvlib/snow.py index ec1fa0dc51..a21a9e45ad 100644 --- a/pvlib/snow.py +++ b/pvlib/snow.py @@ -248,7 +248,8 @@ def _townsend_effective_snow(snow_total, snow_events): def loss_townsend(snow_total, snow_events, surface_tilt, relative_humidity, temp_air, poa_global, slant_height, lower_edge_height, - string_factor=1.0, angle_of_repose=40): + string_factor=1.0, angle_of_repose=40, + front_side_fraction=1.0): ''' Calculates monthly snow loss based on the Townsend monthly snow loss model. @@ -293,6 +294,12 @@ def loss_townsend(snow_total, snow_events, surface_tilt, relative_humidity, Piled snow angle, assumed to stabilize at 40°, the midpoint of 25°-55° avalanching slope angles. [deg] + front_side_fraction : numeric or array-like, default 1.0 + Fraction of monthly energy from front-side insolation (unitless). + Multiplies the calculated loss fraction. For example, + use 0.9 when 90% of monthly energy is from the front side + of a bifacial system and 10% is from the rear side. + Returns ------- loss : array-like @@ -310,6 +317,10 @@ def loss_townsend(snow_total, snow_events, surface_tilt, relative_humidity, publication of [1]_, as described in [2]_. The definition for snow events documented above is based on [3]_. + For bifacial systems, [2]_ recommends including both front-side and + rear-side insolation in ``poa_global``. The resulting loss is + scaled by the front-side energy fraction ``front_side_fraction``. + References ---------- .. [1] Townsend, Tim & Powers, Loren. (2011). Photovoltaics and snow: An @@ -384,4 +395,6 @@ def loss_townsend(snow_total, snow_events, surface_tilt, relative_humidity, * string_factor ) + loss_fraction = loss_fraction * front_side_fraction + return np.clip(loss_fraction, 0, 1) diff --git a/tests/test_snow.py b/tests/test_snow.py index 6d8954011e..46dc0410ce 100644 --- a/tests/test_snow.py +++ b/tests/test_snow.py @@ -247,3 +247,27 @@ def test_loss_townsend_cases(poa_global, surface_tilt, slant_height, poa_global, slant_height, lower_edge_height, string_factor) actual = np.around(actual * 100) assert np.allclose(expected, actual) + + +def test_loss_townsend_front_side_fraction(): + snow_total = np.array([25.4, 25.4, 12.7, 2.54, 0, 0, 0, 0, 0, 0, 12.7, + 25.4]) + snow_events = np.array([2, 2, 1, 0, 0, 0, 0, 0, 0, 0, 2, 3]) + surface_tilt = 20 + relative_humidity = np.full(12, 80) + temp_air = np.full(12, 0) + poa_global = np.full(12, 350000) + slant_height = 2.54 + lower_edge_height = 0.254 + front_side_fraction = 0.9 + + unadjusted = snow.loss_townsend( + snow_total, snow_events, surface_tilt, relative_humidity, temp_air, + poa_global, slant_height, lower_edge_height) + + adjusted = snow.loss_townsend( + snow_total, snow_events, surface_tilt, relative_humidity, temp_air, + poa_global, slant_height, lower_edge_height, + front_side_fraction=front_side_fraction) + + np.testing.assert_allclose(adjusted, unadjusted * front_side_fraction)