@@ -13,30 +13,36 @@ def _time_delta_in_hours(times):
1313 return delta .dt .total_seconds ().div (3600 )
1414
1515
16- def fully_covered_nrel (snowfall , threshold_snowfall = 1. ):
16+ def fully_covered_nrel (snowfall , snow_depth = None , threshold_snowfall = 1. ):
1717 '''
1818 Calculates the timesteps when the row's slant height is fully covered
1919 by snow.
2020
2121 Parameters
2222 ----------
23- snowfall : Series
24- Accumulated snowfall in each time period [cm]
25-
26- threshold_snowfall : float, default 1.0
23+ snowfall: Series
24+ Accumulated snowfall in each time period. [cm]
25+ snow_depth: Series, optional
26+ Snow depth on the ground at the beginning of each time period.
27+ Must have the same index as `snowfall`. [cm]
28+ threshold_snowfall: float, default 1.0
2729 Hourly snowfall above which snow coverage is set to the row's slant
2830 height. [cm/hr]
2931
3032 Returns
3133 ----------
32- boolean: Series
34+ Series
3335 True where the snowfall exceeds the defined threshold to fully cover
3436 the panel.
3537
3638 Notes
3739 -----
3840 Implements the model described in [1]_ with minor improvements in [2]_.
3941
42+ `snow_depth` is used to set coverage=0 when no snow is present on the
43+ ground. This check is described in [2]_ as needed for systems with
44+ low tilt angle.
45+
4046 References
4147 ----------
4248 .. [1] Marion, B.; Schaefer, R.; Caine, H.; Sanchez, G. (2013).
@@ -56,11 +62,15 @@ def fully_covered_nrel(snowfall, threshold_snowfall=1.):
5662 hourly_snow_rate .iloc [0 ] = snowfall .iloc [0 ] / timedelta
5763 else : # can't infer frequency from index
5864 hourly_snow_rate .iloc [0 ] = 0 # replaces NaN
59- return hourly_snow_rate > threshold_snowfall
65+ covered = (hourly_snow_rate > threshold_snowfall )
66+ # no coverage when no snow on the ground
67+ if snow_depth is not None :
68+ covered = covered & (snow_depth > 0. )
69+ return covered
6070
6171
6272def coverage_nrel (snowfall , poa_irradiance , temp_air , surface_tilt ,
63- initial_coverage = 0 , threshold_snowfall = 1. ,
73+ snow_depth = None , initial_coverage = 0 , threshold_snowfall = 1. ,
6474 can_slide_coefficient = - 80. , slide_amount_coefficient = 0.197 ):
6575 '''
6676 Calculates the fraction of the slant height of a row of modules covered by
@@ -82,6 +92,9 @@ def coverage_nrel(snowfall, poa_irradiance, temp_air, surface_tilt,
8292 surface_tilt : numeric
8393 Tilt of module's from horizontal, e.g. surface facing up = 0,
8494 surface facing horizon = 90. [degrees]
95+ snow_depth : Series, optional
96+ Snow depth on the ground at the beginning of each time period.
97+ Must have the same index as `snowfall`. [cm]
8598 initial_coverage : float, default 0
8699 Fraction of row's slant height that is covered with snow at the
87100 beginning of the simulation. [unitless]
@@ -106,6 +119,10 @@ def coverage_nrel(snowfall, poa_irradiance, temp_air, surface_tilt,
106119 In [1]_, `can_slide_coefficient` is termed `m`, and the value of
107120 `slide_amount_coefficient` is given in tenths of a module's slant height.
108121
122+ `snow_depth` is used to set coverage=0 when no snow is present on the
123+ ground. This check is described in [2]_ as needed for systems with
124+ low tilt angle.
125+
109126 References
110127 ----------
111128 .. [1] Marion, B.; Schaefer, R.; Caine, H.; Sanchez, G. (2013).
@@ -117,7 +134,7 @@ def coverage_nrel(snowfall, poa_irradiance, temp_air, surface_tilt,
117134 '''
118135
119136 # find times with new snowfall
120- new_snowfall = fully_covered_nrel (snowfall , threshold_snowfall )
137+ new_snowfall = fully_covered_nrel (snowfall , snow_depth , threshold_snowfall )
121138
122139 # set up output Series
123140 snow_coverage = pd .Series (np .nan , index = poa_irradiance .index )
@@ -143,6 +160,10 @@ def coverage_nrel(snowfall, poa_irradiance, temp_air, surface_tilt,
143160 snow_coverage .ffill (inplace = True )
144161 snow_coverage -= cumulative_sliding
145162
163+ if snow_depth is not None :
164+ # no coverage when there's no snow on the ground
165+ # described in [2] to avoid non-sliding snow for low-tilt systems.
166+ snow_coverage [snow_depth <= 0 ] = 0.
146167 # clean up periods where row is completely uncovered
147168 return snow_coverage .clip (lower = 0 )
148169
0 commit comments