@@ -82,6 +82,8 @@ then set the location and time range data.
82
82
start = pd.Timestamp(datetime.date.today(), tz = tz)
83
83
end = start + pd.Timedelta(days = 7 )
84
84
85
+ irrad_vars = [' ghi' , ' dni' , ' dhi' ]
86
+
85
87
86
88
Next, we instantiate a GFS model object and get the forecast data
87
89
from Unidata.
@@ -118,7 +120,8 @@ problems.
118
120
data[' wind_speed' ] = model.uv_to_speed(data)
119
121
120
122
# calculate irradiance estimates from cloud cover.
121
- # uses Location.get_solarposition and irradiance.liujordan
123
+ # uses a cloud_cover to ghi to dni model or a
124
+ # uses a cloud cover to transmittance to irradiance model.
122
125
# this step is discussed in more detail in the next section
123
126
irrad_data = model.cloud_cover_to_irradiance(data[' total_clouds' ])
124
127
data = data.join(irrad_data, how = ' outer' )
@@ -185,22 +188,71 @@ poor solar position or radiative transfer algorithms. It is often more
185
188
accurate to create empirically derived radiation forecasts from the
186
189
weather models' cloud cover forecasts.
187
190
188
- PVLIB-Python currently uses the Liu-Jordan [Liu60 ]_ model to convert
189
- total cloud cover forecasts to irradiance forecasts. We encourage pvlib
190
- users to implement new cloud cover to irradiance algorithms. The figure
191
- below shows the result of the Liu-Jordan total cloud cover to irradiance
192
- conversion.
191
+ PVLIB-Python provides two basic ways to convert cloud cover forecasts to
192
+ irradiance forecasts. One method assumes a linear relationship between
193
+ cloud cover and GHI, applies the scaling to a clear sky climatology, and
194
+ then uses the DISC model to calculate DNI. The second method assumes a
195
+ linear relationship between cloud cover and atmospheric transmittance,
196
+ and then uses the Liu-Jordan [Liu60 ]_ model to calculate GHI, DNI, and
197
+ DHI.
198
+
199
+ *Caveat emptor *: these algorithms are not rigorously verified! The
200
+ purpose of the forecast module is to provide a few exceedingly simple
201
+ options for users to play with before they develop their own models. We
202
+ strongly encourage pvlib users first read the source code and second
203
+ to implement new cloud cover to irradiance algorithms.
204
+
205
+ The essential parts of the clear sky scaling algorithm are as follows.
206
+
207
+ .. code-block :: python
208
+
209
+ solpos = location.get_solarposition(cloud_cover.index)
210
+ cs = location.get_clearsky(cloud_cover.index, model = ' ineichen' )
211
+ # offset and cloud cover in decimal units here
212
+ ghi = (offset + (1 - offset) * (1 - cloud_cover)) * ghi_clear
213
+ dni = disc(ghi, solpos[' zenith' ], cloud_cover.index)[' dni' ]
214
+ dhi = ghi - dni * np.cos(np.radians(solpos[' zenith' ]))
215
+
216
+ The figure below shows the result of the total cloud cover to
217
+ irradiance conversion using the clear sky scaling algorithm.
193
218
194
219
.. ipython :: python
195
220
196
221
# plot irradiance data
197
- irrad_vars = [' dni' , ' ghi' , ' dhi' ]
198
- data[irrad_vars].plot();
222
+ data = model.rename(raw_data)
223
+ irrads = model.cloud_cover_to_irradiance(data[' total_clouds' ], how = ' clearsky_scaling' )
224
+ irrads.plot();
199
225
plt.ylabel(' Irradiance ($W/m^2$)' );
200
226
plt.xlabel(' Forecast Time ({} )' .format(tz));
201
- plt.title(' GFS 0.5 deg forecast for lat={} , lon={} '
227
+ plt.title(' GFS 0.5 deg forecast for lat={} , lon={} using "clearsky_scaling"'
228
+ .format(latitude, longitude));
229
+ @savefig gfs_irrad_cs.png width =6in
230
+ plt.legend();
231
+
232
+
233
+ The essential parts of the Liu-Jordan cloud cover to irradiance algorithm
234
+ are as follows.
235
+
236
+ .. code-block :: python
237
+
238
+ # cloud cover in percentage units here
239
+ transmittance = ((100.0 - cloud_cover) / 100.0 ) * 0.75
240
+ # irrads is a DataFrame containing ghi, dni, dhi
241
+ irrads = liujordan(apparent_zenith, transmittance, airmass_absolute)
242
+
243
+ The figure below shows the result of the Liu-Jordan total cloud cover to
244
+ irradiance conversion.
245
+
246
+ .. ipython :: python
247
+
248
+ # plot irradiance data
249
+ irrads = model.cloud_cover_to_irradiance(data[' total_clouds' ], how = ' liujordan' )
250
+ irrads.plot();
251
+ plt.ylabel(' Irradiance ($W/m^2$)' );
252
+ plt.xlabel(' Forecast Time ({} )' .format(tz));
253
+ plt.title(' GFS 0.5 deg forecast for lat={} , lon={} using "liujordan"'
202
254
.format(latitude, longitude));
203
- @savefig gfs_irrad .png width =6in
255
+ @savefig gfs_irrad_lj .png width =6in
204
256
plt.legend();
205
257
206
258
@@ -212,18 +264,18 @@ recalculate the irradiance.
212
264
213
265
.. ipython :: python
214
266
215
- from pvlib import irradiance
216
- total_clouds = data[' total_clouds' ].resample(' 5min' ).interpolate()
217
- solar_position = model.location.get_solarposition(total_clouds.index)
218
- irrad_data = irradiance.liujordan(solar_position[' apparent_zenith' ], total_clouds)
219
- irrad_data[irrad_vars].plot();
267
+ resampled_data = data.resample(' 5min' ).interpolate()
268
+ resampled_irrads = model.cloud_cover_to_irradiance(resampled_data[' total_clouds' ], how = ' clearsky_scaling' )
269
+ resampled_irrads.plot();
220
270
plt.ylabel(' Irradiance ($W/m^2$)' );
221
271
plt.xlabel(' Forecast Time ({} )' .format(tz));
222
- plt.title(' GFS 0.5 deg forecast for lat={} , lon={} '
272
+ plt.title(' GFS 0.5 deg forecast for lat={} , lon={} resampled '
223
273
.format(latitude, longitude));
224
274
@savefig gfs_irrad_high_res.png width =6in
225
275
plt.legend();
226
276
277
+ Users may then recombine resampled_irrads and resampled_data using
278
+ slicing :py:func: `pandas.concat ` or :py:meth: `pandas.DataFrame.join `.
227
279
228
280
We reiterate that the open source code enables users to customize the
229
281
model processing to their liking.
0 commit comments