def test_alternative_sun_position(): sun = sun_position() sune = sun_position_ephem() suna = sun_position_astk() # ephem is equivalent < 1% numpy.testing.assert_allclose(sune, sun, rtol=0.01) # astk is equivalent <5 % numpy.testing.assert_allclose(suna, sun, rtol=0.05)
def sun_sources(irradiance=1, dates=None, daydate=_daydate, longitude=_longitude, latitude=_latitude, altitude=_altitude, timezone=_timezone): """ Light sources representing the sun under clear sky conditions Args: irradiance: (float) sum of horizontal irradiance of sources. Using irradiance=1 (default) yields relative contribution of sources. If None, clear sky sun horizontal irradiance predicted by Perez/Ineichen model is used. dates: A pandas datetime index (as generated by pandas.date_range). If None, hourly values for daydate are used. daydate: (str) yyyy-mm-dd (not used if dates is not None). longitude: (float) in degrees latitude: (float) in degrees altitude: (float) in meter timezone:(str) the time zone (not used if dates are already localised) Returns: elevation (degrees), azimuth (degrees, from North positive clockwise) and horizontal irradiance of sources """ c_sky = clear_sky_irradiances(dates=dates, daydate=daydate, longitude=longitude, latitude=latitude, altitude=altitude, timezone=timezone) sun_irradiance = c_sky['ghi'] - c_sky['dhi'] if irradiance is not None: sun_irradiance /= sum(sun_irradiance) sun_irradiance *= irradiance # Sr = (1 -cos(cone half angle)) * 2 * pi, frac = Sr / 2 / pi # fsun = 1 - numpy.cos(numpy.radians(.53 / 2)) sun = sun_position(dates=dates, daydate=daydate, latitude=latitude, longitude=longitude, altitude=altitude, timezone=timezone) return sun['elevation'].values, sun[ 'azimuth'].values, sun_irradiance.values
def clear_sky_irradiances(dates=None, daydate=_daydate, longitude=_longitude, latitude=_latitude, altitude=_altitude, timezone=_timezone): """ Estimate component of sky irradiance for clear sky conditions Args: dates: A pandas datetime index (as generated by pandas.date_range). If None, daydate is used. daydate: (str) yyyy-mm-dd (not used if dates is not None). longitude: (float) in degrees latitude: (float) in degrees altitude: (float) in meter timezone:(str) the time zone (not used if dates are already localised) Returns: a pandas dataframe with global horizontal irradiance, direct normal irradiance and diffuse horizontal irradiance. Details: P. Ineichen and R. Perez, "A New airmass independent formulation for the Linke turbidity coefficient", Solar Energy, vol 73, pp. 151-157, 2002 """ df = sun_position(dates=dates, daydate=daydate, latitude=latitude, longitude=longitude, altitude=altitude, timezone=timezone) tl = pvlib.clearsky.lookup_linke_turbidity(df.index, latitude, longitude) am = air_mass(df['zenith'], altitude) dni_extra = sun_extraradiation(df.index) clearsky = pvlib.clearsky.ineichen(df['zenith'], am, tl, dni_extra=dni_extra, altitude=altitude) clearsky = pandas.concat([df, clearsky], axis=1) return clearsky.loc[:, ['ghi', 'dni', 'dhi']]
def actual_sky_irradiances(dates, ghi, dhi=None, Tdew=None, longitude=_longitude, latitude=_latitude, altitude=_altitude, method='dirint'): """ derive a sky irradiance dataframe from actual weather data""" df = sun_position(dates=dates, latitude=latitude, longitude=longitude, altitude=altitude, filter_night=False) df['am'] = air_mass(df['zenith'], altitude) df['dni_extra'] = sun_extraradiation(df.index) if dhi is None: pressure = pvlib.atmosphere.alt2pres(altitude) dhi = diffuse_horizontal_irradiance(ghi, df['elevation'], dates, pressure=pressure, temp_dew=Tdew, method=method) df['ghi'] = ghi df['dhi'] = dhi el = numpy.radians(df['elevation']) df['dni'] = (df['ghi'] - df['dhi']) / numpy.sin(el) df['brightness'] = brightness(df['am'], df['dhi'], df['dni_extra']) df['clearness'] = clearness(df['dni'], df['dhi'], df['zenith']) return df.loc[(df['elevation'] > 0) & (df['ghi'] > 0) , ['azimuth', 'zenith', 'elevation', 'am', 'dni_extra', 'clearness', 'brightness', 'ghi', 'dni', 'dhi' ]]
def clear_sky_irradiances(dates=_dates, longitude=_longitude, latitude=_latitude, altitude=_altitude, timezone=_timezone, method = 'ineichen'): """ Estimate components of sky irradiance for clear sy conditions at a given location Args: dates: longitude: latitude: altitude: timezone: Returns: a pandas dataframe with DNI, GHI and DHI. Details: the Perez / Ineichen model (2002) is used, except if pvlib is not available. In the later case, GHI is computed after Haurwitz (1945) and DNI after Meinel (1976) P. Ineichen and R. Perez, "A New airmass independent formulation for the Linke turbidity coefficient", Solar Energy, vol 73, pp. 151-157, 2002 B. Haurwitz, "Insolation in Relation to Cloudiness and Cloud Density," Journal of Meteorology, vol. 2, pp. 154-166, 1945. A. B. Meinel and M. P. Meinel, Applied solar energy. Reading, MA: Addison-Wesley Publishing Co., 1976 """ df = sun_position(dates=dates, latitude=latitude, longitude=longitude, altitude=altitude, timezone=timezone) df['am'] = air_mass(df['zenith'], altitude) df['dni_extra'] = sun_extraradiation(df.index) if method == 'ineichen' and pvlib_installed: tl = pvlib.clearsky.lookup_linke_turbidity(df.index, latitude, longitude) clearsky = pvlib.clearsky.ineichen(df['zenith'], df['am'], tl, dni_extra = df['dni_extra'], altitude = altitude) clearsky = pandas.concat([df, clearsky], axis=1) else: clearsky = df z = numpy.radians(df['zenith']) clearsky['ghi'] = 1098 * numpy.cos(z) * numpy.exp(-0.057 / numpy.cos(z)) clearsky['dni'] = df['dni_extra'] * numpy.power(0.7, numpy.power(df['am'], 0.678)) clearsky['dhi'] = clearsky['ghi'] - horizontal_irradiance(clearsky['dni'], df['elevation']) clearsky['brightness'] = brightness(clearsky['am'], clearsky['dhi'], clearsky['dni_extra']) clearsky['clearness'] = clearness(clearsky['dni'], clearsky['dhi'], clearsky['zenith']) return clearsky.loc[:,['azimuth', 'zenith', 'elevation', 'am', 'dni_extra', 'clearness', 'brightness', 'ghi', 'dni', 'dhi' ]]
def sun_path(self, seq): """ Return position of the sun corresponing to a sequence of date """ return sun_position(seq, timezone='utc')
def test_sun_position(): sun = sun_position() assert len(sun) == 15
def sky_sources(sky_type='soc', irradiance=1, turtle_sectors=46, dates=None, daydate=_daydate, longitude=_longitude, latitude=_latitude, altitude=_altitude, timezone=_timezone): """ Light sources representing standard cie sky types in 46 directions Args: sky_type:(str) type of sky luminance model. One of : 'soc' (standard overcast sky), 'uoc' (uniform overcast sky) 'clear_sky' (standard clear sky) irradiance: (float) sum of horizontal irradiance of all sources. If None diffuse horizontal clear_sky irradiance are used for clear_sky type and 20% attenuated clear_sky global horizontal irradiances are used for soc and uoc types. turtle_sectors: (int) the minimal number of sectors to be used for sky discretisation dates: A pandas datetime index (as generated by pandas.date_range). If None, hourly values for daydate are used. daydate: (str) yyyy-mm-dd (not used if dates is not None). longitude: (float) in degrees latitude: (float) in degrees altitude: (float) in meter timezone:(str) the time zone (not used if dates are already localised) Returns: elevation (degrees), azimuth (degrees, from North positive clockwise), and horizontal irradiance of sources """ source_elevation, source_azimuth, source_fraction = sky_discretisation( turtle_sectors) if sky_type == 'soc' or sky_type == 'uoc': radiance = sky_radiance_distribution(source_elevation, source_azimuth, source_fraction, sky_type=sky_type) source_irradiance = horizontal_irradiance(radiance, source_elevation) if irradiance is None: sky_irradiance = clear_sky_irradiances(dates=dates, daydate=daydate, longitude=longitude, latitude=latitude, altitude=altitude, timezone=timezone) irradiance = sum(sky_irradiance['ghi']) * 0.2 elif sky_type == 'clear_sky': sun = sun_position(dates=dates, daydate=daydate, latitude=latitude, longitude=longitude, altitude=altitude, timezone=timezone) c_sky = clear_sky_irradiances(dates=dates, daydate=daydate, longitude=longitude, latitude=latitude, altitude=altitude, timezone=timezone) c_sky = pandas.concat([sun, c_sky], axis=1) if irradiance is None: irradiance = sum(c_sky['dhi']) # temporal weigths : use dhi (diffuse horizontal irradiance) c_sky['wsky'] = c_sky['dhi'] / sum(c_sky['dhi']) source_irradiance = numpy.zeros_like(source_fraction) for i, row in c_sky.iterrows(): rad = sky_radiance_distribution(source_elevation, source_azimuth, source_fraction, sky_type='clear_sky', sun_elevation=row['elevation'], sun_azimuth=row['azimuth'], avoid_sun=True) source_irradiance += ( horizontal_irradiance(rad, source_elevation) * row['wsky']) else: raise ValueError('unknown type: ' + sky_type + ' (should be one of uoc, soc, clear_sky') source_irradiance /= sum(source_irradiance) source_irradiance *= irradiance return source_elevation, source_azimuth, source_irradiance
def sky_irradiances(dates=None, daydate=_daydate, ghi=None, dhi=None, attenuation=None, pressure=101325, temp_dew=None, longitude=_longitude, latitude=_latitude, altitude=_altitude, timezone=_timezone): """ Estimate variables related to sky irradiance. Args: dates: A pandas datetime index (as generated by pandas.date_range). If None, daydate is used. daydate: (str) yyyy-mm-dd (not used if dates is not None). ghi: (array_like) : global horizontal irradiance (W. m-2).If None (default) clear_sky irradiance are used dhi: (array-like): diffuse horizontal irradiance attenuation: (float) a attenuation factor for ghi (actual_ghi = attenuation * ghi). If None (default), no attenuation is applied. If dhi is not None, this parameter is not taken into account. pressure: the site pressure (Pa) (for dirint model) temp_dew: the dew point temperature (dirint model) longitude: (float) in degrees latitude: (float) in degrees altitude: (float) in meter timezone:(str) the time zone (not used if dates are already localised) Returns: a pandas dataframe with azimuth, zenital and elevation angle of the sun, clearness and brightness indices, global horizontal irradiance, direct normal irradiance and diffuse horizontal irradiance of the sky. """ df = sun_position(dates=dates, daydate=daydate, latitude=latitude, longitude=longitude, altitude=altitude, timezone=timezone) if len(df) < 1: # night if ghi is not None: # twilight conditions (sun_el < 0, ghi > 0) df = sun_position(dates=dates, daydate=daydate, latitude=latitude, longitude=longitude, altitude=altitude, timezone=timezone, filter_night=False) df['ghi'] = ghi df['dhi'] = ghi df['dni'] = 0 df['clearness'] = None df['brightness'] = None df = df.loc[df.ghi > 0, :] else: df['ghi'] = 0 df['dhi'] = 0 df['dni'] = 0 df['clearness'] = None df['brightness'] = None else: # day if ghi is None or dhi is None: irr = actual_sky_irradiances(dates=df.index, ghi=ghi, attenuation=attenuation, pressure=pressure, temp_dew=temp_dew, latitude=latitude, longitude=longitude, altitude=altitude, timezone=timezone) df = pandas.concat([df, irr], axis=1) else: df['ghi'] = ghi df['dhi'] = dhi df['dni'] = normal_irradiance( numpy.array(ghi) - numpy.array(dhi), df.elevation) am = air_mass(df['zenith'], altitude) dni_extra = sun_extraradiation(df.index) df['brightness'] = brightness(am, df['dhi'], dni_extra) df['clearness'] = clearness(df['dni'], df['dhi'], df['zenith']) return df.loc[:, [ 'azimuth', 'zenith', 'elevation', 'clearness', 'brightness', 'ghi', 'dni', 'dhi' ]]
def actual_sky_irradiances(dates=None, daydate=_daydate, ghi=None, attenuation=None, pressure=101325, temp_dew=None, longitude=_longitude, latitude=_latitude, altitude=_altitude, timezone=_timezone): """ Estimate component of sky irradiances from measured actual global horizontal irradiance or attenuated clearsky conditions. Args: dates: A pandas datetime index (as generated by pandas.date_range). If None, daydate is used. daydate: (str) yyyy-mm-dd (not used if dates is not None). ghi: (array_like) : global horizontal irradiance (W. m-2).If None (default) clear_sky irradiance are used attenuation: (float) a attenuation factor for ghi (actual_ghi = attenuation * ghi). If None (default), no attenuation is applied pressure: the site pressure (Pa) (for dirint model) temp_dew: the dew point temperature (dirint model) longitude: (float) in degrees latitude: (float) in degrees altitude: (float) in meter timezone:(str) the time zone (not used if dates are already localised) Returns: a pandas dataframe with global horizontal irradiance, direct normal irradiance and diffuse horizontal irradiance. Details: Perez, R., P. Ineichen, E. Maxwell, R. Seals and A. Zelenka, (1992). Dynamic Global-to-Direct Irradiance Conversion Models. ASHRAE Transactions-Research Series, pp. 354-369 """ df = sun_position(dates=dates, daydate=daydate, latitude=latitude, longitude=longitude, altitude=altitude, timezone=timezone) if ghi is None: cs = clear_sky_irradiances(dates=df.index, latitude=latitude, longitude=longitude, altitude=altitude, timezone=timezone) ghi = cs['ghi'] df['ghi'] = ghi if attenuation is not None: df.ghi *= attenuation df['dni'] = pvlib.irradiance.dirint(df.ghi, 90 - df.elevation, df.index, pressure=pressure, temp_dew=temp_dew) df['dhi'] = df.ghi - horizontal_irradiance(df.dni, df.elevation) return df.loc[:, ('ghi', 'dhi', 'dni')]