def test_get_solarposition_altitude():
    times = pd.date_range(datetime.datetime(2003,10,17,13,30,30),
                          periods=1, freq='D', tz=golden.tz)
    ephem_data = solarposition.get_solarposition(times, golden.latitude,
                                                 golden.longitude,
                                                 altitude=golden.altitude,
                                                 temperature=11)
    this_expected = expected.copy()
    this_expected.index = times
    this_expected = np.round(this_expected, 5)
    ephem_data = np.round(ephem_data, 5)
    assert_frame_equal(this_expected, ephem_data[this_expected.columns])

    ephem_data = solarposition.get_solarposition(times, golden.latitude,
                                                 golden.longitude,
                                                 altitude=0.0,
                                                 temperature=11)
    this_expected = expected.copy()
    this_expected.index = times
    this_expected = np.round(this_expected, 5)
    ephem_data = np.round(ephem_data, 5)
    try:
        assert_frame_equal(this_expected, ephem_data[this_expected.columns])
    except AssertionError:
        pass
    else:
        raise AssertionError
Exemplo n.º 2
0
    def get_solarposition(self, times, pressure=None, temperature=12,
                          **kwargs):
        """
        Uses the :py:func:`solarposition.get_solarposition` function
        to calculate the solar zenith, azimuth, etc. at this location.

        Parameters
        ----------
        times : DatetimeIndex
        pressure : None, float, or array-like, default None
            If None, pressure will be calculated using
            :py:func:`atmosphere.alt2pres` and ``self.altitude``.
        temperature : None, float, or array-like, default 12

        kwargs passed to :py:func:`solarposition.get_solarposition`

        Returns
        -------
        solar_position : DataFrame
            Columns depend on the ``method`` kwarg, but always include
            ``zenith`` and ``azimuth``.
        """
        if pressure is None:
            pressure = atmosphere.alt2pres(self.altitude)

        return solarposition.get_solarposition(times, latitude=self.latitude,
                                               longitude=self.longitude,
                                               altitude=self.altitude,
                                               pressure=pressure,
                                               temperature=temperature,
                                               **kwargs)
def test_get_solarposition_error():
    times = pd.date_range(datetime.datetime(2003,10,17,13,30,30),
                          periods=1, freq='D', tz=golden.tz)
    ephem_data = solarposition.get_solarposition(times, golden.latitude,
                                                 golden.longitude,
                                                 pressure=82000,
                                                 temperature=11,
                                                 method='error this')
Exemplo n.º 4
0
def test_get_solarposition_no_kwargs(expected_solpos):
    times = pd.date_range(datetime.datetime(2003,10,17,13,30,30),
                          periods=1, freq='D', tz=golden.tz)
    ephem_data = solarposition.get_solarposition(times, golden.latitude,
                                                 golden.longitude)
    expected_solpos.index = times
    expected_solpos = np.round(expected_solpos, 2)
    ephem_data = np.round(ephem_data, 2)
    assert_frame_equal(expected_solpos, ephem_data[expected_solpos.columns])
def test_get_solarposition_no_kwargs():
    times = pd.date_range(datetime.datetime(2003,10,17,13,30,30),
                          periods=1, freq='D', tz=golden.tz)
    ephem_data = solarposition.get_solarposition(times, golden.latitude,
                                                 golden.longitude)
    this_expected = expected.copy()
    this_expected.index = times
    this_expected = np.round(this_expected, 2)
    ephem_data = np.round(ephem_data, 2)
    assert_frame_equal(this_expected, ephem_data[this_expected.columns])
Exemplo n.º 6
0
def test_get_solarposition_pressure(pressure, expected):
    times = pd.date_range(datetime.datetime(2003,10,17,13,30,30),
                          periods=1, freq='D', tz=golden.tz)
    ephem_data = solarposition.get_solarposition(times, golden.latitude,
                                                 golden.longitude,
                                                 pressure=pressure,
                                                 temperature=11)
    this_expected = expected.copy()
    this_expected.index = times
    this_expected = np.round(this_expected, 5)
    ephem_data = np.round(ephem_data, 5)
    assert_frame_equal(this_expected, ephem_data[this_expected.columns])
Exemplo n.º 7
0
def test_get_solarposition_deltat(delta_t, method, expected_solpos_multi,
                                  golden):
    times = pd.date_range(datetime.datetime(2003,10,17,13,30,30),
                          periods=2, freq='D', tz=golden.tz)
    ephem_data = solarposition.get_solarposition(times, golden.latitude,
                                                 golden.longitude,
                                                 pressure=82000,
                                                 delta_t=delta_t,
                                                 temperature=11,
                                                 method=method)
    this_expected = expected_solpos_multi
    this_expected.index = times
    this_expected = np.round(this_expected, 5)
    ephem_data = np.round(ephem_data, 5)
    assert_frame_equal(this_expected, ephem_data[this_expected.columns])
Exemplo n.º 8
0
def test_get_solarposition_deltat(delta_t, method, expected, golden):
    times = pd.date_range(datetime.datetime(2003, 10, 17, 13, 30, 30),
                          periods=2,
                          freq='D',
                          tz=golden.tz)
    ephem_data = solarposition.get_solarposition(times,
                                                 golden.latitude,
                                                 golden.longitude,
                                                 pressure=82000,
                                                 delta_t=delta_t,
                                                 temperature=11,
                                                 method=method)
    this_expected = expected.copy()
    this_expected.index = times
    this_expected = np.round(this_expected, 5)
    ephem_data = np.round(ephem_data, 5)
    assert_frame_equal(this_expected, ephem_data[this_expected.columns])
def test_get_solarposition_altitude(altitude, expected, golden,
                                    expected_solpos):
    times = pd.date_range(datetime.datetime(2003, 10, 17, 13, 30, 30),
                          periods=1,
                          freq='D',
                          tz=golden.tz)
    ephem_data = solarposition.get_solarposition(times,
                                                 golden.latitude,
                                                 golden.longitude,
                                                 altitude=altitude,
                                                 temperature=11)
    if isinstance(expected, str) and expected == 'expected_solpos':
        expected = expected_solpos
    this_expected = expected.copy()
    this_expected.index = times
    this_expected = np.round(this_expected, 5)
    ephem_data = np.round(ephem_data, 5)
    assert_frame_equal(this_expected, ephem_data[this_expected.columns])
Exemplo n.º 10
0
def test_haurwitz():
    tus = Location(32.2, -111, 'US/Arizona', 700)
    times = pd.date_range(start='2014-06-24', end='2014-06-25', freq='3h')
    times_localized = times.tz_localize(tus.tz)
    ephem_data = solarposition.get_solarposition(times_localized, tus.latitude,
                                                 tus.longitude)
    expected = pd.DataFrame(np.array([[0.],
                                      [0.],
                                      [82.85934048],
                                      [699.74514735],
                                      [1016.50198354],
                                      [838.32103769],
                                      [271.90853863],
                                      [0.],
                                      [0.]]),
                             columns=['ghi'], index=times_localized)
    out = clearsky.haurwitz(ephem_data['zenith'])
    assert_frame_equal(expected, out)
Exemplo n.º 11
0
def test_simplified_solis_series_elevation():
    tus = Location(32.2, -111, 'US/Arizona', 700)
    times = pd.date_range(start='2014-06-24', end='2014-06-25', freq='3h')
    times_localized = times.tz_localize(tus.tz)
    ephem_data = solarposition.get_solarposition(times_localized, tus.latitude,
                                                 tus.longitude)
    expected = pd.DataFrame(
        np.array([[0., 0., 0.], [0., 0., 0.],
                  [377.80060035, 79.91931339, 42.77453223],
                  [869.47538184, 706.37903999, 110.05635962],
                  [958.89448856, 1062.44821373, 129.02349236],
                  [913.3209839, 860.48978599, 118.94598678],
                  [634.01066762, 256.00505836, 72.18396705], [0., 0., 0.],
                  [0., 0., 0.]]),
        columns=['dni', 'ghi', 'dhi'],
        index=times_localized)
    expected = expected[['dhi', 'dni', 'ghi']]

    out = clearsky.simplified_solis(ephem_data['apparent_elevation'])
    assert_frame_equal(expected, out)
Exemplo n.º 12
0
    def transform(self,
                  elevation_round=1,
                  azimuth_round=2,
                  agg_func=np.nanmean):
        # Solar position subroutine requires TZ-aware time stamps or UTC time
        # stamps, but we typically have non-TZ-aware local time, without DST
        # shifts (which is the most natural for solar data). So, step 1 is to
        # convert the time to UTC.
        times = self.data.index.shift(-self.tz_offset, "H")
        # run solar position subroutine
        solpos = get_solarposition(times, self.lat, self.lon)
        # reset the time from UTC to local
        solpos.index = self.data.index
        # join the calculated angles with the power measurments
        triples = solpos[["apparent_elevation",
                          "azimuth"]].join(self.normed_data.loc[self.bix])
        triples = triples.dropna()
        # cut off all the entries corresponding to the sun below the horizon
        triples = triples[triples["apparent_elevation"] >= 0]

        # a function for rounding to the nearest integer c (e.g. 2, 5, 10...)

        def my_round(x, c):
            return c * np.round(x / c, 0)

        # create elevation and azimuth bins
        triples["elevation_angle"] = my_round(triples["apparent_elevation"],
                                              elevation_round)
        triples["azimuth_angle"] = my_round(triples["azimuth"], azimuth_round)
        # group by bins
        grouped = triples.groupby(["azimuth_angle", "elevation_angle"])
        # calculation aggregation function for each bin
        grouped = grouped.agg(agg_func)
        # remove other columns
        grouped = grouped["normalized-power"]
        # convert tall data format to wide data format, fill misisng values
        # with zero, and transpose
        estimates = grouped.unstack().fillna(0).T
        # reverse the first axis
        estimates = estimates.iloc[::-1]
        self.tranformed_data = estimates
Exemplo n.º 13
0
def test_ineichen_series():
    tus = Location(32.2, -111, 'US/Arizona', 700)
    times = pd.date_range(start='2014-06-24', end='2014-06-25', freq='3h')
    times_localized = times.tz_localize(tus.tz)
    ephem_data = solarposition.get_solarposition(times_localized, tus.latitude,
                                                 tus.longitude)
    am = atmosphere.relativeairmass(ephem_data['apparent_zenith'])
    am = atmosphere.absoluteairmass(am, atmosphere.alt2pres(tus.altitude))
    expected = pd.DataFrame(
        np.array([[0., 0., 0.], [0., 0., 0.],
                  [91.12492792, 321.16092181, 51.17628184],
                  [716.46580533, 888.90147035, 99.5050056],
                  [1053.42066043, 953.24925854, 116.32868969],
                  [863.54692781, 922.06124712, 106.95536561],
                  [271.06382274, 655.44925241, 73.05968071], [0., 0., 0.],
                  [0., 0., 0.]]),
        columns=['ghi', 'dni', 'dhi'],
        index=times_localized)

    out = clearsky.ineichen(ephem_data['apparent_zenith'], am, 3)
    assert_frame_equal(expected, out)
Exemplo n.º 14
0
def test_get_solarposition_deltat(delta_t, method, expected_solpos_multi,
                                  golden):
    times = pd.date_range(datetime.datetime(2003, 10, 17, 13, 30, 30),
                          periods=2,
                          freq='D',
                          tz=golden.tz)
    with warnings.catch_warnings():
        # don't warn on method reload or num threads
        warnings.simplefilter("ignore")
        ephem_data = solarposition.get_solarposition(times,
                                                     golden.latitude,
                                                     golden.longitude,
                                                     pressure=82000,
                                                     delta_t=delta_t,
                                                     temperature=11,
                                                     method=method)
    this_expected = expected_solpos_multi
    this_expected.index = times
    this_expected = np.round(this_expected, 5)
    ephem_data = np.round(ephem_data, 5)
    assert_frame_equal(this_expected, ephem_data[this_expected.columns])
Exemplo n.º 15
0
    def get_solarposition(arg_time, arg_lat, arg_long):

        return_data = {}
        solarpos = solarposition.get_solarposition(time=arg_time,
                                                   latitude=arg_lat,
                                                   longitude=arg_long,
                                                   altitude=None,
                                                   pressure=None)

        solarpos_data = json.loads(solarpos.to_json())

        zenith_dict = solarpos_data["zenith"]
        elevation_dict = solarpos_data["elevation"]
        azimuth_dict = solarpos_data["azimuth"]

        azimuth = list(azimuth_dict.values())[0]
        zenith = list(zenith_dict.values())[0]

        return_data['zenith'] = zenith
        return_data['azimuth'] = azimuth

        return return_data
Exemplo n.º 16
0
def get_solar_position(time,
                       latitude,
                       longitude,
                       altitude,
                       pvlib_method="nrel_numba",
                       **kwargs):
    """ Get solar position

    Use pvlib library and use of numba by default
    :param time:
    :param latitude:
    :param longitude:
    :param altitude:
    :param pvlib_method:
    :return:
    """
    return get_solarposition(time,
                             latitude,
                             longitude,
                             altitude,
                             method=pvlib_method,
                             **kwargs)
Exemplo n.º 17
0
def test_simplified_solis_series_elevation():
    tus = Location(32.2, -111, 'US/Arizona', 700)
    times = pd.date_range(start='2014-06-24', end='2014-06-25', freq='3h')
    times_localized = times.tz_localize(tus.tz)
    ephem_data = solarposition.get_solarposition(times_localized, tus.latitude,
                                                 tus.longitude)
    expected = pd.DataFrame(
        np.array([[    0.        ,     0.        ,     0.        ],
                  [    0.        ,     0.        ,     0.        ],
                  [  377.80060035,    79.91931339,    42.77453223],
                  [  869.47538184,   706.37903999,   110.05635962],
                  [  958.89448856,  1062.44821373,   129.02349236],
                  [  913.3209839 ,   860.48978599,   118.94598678],
                  [  634.01066762,   256.00505836,    72.18396705],
                  [    0.        ,     0.        ,     0.        ],
                  [    0.        ,     0.        ,     0.        ]]),
                            columns=['dni', 'ghi', 'dhi'],
                            index=times_localized)
    expected = expected[['dhi', 'dni', 'ghi']]

    out = clearsky.simplified_solis(ephem_data['apparent_elevation'])
    assert_frame_equal(expected, out)
Exemplo n.º 18
0
def get_from_pvgis(lat, lon, tz):
    """Return the pvgis data"""

    # PVGIS information
    info = get_pvgis_tmy(lat, lon)

    # Altitude
    alt = info[2]['location']['elevation']

    # Get th principal information
    df = info[0]

    # Convert UTC to time zone
    df.index = df.index.tz_convert(tz)
    df.index.name = f'Time {tz}'

    # Get the solar position
    solpos = get_solarposition(time=df.index,
                               latitude=lat,
                               longitude=lon,
                               altitude=alt,
                               pressure=df.SP,
                               temperature=df.T2m)

    # Create the schema
    data = df
    data = data.drop(df.columns, axis=1)
    data['HourOfDay'] = df.index.hour
    data['Zenith'] = solpos['zenith']
    data['Temperature'] = df.T2m
    data['Humidity'] = df.RH
    data['WindSpeed'] = df.WS10m
    data['WindDirection'] = df.WD10m
    data['PrecipitableWater'] = gueymard94_pw(df.T2m, df.RH)
    data['Pressure'] = df.SP
    data['ExtraRadiation'] = get_extra_radiation(df.index)
    data['GHI'] = df['G(h)']

    return data
Exemplo n.º 19
0
def sun_position(dates=None, daydate=_day, latitude=_latitude,
                 longitude=_longitude, altitude=_altitude, timezone=_timezone,
                 filter_night=True):
    """ Sun position

    Args:
        dates: a pandas.DatetimeIndex specifying the dates at which sun position
        is required.If None, daydate is used and one position per hour is generated
        daydate: (str) yyyy-mm-dd (not used if dates is not None).
        latitude: float
        longitude: float
        altitude: (float) altitude in m
        timezone: a string identifying the timezone to be associated to dates if
        dates is not already localised.
        This args is not used if dates are already localised
        filter_night (bool) : Should positions of sun during night be filtered ?

    Returns:
        a pandas dataframe with sun position at requested dates indexed by
        localised dates. Sun azimtuth is given from North, positive clockwise.
    """

    if dates is None:
        dates = pandas.date_range(daydate, periods=24, freq='H')

    if dates.tz is None:
        times = dates.tz_localize(timezone)
    else:
        times = dates

    df = get_solarposition(times, latitude, longitude, altitude)
    sunpos = pandas.DataFrame(
        {'elevation': df['apparent_elevation'], 'azimuth': df['azimuth'],
         'zenith': df['apparent_zenith']}, index=df.index)

    if filter_night and sunpos is not None:
        sunpos = sunpos.loc[sunpos['elevation'] > 0, :]

    return sunpos
Exemplo n.º 20
0
 def test_solpos_calc(self):
     data={
         'lat': 38.2,
         'lon': -122.1,
         'freq': 'T',
         'tz': -8,
         'start': '2018-01-01 07:00',
         'end': '2018-01-01 08:00'
     }
     r = self.client.get('/api/v1/pvlib/solarposition/', data)
     self.assertEqual(r.status_code, 200)
     s = pd.DataFrame(r.json()).T
     t = pd.DatetimeIndex(s.index)
     times = pd.DatetimeIndex(
         start=data['start'], end=data['end'],
         freq=data['freq'], tz='Etc/GMT{:+d}'.format(-data['tz']))
     solpos = solarposition.get_solarposition(
         times, data['lat'], data['lon'])
     assert np.allclose(
         times.values.astype(int), t.values.astype(int))
     assert np.allclose(solpos.apparent_zenith, s.apparent_zenith)
     assert np.allclose(solpos.azimuth, s.azimuth)
Exemplo n.º 21
0
def test_ineichen_series():
    tus = Location(32.2, -111, 'US/Arizona', 700)
    times = pd.date_range(start='2014-06-24', end='2014-06-25', freq='3h')
    times_localized = times.tz_localize(tus.tz)
    ephem_data = solarposition.get_solarposition(times_localized, tus.latitude,
                                                 tus.longitude)
    am = atmosphere.relativeairmass(ephem_data['apparent_zenith'])
    am = atmosphere.absoluteairmass(am, atmosphere.alt2pres(tus.altitude))
    expected = pd.DataFrame(np.
        array([[    0.        ,     0.        ,     0.        ],
               [    0.        ,     0.        ,     0.        ],
               [   91.12492792,   321.16092181,    51.17628184],
               [  716.46580533,   888.90147035,    99.5050056 ],
               [ 1053.42066043,   953.24925854,   116.32868969],
               [  863.54692781,   922.06124712,   106.95536561],
               [  271.06382274,   655.44925241,    73.05968071],
               [    0.        ,     0.        ,     0.        ],
               [    0.        ,     0.        ,     0.        ]]),
                            columns=['ghi', 'dni', 'dhi'],
                            index=times_localized)

    out = clearsky.ineichen(ephem_data['apparent_zenith'], am, 3)
    assert_frame_equal(expected, out)
Exemplo n.º 22
0
def detectLocation(pickleLocation, filePrefix):
	with open(f'{pickleLocation}/{filePrefix}-danceData.json', 'r') as f:
		waggles = json.load(f)

	date = dt.datetime.strptime(waggles['recordDate'], '%a %b %d %H:%M:%S %Y')
	lat, lon = (37.561343, -77.465806)

	solarposition = sp.get_solarposition(date, lat, lon)

	waggles['azimuth'] = str(solarposition['azimuth'][0])


	keys = [k for k, v in waggles.items() if 'waggle-' in k]


	for waggle in keys:
		waggles[waggle]['distance'] = get_distance(waggles, waggle)
	

	prettyPrint(waggles)

	with open(f'{pickleLocation}/{filePrefix}-danceData.json', 'w') as f:
		json.dump(waggles, f)
Exemplo n.º 23
0
    def calc_radiation(self, data, cloud_type='total_clouds'):
        '''
        Determines shortwave radiation values if they are missing from 
        the model data.

        Parameters
        ----------
        data: netcdf
            Query data formatted in netcdf format.
        cloud_type: string
            Type of cloud cover to use for calculating radiation values.
        '''
        self.rad_type = {}
        if not self.lbox and cloud_type in self.modelvariables:
            cloud_prct = self.data[cloud_type]
            solpos = get_solarposition(self.time, self.location)
            self.zenith = np.array(solpos.zenith.tz_convert('UTC'))
            for rad in ['dni', 'dhi', 'ghi']:
                if self.model_name is 'HRRR_ESRL':
                    # HRRR_ESRL is the only model with the
                    # correct equation of time.
                    if rad in self.modelvariables:
                        self.data[rad] = pd.Series(
                            data[self.variables[rad]][:].squeeze(),
                            index=self.time)
                        self.rad_type[rad] = 'forecast'
                        self.data[rad].fillna(0, inplace=True)
                else:
                    for rad in ['dni', 'dhi', 'ghi']:
                        self.rad_type[rad] = 'liujordan'
                        self.data[rad] = liujordan(self.zenith,
                                                   cloud_prct)[rad]
                        self.data[rad].fillna(0, inplace=True)

            for var in ['dni', 'dhi', 'ghi']:
                self.data[var].fillna(0, inplace=True)
                self.var_units[var] = '$W m^{-2}$'
Exemplo n.º 24
0
    def get_solarposition(self,
                          times,
                          pressure=None,
                          temperature=12,
                          **kwargs):
        """
        Uses the :py:func:`solarposition.get_solarposition` function
        to calculate the solar zenith, azimuth, etc. at this location.

        Parameters
        ----------
        times : pandas.DatetimeIndex
            Must be localized or UTC will be assumed.
        pressure : None, float, or array-like, default None
            If None, pressure will be calculated using
            :py:func:`atmosphere.alt2pres` and ``self.altitude``.
        temperature : None, float, or array-like, default 12

        kwargs
            passed to :py:func:`solarposition.get_solarposition`

        Returns
        -------
        solar_position : DataFrame
            Columns depend on the ``method`` kwarg, but always include
            ``zenith`` and ``azimuth``.
        """
        if pressure is None:
            pressure = atmosphere.alt2pres(self.altitude)

        return solarposition.get_solarposition(times,
                                               latitude=self.latitude,
                                               longitude=self.longitude,
                                               altitude=self.altitude,
                                               pressure=pressure,
                                               temperature=temperature,
                                               **kwargs)
Exemplo n.º 25
0
    def calc_radiation(self, data, cloud_type='total_clouds'):
        '''
        Determines shortwave radiation values if they are missing from 
        the model data.

        Parameters
        ----------
        data: netcdf
            Query data formatted in netcdf format.
        cloud_type: string
            Type of cloud cover to use for calculating radiation values.
        '''
        self.rad_type = {}
        if not self.lbox and cloud_type in self.modelvariables:           
            cloud_prct = self.data[cloud_type]
            solpos = get_solarposition(self.time, self.location)
            self.zenith = np.array(solpos.zenith.tz_convert('UTC'))
            for rad in ['dni','dhi','ghi']:
                if self.model_name is 'HRRR_ESRL':
                    # HRRR_ESRL is the only model with the 
                    # correct equation of time.
                    if rad in self.modelvariables:
                        self.data[rad] = pd.Series(
                            data[self.variables[rad]][:].squeeze(), 
                            index=self.time)
                        self.rad_type[rad] = 'forecast'
                        self.data[rad].fillna(0, inplace=True)
                else:
                    for rad in ['dni','dhi','ghi']:
                        self.rad_type[rad] = 'liujordan'
                        self.data[rad] = liujordan(self.zenith, cloud_prct)[rad]
                        self.data[rad].fillna(0, inplace=True)

            for var in ['dni', 'dhi', 'ghi']:
                self.data[var].fillna(0, inplace=True)
                self.var_units[var] = '$W m^{-2}$'
Exemplo n.º 26
0
from pvlib import solarposition, atmosphere, clearsky
import pandas as pd
import pvlib as pvlib
import matplotlib.pyplot as plt
import pylab

lat = 34.42
lon = -119.842
alt = 6200
date = '2019-12-06'

# Must be longer than a day to make sure we see a continuous cycle
index = pd.date_range(start=date, freq='1s', periods=24 * 60 * 60 * 2)

# solar position data frame (first plot)
solar_df = solarposition.get_solarposition(index, lat, lon)

# this loops thru the elements and picks the left/right indexes for one continuous cycle based on the apparent_elevation
# graph. These values are then used to trim the dataframes so we are only operating on data where the sun is present.
left = -1
right = -1
prev = solar_df.iloc[0]["apparent_elevation"]
for t in solar_df.itertuples():
    curr = t.apparent_elevation
    if left == -1 and prev <= 0 and curr > 0:
        left = t.Index
    if left != -1 and right == -1 and prev >= 0 and curr < 0:
        right = t.Index
        break
    prev = curr
Exemplo n.º 27
0
def calculate_overcast_spectrl2():
    """
    This example will loop over a range of cloud covers and latitudes
    (at longitude=0) for a specific date and calculate the spectral
    irradiance with and without accounting for clouds. Clouds are accounted for
    by applying the cloud opacity factor defined in [1]. Several steps
    are required:
    1. Calculate the atmospheric and solar conditions for the
    location and time
    2. Calculate the spectral irradiance using `pvlib.spectrum.spectrl2`
    for clear sky conditions
    3. Calculate the dni, dhi, and ghi for cloudy conditions using
    `pvlib.irradiance.campbell_norman`
    4. Determine total in-plane irradiance and its beam,
    sky diffuse and ground
    reflected components for cloudy conditions -
    `pvlib.irradiance.get_total_irradiance`
    5. Calculate the dni, dhi, and ghi for clear sky conditions
    using `pvlib.irradiance.campbell_norman`
    6. Determine total in-plane irradiance and its beam,
    sky diffuse and ground
    reflected components for clear sky conditions -
    `pvlib.irradiance.get_total_irradiance`
    7. Calculate the cloud opacity factor [1] and scale the
    spectral results from step 4 - func cloud_opacity_factor
    8. Plot the results  - func plot_spectral_irradiance
    """
    month = 2
    hour_of_day = 12
    altitude = 0.0
    longitude = 0.0
    latitudes = [10, 40]

    # cloud cover in fraction units
    cloud_covers = [0.2, 0.5]
    water_vapor_content = 0.5
    tau500 = 0.1
    ground_albedo = 0.06
    ozone = 0.3
    surface_tilt = 0.0

    ctime, pv_system = setup_pv_system(month, hour_of_day)

    for cloud_cover in cloud_covers:
        for latitude in latitudes:
            sol = get_solarposition(ctime, latitude, longitude)
            az = sol['apparent_zenith'].to_numpy()
            airmass_relative = get_relative_airmass(az,
                                                    model='kastenyoung1989')
            pressure = pvlib.atmosphere.alt2pres(altitude)
            az = sol['apparent_zenith'].to_numpy()
            azimuth = sol['azimuth'].to_numpy()
            surface_azimuth = pv_system['surface_azimuth']

            transmittance = (1.0 - cloud_cover) * 0.75
            calc_aoi = aoi(surface_tilt, surface_azimuth, az, azimuth)

            # day of year is an int64index array so access first item
            day_of_year = ctime.dayofyear[0]

            spectra = pvlib.spectrum.spectrl2(
                apparent_zenith=az,
                aoi=calc_aoi,
                surface_tilt=surface_tilt,
                ground_albedo=ground_albedo,
                surface_pressure=pressure,
                relative_airmass=airmass_relative,
                precipitable_water=water_vapor_content,
                ozone=ozone,
                aerosol_turbidity_500nm=tau500,
                dayofyear=day_of_year)

            irrads_clouds = campbell_norman(sol['zenith'].to_numpy(),
                                            transmittance)

            # Convert the irradiance to a plane with tilt zero
            # horizontal to the earth. This is done applying
            #  tilt=0 to POA calculations using the output from
            # `campbell_norman`. The POA calculations include
            # calculating sky and ground diffuse light where
            # specific models can be selected (we use default).
            poa_irr_clouds = get_total_irradiance(
                surface_tilt=surface_tilt,
                surface_azimuth=pv_system['surface_azimuth'],
                dni=irrads_clouds['dni'],
                ghi=irrads_clouds['ghi'],
                dhi=irrads_clouds['dhi'],
                solar_zenith=sol['apparent_zenith'],
                solar_azimuth=sol['azimuth'])

            show_info(latitude, poa_irr_clouds)
            zen = sol['zenith'].to_numpy()
            irr_clearsky = campbell_norman(zen, transmittance=0.75)

            poa_irr_clearsky = get_total_irradiance(
                surface_tilt=surface_tilt,
                surface_azimuth=pv_system['surface_azimuth'],
                dni=irr_clearsky['dni'],
                ghi=irr_clearsky['ghi'],
                dhi=irr_clearsky['dhi'],
                solar_zenith=sol['apparent_zenith'],
                solar_azimuth=sol['azimuth'])

            show_info(latitude, poa_irr_clearsky)
            poa_dr = poa_irr_clouds['poa_direct'].values
            poa_diff = poa_irr_clouds['poa_diffuse'].values
            poa_global = poa_irr_clouds['poa_global'].values
            f_dir, f_diff = cloud_opacity_factor(poa_dr, poa_diff, poa_global,
                                                 spectra)

            plot_spectral_irr(spectra,
                              f_dir,
                              f_diff,
                              lat=latitude,
                              doy=day_of_year,
                              year=ctime.year[0],
                              clouds=cloud_cover)
Exemplo n.º 28
0
from pvlib import tmy
from pvlib import pvsystem
from pvlib import clearsky
from pvlib import irradiance
from pvlib import atmosphere
from pvlib import solarposition
from pvlib.location import Location

latitude = 32.2
longitude = -111
tus = Location(latitude, longitude, 'US/Arizona', 700, 'Tucson')
times = pd.date_range(start=datetime.datetime(2014,1,1),
                      end=datetime.datetime(2014,1,2), freq='1Min')
ephem_data = solarposition.get_solarposition(times,
                                             latitude=latitude,
                                             longitude=longitude,
                                             method='nrel_numpy')
irrad_data = clearsky.ineichen(times, latitude=latitude, longitude=longitude,
                               linke_turbidity=3,
                               solarposition_method='nrel_numpy')
aoi = irradiance.aoi(0, 0, ephem_data['apparent_zenith'],
                     ephem_data['azimuth'])
am = atmosphere.relativeairmass(ephem_data.apparent_zenith)

meta = {'latitude': 37.8,
        'longitude': -122.3,
        'altitude': 10,
        'Name': 'Oakland',
        'State': 'CA',
        'TZ': -8}
Exemplo n.º 29
0
def basic_chain(times,
                latitude,
                longitude,
                module_parameters,
                inverter_parameters,
                irradiance=None,
                weather=None,
                surface_tilt=None,
                surface_azimuth=None,
                orientation_strategy=None,
                transposition_model='haydavies',
                solar_position_method='nrel_numpy',
                airmass_model='kastenyoung1989',
                altitude=None,
                pressure=None,
                **kwargs):
    """
    An experimental function that computes all of the modeling steps
    necessary for calculating power or energy for a PV system at a given
    location.

    Parameters
    ----------
    times : DatetimeIndex
        Times at which to evaluate the model.

    latitude : float.
        Positive is north of the equator.
        Use decimal degrees notation.

    longitude : float.
        Positive is east of the prime meridian.
        Use decimal degrees notation.

    module_parameters : None, dict or Series
        Module parameters as defined by the SAPM.

    inverter_parameters : None, dict or Series
        Inverter parameters as defined by the CEC.

    irradiance : None or DataFrame, default None
        If None, calculates clear sky data.
        Columns must be 'dni', 'ghi', 'dhi'.

    weather : None or DataFrame, default None
        If None, assumes air temperature is 20 C and
        wind speed is 0 m/s.
        Columns must be 'wind_speed', 'temp_air'.

    surface_tilt : None, float or Series, default None
        Surface tilt angles in decimal degrees.
        The tilt angle is defined as degrees from horizontal
        (e.g. surface facing up = 0, surface facing horizon = 90)

    surface_azimuth : None, float or Series, default None
        Surface azimuth angles in decimal degrees.
        The azimuth convention is defined
        as degrees east of north
        (North=0, South=180, East=90, West=270).

    orientation_strategy : None or str, default None
        The strategy for aligning the modules.
        If not None, sets the ``surface_azimuth`` and ``surface_tilt``
        properties of the ``system``. Allowed strategies include 'flat',
        'south_at_latitude_tilt'. Ignored for SingleAxisTracker systems.

    transposition_model : str, default 'haydavies'
        Passed to system.get_irradiance.

    solar_position_method : str, default 'nrel_numpy'
        Passed to solarposition.get_solarposition.

    airmass_model : str, default 'kastenyoung1989'
        Passed to atmosphere.relativeairmass.

    altitude : None or float, default None
        If None, computed from pressure. Assumed to be 0 m
        if pressure is also None.

    pressure : None or float, default None
        If None, computed from altitude. Assumed to be 101325 Pa
        if altitude is also None.

    **kwargs
        Arbitrary keyword arguments.
        See code for details.

    Returns
    -------
    output : (dc, ac)
        Tuple of DC power (with SAPM parameters) (DataFrame) and AC
        power (Series).
    """

    # use surface_tilt and surface_azimuth if provided,
    # otherwise set them using the orientation_strategy
    if surface_tilt is not None and surface_azimuth is not None:
        pass
    elif orientation_strategy is not None:
        surface_tilt, surface_azimuth = \
            get_orientation(orientation_strategy, latitude=latitude)
    else:
        raise ValueError('orientation_strategy or surface_tilt and '
                         'surface_azimuth must be provided')

    times = times

    if altitude is None and pressure is None:
        altitude = 0.
        pressure = 101325.
    elif altitude is None:
        altitude = atmosphere.pres2alt(pressure)
    elif pressure is None:
        pressure = atmosphere.alt2pres(altitude)

    solar_position = solarposition.get_solarposition(
        times,
        latitude,
        longitude,
        altitude=altitude,
        pressure=pressure,
        method=solar_position_method,
        **kwargs)

    # possible error with using apparent zenith with some models
    airmass = atmosphere.get_relative_airmass(
        solar_position['apparent_zenith'], model=airmass_model)
    airmass = atmosphere.get_absolute_airmass(airmass, pressure)
    dni_extra = pvlib.irradiance.get_extra_radiation(solar_position.index)

    aoi = pvlib.irradiance.aoi(surface_tilt, surface_azimuth,
                               solar_position['apparent_zenith'],
                               solar_position['azimuth'])

    if irradiance is None:
        linke_turbidity = clearsky.lookup_linke_turbidity(
            solar_position.index, latitude, longitude)
        irradiance = clearsky.ineichen(solar_position['apparent_zenith'],
                                       airmass,
                                       linke_turbidity,
                                       altitude=altitude,
                                       dni_extra=dni_extra)

    total_irrad = pvlib.irradiance.get_total_irradiance(
        surface_tilt,
        surface_azimuth,
        solar_position['apparent_zenith'],
        solar_position['azimuth'],
        irradiance['dni'],
        irradiance['ghi'],
        irradiance['dhi'],
        model=transposition_model,
        dni_extra=dni_extra)

    if weather is None:
        weather = {'wind_speed': 0, 'temp_air': 20}

    temps = pvsystem.sapm_celltemp(total_irrad['poa_global'],
                                   weather['wind_speed'], weather['temp_air'])

    effective_irradiance = pvsystem.sapm_effective_irradiance(
        total_irrad['poa_direct'], total_irrad['poa_diffuse'], airmass, aoi,
        module_parameters)

    dc = pvsystem.sapm(effective_irradiance, temps['temp_cell'],
                       module_parameters)

    ac = pvsystem.snlinverter(dc['v_mp'], dc['p_mp'], inverter_parameters)

    return dc, ac
Exemplo n.º 30
0
def ineichen(time,
             location,
             linke_turbidity=None,
             solarposition_method='pyephem',
             zenith_data=None,
             airmass_model='young1994',
             airmass_data=None,
             interp_turbidity=True):
    '''
    Determine clear sky GHI, DNI, and DHI from Ineichen/Perez model

    Implements the Ineichen and Perez clear sky model for global horizontal
    irradiance (GHI), direct normal irradiance (DNI), and calculates
    the clear-sky diffuse horizontal (DHI) component as the difference
    between GHI and DNI*cos(zenith) as presented in [1, 2]. A report on clear
    sky models found the Ineichen/Perez model to have excellent performance
    with a minimal input data set [3]. 
    
    Default values for montly Linke turbidity provided by SoDa [4, 5].

    Parameters
    -----------
    time : pandas.DatetimeIndex
    
    location : pvlib.Location
    
    linke_turbidity : None or float
        If None, uses ``LinkeTurbidities.mat`` lookup table.
    
    solarposition_method : string
        Sets the solar position algorithm. 
        See solarposition.get_solarposition()
    
    zenith_data : None or Series
        If None, ephemeris data will be calculated using ``solarposition_method``.
    
    airmass_model : string
        See pvlib.airmass.relativeairmass().
    
    airmass_data : None or Series
        If None, absolute air mass data will be calculated using 
        ``airmass_model`` and location.alitude.
    
    interp_turbidity : bool
        If ``True``, interpolates the monthly Linke turbidity values
        found in ``LinkeTurbidities.mat`` to daily values.

    Returns
    --------
    DataFrame with the following columns: ``ghi, dni, dhi``.

    Notes
    -----
    If you are using this function
    in a loop, it may be faster to load LinkeTurbidities.mat outside of
    the loop and feed it in as a keyword argument, rather than
    having the function open and process the file each time it is called.

    References
    ----------

    [1] P. Ineichen and R. Perez, "A New airmass independent formulation for
        the Linke turbidity coefficient", Solar Energy, vol 73, pp. 151-157, 2002.

    [2] R. Perez et. al., "A New Operational Model for Satellite-Derived
        Irradiances: Description and Validation", Solar Energy, vol 73, pp.
        307-317, 2002.

    [3] M. Reno, C. Hansen, and J. Stein, "Global Horizontal Irradiance Clear
        Sky Models: Implementation and Analysis", Sandia National
        Laboratories, SAND2012-2389, 2012.

    [4] http://www.soda-is.com/eng/services/climat_free_eng.php#c5 (obtained
        July 17, 2012).

    [5] J. Remund, et. al., "Worldwide Linke Turbidity Information", Proc.
        ISES Solar World Congress, June 2003. Goteborg, Sweden.
    '''
    # Initial implementation of this algorithm by Matthew Reno.
    # Ported to python by Rob Andrews
    # Added functionality by Will Holmgren (@wholmgren)

    I0 = irradiance.extraradiation(time.dayofyear)

    if zenith_data is None:
        ephem_data = solarposition.get_solarposition(
            time, location, method=solarposition_method)
        time = ephem_data.index  # fixes issue with time possibly not being tz-aware
        try:
            ApparentZenith = ephem_data['apparent_zenith']
        except KeyError:
            ApparentZenith = ephem_data['zenith']
            logger.warning('could not find apparent_zenith. using zenith')
    else:
        ApparentZenith = zenith_data
    #ApparentZenith[ApparentZenith >= 90] = 90 # can cause problems in edge cases

    if linke_turbidity is None:
        TL = lookup_linke_turbidity(time,
                                    location.latitude,
                                    location.longitude,
                                    interp_turbidity=interp_turbidity)
    else:
        TL = linke_turbidity

    # Get the absolute airmass assuming standard local pressure (per
    # alt2pres) using Kasten and Young's 1989 formula for airmass.

    if airmass_data is None:
        AMabsolute = atmosphere.absoluteairmass(
            airmass_relative=atmosphere.relativeairmass(
                ApparentZenith, airmass_model),
            pressure=atmosphere.alt2pres(location.altitude))
    else:
        AMabsolute = airmass_data

    fh1 = np.exp(-location.altitude / 8000.)
    fh2 = np.exp(-location.altitude / 1250.)
    cg1 = 5.09e-05 * location.altitude + 0.868
    cg2 = 3.92e-05 * location.altitude + 0.0387
    logger.debug('fh1=%s, fh2=%s, cg1=%s, cg2=%s', fh1, fh2, cg1, cg2)

    #  Dan's note on the TL correction: By my reading of the publication on
    #  pages 151-157, Ineichen and Perez introduce (among other things) three
    #  things. 1) Beam model in eqn. 8, 2) new turbidity factor in eqn 9 and
    #  appendix A, and 3) Global horizontal model in eqn. 11. They do NOT appear
    #  to use the new turbidity factor (item 2 above) in either the beam or GHI
    #  models. The phrasing of appendix A seems as if there are two separate
    #  corrections, the first correction is used to correct the beam/GHI models,
    #  and the second correction is used to correct the revised turibidity
    #  factor. In my estimation, there is no need to correct the turbidity
    #  factor used in the beam/GHI models.

    #  Create the corrected TL for TL < 2
    #  TLcorr = TL;
    #  TLcorr(TL < 2) = TLcorr(TL < 2) - 0.25 .* (2-TLcorr(TL < 2)) .^ (0.5);

    #  This equation is found in Solar Energy 73, pg 311.
    #  Full ref: Perez et. al., Vol. 73, pp. 307-317 (2002).
    #  It is slightly different than the equation given in Solar Energy 73, pg 156.
    #  We used the equation from pg 311 because of the existence of known typos
    #  in the pg 156 publication (notably the fh2-(TL-1) should be fh2 * (TL-1)).

    cos_zenith = tools.cosd(ApparentZenith)

    clearsky_GHI = (cg1 * I0 * cos_zenith * np.exp(-cg2 * AMabsolute *
                                                   (fh1 + fh2 * (TL - 1))) *
                    np.exp(0.01 * AMabsolute**1.8))
    clearsky_GHI[clearsky_GHI < 0] = 0

    # BncI == "normal beam clear sky radiation"
    b = 0.664 + 0.163 / fh1
    BncI = b * I0 * np.exp(-0.09 * AMabsolute * (TL - 1))
    logger.debug('b=%s', b)

    # "empirical correction" SE 73, 157 & SE 73, 312.
    BncI_2 = (clearsky_GHI * (1 - (0.1 - 0.2 * np.exp(-TL)) /
                              (0.1 + 0.882 / fh1)) / cos_zenith)

    clearsky_DNI = np.minimum(BncI, BncI_2)

    clearsky_DHI = clearsky_GHI - clearsky_DNI * cos_zenith

    df_out = pd.DataFrame({
        'ghi': clearsky_GHI,
        'dni': clearsky_DNI,
        'dhi': clearsky_DHI
    })
    df_out.fillna(0, inplace=True)

    return df_out
Exemplo n.º 31
0
rad_meteo = pd.read_csv(csvFilePath, sep=';',  decimal = '.', parse_dates = [0], date_parser=dateparser)  
dateTimeRESET = pd.Series(reset(rad_meteo.iloc[:,0])).dt.round("H") #remove to have interger hour correction of datetime of winet
rad_meteo['Data'] = dateTimeRESET #cambio vettore index data con data corretta
RadDT = rad_meteo.set_index('Data')
RadDT = pd.DataFrame(RadDT)
RadDT.plot()
RadDtzT = RadDT.tz_localize('CET')
## Calcola RADIAZIONE da PVLIB
# pvlib.irradiance.poa_horizontal_ratio(84, 90, 15, 0)
# pvlib.irradiance.isotropic(84, 300)
lat = 44.549192
long = 11.416346
tus = Location(lat, long, 'Europe/Rome', 32, 'Cadriano')
times = pd.date_range(start='2020-06-01', end='2020-10-20', freq='60min', tz=tus.tz)
cs = tus.get_clearsky(times)  # RadiationCalculated
solpos = solarposition.get_solarposition(times, lat, long)#sun elevation
frames = pd.concat([cs, solpos],axis = 1)#combine
frames['dhi/ghiRatio'] = frames['dhi']/frames['ghi'] #calculate theoretical ghi/dhi

cs[['dni', 'dhi']].plot();
plt.ylabel('Irradiance $W/m^2$');
plt.title('sun radiation parameters');
frames.plot();
plt.ylabel('degree');
plt.title('solpos');

#FACCIO MERGE dei dati rilevati dalla centralina winet e dei dati simulati con il MODELLO pvlib
##merge Radiazione From Winet with CalRadiation
mergeRadiation = pd.merge(frames, RadDtzT, how='left', left_index=True, right_index=True)
mergeRadiation[['par_wm2', 'ghi']].plot();
mergeRadiation['par_wm2_dhi'] = mergeRadiation['par_wm2']*mergeRadiation['dhi/ghiRatio'] # stimo la radiazione diffusa dal rapporto tra rad glo/rad diff in giornata senza nuvole da modello
Exemplo n.º 32
0
# towards the sun as much as possible in order to maximize the cross section
# presented towards incoming beam irradiance.

from pvlib import solarposition, tracking
import pandas as pd
import matplotlib.pyplot as plt

tz = 'US/Eastern'
lat, lon = 40, -80

times = pd.date_range('2019-01-01',
                      '2019-01-02',
                      closed='left',
                      freq='5min',
                      tz=tz)
solpos = solarposition.get_solarposition(times, lat, lon)

truetracking_angles = tracking.singleaxis(
    apparent_zenith=solpos['apparent_zenith'],
    apparent_azimuth=solpos['azimuth'],
    axis_tilt=0,
    axis_azimuth=180,
    max_angle=90,
    backtrack=False,  # for true-tracking
    gcr=0.5)  # irrelevant for true-tracking

truetracking_position = truetracking_angles['tracker_theta'].fillna(0)
truetracking_position.plot(title='Truetracking Curve')

plt.show()
Exemplo n.º 33
0
def test_ephemeris_functional():
    solarposition.get_solarposition(
        time=times, location=golden_mst, method='ephemeris')
Exemplo n.º 34
0
    goes_files = [
        GOESFilename.from_path(f)
        for f in Path("/storage/projects/goes_alg/goes_data/west/CMIP").glob(
            "*MCMIPC*.nc")
    ]

    final_countdown = []
    for gfile in goes_files:
        if gfile.start.hour < 13:
            continue
        logging.info("Processing file from %s", gfile.start)
        with xr.open_dataset(gfile.filename) as goes_ds:
            tomerge = []
            for _, site in site_data.groupby("site"):
                tomerge.append(process_site(goes_ds, site))
            final_countdown.append(xr.merge(tomerge))
    output = xr.merge(final_countdown)

    m = []
    for _, site in site_data.groupby("site"):
        da = (get_solarposition(output.time.data,
                                site.latitude.data, site.longitude.data)[[
                                    "zenith", "azimuth"
                                ]].to_xarray().rename({"index": "time"}))
        da.coords["site"] = site.site
        m.append(da)

    solpos = xr.concat(m, "site").transpose("time", "site")
    fullout = xr.merge([output, solpos])
    fullout.to_netcdf("combined_mcmip.nc")
Exemplo n.º 35
0
    def get_forecast_generation(self, dev_df, forecast_period=48):
        req_ts = max(dev_df.index).replace(
            microsecond=0, second=0, minute=0) + datetime.timedelta(hours=1)
        dev = list(dev_df.columns)[0]
        days = pd.date_range(start=req_ts,
                             end=req_ts +
                             datetime.timedelta(hours=forecast_period - 1),
                             freq='1H')
        self.latest += "Doing forecast for Generation :" + dev + "\n"

        # Pv Info
        lat = -2.483535
        long = 29.523457
        # https://www.daftlogic.com/sandbox-google-maps-find-altitude.htm
        height = 2139
        # typical temperature between 15 and 28 yearly, taking 22 as average
        typ_temp = 22
        # Efficienct
        effic = 0.155
        # Area m2
        area = 16.37
        # Surface
        surf_tilt = 15
        surf_az = 128  # It might be more like 119.5
        # effic-scalar
        scalar = 0.6

        tus = Location(lat, long, "Africa/Kigali", height, 'Kigeme')
        try:
            cs = tus.get_clearsky(
                days,
                model='ineichen')  # ineichen with climatology table by default
        except ImportError:
            self.latest += "- Import Error on Tables, using fixed turbidity - not a major problem"
            cs = tus.get_clearsky(days, model="ineichen", linke_turbidity=3)
        sun_pos = get_solarposition(cs.index,
                                    lat,
                                    long,
                                    altitude=height,
                                    pressure=None,
                                    method='nrel_numpy',
                                    temperature=typ_temp)

        # \[I_{tot} = I_{beam} + I_{sky} + I_{ground}\]
        total_irrad = pvlib.irradiance.get_total_irradiance(
            surf_tilt,
            surf_az,
            sun_pos['zenith'],
            sun_pos['azimuth'],
            cs['dni'],
            cs['ghi'],
            cs['dhi'],
            DNI_ET=None,
            AM=None,
            albedo=0.13,
            surface_type="grass",
            model='isotropic',
            model_perez='allsitescomposite1990')
        poa = total_irrad['poa_global'] * effic * area * scalar
        poa = poa.to_frame()
        poa['timestamp'] = poa.index
        poa = poa.rename(columns={'poa_global': dev})
        return poa
Exemplo n.º 36
0
def ineichen(
    time,
    location,
    linke_turbidity=None,
    solarposition_method="pyephem",
    zenith_data=None,
    airmass_model="young1994",
    airmass_data=None,
    interp_turbidity=True,
):
    """
    Determine clear sky GHI, DNI, and DHI from Ineichen/Perez model

    Implements the Ineichen and Perez clear sky model for global horizontal
    irradiance (GHI), direct normal irradiance (DNI), and calculates
    the clear-sky diffuse horizontal (DHI) component as the difference
    between GHI and DNI*cos(zenith) as presented in [1, 2]. A report on clear
    sky models found the Ineichen/Perez model to have excellent performance
    with a minimal input data set [3]. 
    
    Default values for montly Linke turbidity provided by SoDa [4, 5].

    Parameters
    -----------
    time : pandas.DatetimeIndex
    
    location : pvlib.Location
    
    linke_turbidity : None or float
        If None, uses ``LinkeTurbidities.mat`` lookup table.
    
    solarposition_method : string
        Sets the solar position algorithm. 
        See solarposition.get_solarposition()
    
    zenith_data : None or pandas.Series
        If None, ephemeris data will be calculated using ``solarposition_method``.
    
    airmass_model : string
        See pvlib.airmass.relativeairmass().
    
    airmass_data : None or pandas.Series
        If None, absolute air mass data will be calculated using 
        ``airmass_model`` and location.alitude.
    
    interp_turbidity : bool
        If ``True``, interpolates the monthly Linke turbidity values
        found in ``LinkeTurbidities.mat`` to daily values.

    Returns
    --------
    DataFrame with the following columns: ``GHI, DNI, DHI``.

    Notes
    -----
    If you are using this function
    in a loop, it may be faster to load LinkeTurbidities.mat outside of
    the loop and feed it in as a variable, rather than
    having the function open the file each time it is called.

    References
    ----------

    [1] P. Ineichen and R. Perez, "A New airmass independent formulation for
        the Linke turbidity coefficient", Solar Energy, vol 73, pp. 151-157, 2002.

    [2] R. Perez et. al., "A New Operational Model for Satellite-Derived
        Irradiances: Description and Validation", Solar Energy, vol 73, pp.
        307-317, 2002.

    [3] M. Reno, C. Hansen, and J. Stein, "Global Horizontal Irradiance Clear
        Sky Models: Implementation and Analysis", Sandia National
        Laboratories, SAND2012-2389, 2012.

    [4] http://www.soda-is.com/eng/services/climat_free_eng.php#c5 (obtained
        July 17, 2012).

    [5] J. Remund, et. al., "Worldwide Linke Turbidity Information", Proc.
        ISES Solar World Congress, June 2003. Goteborg, Sweden.
    """
    # Initial implementation of this algorithm by Matthew Reno.
    # Ported to python by Rob Andrews
    # Added functionality by Will Holmgren

    I0 = irradiance.extraradiation(time.dayofyear)

    if zenith_data is None:
        ephem_data = solarposition.get_solarposition(time, location, method=solarposition_method)
        time = ephem_data.index  # fixes issue with time possibly not being tz-aware
        try:
            ApparentZenith = ephem_data["apparent_zenith"]
        except KeyError:
            ApparentZenith = ephem_data["zenith"]
            logger.warning("could not find apparent_zenith. using zenith")
    else:
        ApparentZenith = zenith_data
    # ApparentZenith[ApparentZenith >= 90] = 90 # can cause problems in edge cases

    if linke_turbidity is None:
        # The .mat file 'LinkeTurbidities.mat' contains a single 2160 x 4320 x 12
        # matrix of type uint8 called 'LinkeTurbidity'. The rows represent global
        # latitudes from 90 to -90 degrees; the columns represent global longitudes
        # from -180 to 180; and the depth (third dimension) represents months of
        # the year from January (1) to December (12). To determine the Linke
        # turbidity for a position on the Earth's surface for a given month do the
        # following: LT = LinkeTurbidity(LatitudeIndex, LongitudeIndex, month).
        # Note that the numbers within the matrix are 20 * Linke Turbidity,
        # so divide the number from the file by 20 to get the
        # turbidity.

        try:
            import scipy.io
        except ImportError:
            raise ImportError(
                "The Linke turbidity lookup table requires scipy. "
                + "You can still use clearsky.ineichen if you "
                + "supply your own turbidities."
            )

        # consider putting this code at module level
        this_path = os.path.dirname(os.path.abspath(__file__))
        logger.debug("this_path={}".format(this_path))

        mat = scipy.io.loadmat(os.path.join(this_path, "data", "LinkeTurbidities.mat"))
        linke_turbidity = mat["LinkeTurbidity"]
        LatitudeIndex = np.round_(_linearly_scale(location.latitude, 90, -90, 1, 2160))
        LongitudeIndex = np.round_(_linearly_scale(location.longitude, -180, 180, 1, 4320))
        g = linke_turbidity[LatitudeIndex][LongitudeIndex]
        if interp_turbidity:
            logger.info("interpolating turbidity to the day")
            g2 = np.concatenate([[g[-1]], g, [g[0]]])  # wrap ends around
            days = np.linspace(-15, 380, num=14)  # map day of year onto month (approximate)
            LT = pd.Series(np.interp(time.dayofyear, days, g2), index=time)
        else:
            logger.info("using monthly turbidity")
            ApplyMonth = lambda x: g[x[0] - 1]
            LT = pd.DataFrame(time.month, index=time)
            LT = LT.apply(ApplyMonth, axis=1)
        TL = LT / 20.0
        logger.info("using TL=\n{}".format(TL))
    else:
        TL = linke_turbidity

    # Get the absolute airmass assuming standard local pressure (per
    # alt2pres) using Kasten and Young's 1989 formula for airmass.

    if airmass_data is None:
        AMabsolute = atmosphere.absoluteairmass(
            AMrelative=atmosphere.relativeairmass(ApparentZenith, airmass_model),
            pressure=atmosphere.alt2pres(location.altitude),
        )
    else:
        AMabsolute = airmass_data

    fh1 = np.exp(-location.altitude / 8000.0)
    fh2 = np.exp(-location.altitude / 1250.0)
    cg1 = 5.09e-05 * location.altitude + 0.868
    cg2 = 3.92e-05 * location.altitude + 0.0387
    logger.debug("fh1={}, fh2={}, cg1={}, cg2={}".format(fh1, fh2, cg1, cg2))

    #  Dan's note on the TL correction: By my reading of the publication on
    #  pages 151-157, Ineichen and Perez introduce (among other things) three
    #  things. 1) Beam model in eqn. 8, 2) new turbidity factor in eqn 9 and
    #  appendix A, and 3) Global horizontal model in eqn. 11. They do NOT appear
    #  to use the new turbidity factor (item 2 above) in either the beam or GHI
    #  models. The phrasing of appendix A seems as if there are two separate
    #  corrections, the first correction is used to correct the beam/GHI models,
    #  and the second correction is used to correct the revised turibidity
    #  factor. In my estimation, there is no need to correct the turbidity
    #  factor used in the beam/GHI models.

    #  Create the corrected TL for TL < 2
    #  TLcorr = TL;
    #  TLcorr(TL < 2) = TLcorr(TL < 2) - 0.25 .* (2-TLcorr(TL < 2)) .^ (0.5);

    #  This equation is found in Solar Energy 73, pg 311.
    #  Full ref: Perez et. al., Vol. 73, pp. 307-317 (2002).
    #  It is slightly different than the equation given in Solar Energy 73, pg 156.
    #  We used the equation from pg 311 because of the existence of known typos
    #  in the pg 156 publication (notably the fh2-(TL-1) should be fh2 * (TL-1)).

    cos_zenith = tools.cosd(ApparentZenith)

    clearsky_GHI = (
        cg1 * I0 * cos_zenith * np.exp(-cg2 * AMabsolute * (fh1 + fh2 * (TL - 1))) * np.exp(0.01 * AMabsolute ** 1.8)
    )
    clearsky_GHI[clearsky_GHI < 0] = 0

    # BncI == "normal beam clear sky radiation"
    b = 0.664 + 0.163 / fh1
    BncI = b * I0 * np.exp(-0.09 * AMabsolute * (TL - 1))
    logger.debug("b={}".format(b))

    # "empirical correction" SE 73, 157 & SE 73, 312.
    BncI_2 = clearsky_GHI * (1 - (0.1 - 0.2 * np.exp(-TL)) / (0.1 + 0.882 / fh1)) / cos_zenith
    # return BncI, BncI_2
    clearsky_DNI = np.minimum(BncI, BncI_2)  # Will H: use np.minimum explicitly

    clearsky_DHI = clearsky_GHI - clearsky_DNI * cos_zenith

    df_out = pd.DataFrame({"GHI": clearsky_GHI, "DNI": clearsky_DNI, "DHI": clearsky_DHI})
    df_out.fillna(0, inplace=True)
    # df_out['BncI'] = BncI
    # df_out['BncI_2'] = BncI

    return df_out
Exemplo n.º 37
0
import numpy as np
import pandas as pd

import pytest
from numpy.testing import assert_allclose

from pvlib.location import Location
from pvlib import solarposition
from pvlib import atmosphere


latitude, longitude, tz, altitude = 32.2, -111, 'US/Arizona', 700

times = pd.date_range(start='20140626', end='20140626', freq='6h', tz=tz)

ephem_data = solarposition.get_solarposition(times, latitude, longitude)


# need to add physical tests instead of just functional tests

def test_pres2alt():
    atmosphere.pres2alt(100000)


def test_alt2press():
    atmosphere.pres2alt(1000)


@pytest.mark.parametrize("model",
    ['simple', 'kasten1966', 'youngirvine1967', 'kastenyoung1989',
     'gueymard1993', 'young1994', 'pickering2002'])
Exemplo n.º 38
0
def ineichen(time,
             location,
             linke_turbidity=None,
             solarposition_method='pyephem',
             zenith_data=None,
             airmass_model='young1994',
             airmass_data=None,
             interp_turbidity=True):
    '''
    Determine clear sky GHI, DNI, and DHI from Ineichen/Perez model

    Implements the Ineichen and Perez clear sky model for global horizontal
    irradiance (GHI), direct normal irradiance (DNI), and calculates
    the clear-sky diffuse horizontal (DHI) component as the difference
    between GHI and DNI*cos(zenith) as presented in [1, 2]. A report on clear
    sky models found the Ineichen/Perez model to have excellent performance
    with a minimal input data set [3]. 
    
    Default values for montly Linke turbidity provided by SoDa [4, 5].

    Parameters
    -----------
    time : pandas.DatetimeIndex
    
    location : pvlib.Location
    
    linke_turbidity : None or float
        If None, uses ``LinkeTurbidities.mat`` lookup table.
    
    solarposition_method : string
        Sets the solar position algorithm. 
        See solarposition.get_solarposition()
    
    zenith_data : None or pandas.Series
        If None, ephemeris data will be calculated using ``solarposition_method``.
    
    airmass_model : string
        See pvlib.airmass.relativeairmass().
    
    airmass_data : None or pandas.Series
        If None, absolute air mass data will be calculated using 
        ``airmass_model`` and location.alitude.
    
    interp_turbidity : bool
        If ``True``, interpolates the monthly Linke turbidity values
        found in ``LinkeTurbidities.mat`` to daily values.

    Returns
    --------
    DataFrame with the following columns: ``GHI, DNI, DHI``.

    Notes
    -----
    If you are using this function
    in a loop, it may be faster to load LinkeTurbidities.mat outside of
    the loop and feed it in as a variable, rather than
    having the function open the file each time it is called.

    References
    ----------

    [1] P. Ineichen and R. Perez, "A New airmass independent formulation for
        the Linke turbidity coefficient", Solar Energy, vol 73, pp. 151-157, 2002.

    [2] R. Perez et. al., "A New Operational Model for Satellite-Derived
        Irradiances: Description and Validation", Solar Energy, vol 73, pp.
        307-317, 2002.

    [3] M. Reno, C. Hansen, and J. Stein, "Global Horizontal Irradiance Clear
        Sky Models: Implementation and Analysis", Sandia National
        Laboratories, SAND2012-2389, 2012.

    [4] http://www.soda-is.com/eng/services/climat_free_eng.php#c5 (obtained
        July 17, 2012).

    [5] J. Remund, et. al., "Worldwide Linke Turbidity Information", Proc.
        ISES Solar World Congress, June 2003. Goteborg, Sweden.
    '''
    # Initial implementation of this algorithm by Matthew Reno.
    # Ported to python by Rob Andrews
    # Added functionality by Will Holmgren

    I0 = irradiance.extraradiation(time.dayofyear)

    if zenith_data is None:
        ephem_data = solarposition.get_solarposition(
            time, location, method=solarposition_method)
        time = ephem_data.index  # fixes issue with time possibly not being tz-aware
        try:
            ApparentZenith = ephem_data['apparent_zenith']
        except KeyError:
            ApparentZenith = ephem_data['zenith']
            logger.warning('could not find apparent_zenith. using zenith')
    else:
        ApparentZenith = zenith_data
    #ApparentZenith[ApparentZenith >= 90] = 90 # can cause problems in edge cases

    if linke_turbidity is None:
        # The .mat file 'LinkeTurbidities.mat' contains a single 2160 x 4320 x 12
        # matrix of type uint8 called 'LinkeTurbidity'. The rows represent global
        # latitudes from 90 to -90 degrees; the columns represent global longitudes
        # from -180 to 180; and the depth (third dimension) represents months of
        # the year from January (1) to December (12). To determine the Linke
        # turbidity for a position on the Earth's surface for a given month do the
        # following: LT = LinkeTurbidity(LatitudeIndex, LongitudeIndex, month).
        # Note that the numbers within the matrix are 20 * Linke Turbidity,
        # so divide the number from the file by 20 to get the
        # turbidity.

        try:
            import scipy.io
        except ImportError:
            raise ImportError(
                'The Linke turbidity lookup table requires scipy. ' +
                'You can still use clearsky.ineichen if you ' +
                'supply your own turbidities.')

        # consider putting this code at module level
        this_path = os.path.dirname(os.path.abspath(__file__))
        logger.debug('this_path={}'.format(this_path))

        mat = scipy.io.loadmat(
            os.path.join(this_path, 'data', 'LinkeTurbidities.mat'))
        linke_turbidity = mat['LinkeTurbidity']
        LatitudeIndex = np.round_(
            _linearly_scale(location.latitude, 90, -90, 1, 2160))
        LongitudeIndex = np.round_(
            _linearly_scale(location.longitude, -180, 180, 1, 4320))
        g = linke_turbidity[LatitudeIndex][LongitudeIndex]
        if interp_turbidity:
            logger.info('interpolating turbidity to the day')
            g2 = np.concatenate([[g[-1]], g, [g[0]]])  # wrap ends around
            days = np.linspace(
                -15, 380, num=14)  # map day of year onto month (approximate)
            LT = pd.Series(np.interp(time.dayofyear, days, g2), index=time)
        else:
            logger.info('using monthly turbidity')
            ApplyMonth = lambda x: g[x[0] - 1]
            LT = pd.DataFrame(time.month, index=time)
            LT = LT.apply(ApplyMonth, axis=1)
        TL = LT / 20.
        logger.info('using TL=\n{}'.format(TL))
    else:
        TL = linke_turbidity

    # Get the absolute airmass assuming standard local pressure (per
    # alt2pres) using Kasten and Young's 1989 formula for airmass.

    if airmass_data is None:
        AMabsolute = atmosphere.absoluteairmass(
            AMrelative=atmosphere.relativeairmass(ApparentZenith,
                                                  airmass_model),
            pressure=atmosphere.alt2pres(location.altitude))
    else:
        AMabsolute = airmass_data

    fh1 = np.exp(-location.altitude / 8000.)
    fh2 = np.exp(-location.altitude / 1250.)
    cg1 = 5.09e-05 * location.altitude + 0.868
    cg2 = 3.92e-05 * location.altitude + 0.0387
    logger.debug('fh1={}, fh2={}, cg1={}, cg2={}'.format(fh1, fh2, cg1, cg2))

    #  Dan's note on the TL correction: By my reading of the publication on
    #  pages 151-157, Ineichen and Perez introduce (among other things) three
    #  things. 1) Beam model in eqn. 8, 2) new turbidity factor in eqn 9 and
    #  appendix A, and 3) Global horizontal model in eqn. 11. They do NOT appear
    #  to use the new turbidity factor (item 2 above) in either the beam or GHI
    #  models. The phrasing of appendix A seems as if there are two separate
    #  corrections, the first correction is used to correct the beam/GHI models,
    #  and the second correction is used to correct the revised turibidity
    #  factor. In my estimation, there is no need to correct the turbidity
    #  factor used in the beam/GHI models.

    #  Create the corrected TL for TL < 2
    #  TLcorr = TL;
    #  TLcorr(TL < 2) = TLcorr(TL < 2) - 0.25 .* (2-TLcorr(TL < 2)) .^ (0.5);

    #  This equation is found in Solar Energy 73, pg 311.
    #  Full ref: Perez et. al., Vol. 73, pp. 307-317 (2002).
    #  It is slightly different than the equation given in Solar Energy 73, pg 156.
    #  We used the equation from pg 311 because of the existence of known typos
    #  in the pg 156 publication (notably the fh2-(TL-1) should be fh2 * (TL-1)).

    cos_zenith = tools.cosd(ApparentZenith)

    clearsky_GHI = cg1 * I0 * cos_zenith * np.exp(
        -cg2 * AMabsolute * (fh1 + fh2 *
                             (TL - 1))) * np.exp(0.01 * AMabsolute**1.8)
    clearsky_GHI[clearsky_GHI < 0] = 0

    # BncI == "normal beam clear sky radiation"
    b = 0.664 + 0.163 / fh1
    BncI = b * I0 * np.exp(-0.09 * AMabsolute * (TL - 1))
    logger.debug('b={}'.format(b))

    # "empirical correction" SE 73, 157 & SE 73, 312.
    BncI_2 = clearsky_GHI * (1 - (0.1 - 0.2 * np.exp(-TL)) /
                             (0.1 + 0.882 / fh1)) / cos_zenith
    #return BncI, BncI_2
    clearsky_DNI = np.minimum(BncI,
                              BncI_2)  # Will H: use np.minimum explicitly

    clearsky_DHI = clearsky_GHI - clearsky_DNI * cos_zenith

    df_out = pd.DataFrame({
        'GHI': clearsky_GHI,
        'DNI': clearsky_DNI,
        'DHI': clearsky_DHI
    })
    df_out.fillna(0, inplace=True)
    #df_out['BncI'] = BncI
    #df_out['BncI_2'] = BncI

    return df_out
Exemplo n.º 39
0
from nose.tools import assert_almost_equals

from pvlib.location import Location
from pvlib import solarposition
from pvlib import atmosphere

# setup times and location to be tested.
times = pd.date_range(start=datetime.datetime(2014, 6, 24),
                      end=datetime.datetime(2014, 6, 26),
                      freq='1Min')

tus = Location(32.2, -111, 'US/Arizona', 700)

times_localized = times.tz_localize(tus.tz)

ephem_data = solarposition.get_solarposition(times_localized, tus.latitude,
                                             tus.longitude)

# need to add physical tests instead of just functional tests


def test_pres2alt():
    atmosphere.pres2alt(100000)


def test_alt2press():
    atmosphere.pres2alt(1000)


# two functions combined will generate unique unit tests for each model
def test_airmasses():
    models = [
Exemplo n.º 40
0
def basic_chain(times, latitude, longitude,
                module_parameters, inverter_parameters,
                irradiance=None, weather=None,
                surface_tilt=None, surface_azimuth=None,
                orientation_strategy=None,
                transposition_model='haydavies',
                solar_position_method='nrel_numpy',
                airmass_model='kastenyoung1989',
                altitude=None, pressure=None,
                **kwargs):
    """
    An experimental function that computes all of the modeling steps
    necessary for calculating power or energy for a PV system at a given
    location.

    Parameters
    ----------
    times : DatetimeIndex
        Times at which to evaluate the model.

    latitude : float.
        Positive is north of the equator.
        Use decimal degrees notation.

    longitude : float.
        Positive is east of the prime meridian.
        Use decimal degrees notation.

    module_parameters : None, dict or Series
        Module parameters as defined by the SAPM.

    inverter_parameters : None, dict or Series
        Inverter parameters as defined by the CEC.

    irradiance : None or DataFrame
        If None, calculates clear sky data.
        Columns must be 'dni', 'ghi', 'dhi'.

    weather : None or DataFrame
        If None, assumes air temperature is 20 C and
        wind speed is 0 m/s.
        Columns must be 'wind_speed', 'temp_air'.

    surface_tilt : float or Series
        Surface tilt angles in decimal degrees.
        The tilt angle is defined as degrees from horizontal
        (e.g. surface facing up = 0, surface facing horizon = 90)

    surface_azimuth : float or Series
        Surface azimuth angles in decimal degrees.
        The azimuth convention is defined
        as degrees east of north
        (North=0, South=180, East=90, West=270).

    orientation_strategy : None or str
        The strategy for aligning the modules.
        If not None, sets the ``surface_azimuth`` and ``surface_tilt``
        properties of the ``system``.

    transposition_model : str
        Passed to system.get_irradiance.

    solar_position_method : str
        Passed to location.get_solarposition.

    airmass_model : str
        Passed to location.get_airmass.

    altitude : None or float
        If None, computed from pressure. Assumed to be 0 m
        if pressure is also None.

    pressure : None or float
        If None, computed from altitude. Assumed to be 101325 Pa
        if altitude is also None.

    **kwargs
        Arbitrary keyword arguments.
        See code for details.

    Returns
    -------
    output : (dc, ac)
        Tuple of DC power (with SAPM parameters) (DataFrame) and AC
        power (Series).
    """

    # use surface_tilt and surface_azimuth if provided,
    # otherwise set them using the orientation_strategy
    if surface_tilt is not None and surface_azimuth is not None:
        pass
    elif orientation_strategy is not None:
        surface_tilt, surface_azimuth = \
            get_orientation(orientation_strategy, latitude=latitude)
    else:
        raise ValueError('orientation_strategy or surface_tilt and ' +
                         'surface_azimuth must be provided')

    times = times

    if altitude is None and pressure is None:
        altitude = 0.
        pressure = 101325.
    elif altitude is None:
        altitude = atmosphere.pres2alt(pressure)
    elif pressure is None:
        pressure = atmosphere.alt2pres(altitude)

    solar_position = solarposition.get_solarposition(times, latitude,
                                                     longitude,
                                                     altitude=altitude,
                                                     pressure=pressure,
                                                     **kwargs)

    # possible error with using apparent zenith with some models
    airmass = atmosphere.relativeairmass(solar_position['apparent_zenith'],
                                         model=airmass_model)
    airmass = atmosphere.absoluteairmass(airmass, pressure)
    dni_extra = pvlib.irradiance.extraradiation(solar_position.index)
    dni_extra = pd.Series(dni_extra, index=solar_position.index)

    aoi = pvlib.irradiance.aoi(surface_tilt, surface_azimuth,
                               solar_position['apparent_zenith'],
                               solar_position['azimuth'])

    if irradiance is None:
        irradiance = clearsky.ineichen(
            solar_position.index,
            latitude,
            longitude,
            zenith_data=solar_position['apparent_zenith'],
            airmass_data=airmass,
            altitude=altitude)

    total_irrad = pvlib.irradiance.total_irrad(
        surface_tilt,
        surface_azimuth,
        solar_position['apparent_zenith'],
        solar_position['azimuth'],
        irradiance['dni'],
        irradiance['ghi'],
        irradiance['dhi'],
        model=transposition_model,
        dni_extra=dni_extra)

    if weather is None:
        weather = {'wind_speed': 0, 'temp_air': 20}

    temps = pvsystem.sapm_celltemp(total_irrad['poa_global'],
                                   weather['wind_speed'],
                                   weather['temp_air'])

    dc = pvsystem.sapm(module_parameters, total_irrad['poa_direct'],
                       total_irrad['poa_diffuse'],
                       temps['temp_cell'],
                       airmass,
                       aoi)

    ac = pvsystem.snlinverter(inverter_parameters, dc['v_mp'], dc['p_mp'])

    return dc, ac
Exemplo n.º 41
0
def irrad_tilt(time,
               lat,
               long,
               panel_elev,
               panel_az,
               irrad,
               alb,
               alt=None,
               pressure=None,
               temp=None):
    '''
    Function to calculate the solar irradiance on arbitrary tited surface/
    PV panel and a arbitrary location at any given time.
    In order to obtain the solar position [1] is used and angle calculations
    are done according to [2]

    Parameters
    ----------
    time : Panda DateTimeIndex
        Must be date from Panda DateTimeIndex --> date and time to be assessed.
    lat : float
        Latitude of location in decimal; South of equator is negative.
    long : float
        Longitude of location in decimal; West of Greenwhich is negative.
    panel_elev : float
        Elevation angle of the PV panel surface (0-90, while 0 is horizontal) 
        in °.
    panel_az : float
        Azimuth angle of the PV panel surface (0-359, while 0 is north, 90 is
        east, 180 is south and 270 is west) in °.
    irrad : panda Dataframe
        Dataframe with panda DateTimeIndex, global horizontal irradiance
        ('G(h)'), direct normal irradiance ('Gb(n)') and diffuse horizontal
        irradiance ('Gd(h)') --> it is important that the collumns are named
        respectively.
    alb : float
        Albedo; Surface dependent reflection coefficient --> consult 
        https://de.wikipedia.org/wiki/Albedo for values.
    alt : float or None, optional
        Altitude of location above sea level m. The default is None.
    pressure : float or None, optional
        In Pa The default is None.
    temp : float or None, optional
        Average temperature in °C of location. The default is None.

    Returns
    -------
    irrad_t : float
        Irradiance on tilted surface for specific location and time.
        
    References
    -------
    [1] William F. Holmgren, Clifford W. Hansen, and Mark A. Mikofski.
    “pvlib python: a python package for modeling solar energy systems.” 
    Journal of Open Source Software, 3(29), 884, (2018). 
    https://doi.org/10.21105/joss.00884
    
    [2] Eiker Ursula. "Solare Technologien für Gebäude" Springer, (2012).
    https://doi.org/10.1007/978-3-8348-8237-0

    '''

    solar_pos = solarposition.get_solarposition(time, lat, long, alt, pressure,
                                                'nrel_numpy', temp)
    sol_az = solar_pos.at[time, 'azimuth']
    sol_zen = solar_pos.at[time, 'zenith']

    cos_tilt = np.cos(
        np.radians(sol_zen) * np.cos(np.radians(panel_elev)) +
        np.sin(np.radians(sol_zen)) * np.sin(np.radians(panel_elev)) *
        np.cos(np.radians(sol_az - panel_az)))

    irrad_dir_t = irrad.at[time, "Gb(n)"] * np.maximum(
        0, cos_tilt / np.sin(np.radians(90 - sol_zen)))
    irrad_diff_t = irrad.at[time, "Gd(h)"] * (
        1 + np.cos(np.radians(panel_elev))) * 0.5
    irrad_ref_t = irrad.at[time, "G(h)"] * alb * (
        1 - np.cos(np.radians(panel_elev))) * 0.5
    irrad_t = irrad_dir_t + irrad_diff_t + irrad_ref_t

    return irrad_t
Exemplo n.º 42
0
from nose.tools import raises
from numpy.testing import assert_almost_equal, assert_allclose
from pandas.util.testing import assert_frame_equal, assert_series_equal

from pvlib.location import Location
from pvlib import clearsky
from pvlib import solarposition

from . import requires_scipy

# setup times and location to be tested.
tus = Location(32.2, -111, 'US/Arizona', 700)
times = pd.date_range(start='2014-06-24', end='2014-06-25', freq='3h')
times_localized = times.tz_localize(tus.tz)

ephem_data = solarposition.get_solarposition(times_localized, tus.latitude,
                                             tus.longitude)

@requires_scipy
def test_ineichen_required():
    # the clearsky function should call lookup_linke_turbidity by default
    expected = pd.DataFrame(
        np.array([[    0.        ,     0.        ,     0.        ],
                  [    0.        ,     0.        ,     0.        ],
                  [   51.47811191,   265.33462162,    84.48262202],
                  [  105.008507  ,   832.29100407,   682.67761951],
                  [  121.97988054,   901.31821834,  1008.02102657],
                  [  112.57957512,   867.76297247,   824.61702926],
                  [   76.69672675,   588.8462898 ,   254.5808329 ],
                  [    0.        ,     0.        ,     0.        ],
                  [    0.        ,     0.        ,     0.        ]]),
                            columns=['dhi', 'dni', 'ghi'],
Exemplo n.º 43
0
from pvlib.location import Location
from pvlib import clearsky
from pvlib import solarposition
from pvlib import irradiance
from pvlib import atmosphere

from conftest import requires_ephem, requires_numba, needs_numpy_1_10

# setup times and location to be tested.
tus = Location(32.2, -111, 'US/Arizona', 700)

# must include night values
times = pd.date_range(start='20140624', freq='6H', periods=4, tz=tus.tz)

ephem_data = solarposition.get_solarposition(times,
                                             tus.latitude,
                                             tus.longitude,
                                             method='nrel_numpy')

irrad_data = tus.get_clearsky(times, model='ineichen', linke_turbidity=3)

dni_et = irradiance.extraradiation(times.dayofyear)

ghi = irrad_data['ghi']

# setup for et rad test. put it here for readability
timestamp = pd.Timestamp('20161026')
dt_index = pd.DatetimeIndex([timestamp])
doy = timestamp.dayofyear
dt_date = timestamp.date()
dt_datetime = datetime.datetime.combine(dt_date, datetime.time(0))
dt_np64 = np.datetime64(dt_datetime)
Exemplo n.º 44
0
import pandas as pd

from nose.tools import raises
from numpy.testing import assert_almost_equal
from pandas.util.testing import assert_frame_equal, assert_series_equal

from pvlib.location import Location
from pvlib import clearsky
from pvlib import solarposition

# setup times and location to be tested.
tus = Location(32.2, -111, 'US/Arizona', 700)
times = pd.date_range(start='2014-06-24', end='2014-06-25', freq='3h')
times_localized = times.tz_localize(tus.tz)

ephem_data = solarposition.get_solarposition(times, tus)


def test_ineichen_required():
    # the clearsky function should call lookup_linke_turbidity by default
    # will fail without scipy
    expected = pd.DataFrame(
        np.array([[0., 0., 0.], [0., 0., 0.],
                  [40.53660309, 302.47614235, 78.1470311],
                  [98.88372629, 865.98938602, 699.93403875],
                  [122.57870881, 931.83716051, 1038.62116584],
                  [109.30270612, 899.88002304, 847.68806472],
                  [64.25699595, 629.91187925, 254.53048144], [0., 0., 0.],
                  [0., 0., 0.]]),
        columns=['dhi', 'dni', 'ghi'],
        index=times_localized)
Exemplo n.º 45
0
import pandas as pd

from nose.tools import assert_equals, assert_almost_equals

from pvlib import tmy
from pvlib import pvsystem
from pvlib import clearsky
from pvlib import irradiance
from pvlib import atmosphere
from pvlib import solarposition
from pvlib.location import Location

tus = Location(32.2, -111, 'US/Arizona', 700, 'Tucson')
times = pd.date_range(start=datetime.datetime(2014,1,1),
                      end=datetime.datetime(2014,1,2), freq='1Min')
ephem_data = solarposition.get_solarposition(times, tus, method='pyephem')
irrad_data = clearsky.ineichen(times, tus, linke_turbidity=3,
                               solarposition_method='pyephem')
aoi = irradiance.aoi(0, 0, ephem_data['apparent_zenith'],
                     ephem_data['apparent_azimuth'])
am = atmosphere.relativeairmass(ephem_data.apparent_zenith)

meta = {'latitude': 37.8,
        'longitude': -122.3,
        'altitude': 10,
        'Name': 'Oakland',
        'State': 'CA',
        'TZ': -8}

pvlib_abspath = os.path.dirname(os.path.abspath(inspect.getfile(tmy)))
Exemplo n.º 46
0
def sun_position(dates=None, daydate=_day, latitude=_latitude, longitude=_longitude,
                 altitude=_altitude, timezone=_timezone, method='pvlib',
                 filter_night=True):
    """ Sun position

    Args:
        dates: a pandas.DatetimeIndex specifying the dates at which sun position
        is required.If None, daydate is used and one position per hour is generated
        daydate: (str) yyyy-mm-dd (not used if dates is not None).
        latitude: float
        longitude: float
        altitude: (float) altitude in m
        timezone: a string identifying the timezone to be associated to dates if
        dates is not already localised.
        This args is not used if dates are already localised
        method: (string) the method to use. default uses pvlib. other methods are
        'ephem' (using ephem package) or 'astk' (using this module)
        filter_night (bool) : Should positions of sun during night be filtered ?

    Returns:
        a pandas dataframe with sun position at requested dates indexed by
        localised dates. Sun azimtuth is given from North, positive clockwise.
    """

    if dates is None:
        dates = pandas.date_range(daydate, periods=24, freq='H')

    if dates.tz is None:
        times = dates.tz_localize(timezone)
    else:
        times = dates

    sunpos = None

    if method == 'pvlib':
        df = get_solarposition(times, latitude, longitude, altitude)
        sunpos = pandas.DataFrame(
            {'elevation': df['apparent_elevation'], 'azimuth': df['azimuth'],
             'zenith': df['apparent_zenith']}, index=df.index)
    elif method == 'ephem':
        d = times.tz_convert('UTC')
        hUTC = d.hour + d.minute / 60.
        dayofyear = d.dayofyear
        year = d.year
        fun = numpy.frompyfunc(ephem_sun_position, 5, 2)
        alt, az = fun(hUTC, dayofyear, year, latitude, longitude)
        sunpos = pandas.DataFrame(
            {'elevation': alt.astype(float), 'azimuth': az.astype(float)},
            index=times)
        sunpos['zenith'] = 90 - sunpos['elevation']
    elif method == 'astk':
        d = times.tz_convert('UTC')
        hUTC = d.hour + d.minute / 60.
        dayofyear = d.dayofyear
        year = d.year
        el = sun_elevation(hUTC, dayofyear, year, latitude, longitude)
        az = sun_azimuth(hUTC, dayofyear, year, latitude, longitude)
        sunpos = pandas.DataFrame(
            {'elevation': el, 'zenith': 90 - el, 'azimuth': az}, index=times)
    else:
        raise ValueError(
            'unknown method: ' + method + 'available methods are : pvlib, ephem and astk')

    if filter_night and sunpos is not None:
        sunpos = sunpos.loc[sunpos['elevation'] > 0, :]

    return sunpos
Exemplo n.º 47
0
from nose.tools import raises

from numpy.testing import assert_almost_equal

from pvlib.location import Location
from pvlib import clearsky
from pvlib import solarposition

# setup times and location to be tested.
times = pd.date_range(start=datetime.datetime(2014, 6, 24), end=datetime.datetime(2014, 6, 26), freq="1Min")

tus = Location(32.2, -111, "US/Arizona", 700)

times_localized = times.tz_localize(tus.tz)

ephem_data = solarposition.get_solarposition(times, tus)


# test the ineichen clear sky model implementation in a few ways


def test_ineichen_required():
    # the clearsky function should lookup the linke turbidity on its own
    # will fail without scipy
    clearsky.ineichen(times, tus)


def test_ineichen_supply_linke():
    clearsky.ineichen(times, tus, linke_turbidity=3)

Exemplo n.º 48
0
def ineichen(time, latitude, longitude, altitude=0, linke_turbidity=None,
             solarposition_method='nrel_numpy', zenith_data=None,
             airmass_model='young1994', airmass_data=None,
             interp_turbidity=True):
    '''
    Determine clear sky GHI, DNI, and DHI from Ineichen/Perez model

    Implements the Ineichen and Perez clear sky model for global horizontal
    irradiance (GHI), direct normal irradiance (DNI), and calculates
    the clear-sky diffuse horizontal (DHI) component as the difference
    between GHI and DNI*cos(zenith) as presented in [1, 2]. A report on clear
    sky models found the Ineichen/Perez model to have excellent performance
    with a minimal input data set [3].

    Default values for montly Linke turbidity provided by SoDa [4, 5].

    Parameters
    -----------
    time : pandas.DatetimeIndex

    latitude : float

    longitude : float

    altitude : float

    linke_turbidity : None or float
        If None, uses ``LinkeTurbidities.mat`` lookup table.

    solarposition_method : string
        Sets the solar position algorithm.
        See solarposition.get_solarposition()

    zenith_data : None or Series
        If None, ephemeris data will be calculated using ``solarposition_method``.

    airmass_model : string
        See pvlib.airmass.relativeairmass().

    airmass_data : None or Series
        If None, absolute air mass data will be calculated using
        ``airmass_model`` and location.alitude.

    interp_turbidity : bool
        If ``True``, interpolates the monthly Linke turbidity values
        found in ``LinkeTurbidities.mat`` to daily values.

    Returns
    --------
    DataFrame with the following columns: ``ghi, dni, dhi``.

    Notes
    -----
    If you are using this function
    in a loop, it may be faster to load LinkeTurbidities.mat outside of
    the loop and feed it in as a keyword argument, rather than
    having the function open and process the file each time it is called.

    References
    ----------

    [1] P. Ineichen and R. Perez, "A New airmass independent formulation for
        the Linke turbidity coefficient", Solar Energy, vol 73, pp. 151-157, 2002.

    [2] R. Perez et. al., "A New Operational Model for Satellite-Derived
        Irradiances: Description and Validation", Solar Energy, vol 73, pp.
        307-317, 2002.

    [3] M. Reno, C. Hansen, and J. Stein, "Global Horizontal Irradiance Clear
        Sky Models: Implementation and Analysis", Sandia National
        Laboratories, SAND2012-2389, 2012.

    [4] http://www.soda-is.com/eng/services/climat_free_eng.php#c5 (obtained
        July 17, 2012).

    [5] J. Remund, et. al., "Worldwide Linke Turbidity Information", Proc.
        ISES Solar World Congress, June 2003. Goteborg, Sweden.
    '''
    # Initial implementation of this algorithm by Matthew Reno.
    # Ported to python by Rob Andrews
    # Added functionality by Will Holmgren (@wholmgren)

    I0 = irradiance.extraradiation(time.dayofyear)

    if zenith_data is None:
        ephem_data = solarposition.get_solarposition(time,
                                                     latitude=latitude,
                                                     longitude=longitude,
                                                     altitude=altitude,
                                                     method=solarposition_method)
        time = ephem_data.index # fixes issue with time possibly not being tz-aware
        try:
            ApparentZenith = ephem_data['apparent_zenith']
        except KeyError:
            ApparentZenith = ephem_data['zenith']
            logger.warning('could not find apparent_zenith. using zenith')
    else:
        ApparentZenith = zenith_data
    #ApparentZenith[ApparentZenith >= 90] = 90 # can cause problems in edge cases


    if linke_turbidity is None:
        TL = lookup_linke_turbidity(time, latitude, longitude,
                                    interp_turbidity=interp_turbidity)
    else:
        TL = linke_turbidity

    # Get the absolute airmass assuming standard local pressure (per
    # alt2pres) using Kasten and Young's 1989 formula for airmass.

    if airmass_data is None:
        AMabsolute = atmosphere.absoluteairmass(airmass_relative=atmosphere.relativeairmass(ApparentZenith, airmass_model),
                                                pressure=atmosphere.alt2pres(altitude))
    else:
        AMabsolute = airmass_data

    fh1 = np.exp(-altitude/8000.)
    fh2 = np.exp(-altitude/1250.)
    cg1 = 5.09e-05 * altitude + 0.868
    cg2 = 3.92e-05 * altitude + 0.0387
    logger.debug('fh1=%s, fh2=%s, cg1=%s, cg2=%s', fh1, fh2, cg1, cg2)

    #  Dan's note on the TL correction: By my reading of the publication on
    #  pages 151-157, Ineichen and Perez introduce (among other things) three
    #  things. 1) Beam model in eqn. 8, 2) new turbidity factor in eqn 9 and
    #  appendix A, and 3) Global horizontal model in eqn. 11. They do NOT appear
    #  to use the new turbidity factor (item 2 above) in either the beam or GHI
    #  models. The phrasing of appendix A seems as if there are two separate
    #  corrections, the first correction is used to correct the beam/GHI models,
    #  and the second correction is used to correct the revised turibidity
    #  factor. In my estimation, there is no need to correct the turbidity
    #  factor used in the beam/GHI models.

    #  Create the corrected TL for TL < 2
    #  TLcorr = TL;
    #  TLcorr(TL < 2) = TLcorr(TL < 2) - 0.25 .* (2-TLcorr(TL < 2)) .^ (0.5);

    #  This equation is found in Solar Energy 73, pg 311.
    #  Full ref: Perez et. al., Vol. 73, pp. 307-317 (2002).
    #  It is slightly different than the equation given in Solar Energy 73, pg 156.
    #  We used the equation from pg 311 because of the existence of known typos
    #  in the pg 156 publication (notably the fh2-(TL-1) should be fh2 * (TL-1)).

    cos_zenith = tools.cosd(ApparentZenith)

    clearsky_GHI = ( cg1 * I0 * cos_zenith *
                     np.exp(-cg2*AMabsolute*(fh1 + fh2*(TL - 1))) *
                     np.exp(0.01*AMabsolute**1.8) )
    clearsky_GHI[clearsky_GHI < 0] = 0

    # BncI == "normal beam clear sky radiation"
    b = 0.664 + 0.163/fh1
    BncI = b * I0 * np.exp( -0.09 * AMabsolute * (TL - 1) )
    logger.debug('b=%s', b)

    # "empirical correction" SE 73, 157 & SE 73, 312.
    BncI_2 = ( clearsky_GHI *
               ( 1 - (0.1 - 0.2*np.exp(-TL))/(0.1 + 0.882/fh1) ) /
               cos_zenith )

    clearsky_DNI = np.minimum(BncI, BncI_2)

    clearsky_DHI = clearsky_GHI - clearsky_DNI*cos_zenith

    df_out = pd.DataFrame({'ghi':clearsky_GHI, 'dni':clearsky_DNI,
                           'dhi':clearsky_DHI})
    df_out.fillna(0, inplace=True)

    return df_out