@@ -82,6 +82,8 @@ then set the location and time range data.
8282 start = pd.Timestamp(datetime.date.today(), tz = tz)
8383 end = start + pd.Timedelta(days = 7 )
8484
85+ irrad_vars = [' ghi' , ' dni' , ' dhi' ]
86+
8587
8688 Next, we instantiate a GFS model object and get the forecast data
8789from Unidata.
@@ -118,7 +120,8 @@ problems.
118120 data[' wind_speed' ] = model.uv_to_speed(data)
119121
120122 # 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.
122125 # this step is discussed in more detail in the next section
123126 irrad_data = model.cloud_cover_to_irradiance(data[' total_clouds' ])
124127 data = data.join(irrad_data, how = ' outer' )
@@ -185,22 +188,71 @@ poor solar position or radiative transfer algorithms. It is often more
185188accurate to create empirically derived radiation forecasts from the
186189weather models' cloud cover forecasts.
187190
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.
193218
194219.. ipython :: python
195220
196221 # 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();
199225 plt.ylabel(' Irradiance ($W/m^2$)' );
200226 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"'
202254 .format(latitude, longitude));
203- @savefig gfs_irrad .png width =6in
255+ @savefig gfs_irrad_lj .png width =6in
204256 plt.legend();
205257
206258
@@ -212,18 +264,18 @@ recalculate the irradiance.
212264
213265.. ipython :: python
214266
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();
220270 plt.ylabel(' Irradiance ($W/m^2$)' );
221271 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 '
223273 .format(latitude, longitude));
224274 @savefig gfs_irrad_high_res.png width =6in
225275 plt.legend();
226276
277+ Users may then recombine resampled_irrads and resampled_data using
278+ slicing :py:func: `pandas.concat ` or :py:meth: `pandas.DataFrame.join `.
227279
228280We reiterate that the open source code enables users to customize the
229281model processing to their liking.
0 commit comments